summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/cryptopp/Doxyfile1634
-rw-r--r--lib/cryptopp/License.txt51
-rw-r--r--lib/cryptopp/Readme.txt452
-rw-r--r--lib/cryptopp/adler32.cpp77
-rw-r--r--lib/cryptopp/adler32.h28
-rw-r--r--lib/cryptopp/aes.h16
-rw-r--r--lib/cryptopp/algebra.cpp340
-rw-r--r--lib/cryptopp/algebra.h285
-rw-r--r--lib/cryptopp/algparam.cpp75
-rw-r--r--lib/cryptopp/algparam.h398
-rw-r--r--lib/cryptopp/argnames.h81
-rw-r--r--lib/cryptopp/asn.cpp597
-rw-r--r--lib/cryptopp/asn.h369
-rw-r--r--lib/cryptopp/authenc.cpp180
-rw-r--r--lib/cryptopp/authenc.h49
-rw-r--r--lib/cryptopp/base32.cpp39
-rw-r--r--lib/cryptopp/base32.h38
-rw-r--r--lib/cryptopp/base64.cpp42
-rw-r--r--lib/cryptopp/base64.h36
-rw-r--r--lib/cryptopp/basecode.cpp238
-rw-r--r--lib/cryptopp/basecode.h86
-rw-r--r--lib/cryptopp/cbcmac.cpp62
-rw-r--r--lib/cryptopp/cbcmac.h50
-rw-r--r--lib/cryptopp/ccm.cpp140
-rw-r--r--lib/cryptopp/ccm.h101
-rw-r--r--lib/cryptopp/channels.cpp309
-rw-r--r--lib/cryptopp/channels.h123
-rw-r--r--lib/cryptopp/cmac.cpp122
-rw-r--r--lib/cryptopp/cmac.h52
-rw-r--r--lib/cryptopp/config.h462
-rw-r--r--lib/cryptopp/cpu.cpp199
-rw-r--r--lib/cryptopp/cpu.h345
-rw-r--r--lib/cryptopp/crc.cpp160
-rw-r--r--lib/cryptopp/crc.h42
-rw-r--r--lib/cryptopp/cryptlib.cpp828
-rw-r--r--lib/cryptopp/cryptlib.h1655
-rw-r--r--lib/cryptopp/default.cpp258
-rw-r--r--lib/cryptopp/default.h104
-rw-r--r--lib/cryptopp/des.cpp449
-rw-r--r--lib/cryptopp/des.h144
-rw-r--r--lib/cryptopp/dessp.cpp95
-rw-r--r--lib/cryptopp/dh.cpp19
-rw-r--r--lib/cryptopp/dh.h99
-rw-r--r--lib/cryptopp/dh2.cpp22
-rw-r--r--lib/cryptopp/dh2.h58
-rw-r--r--lib/cryptopp/dll.cpp146
-rw-r--r--lib/cryptopp/dll.h70
-rw-r--r--lib/cryptopp/dmac.h93
-rw-r--r--lib/cryptopp/dsa.cpp63
-rw-r--r--lib/cryptopp/dsa.h35
-rw-r--r--lib/cryptopp/eax.cpp59
-rw-r--r--lib/cryptopp/eax.h91
-rw-r--r--lib/cryptopp/ec2n.cpp292
-rw-r--r--lib/cryptopp/ec2n.h113
-rw-r--r--lib/cryptopp/eccrypto.cpp694
-rw-r--r--lib/cryptopp/eccrypto.h280
-rw-r--r--lib/cryptopp/ecp.cpp473
-rw-r--r--lib/cryptopp/ecp.h126
-rw-r--r--lib/cryptopp/elgamal.cpp17
-rw-r--r--lib/cryptopp/elgamal.h121
-rw-r--r--lib/cryptopp/emsa2.cpp34
-rw-r--r--lib/cryptopp/emsa2.h86
-rw-r--r--lib/cryptopp/eprecomp.cpp112
-rw-r--r--lib/cryptopp/eprecomp.h75
-rw-r--r--lib/cryptopp/esign.cpp210
-rw-r--r--lib/cryptopp/esign.h128
-rw-r--r--lib/cryptopp/factory.h136
-rw-r--r--lib/cryptopp/files.cpp259
-rw-r--r--lib/cryptopp/files.h112
-rw-r--r--lib/cryptopp/filters.cpp1120
-rw-r--r--lib/cryptopp/filters.h810
-rw-r--r--lib/cryptopp/fips140.cpp84
-rw-r--r--lib/cryptopp/fips140.h59
-rw-r--r--lib/cryptopp/fltrimpl.h67
-rw-r--r--lib/cryptopp/gcm.cpp828
-rw-r--r--lib/cryptopp/gcm.h106
-rw-r--r--lib/cryptopp/gf256.cpp34
-rw-r--r--lib/cryptopp/gf256.h66
-rw-r--r--lib/cryptopp/gf2_32.cpp99
-rw-r--r--lib/cryptopp/gf2_32.h66
-rw-r--r--lib/cryptopp/gf2n.cpp882
-rw-r--r--lib/cryptopp/gf2n.h369
-rw-r--r--lib/cryptopp/gfpcrypt.cpp273
-rw-r--r--lib/cryptopp/gfpcrypt.h528
-rw-r--r--lib/cryptopp/gzip.h65
-rw-r--r--lib/cryptopp/hex.cpp44
-rw-r--r--lib/cryptopp/hex.h36
-rw-r--r--lib/cryptopp/hmac.cpp86
-rw-r--r--lib/cryptopp/hmac.h61
-rw-r--r--lib/cryptopp/hrtimer.cpp138
-rw-r--r--lib/cryptopp/hrtimer.h61
-rw-r--r--lib/cryptopp/integer.cpp4235
-rw-r--r--lib/cryptopp/integer.h420
-rw-r--r--lib/cryptopp/iterhash.cpp160
-rw-r--r--lib/cryptopp/iterhash.h106
-rw-r--r--lib/cryptopp/lubyrack.h141
-rw-r--r--lib/cryptopp/luc.cpp210
-rw-r--r--lib/cryptopp/luc.h236
-rw-r--r--lib/cryptopp/md2.cpp120
-rw-r--r--lib/cryptopp/md2.h46
-rw-r--r--lib/cryptopp/md4.cpp110
-rw-r--r--lib/cryptopp/md4.h35
-rw-r--r--lib/cryptopp/md5.cpp118
-rw-r--r--lib/cryptopp/md5.h33
-rw-r--r--lib/cryptopp/mdc.h72
-rw-r--r--lib/cryptopp/misc.cpp189
-rw-r--r--lib/cryptopp/misc.h1282
-rw-r--r--lib/cryptopp/modarith.h158
-rw-r--r--lib/cryptopp/modes.cpp245
-rw-r--r--lib/cryptopp/modes.h422
-rw-r--r--lib/cryptopp/modexppc.h34
-rw-r--r--lib/cryptopp/mqueue.cpp174
-rw-r--r--lib/cryptopp/mqueue.h100
-rw-r--r--lib/cryptopp/mqv.cpp13
-rw-r--r--lib/cryptopp/mqv.h141
-rw-r--r--lib/cryptopp/nbtheory.cpp1123
-rw-r--r--lib/cryptopp/nbtheory.h131
-rw-r--r--lib/cryptopp/network.cpp550
-rw-r--r--lib/cryptopp/network.h235
-rw-r--r--lib/cryptopp/nr.h6
-rw-r--r--lib/cryptopp/oaep.cpp97
-rw-r--r--lib/cryptopp/oaep.h42
-rw-r--r--lib/cryptopp/oids.h123
-rw-r--r--lib/cryptopp/osrng.cpp192
-rw-r--r--lib/cryptopp/osrng.h156
-rw-r--r--lib/cryptopp/pch.cpp1
-rw-r--r--lib/cryptopp/pch.h21
-rw-r--r--lib/cryptopp/pkcspad.cpp124
-rw-r--r--lib/cryptopp/pkcspad.h94
-rw-r--r--lib/cryptopp/polynomi.cpp577
-rw-r--r--lib/cryptopp/polynomi.h459
-rw-r--r--lib/cryptopp/pssr.cpp145
-rw-r--r--lib/cryptopp/pssr.h66
-rw-r--r--lib/cryptopp/pubkey.cpp165
-rw-r--r--lib/cryptopp/pubkey.h1678
-rw-r--r--lib/cryptopp/pwdbased.h214
-rw-r--r--lib/cryptopp/queue.cpp565
-rw-r--r--lib/cryptopp/queue.h144
-rw-r--r--lib/cryptopp/rabin.cpp221
-rw-r--r--lib/cryptopp/rabin.h107
-rw-r--r--lib/cryptopp/randpool.cpp63
-rw-r--r--lib/cryptopp/randpool.h33
-rw-r--r--lib/cryptopp/rdtables.cpp172
-rw-r--r--lib/cryptopp/resource.h15
-rw-r--r--lib/cryptopp/rijndael.cpp1261
-rw-r--r--lib/cryptopp/rijndael.h68
-rw-r--r--lib/cryptopp/rng.cpp155
-rw-r--r--lib/cryptopp/rng.h77
-rw-r--r--lib/cryptopp/rsa.cpp304
-rw-r--r--lib/cryptopp/rsa.h174
-rw-r--r--lib/cryptopp/rw.cpp196
-rw-r--r--lib/cryptopp/rw.h102
-rw-r--r--lib/cryptopp/safer.cpp153
-rw-r--r--lib/cryptopp/safer.h86
-rw-r--r--lib/cryptopp/seal.cpp213
-rw-r--r--lib/cryptopp/seal.h44
-rw-r--r--lib/cryptopp/secblock.h467
-rw-r--r--lib/cryptopp/seckey.h221
-rw-r--r--lib/cryptopp/seed.cpp104
-rw-r--r--lib/cryptopp/seed.h38
-rw-r--r--lib/cryptopp/sha.cpp900
-rw-r--r--lib/cryptopp/sha.h63
-rw-r--r--lib/cryptopp/shacal2.cpp140
-rw-r--r--lib/cryptopp/shacal2.h54
-rw-r--r--lib/cryptopp/simple.cpp14
-rw-r--r--lib/cryptopp/simple.h209
-rw-r--r--lib/cryptopp/smartptr.h223
-rw-r--r--lib/cryptopp/socketft.cpp531
-rw-r--r--lib/cryptopp/socketft.h224
-rw-r--r--lib/cryptopp/square.cpp177
-rw-r--r--lib/cryptopp/square.h58
-rw-r--r--lib/cryptopp/squaretb.cpp582
-rw-r--r--lib/cryptopp/stdcpp.h41
-rw-r--r--lib/cryptopp/strciphr.cpp252
-rw-r--r--lib/cryptopp/strciphr.h306
-rw-r--r--lib/cryptopp/tea.cpp159
-rw-r--r--lib/cryptopp/tea.h132
-rw-r--r--lib/cryptopp/tiger.cpp265
-rw-r--r--lib/cryptopp/tiger.h24
-rw-r--r--lib/cryptopp/tigertab.cpp525
-rw-r--r--lib/cryptopp/trdlocal.cpp73
-rw-r--r--lib/cryptopp/trdlocal.h44
-rw-r--r--lib/cryptopp/trunhash.h48
-rw-r--r--lib/cryptopp/ttmac.cpp338
-rw-r--r--lib/cryptopp/ttmac.h38
-rw-r--r--lib/cryptopp/validate.h81
-rw-r--r--lib/cryptopp/vmac.cpp832
-rw-r--r--lib/cryptopp/vmac.h68
-rw-r--r--lib/cryptopp/wait.cpp397
-rw-r--r--lib/cryptopp/wait.h208
-rw-r--r--lib/cryptopp/winpipes.cpp205
-rw-r--r--lib/cryptopp/winpipes.h142
-rw-r--r--lib/cryptopp/words.h103
-rw-r--r--lib/expat/ascii.h92
-rw-r--r--lib/expat/asciitab.h36
-rw-r--r--lib/expat/expat.h1014
-rw-r--r--lib/expat/expat_external.h115
-rw-r--r--lib/expat/iasciitab.h37
-rw-r--r--lib/expat/internal.h73
-rw-r--r--lib/expat/latin1tab.h36
-rw-r--r--lib/expat/nametab.h150
-rw-r--r--lib/expat/utf8tab.h37
-rw-r--r--lib/expat/winconfig.h30
-rw-r--r--lib/expat/xmlparse.c6294
-rw-r--r--lib/expat/xmlrole.c1482
-rw-r--r--lib/expat/xmlrole.h114
-rw-r--r--lib/expat/xmltok.c1684
-rw-r--r--lib/expat/xmltok.h316
-rw-r--r--lib/expat/xmltok_impl.c1800
-rw-r--r--lib/expat/xmltok_impl.h46
-rw-r--r--lib/expat/xmltok_ns.c119
-rw-r--r--lib/inifile/iniFile.cpp807
-rw-r--r--lib/inifile/iniFile.h205
-rw-r--r--lib/jsoncpp/include/json/autolink.h19
-rw-r--r--lib/jsoncpp/include/json/config.h43
-rw-r--r--lib/jsoncpp/include/json/features.h42
-rw-r--r--lib/jsoncpp/include/json/forwards.h39
-rw-r--r--lib/jsoncpp/include/json/json.h10
-rw-r--r--lib/jsoncpp/include/json/reader.h196
-rw-r--r--lib/jsoncpp/include/json/value.h1069
-rw-r--r--lib/jsoncpp/include/json/writer.h174
-rw-r--r--lib/jsoncpp/src/lib_json/json_batchallocator.h125
-rw-r--r--lib/jsoncpp/src/lib_json/json_internalarray.inl448
-rw-r--r--lib/jsoncpp/src/lib_json/json_internalmap.inl607
-rw-r--r--lib/jsoncpp/src/lib_json/json_reader.cpp885
-rw-r--r--lib/jsoncpp/src/lib_json/json_value.cpp1727
-rw-r--r--lib/jsoncpp/src/lib_json/json_valueiterator.inl292
-rw-r--r--lib/jsoncpp/src/lib_json/json_writer.cpp829
-rw-r--r--lib/jsoncpp/src/lib_json/sconscript8
-rw-r--r--lib/lua/COPYRIGHT34
-rw-r--r--lib/lua/HISTORY183
-rw-r--r--lib/lua/INSTALL99
-rw-r--r--lib/lua/Makefile128
-rw-r--r--lib/lua/README37
-rw-r--r--lib/lua/src/Makefile182
-rw-r--r--lib/lua/src/lapi.c1087
-rw-r--r--lib/lua/src/lapi.h16
-rw-r--r--lib/lua/src/lauxlib.c652
-rw-r--r--lib/lua/src/lauxlib.h174
-rw-r--r--lib/lua/src/lbaselib.c653
-rw-r--r--lib/lua/src/lcode.c839
-rw-r--r--lib/lua/src/lcode.h76
-rw-r--r--lib/lua/src/ldblib.c397
-rw-r--r--lib/lua/src/ldebug.c638
-rw-r--r--lib/lua/src/ldebug.h33
-rw-r--r--lib/lua/src/ldo.c518
-rw-r--r--lib/lua/src/ldo.h57
-rw-r--r--lib/lua/src/ldump.c164
-rw-r--r--lib/lua/src/lfunc.c174
-rw-r--r--lib/lua/src/lfunc.h34
-rw-r--r--lib/lua/src/lgc.c711
-rw-r--r--lib/lua/src/lgc.h110
-rw-r--r--lib/lua/src/linit.c38
-rw-r--r--lib/lua/src/liolib.c553
-rw-r--r--lib/lua/src/llex.c465
-rw-r--r--lib/lua/src/llex.h81
-rw-r--r--lib/lua/src/llimits.h128
-rw-r--r--lib/lua/src/lmathlib.c263
-rw-r--r--lib/lua/src/lmem.c86
-rw-r--r--lib/lua/src/lmem.h49
-rw-r--r--lib/lua/src/loadlib.c666
-rw-r--r--lib/lua/src/lobject.c214
-rw-r--r--lib/lua/src/lobject.h381
-rw-r--r--lib/lua/src/lopcodes.c102
-rw-r--r--lib/lua/src/lopcodes.h268
-rw-r--r--lib/lua/src/loslib.c243
-rw-r--r--lib/lua/src/lparser.c1339
-rw-r--r--lib/lua/src/lparser.h82
-rw-r--r--lib/lua/src/lstate.c214
-rw-r--r--lib/lua/src/lstate.h169
-rw-r--r--lib/lua/src/lstring.c111
-rw-r--r--lib/lua/src/lstring.h31
-rw-r--r--lib/lua/src/lstrlib.c869
-rw-r--r--lib/lua/src/ltable.c588
-rw-r--r--lib/lua/src/ltable.h40
-rw-r--r--lib/lua/src/ltablib.c287
-rw-r--r--lib/lua/src/ltm.c75
-rw-r--r--lib/lua/src/ltm.h54
-rw-r--r--lib/lua/src/lua.c392
-rw-r--r--lib/lua/src/lua.h390
-rw-r--r--lib/lua/src/luac.c202
-rw-r--r--lib/lua/src/luaconf.h763
-rw-r--r--lib/lua/src/lualib.h53
-rw-r--r--lib/lua/src/lundump.c227
-rw-r--r--lib/lua/src/lundump.h36
-rw-r--r--lib/lua/src/lvm.c763
-rw-r--r--lib/lua/src/lvm.h36
-rw-r--r--lib/lua/src/lzio.c82
-rw-r--r--lib/lua/src/lzio.h67
-rw-r--r--lib/lua/src/print.c227
-rw-r--r--lib/luaexpat/lxplib.c599
-rw-r--r--lib/luaexpat/lxplib.h24
-rw-r--r--lib/md5/md5.cpp369
-rw-r--r--lib/md5/md5.h93
-rw-r--r--lib/sqlite/lsqlite3.c2175
-rw-r--r--lib/sqlite/sqlite3.c138114
-rw-r--r--lib/sqlite/sqlite3.h7174
-rw-r--r--lib/sqlite/urls.txt9
-rw-r--r--lib/tolua++/COPYRIGHT33
-rw-r--r--lib/tolua++/INSTALL42
-rw-r--r--lib/tolua++/Makefile5
-rw-r--r--lib/tolua++/README30
-rw-r--r--lib/tolua++/README-5.150
-rw-r--r--lib/tolua++/SConstruct180
-rw-r--r--lib/tolua++/include/tolua++.h186
-rw-r--r--lib/tolua++/src/bin/SCsub12
-rw-r--r--lib/tolua++/src/bin/lua/all.lua30
-rw-r--r--lib/tolua++/src/bin/lua/array.lua233
-rw-r--r--lib/tolua++/src/bin/lua/basic.lua414
-rw-r--r--lib/tolua++/src/bin/lua/class.lua202
-rw-r--r--lib/tolua++/src/bin/lua/clean.lua79
-rw-r--r--lib/tolua++/src/bin/lua/code.lua105
-rw-r--r--lib/tolua++/src/bin/lua/compat-5.1.lua57
-rw-r--r--lib/tolua++/src/bin/lua/compat.lua193
-rw-r--r--lib/tolua++/src/bin/lua/container.lua786
-rw-r--r--lib/tolua++/src/bin/lua/custom.lua45
-rw-r--r--lib/tolua++/src/bin/lua/declaration.lua579
-rw-r--r--lib/tolua++/src/bin/lua/define.lua63
-rw-r--r--lib/tolua++/src/bin/lua/doit.lua102
-rw-r--r--lib/tolua++/src/bin/lua/enumerate.lua106
-rw-r--r--lib/tolua++/src/bin/lua/feature.lua139
-rw-r--r--lib/tolua++/src/bin/lua/function.lua577
-rw-r--r--lib/tolua++/src/bin/lua/module.lua68
-rw-r--r--lib/tolua++/src/bin/lua/namespace.lua52
-rw-r--r--lib/tolua++/src/bin/lua/operator.lua220
-rw-r--r--lib/tolua++/src/bin/lua/package.lua343
-rw-r--r--lib/tolua++/src/bin/lua/template_class.lua82
-rw-r--r--lib/tolua++/src/bin/lua/typedef.lua71
-rw-r--r--lib/tolua++/src/bin/lua/variable.lua300
-rw-r--r--lib/tolua++/src/bin/lua/verbatim.lua78
-rw-r--r--lib/tolua++/src/lib/SCsub18
-rw-r--r--lib/tolua++/src/lib/tolua_event.c536
-rw-r--r--lib/tolua++/src/lib/tolua_event.h24
-rw-r--r--lib/tolua++/src/lib/tolua_is.c621
-rw-r--r--lib/tolua++/src/lib/tolua_map.c704
-rw-r--r--lib/tolua++/src/lib/tolua_push.c171
-rw-r--r--lib/tolua++/src/lib/tolua_to.c133
-rw-r--r--lib/tolua++/win32/tolualib/tolualib.vcproj197
-rw-r--r--lib/tolua++/win32/tolualib/tolualib.vcproj.LAPTOPF.Kevin.user65
-rw-r--r--lib/tolua++/win32/tolualib/tolualib.vcxproj80
-rw-r--r--lib/tolua++/win32/tolualib/tolualib.vcxproj.filters39
-rw-r--r--lib/tolua++/win32/tolualib/tolualib.vcxproj.user3
-rw-r--r--lib/tolua++/win32/vc7/clean.bat15
-rw-r--r--lib/tolua++/win32/vc7/toluapp.sln48
-rw-r--r--lib/tolua++/win32/vc7/toluapp.vcproj439
-rw-r--r--lib/tolua++/win32/vc7/toluapp.vcproj.LAPTOPF.Kevin.user121
-rw-r--r--lib/tolua++/win32/vc7/toluapp.vcxproj176
-rw-r--r--lib/tolua++/win32/vc7/toluapp.vcxproj.filters45
-rw-r--r--lib/tolua++/win32/vc7/toluapp.vcxproj.user3
-rw-r--r--lib/zlib/adler32.c179
-rw-r--r--lib/zlib/compress.c80
-rw-r--r--lib/zlib/crc32.c425
-rw-r--r--lib/zlib/crc32.h441
-rw-r--r--lib/zlib/deflate.c1965
-rw-r--r--lib/zlib/deflate.h346
-rw-r--r--lib/zlib/example.c601
-rw-r--r--lib/zlib/gzclose.c25
-rw-r--r--lib/zlib/gzguts.h193
-rw-r--r--lib/zlib/gzlib.c620
-rw-r--r--lib/zlib/gzread.c589
-rw-r--r--lib/zlib/gzwrite.c565
-rw-r--r--lib/zlib/infback.c640
-rw-r--r--lib/zlib/inffast.c340
-rw-r--r--lib/zlib/inffast.h11
-rw-r--r--lib/zlib/inffixed.h94
-rw-r--r--lib/zlib/inflate.c1496
-rw-r--r--lib/zlib/inflate.h122
-rw-r--r--lib/zlib/inftrees.c306
-rw-r--r--lib/zlib/inftrees.h62
-rw-r--r--lib/zlib/minigzip.c631
-rw-r--r--lib/zlib/trees.c1224
-rw-r--r--lib/zlib/trees.h128
-rw-r--r--lib/zlib/uncompr.c59
-rw-r--r--lib/zlib/zconf.h506
-rw-r--r--lib/zlib/zlib.h1744
-rw-r--r--lib/zlib/zutil.c324
-rw-r--r--lib/zlib/zutil.h252
377 files changed, 258209 insertions, 0 deletions
diff --git a/lib/cryptopp/Doxyfile b/lib/cryptopp/Doxyfile
new file mode 100644
index 000000000..c221fdf56
--- /dev/null
+++ b/lib/cryptopp/Doxyfile
@@ -0,0 +1,1634 @@
+# Doxyfile 1.7.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = Crypto++
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = NO
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = .
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.h \
+ *.cpp
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = adhoc.cpp
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = .
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 3
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT =
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvances is that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT =
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT =
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH = .
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _WIN32 \
+ _WINDOWS \
+ __FreeBSD__ \
+ CRYPTOPP_DOXYGEN_PROCESSING
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans.ttf
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/lib/cryptopp/License.txt b/lib/cryptopp/License.txt
new file mode 100644
index 000000000..c5d3f34b1
--- /dev/null
+++ b/lib/cryptopp/License.txt
@@ -0,0 +1,51 @@
+Compilation Copyright (c) 1995-2013 by Wei Dai. All rights reserved.
+This copyright applies only to this software distribution package
+as a compilation, and does not imply a copyright on any particular
+file in the package.
+
+All individual files in this compilation are placed in the public domain by
+Wei Dai and other contributors.
+
+I would like to thank the following authors for placing their works into
+the public domain:
+
+Joan Daemen - 3way.cpp
+Leonard Janke - cast.cpp, seal.cpp
+Steve Reid - cast.cpp
+Phil Karn - des.cpp
+Andrew M. Kuchling - md2.cpp, md4.cpp
+Colin Plumb - md5.cpp
+Seal Woods - rc6.cpp
+Chris Morgan - rijndael.cpp
+Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp
+Richard De Moliner - safer.cpp
+Matthew Skala - twofish.cpp
+Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp
+Ronny Van Keer - sha3.cpp
+
+The Crypto++ Library (as a compilation) is currently licensed under the Boost
+Software License 1.0 (http://www.boost.org/users/license.html).
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/lib/cryptopp/Readme.txt b/lib/cryptopp/Readme.txt
new file mode 100644
index 000000000..5f3b4525d
--- /dev/null
+++ b/lib/cryptopp/Readme.txt
@@ -0,0 +1,452 @@
+Crypto++: a C++ Class Library of Cryptographic Schemes
+Version 5.6.2 - 2/20/2013
+
+Crypto++ Library is a free C++ class library of cryptographic schemes.
+Currently the library contains the following algorithms:
+
+ algorithm type name
+
+ authenticated encryption schemes GCM, CCM, EAX
+
+ high speed stream ciphers Panama, Sosemanuk, Salsa20, XSalsa20
+
+ AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
+ CAST-256
+
+ IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
+ other block ciphers Camellia, SEED, RC5, Blowfish, TEA, XTEA,
+ Skipjack, SHACAL-2
+
+ block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
+ CFB, OFB, counter mode (CTR)
+
+ message authentication codes VMAC, HMAC, GMAC, CMAC, CBC-MAC, DMAC,
+ Two-Track-MAC
+
+ SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and
+ hash functions SHA-512), SHA-3, Tiger, WHIRLPOOL, RIPEMD-128,
+ RIPEMD-256, RIPEMD-160, RIPEMD-320
+
+ RSA, DSA, ElGamal, Nyberg-Rueppel (NR),
+ public-key cryptography Rabin-Williams (RW), LUC, LUCELG,
+ DLIES (variants of DHAES), ESIGN
+
+ padding schemes for public-key PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363
+ systems EMSA2 and EMSA5
+
+ Diffie-Hellman (DH), Unified Diffie-Hellman
+ key agreement schemes (DH2), Menezes-Qu-Vanstone (MQV), LUCDIF,
+ XTR-DH
+
+ elliptic curve cryptography ECDSA, ECNR, ECIES, ECDH, ECMQV
+
+ insecure or obsolescent MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL
+algorithms retained for backwards 3.0, WAKE-OFB, DESX (DES-XEX3), RC2,
+ compatibility and historical SAFER, 3-WAY, GOST, SHARK, CAST-128, Square
+ value
+
+Other features include:
+
+ * pseudo random number generators (PRNG): ANSI X9.17 appendix C, RandomPool
+ * password based key derivation functions: PBKDF1 and PBKDF2 from PKCS #5,
+ PBKDF from PKCS #12 appendix B
+ * Shamir's secret sharing scheme and Rabin's information dispersal algorithm
+ (IDA)
+ * fast multi-precision integer (bignum) and polynomial operations
+ * finite field arithmetics, including GF(p) and GF(2^n)
+ * prime number generation and verification
+ * useful non-cryptographic algorithms
+ + DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and
+ zlib (RFC 1950) format support
+ + hex, base-32, and base-64 coding/decoding
+ + 32-bit CRC and Adler32 checksum
+ * class wrappers for these operating system features (optional):
+ + high resolution timers on Windows, Unix, and Mac OS
+ + Berkeley and Windows style sockets
+ + Windows named pipes
+ + /dev/random, /dev/urandom, /dev/srandom
+ + Microsoft's CryptGenRandom on Windows
+ * A high level interface for most of the above, using a filter/pipeline
+ metaphor
+ * benchmarks and validation testing
+ * x86, x86-64 (x64), MMX, and SSE2 assembly code for the most commonly used
+ algorithms, with run-time CPU feature detection and code selection
+ * some versions are available in FIPS 140-2 validated form
+
+You are welcome to use it for any purpose without paying me, but see
+License.txt for the fine print.
+
+The following compilers are supported for this release. Please visit
+http://www.cryptopp.com the most up to date build instructions and porting notes.
+
+ * MSVC 6.0 - 2010
+ * GCC 3.3 - 4.5
+ * C++Builder 2010
+ * Intel C++ Compiler 9 - 11.1
+ * Sun Studio 12u1, Express 11/08, Express 06/10
+
+*** Important Usage Notes ***
+
+1. If a constructor for A takes a pointer to an object B (except primitive
+types such as int and char), then A owns B and will delete B at A's
+destruction. If a constructor for A takes a reference to an object B,
+then the caller retains ownership of B and should not destroy it until
+A no longer needs it.
+
+2. Crypto++ is thread safe at the class level. This means you can use
+Crypto++ safely in a multithreaded application, but you must provide
+synchronization when multiple threads access a common Crypto++ object.
+
+*** MSVC-Specific Information ***
+
+On Windows, Crypto++ can be compiled into 3 forms: a static library
+including all algorithms, a DLL with only FIPS Approved algorithms, and
+a static library with only algorithms not in the DLL.
+(FIPS Approved means Approved according to the FIPS 140-2 standard.)
+The DLL may be used by itself, or it may be used together with the second
+form of the static library. MSVC project files are included to build
+all three forms, and sample applications using each of the three forms
+are also included.
+
+To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET
+2003) or "cryptest.sln" (for MSVC 2005 - 2010) workspace file and build one or
+more of the following projects:
+
+cryptopp - This builds the DLL. Please note that if you wish to use Crypto++
+ as a FIPS validated module, you must use a pre-built DLL that has undergone
+ the FIPS validation process instead of building your own.
+dlltest - This builds a sample application that only uses the DLL.
+cryptest Non-DLL-Import Configuration - This builds the full static library
+ along with a full test driver.
+cryptest DLL-Import Configuration - This builds a static library containing
+ only algorithms not in the DLL, along with a full test driver that uses
+ both the DLL and the static library.
+
+To use the Crypto++ DLL in your application, #include "dll.h" before including
+any other Crypto++ header files, and place the DLL in the same directory as
+your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp")
+so you don't have to explicitly list the import library in your project
+settings. To use a static library form of Crypto++, make the "cryptlib"
+project a dependency of your application project, or specify it as
+an additional library to link with in your project settings.
+In either case you should check the compiler options to
+make sure that the library and your application are using the same C++
+run-time libraries and calling conventions.
+
+*** DLL Memory Management ***
+
+Because it's possible for the Crypto++ DLL to delete objects allocated
+by the calling application, they must use the same C++ memory heap. Three
+methods are provided to achieve this.
+1. The calling application can tell Crypto++ what heap to use. This method
+ is required when the calling application uses a non-standard heap.
+2. Crypto++ can tell the calling application what heap to use. This method
+ is required when the calling application uses a statically linked C++ Run
+ Time Library. (Method 1 does not work in this case because the Crypto++ DLL
+ is initialized before the calling application's heap is initialized.)
+3. Crypto++ can automatically use the heap provided by the calling application's
+ dynamically linked C++ Run Time Library. The calling application must
+ make sure that the dynamically linked C++ Run Time Library is initialized
+ before Crypto++ is loaded. (At this time it is not clear if it is possible
+ to control the order in which DLLs are initialized on Windows 9x machines,
+ so it might be best to avoid using this method.)
+
+When Crypto++ attaches to a new process, it searches all modules loaded
+into the process space for exported functions "GetNewAndDeleteForCryptoPP"
+and "SetNewAndDeleteFromCryptoPP". If one of these functions is found,
+Crypto++ uses methods 1 or 2, respectively, by calling the function.
+Otherwise, method 3 is used.
+
+*** GCC-Specific Information ***
+
+A makefile is included for you to compile Crypto++ with GCC. Make sure
+you are using GNU Make and GNU ld. The make process will produce two files,
+libcryptopp.a and cryptest.exe. Run "cryptest.exe v" for the validation
+suite.
+
+*** Documentation and Support ***
+
+Crypto++ is documented through inline comments in header files, which are
+processed through Doxygen to produce an HTML reference manual. You can find
+a link to the manual from http://www.cryptopp.com. Also at that site is
+the Crypto++ FAQ, which you should browse through before attempting to
+use this library, because it will likely answer many of questions that
+may come up.
+
+If you run into any problems, please try the Crypto++ mailing list.
+The subscription information and the list archive are available on
+http://www.cryptopp.com. You can also email me directly by visiting
+http://www.weidai.com, but you will probably get a faster response through
+the mailing list.
+
+*** History ***
+
+1.0 - First public release. Withdrawn at the request of RSA DSI.
+ - included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA,
+ MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression
+ - had a serious bug in the RSA key generation code.
+
+1.1 - Removed RSA, RC4, RC5
+ - Disabled calls to RSAREF's non-public functions
+ - Minor bugs fixed
+
+2.0 - a completely new, faster multiprecision integer class
+ - added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser,
+ elliptic curve algorithms
+ - added the Lucas strong probable primality test
+ - ElGamal encryption and signature schemes modified to avoid weaknesses
+ - Diamond changed to Diamond2 because of key schedule weakness
+ - fixed bug in WAKE key setup
+ - SHS class renamed to SHA
+ - lots of miscellaneous optimizations
+
+2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC,
+ OAEP, PSSR, SHARK
+ - added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms
+ - added back RC5 and a new RSA
+ - optimizations in elliptic curves over GF(p)
+ - changed Rabin to use OAEP and PSSR
+ - changed many classes to allow copy constructors to work correctly
+ - improved exception generation and handling
+
+2.2 - added SEAL, CAST-128, Square
+ - fixed bug in HAVAL (padding problem)
+ - fixed bug in triple-DES (decryption order was reversed)
+ - fixed bug in RC5 (couldn't handle key length not a multiple of 4)
+ - changed HMAC to conform to RFC-2104 (which is not compatible
+ with the original HMAC)
+ - changed secret sharing and information dispersal to use GF(2^32)
+ instead of GF(65521)
+ - removed zero knowledge prover/verifier for graph isomorphism
+ - removed several utility classes in favor of the C++ standard library
+
+2.3 - ported to EGCS
+ - fixed incomplete workaround of min/max conflict in MSVC
+
+3.0 - placed all names into the "CryptoPP" namespace
+ - added MD2, RC2, RC6, MARS, RW, DH2, MQV, ECDHC, CBC-CTS
+ - added abstract base classes PK_SimpleKeyAgreementDomain and
+ PK_AuthenticatedKeyAgreementDomain
+ - changed DH and LUCDIF to implement the PK_SimpleKeyAgreementDomain
+ interface and to perform domain parameter and key validation
+ - changed interfaces of PK_Signer and PK_Verifier to sign and verify
+ messages instead of message digests
+ - changed OAEP to conform to PKCS#1 v2.0
+ - changed benchmark code to produce HTML tables as output
+ - changed PSSR to track IEEE P1363a
+ - renamed ElGamalSignature to NR and changed it to track IEEE P1363
+ - renamed ECKEP to ECMQVC and changed it to track IEEE P1363
+ - renamed several other classes for clarity
+ - removed support for calling RSAREF
+ - removed option to compile old SHA (SHA-0)
+ - removed option not to throw exceptions
+
+3.1 - added ARC4, Rijndael, Twofish, Serpent, CBC-MAC, DMAC
+ - added interface for querying supported key lengths of symmetric ciphers
+ and MACs
+ - added sample code for RSA signature and verification
+ - changed CBC-CTS to be compatible with RFC 2040
+ - updated SEAL to version 3.0 of the cipher specification
+ - optimized multiprecision squaring and elliptic curves over GF(p)
+ - fixed bug in MARS key setup
+ - fixed bug with attaching objects to Deflator
+
+3.2 - added DES-XEX3, ECDSA, DefaultEncryptorWithMAC
+ - renamed DES-EDE to DES-EDE2 and TripleDES to DES-EDE3
+ - optimized ARC4
+ - generalized DSA to allow keys longer than 1024 bits
+ - fixed bugs in GF2N and ModularArithmetic that can cause calculation errors
+ - fixed crashing bug in Inflator when given invalid inputs
+ - fixed endian bug in Serpent
+ - fixed padding bug in Tiger
+
+4.0 - added Skipjack, CAST-256, Panama, SHA-2 (SHA-256, SHA-384, and SHA-512),
+ and XTR-DH
+ - added a faster variant of Rabin's Information Dispersal Algorithm (IDA)
+ - added class wrappers for these operating system features:
+ - high resolution timers on Windows, Unix, and MacOS
+ - Berkeley and Windows style sockets
+ - Windows named pipes
+ - /dev/random and /dev/urandom on Linux and FreeBSD
+ - Microsoft's CryptGenRandom on Windows
+ - added support for SEC 1 elliptic curve key format and compressed points
+ - added support for X.509 public key format (subjectPublicKeyInfo) for
+ RSA, DSA, and elliptic curve schemes
+ - added support for DER and OpenPGP signature format for DSA
+ - added support for ZLIB compressed data format (RFC 1950)
+ - changed elliptic curve encryption to use ECIES (as defined in SEC 1)
+ - changed MARS key schedule to reflect the latest specification
+ - changed BufferedTransformation interface to support multiple channels
+ and messages
+ - changed CAST and SHA-1 implementations to use public domain source code
+ - fixed bug in StringSource
+ - optmized multi-precision integer code for better performance
+
+4.1 - added more support for the recommended elliptic curve parameters in SEC 2
+ - added Panama MAC, MARC4
+ - added IV stealing feature to CTS mode
+ - added support for PKCS #8 private key format for RSA, DSA, and elliptic
+ curve schemes
+ - changed Deflate, MD5, Rijndael, and Twofish to use public domain code
+ - fixed a bug with flushing compressed streams
+ - fixed a bug with decompressing stored blocks
+ - fixed a bug with EC point decompression using non-trinomial basis
+ - fixed a bug in NetworkSource::GeneralPump()
+ - fixed a performance issue with EC over GF(p) decryption
+ - fixed syntax to allow GCC to compile without -fpermissive
+ - relaxed some restrictions in the license
+
+4.2 - added support for longer HMAC keys
+ - added MD4 (which is not secure so use for compatibility purposes only)
+ - added compatibility fixes/workarounds for STLport 4.5, GCC 3.0.2,
+ and MSVC 7.0
+ - changed MD2 to use public domain code
+ - fixed a bug with decompressing multiple messages with the same object
+ - fixed a bug in CBC-MAC with MACing multiple messages with the same object
+ - fixed a bug in RC5 and RC6 with zero-length keys
+ - fixed a bug in Adler32 where incorrect checksum may be generated
+
+5.0 - added ESIGN, DLIES, WAKE-OFB, PBKDF1 and PBKDF2 from PKCS #5
+ - added key validation for encryption and signature public/private keys
+ - renamed StreamCipher interface to SymmetricCipher, which is now implemented
+ by both stream ciphers and block cipher modes including ECB and CBC
+ - added keying interfaces to support resetting of keys and IVs without
+ having to destroy and recreate objects
+ - changed filter interface to support non-blocking input/output
+ - changed SocketSource and SocketSink to use overlapped I/O on Microsoft Windows
+ - grouped related classes inside structs to help templates, for example
+ AESEncryption and AESDecryption are now AES::Encryption and AES::Decryption
+ - where possible, typedefs have been added to improve backwards
+ compatibility when the CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY macro is defined
+ - changed Serpent, HAVAL and IDEA to use public domain code
+ - implemented SSE2 optimizations for Integer operations
+ - fixed a bug in HMAC::TruncatedFinal()
+ - fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02
+
+5.01 - added known answer test for X9.17 RNG in FIPS 140 power-up self test
+ - submitted to NIST/CSE, but not publicly released
+
+5.02 - changed EDC test to MAC integrity check using HMAC/SHA1
+ - improved performance of integrity check
+ - added blinding to defend against RSA timing attack
+
+5.03 - created DLL version of Crypto++ for FIPS 140-2 validation
+ - fixed vulnerabilities in GetNextIV for CTR and OFB modes
+
+5.0.4 - Removed DES, SHA-256, SHA-384, SHA-512 from DLL
+
+5.1 - added PSS padding and changed PSSR to track IEEE P1363a draft standard
+ - added blinding for RSA and Rabin to defend against timing attacks
+ on decryption operations
+ - changed signing and decryption APIs to support the above
+ - changed WaitObjectContainer to allow waiting for more than 64
+ objects at a time on Win32 platforms
+ - fixed a bug in CBC and ECB modes with processing non-aligned data
+ - fixed standard conformance bugs in DLIES (DHAES mode) and RW/EMSA2
+ signature scheme (these fixes are not backwards compatible)
+ - fixed a number of compiler warnings, minor bugs, and portability problems
+ - removed Sapphire
+
+5.2 - merged in changes for 5.01 - 5.0.4
+ - added support for using encoding parameters and key derivation parameters
+ with public key encryption (implemented by OAEP and DL/ECIES)
+ - added Camellia, SHACAL-2, Two-Track-MAC, Whirlpool, RIPEMD-320,
+ RIPEMD-128, RIPEMD-256, Base-32 coding, FIPS variant of CFB mode
+ - added ThreadUserTimer for timing thread CPU usage
+ - added option for password-based key derivation functions
+ to iterate until a mimimum elapsed thread CPU time is reached
+ - added option (on by default) for DEFLATE compression to detect
+ uncompressible files and process them more quickly
+ - improved compatibility and performance on 64-bit platforms,
+ including Alpha, IA-64, x86-64, PPC64, Sparc64, and MIPS64
+ - fixed ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding.
+ - fixed encoding/decoding of PKCS #8 privateKeyInfo to properly
+ handle optional attributes
+
+5.2.1 - fixed bug in the "dlltest" DLL testing program
+ - fixed compiling with STLport using VC .NET
+ - fixed compiling with -fPIC using GCC
+ - fixed compiling with -msse2 on systems without memalign()
+ - fixed inability to instantiate PanamaMAC
+ - fixed problems with inline documentation
+
+5.2.2 - added SHA-224
+ - put SHA-256, SHA-384, SHA-512, RSASSA-PSS into DLL
+
+5.2.3 - fixed issues with FIPS algorithm test vectors
+ - put RSASSA-ISO into DLL
+
+5.3 - ported to MSVC 2005 with support for x86-64
+ - added defense against AES timing attacks, and more AES test vectors
+ - changed StaticAlgorithmName() of Rijndael to "AES", CTR to "CTR"
+
+5.4 - added Salsa20
+ - updated Whirlpool to version 3.0
+ - ported to GCC 4.1, Sun C++ 5.8, and Borland C++Builder 2006
+
+5.5 - added VMAC and Sosemanuk (with x86-64 and SSE2 assembly)
+ - improved speed of integer arithmetic, AES, SHA-512, Tiger, Salsa20,
+ Whirlpool, and PANAMA cipher using assembly (x86-64, MMX, SSE2)
+ - optimized Camellia and added defense against timing attacks
+ - updated benchmarks code to show cycles per byte and to time key/IV setup
+ - started using OpenMP for increased multi-core speed
+ - enabled GCC optimization flags by default in GNUmakefile
+ - added blinding and computational error checking for RW signing
+ - changed RandomPool, X917RNG, GetNextIV, DSA/NR/ECDSA/ECNR to reduce
+ the risk of reusing random numbers and IVs after virtual machine state
+ rollback
+ - changed default FIPS mode RNG from AutoSeededX917RNG<DES_EDE3> to
+ AutoSeededX917RNG<AES>
+ - fixed PANAMA cipher interface to accept 256-bit key and 256-bit IV
+ - moved MD2, MD4, MD5, PanamaHash, ARC4, WAKE_CFB into the namespace "Weak"
+ - removed HAVAL, MD5-MAC, XMAC
+
+5.5.1 - fixed VMAC validation failure on 32-bit big-endian machines
+
+5.5.2 - ported x64 assembly language code for AES, Salsa20, Sosemanuk, and Panama
+ to MSVC 2005 (using MASM since MSVC doesn't support inline assembly on x64)
+ - fixed Salsa20 initialization crash on non-SSE2 machines
+ - fixed Whirlpool crash on Pentium 2 machines
+ - fixed possible branch prediction analysis (BPA) vulnerability in
+ MontgomeryReduce(), which may affect security of RSA, RW, LUC
+ - fixed link error with MSVC 2003 when using "debug DLL" form of runtime library
+ - fixed crash in SSE2_Add on P4 machines when compiled with
+ MSVC 6.0 SP5 with Processor Pack
+ - ported to MSVC 2008, GCC 4.2, Sun CC 5.9, Intel C++ Compiler 10.0,
+ and Borland C++Builder 2007
+
+5.6.0 - added AuthenticatedSymmetricCipher interface class and Filter wrappers
+ - added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED
+ - added support for variable length IVs
+ - added OIDs for Brainpool elliptic curve parameters
+ - improved AES and SHA-256 speed on x86 and x64
+ - changed BlockTransformation interface to no longer assume data alignment
+ - fixed incorrect VMAC computation on message lengths
+ that are >64 mod 128 (x86 assembly version is not affected)
+ - fixed compiler error in vmac.cpp on x86 with GCC -fPIC
+ - fixed run-time validation error on x86-64 with GCC 4.3.2 -O2
+ - fixed HashFilter bug when putMessage=true
+ - fixed AES-CTR data alignment bug that causes incorrect encryption on ARM
+ - removed WORD64_AVAILABLE; compiler support for 64-bit int is now required
+ - ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11
+
+5.6.1 - added support for AES-NI and CLMUL instruction sets in AES and GMAC/GCM
+ - removed WAKE-CFB
+ - fixed several bugs in the SHA-256 x86/x64 assembly code:
+ * incorrect hash on non-SSE2 x86 machines on non-aligned input
+ * incorrect hash on x86 machines when input crosses 0x80000000
+ * incorrect hash on x64 when compiled with GCC with optimizations enabled
+ - fixed bugs in AES x86 and x64 assembly causing crashes in some MSVC build configurations
+ - switched to a public domain implementation of MARS
+ - ported to MSVC 2010, GCC 4.5.1, Sun Studio 12u1, C++Builder 2010, Intel C++ Compiler 11.1
+ - renamed the MSVC DLL project to "cryptopp" for compatibility with MSVC 2010
+
+5.6.2 - changed license to Boost Software License 1.0
+ - added SHA-3 (Keccak)
+ - updated DSA to FIPS 186-3 (see DSA2 class)
+ - fixed Blowfish minimum keylength to be 4 bytes (32 bits)
+ - fixed Salsa validation failure when compiling with GCC 4.6
+ - fixed infinite recursion when on x64, assembly disabled, and no AESNI
+ - ported to MSVC 2012, GCC 4.7, Clang 3.2, Solaris Studio 12.3, Intel C++ Compiler 13.0
+
+Written by Wei Dai
diff --git a/lib/cryptopp/adler32.cpp b/lib/cryptopp/adler32.cpp
new file mode 100644
index 000000000..0d52c0838
--- /dev/null
+++ b/lib/cryptopp/adler32.cpp
@@ -0,0 +1,77 @@
+// adler32.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "adler32.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void Adler32::Update(const byte *input, size_t length)
+{
+ const unsigned long BASE = 65521;
+
+ unsigned long s1 = m_s1;
+ unsigned long s2 = m_s2;
+
+ if (length % 8 != 0)
+ {
+ do
+ {
+ s1 += *input++;
+ s2 += s1;
+ length--;
+ } while (length % 8 != 0);
+
+ if (s1 >= BASE)
+ s1 -= BASE;
+ s2 %= BASE;
+ }
+
+ while (length > 0)
+ {
+ s1 += input[0]; s2 += s1;
+ s1 += input[1]; s2 += s1;
+ s1 += input[2]; s2 += s1;
+ s1 += input[3]; s2 += s1;
+ s1 += input[4]; s2 += s1;
+ s1 += input[5]; s2 += s1;
+ s1 += input[6]; s2 += s1;
+ s1 += input[7]; s2 += s1;
+
+ length -= 8;
+ input += 8;
+
+ if (s1 >= BASE)
+ s1 -= BASE;
+ if (length % 0x8000 == 0)
+ s2 %= BASE;
+ }
+
+ assert(s1 < BASE);
+ assert(s2 < BASE);
+
+ m_s1 = (word16)s1;
+ m_s2 = (word16)s2;
+}
+
+void Adler32::TruncatedFinal(byte *hash, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ switch (size)
+ {
+ default:
+ hash[3] = byte(m_s1);
+ case 3:
+ hash[2] = byte(m_s1 >> 8);
+ case 2:
+ hash[1] = byte(m_s2);
+ case 1:
+ hash[0] = byte(m_s2 >> 8);
+ case 0:
+ ;
+ }
+
+ Reset();
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/adler32.h b/lib/cryptopp/adler32.h
new file mode 100644
index 000000000..0ed803da9
--- /dev/null
+++ b/lib/cryptopp/adler32.h
@@ -0,0 +1,28 @@
+#ifndef CRYPTOPP_ADLER32_H
+#define CRYPTOPP_ADLER32_H
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! ADLER-32 checksum calculations
+class Adler32 : public HashTransformation
+{
+public:
+ CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
+ Adler32() {Reset();}
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *hash, size_t size);
+ unsigned int DigestSize() const {return DIGESTSIZE;}
+ static const char * StaticAlgorithmName() {return "Adler32";}
+ std::string AlgorithmName() const {return StaticAlgorithmName();}
+
+private:
+ void Reset() {m_s1 = 1; m_s2 = 0;}
+
+ word16 m_s1, m_s2;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/aes.h b/lib/cryptopp/aes.h
new file mode 100644
index 000000000..008754256
--- /dev/null
+++ b/lib/cryptopp/aes.h
@@ -0,0 +1,16 @@
+#ifndef CRYPTOPP_AES_H
+#define CRYPTOPP_AES_H
+
+#include "rijndael.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! <a href="http://www.cryptolounge.org/wiki/AES">AES</a> winner, announced on 10/2/2000
+DOCUMENTED_TYPEDEF(Rijndael, AES);
+
+typedef RijndaelEncryption AESEncryption;
+typedef RijndaelDecryption AESDecryption;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/algebra.cpp b/lib/cryptopp/algebra.cpp
new file mode 100644
index 000000000..958e63701
--- /dev/null
+++ b/lib/cryptopp/algebra.cpp
@@ -0,0 +1,340 @@
+// algebra.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice
+#define CRYPTOPP_ALGEBRA_CPP
+
+#include "algebra.h"
+#include "integer.h"
+
+#include <vector>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
+{
+ return this->Add(a, a);
+}
+
+template <class T> const T& AbstractGroup<T>::Subtract(const Element &a, const Element &b) const
+{
+ // make copy of a in case Inverse() overwrites it
+ Element a1(a);
+ return this->Add(a1, Inverse(b));
+}
+
+template <class T> T& AbstractGroup<T>::Accumulate(Element &a, const Element &b) const
+{
+ return a = this->Add(a, b);
+}
+
+template <class T> T& AbstractGroup<T>::Reduce(Element &a, const Element &b) const
+{
+ return a = this->Subtract(a, b);
+}
+
+template <class T> const T& AbstractRing<T>::Square(const Element &a) const
+{
+ return this->Multiply(a, a);
+}
+
+template <class T> const T& AbstractRing<T>::Divide(const Element &a, const Element &b) const
+{
+ // make copy of a in case MultiplicativeInverse() overwrites it
+ Element a1(a);
+ return this->Multiply(a1, this->MultiplicativeInverse(b));
+}
+
+template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a, const Element &b) const
+{
+ Element q;
+ this->DivisionAlgorithm(result, q, a, b);
+ return result;
+}
+
+template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a, const Element &b) const
+{
+ Element g[3]={b, a};
+ unsigned int i0=0, i1=1, i2=2;
+
+ while (!this->Equal(g[i1], this->Identity()))
+ {
+ g[i2] = this->Mod(g[i0], g[i1]);
+ unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
+ }
+
+ return result = g[i0];
+}
+
+template <class T> const typename QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(const Element &a) const
+{
+ Element g[3]={m_modulus, a};
+ Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
+ Element y;
+ unsigned int i0=0, i1=1, i2=2;
+
+ while (!this->Equal(g[i1], this->Identity()))
+ {
+ // y = g[i0] / g[i1];
+ // g[i2] = g[i0] % g[i1];
+ m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
+ // v[i2] = v[i0] - (v[i1] * y);
+ v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
+ unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
+ }
+
+ return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity();
+}
+
+template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base, const Integer &exponent) const
+{
+ Element result;
+ this->SimultaneousMultiply(&result, base, &exponent, 1);
+ return result;
+}
+
+template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
+{
+ const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount());
+ if (expLen==0)
+ return this->Identity();
+
+ const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
+ const unsigned tableSize = 1<<w;
+ std::vector<Element> powerTable(tableSize << w);
+
+ powerTable[1] = x;
+ powerTable[tableSize] = y;
+ if (w==1)
+ powerTable[3] = this->Add(x,y);
+ else
+ {
+ powerTable[2] = this->Double(x);
+ powerTable[2*tableSize] = this->Double(y);
+
+ unsigned i, j;
+
+ for (i=3; i<tableSize; i+=2)
+ powerTable[i] = Add(powerTable[i-2], powerTable[2]);
+ for (i=1; i<tableSize; i+=2)
+ for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
+ powerTable[j] = Add(powerTable[j-tableSize], y);
+
+ for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
+ powerTable[i] = Add(powerTable[i-2*tableSize], powerTable[2*tableSize]);
+ for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
+ for (j=i+2; j<i+tableSize; j+=2)
+ powerTable[j] = Add(powerTable[j-1], x);
+ }
+
+ Element result;
+ unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
+ bool firstTime = true;
+
+ for (int i = expLen-1; i>=0; i--)
+ {
+ power1 = 2*power1 + e1.GetBit(i);
+ power2 = 2*power2 + e2.GetBit(i);
+
+ if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
+ {
+ unsigned squaresBefore = prevPosition-i;
+ unsigned squaresAfter = 0;
+ prevPosition = i;
+ while ((power1 || power2) && power1%2 == 0 && power2%2==0)
+ {
+ power1 /= 2;
+ power2 /= 2;
+ squaresBefore--;
+ squaresAfter++;
+ }
+ if (firstTime)
+ {
+ result = powerTable[(power2<<w) + power1];
+ firstTime = false;
+ }
+ else
+ {
+ while (squaresBefore--)
+ result = this->Double(result);
+ if (power1 || power2)
+ Accumulate(result, powerTable[(power2<<w) + power1]);
+ }
+ while (squaresAfter--)
+ result = this->Double(result);
+ power1 = power2 = 0;
+ }
+ }
+ return result;
+}
+
+template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end)
+{
+ if (end-begin == 1)
+ return group.ScalarMultiply(begin->base, begin->exponent);
+ else if (end-begin == 2)
+ return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent);
+ else
+ {
+ Integer q, t;
+ Iterator last = end;
+ --last;
+
+ std::make_heap(begin, end);
+ std::pop_heap(begin, end);
+
+ while (!!begin->exponent)
+ {
+ // last->exponent is largest exponent, begin->exponent is next largest
+ t = last->exponent;
+ Integer::Divide(last->exponent, q, t, begin->exponent);
+
+ if (q == Integer::One())
+ group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply()
+ else
+ group.Accumulate(begin->base, group.ScalarMultiply(last->base, q));
+
+ std::push_heap(begin, end);
+ std::pop_heap(begin, end);
+ }
+
+ return group.ScalarMultiply(last->base, last->exponent);
+ }
+}
+
+struct WindowSlider
+{
+ WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0)
+ : exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false)
+ {
+ if (windowSize == 0)
+ {
+ unsigned int expLen = exp.BitCount();
+ windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7)))));
+ }
+ windowModulus <<= windowSize;
+ }
+
+ void FindNextWindow()
+ {
+ unsigned int expLen = exp.WordCount() * WORD_BITS;
+ unsigned int skipCount = firstTime ? 0 : windowSize;
+ firstTime = false;
+ while (!exp.GetBit(skipCount))
+ {
+ if (skipCount >= expLen)
+ {
+ finished = true;
+ return;
+ }
+ skipCount++;
+ }
+
+ exp >>= skipCount;
+ windowBegin += skipCount;
+ expWindow = word32(exp % (word(1) << windowSize));
+
+ if (fastNegate && exp.GetBit(windowSize))
+ {
+ negateNext = true;
+ expWindow = (word32(1) << windowSize) - expWindow;
+ exp += windowModulus;
+ }
+ else
+ negateNext = false;
+ }
+
+ Integer exp, windowModulus;
+ unsigned int windowSize, windowBegin;
+ word32 expWindow;
+ bool fastNegate, negateNext, firstTime, finished;
+};
+
+template <class T>
+void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const
+{
+ std::vector<std::vector<Element> > buckets(expCount);
+ std::vector<WindowSlider> exponents;
+ exponents.reserve(expCount);
+ unsigned int i;
+
+ for (i=0; i<expCount; i++)
+ {
+ assert(expBegin->NotNegative());
+ exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
+ exponents[i].FindNextWindow();
+ buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
+ }
+
+ unsigned int expBitPosition = 0;
+ Element g = base;
+ bool notDone = true;
+
+ while (notDone)
+ {
+ notDone = false;
+ for (i=0; i<expCount; i++)
+ {
+ if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
+ {
+ Element &bucket = buckets[i][exponents[i].expWindow/2];
+ if (exponents[i].negateNext)
+ Accumulate(bucket, Inverse(g));
+ else
+ Accumulate(bucket, g);
+ exponents[i].FindNextWindow();
+ }
+ notDone = notDone || !exponents[i].finished;
+ }
+
+ if (notDone)
+ {
+ g = Double(g);
+ expBitPosition++;
+ }
+ }
+
+ for (i=0; i<expCount; i++)
+ {
+ Element &r = *results++;
+ r = buckets[i][buckets[i].size()-1];
+ if (buckets[i].size() > 1)
+ {
+ for (int j = (int)buckets[i].size()-2; j >= 1; j--)
+ {
+ Accumulate(buckets[i][j], buckets[i][j+1]);
+ Accumulate(r, buckets[i][j]);
+ }
+ Accumulate(buckets[i][0], buckets[i][1]);
+ r = Add(Double(r), buckets[i][0]);
+ }
+ }
+}
+
+template <class T> T AbstractRing<T>::Exponentiate(const Element &base, const Integer &exponent) const
+{
+ Element result;
+ SimultaneousExponentiate(&result, base, &exponent, 1);
+ return result;
+}
+
+template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
+{
+ return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(x, e1, y, e2);
+}
+
+template <class Element, class Iterator> Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end)
+{
+ return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(), begin, end);
+}
+
+template <class T>
+void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const
+{
+ MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base, exponents, expCount);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/algebra.h b/lib/cryptopp/algebra.h
new file mode 100644
index 000000000..13038bd80
--- /dev/null
+++ b/lib/cryptopp/algebra.h
@@ -0,0 +1,285 @@
+#ifndef CRYPTOPP_ALGEBRA_H
+#define CRYPTOPP_ALGEBRA_H
+
+#include "config.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+class Integer;
+
+// "const Element&" returned by member functions are references
+// to internal data members. Since each object may have only
+// one such data member for holding results, the following code
+// will produce incorrect results:
+// abcd = group.Add(group.Add(a,b), group.Add(c,d));
+// But this should be fine:
+// abcd = group.Add(a, group.Add(b, group.Add(c,d));
+
+//! Abstract Group
+template <class T> class CRYPTOPP_NO_VTABLE AbstractGroup
+{
+public:
+ typedef T Element;
+
+ virtual ~AbstractGroup() {}
+
+ virtual bool Equal(const Element &a, const Element &b) const =0;
+ virtual const Element& Identity() const =0;
+ virtual const Element& Add(const Element &a, const Element &b) const =0;
+ virtual const Element& Inverse(const Element &a) const =0;
+ virtual bool InversionIsFast() const {return false;}
+
+ virtual const Element& Double(const Element &a) const;
+ virtual const Element& Subtract(const Element &a, const Element &b) const;
+ virtual Element& Accumulate(Element &a, const Element &b) const;
+ virtual Element& Reduce(Element &a, const Element &b) const;
+
+ virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
+ virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
+};
+
+//! Abstract Ring
+template <class T> class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup<T>
+{
+public:
+ typedef T Element;
+
+ AbstractRing() {m_mg.m_pRing = this;}
+ AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
+ AbstractRing& operator=(const AbstractRing &source) {return *this;}
+
+ virtual bool IsUnit(const Element &a) const =0;
+ virtual const Element& MultiplicativeIdentity() const =0;
+ virtual const Element& Multiply(const Element &a, const Element &b) const =0;
+ virtual const Element& MultiplicativeInverse(const Element &a) const =0;
+
+ virtual const Element& Square(const Element &a) const;
+ virtual const Element& Divide(const Element &a, const Element &b) const;
+
+ virtual Element Exponentiate(const Element &a, const Integer &e) const;
+ virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
+
+ virtual const AbstractGroup<T>& MultiplicativeGroup() const
+ {return m_mg;}
+
+private:
+ class MultiplicativeGroupT : public AbstractGroup<T>
+ {
+ public:
+ const AbstractRing<T>& GetRing() const
+ {return *m_pRing;}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return GetRing().Equal(a, b);}
+
+ const Element& Identity() const
+ {return GetRing().MultiplicativeIdentity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return GetRing().Multiply(a, b);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a = GetRing().Multiply(a, b);}
+
+ const Element& Inverse(const Element &a) const
+ {return GetRing().MultiplicativeInverse(a);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return GetRing().Divide(a, b);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a = GetRing().Divide(a, b);}
+
+ const Element& Double(const Element &a) const
+ {return GetRing().Square(a);}
+
+ Element ScalarMultiply(const Element &a, const Integer &e) const
+ {return GetRing().Exponentiate(a, e);}
+
+ Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
+ {return GetRing().CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
+ {GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
+
+ const AbstractRing<T> *m_pRing;
+ };
+
+ MultiplicativeGroupT m_mg;
+};
+
+// ********************************************************
+
+//! Base and Exponent
+template <class T, class E = Integer>
+struct BaseAndExponent
+{
+public:
+ BaseAndExponent() {}
+ BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
+ bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
+ T base;
+ E exponent;
+};
+
+// VC60 workaround: incomplete member template support
+template <class Element, class Iterator>
+ Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
+template <class Element, class Iterator>
+ Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
+
+// ********************************************************
+
+//! Abstract Euclidean Domain
+template <class T> class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing<T>
+{
+public:
+ typedef T Element;
+
+ virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
+
+ virtual const Element& Mod(const Element &a, const Element &b) const =0;
+ virtual const Element& Gcd(const Element &a, const Element &b) const;
+
+protected:
+ mutable Element result;
+};
+
+// ********************************************************
+
+//! EuclideanDomainOf
+template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
+{
+public:
+ typedef T Element;
+
+ EuclideanDomainOf() {}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return a==b;}
+
+ const Element& Identity() const
+ {return Element::Zero();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return result = a+b;}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a+=b;}
+
+ const Element& Inverse(const Element &a) const
+ {return result = -a;}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return result = a-b;}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a-=b;}
+
+ const Element& Double(const Element &a) const
+ {return result = a.Doubled();}
+
+ const Element& MultiplicativeIdentity() const
+ {return Element::One();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return result = a*b;}
+
+ const Element& Square(const Element &a) const
+ {return result = a.Squared();}
+
+ bool IsUnit(const Element &a) const
+ {return a.IsUnit();}
+
+ const Element& MultiplicativeInverse(const Element &a) const
+ {return result = a.MultiplicativeInverse();}
+
+ const Element& Divide(const Element &a, const Element &b) const
+ {return result = a/b;}
+
+ const Element& Mod(const Element &a, const Element &b) const
+ {return result = a%b;}
+
+ void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
+ {Element::Divide(r, q, a, d);}
+
+ bool operator==(const EuclideanDomainOf<T> &rhs) const
+ {return true;}
+
+private:
+ mutable Element result;
+};
+
+//! Quotient Ring
+template <class T> class QuotientRing : public AbstractRing<typename T::Element>
+{
+public:
+ typedef T EuclideanDomain;
+ typedef typename T::Element Element;
+
+ QuotientRing(const EuclideanDomain &domain, const Element &modulus)
+ : m_domain(domain), m_modulus(modulus) {}
+
+ const EuclideanDomain & GetDomain() const
+ {return m_domain;}
+
+ const Element& GetModulus() const
+ {return m_modulus;}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
+
+ const Element& Identity() const
+ {return m_domain.Identity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return m_domain.Add(a, b);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return m_domain.Accumulate(a, b);}
+
+ const Element& Inverse(const Element &a) const
+ {return m_domain.Inverse(a);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return m_domain.Subtract(a, b);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return m_domain.Reduce(a, b);}
+
+ const Element& Double(const Element &a) const
+ {return m_domain.Double(a);}
+
+ bool IsUnit(const Element &a) const
+ {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
+
+ const Element& MultiplicativeIdentity() const
+ {return m_domain.MultiplicativeIdentity();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
+
+ const Element& Square(const Element &a) const
+ {return m_domain.Mod(m_domain.Square(a), m_modulus);}
+
+ const Element& MultiplicativeInverse(const Element &a) const;
+
+ bool operator==(const QuotientRing<T> &rhs) const
+ {return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;}
+
+protected:
+ EuclideanDomain m_domain;
+ Element m_modulus;
+};
+
+NAMESPACE_END
+
+#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
+#include "algebra.cpp"
+#endif
+
+#endif
diff --git a/lib/cryptopp/algparam.cpp b/lib/cryptopp/algparam.cpp
new file mode 100644
index 000000000..a70d5dd95
--- /dev/null
+++ b/lib/cryptopp/algparam.cpp
@@ -0,0 +1,75 @@
+// algparam.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "algparam.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+PAssignIntToInteger g_pAssignIntToInteger = NULL;
+
+bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ if (strcmp(name, "ValueNames") == 0)
+ return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue);
+ else
+ return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue);
+}
+
+void AlgorithmParametersBase::operator=(const AlgorithmParametersBase& rhs)
+{
+ assert(false);
+}
+
+bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ if (strcmp(name, "ValueNames") == 0)
+ {
+ NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType);
+ if (m_next.get())
+ m_next->GetVoidValue(name, valueType, pValue);
+ (*reinterpret_cast<std::string *>(pValue) += m_name) += ";";
+ return true;
+ }
+ else if (strcmp(name, m_name) == 0)
+ {
+ AssignValue(name, valueType, pValue);
+ m_used = true;
+ return true;
+ }
+ else if (m_next.get())
+ return m_next->GetVoidValue(name, valueType, pValue);
+ else
+ return false;
+}
+
+AlgorithmParameters::AlgorithmParameters()
+ : m_defaultThrowIfNotUsed(true)
+{
+}
+
+AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x)
+ : m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed)
+{
+ m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
+}
+
+AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x)
+{
+ m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
+ return *this;
+}
+
+bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ if (m_next.get())
+ return m_next->GetVoidValue(name, valueType, pValue);
+ else
+ return false;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/algparam.h b/lib/cryptopp/algparam.h
new file mode 100644
index 000000000..ea5129c22
--- /dev/null
+++ b/lib/cryptopp/algparam.h
@@ -0,0 +1,398 @@
+#ifndef CRYPTOPP_ALGPARAM_H
+#define CRYPTOPP_ALGPARAM_H
+
+#include "cryptlib.h"
+#include "smartptr.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! used to pass byte array input as part of a NameValuePairs object
+/*! the deepCopy option is used when the NameValuePairs object can't
+ keep a copy of the data available */
+class ConstByteArrayParameter
+{
+public:
+ ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
+ {
+ Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
+ }
+ ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
+ {
+ Assign(data, size, deepCopy);
+ }
+ template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
+ {
+ CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
+ Assign((const byte *)string.data(), string.size(), deepCopy);
+ }
+
+ void Assign(const byte *data, size_t size, bool deepCopy)
+ {
+ if (deepCopy)
+ m_block.Assign(data, size);
+ else
+ {
+ m_data = data;
+ m_size = size;
+ }
+ m_deepCopy = deepCopy;
+ }
+
+ const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
+ const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
+ size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
+
+private:
+ bool m_deepCopy;
+ const byte *m_data;
+ size_t m_size;
+ SecByteBlock m_block;
+};
+
+class ByteArrayParameter
+{
+public:
+ ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
+ : m_data(data), m_size(size) {}
+ ByteArrayParameter(SecByteBlock &block)
+ : m_data(block.begin()), m_size(block.size()) {}
+
+ byte *begin() const {return m_data;}
+ byte *end() const {return m_data + m_size;}
+ size_t size() const {return m_size;}
+
+private:
+ byte *m_data;
+ size_t m_size;
+};
+
+class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
+{
+public:
+ CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
+ : m_pairs1(pairs1), m_pairs2(pairs2) {}
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+
+private:
+ const NameValuePairs &m_pairs1, &m_pairs2;
+};
+
+template <class T, class BASE>
+class GetValueHelperClass
+{
+public:
+ GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
+ : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
+ {
+ if (strcmp(m_name, "ValueNames") == 0)
+ {
+ m_found = m_getValueNames = true;
+ NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
+ if (searchFirst)
+ searchFirst->GetVoidValue(m_name, valueType, pValue);
+ if (typeid(T) != typeid(BASE))
+ pObject->BASE::GetVoidValue(m_name, valueType, pValue);
+ ((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
+ }
+
+ if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
+ {
+ NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
+ *reinterpret_cast<const T **>(pValue) = pObject;
+ m_found = true;
+ return;
+ }
+
+ if (!m_found && searchFirst)
+ m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
+
+ if (!m_found && typeid(T) != typeid(BASE))
+ m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
+ }
+
+ operator bool() const {return m_found;}
+
+ template <class R>
+ GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
+ {
+ if (m_getValueNames)
+ (*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
+ if (!m_found && strcmp(name, m_name) == 0)
+ {
+ NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
+ *reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
+ m_found = true;
+ }
+ return *this;
+ }
+
+ GetValueHelperClass<T,BASE> &Assignable()
+ {
+#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
+ if (m_getValueNames)
+ ((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
+ if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
+ {
+ NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
+ *reinterpret_cast<T *>(m_pValue) = *m_pObject;
+ m_found = true;
+ }
+#endif
+ return *this;
+ }
+
+private:
+ const T *m_pObject;
+ const char *m_name;
+ const std::type_info *m_valueType;
+ void *m_pValue;
+ bool m_found, m_getValueNames;
+};
+
+template <class BASE, class T>
+GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
+{
+ return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
+}
+
+template <class T>
+GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
+{
+ return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
+}
+
+// ********************************************************
+
+template <class R>
+R Hack_DefaultValueFromConstReferenceType(const R &)
+{
+ return R();
+}
+
+template <class R>
+bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
+{
+ return source.GetValue(name, const_cast<R &>(value));
+}
+
+template <class T, class BASE>
+class AssignFromHelperClass
+{
+public:
+ AssignFromHelperClass(T *pObject, const NameValuePairs &source)
+ : m_pObject(pObject), m_source(source), m_done(false)
+ {
+ if (source.GetThisObject(*pObject))
+ m_done = true;
+ else if (typeid(BASE) != typeid(T))
+ pObject->BASE::AssignFrom(source);
+ }
+
+ template <class R>
+ AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
+ {
+ if (!m_done)
+ {
+ R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
+ if (!Hack_GetValueIntoConstReference(m_source, name, value))
+ throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
+ (m_pObject->*pm)(value);
+ }
+ return *this;
+ }
+
+ template <class R, class S>
+ AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
+ {
+ if (!m_done)
+ {
+ R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
+ if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
+ throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
+ S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
+ if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
+ throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
+ (m_pObject->*pm)(value1, value2);
+ }
+ return *this;
+ }
+
+private:
+ T *m_pObject;
+ const NameValuePairs &m_source;
+ bool m_done;
+};
+
+template <class BASE, class T>
+AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
+{
+ return AssignFromHelperClass<T, BASE>(pObject, source);
+}
+
+template <class T>
+AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
+{
+ return AssignFromHelperClass<T, T>(pObject, source);
+}
+
+// ********************************************************
+
+// to allow the linker to discard Integer code if not needed.
+typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
+CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
+
+CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
+
+class CRYPTOPP_DLL AlgorithmParametersBase
+{
+public:
+ class ParameterNotUsed : public Exception
+ {
+ public:
+ ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
+ };
+
+ // this is actually a move, not a copy
+ AlgorithmParametersBase(const AlgorithmParametersBase &x)
+ : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
+ {
+ m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
+ x.m_used = true;
+ }
+
+ AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
+ : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
+
+ virtual ~AlgorithmParametersBase()
+ {
+#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
+ if (!std::uncaught_exception())
+#else
+ try
+#endif
+ {
+ if (m_throwIfNotUsed && !m_used)
+ throw ParameterNotUsed(m_name);
+ }
+#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
+ catch(...)
+ {
+ }
+#endif
+ }
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+
+protected:
+ friend class AlgorithmParameters;
+ void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
+
+ virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
+ virtual void MoveInto(void *p) const =0; // not really const
+
+ const char *m_name;
+ bool m_throwIfNotUsed;
+ mutable bool m_used;
+ member_ptr<AlgorithmParametersBase> m_next;
+};
+
+template <class T>
+class AlgorithmParametersTemplate : public AlgorithmParametersBase
+{
+public:
+ AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
+ : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
+ {
+ }
+
+ void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ // special case for retrieving an Integer parameter when an int was passed in
+ if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
+ {
+ NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
+ *reinterpret_cast<T *>(pValue) = m_value;
+ }
+ }
+
+ void MoveInto(void *buffer) const
+ {
+ AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
+ }
+
+protected:
+ T m_value;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
+
+class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
+{
+public:
+ AlgorithmParameters();
+
+#ifdef __BORLANDC__
+ template <class T>
+ AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
+ : m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
+ , m_defaultThrowIfNotUsed(throwIfNotUsed)
+ {
+ }
+#endif
+
+ AlgorithmParameters(const AlgorithmParameters &x);
+
+ AlgorithmParameters & operator=(const AlgorithmParameters &x);
+
+ template <class T>
+ AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
+ {
+ member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
+ p->m_next.reset(m_next.release());
+ m_next.reset(p.release());
+ m_defaultThrowIfNotUsed = throwIfNotUsed;
+ return *this;
+ }
+
+ template <class T>
+ AlgorithmParameters & operator()(const char *name, const T &value)
+ {
+ return operator()(name, value, m_defaultThrowIfNotUsed);
+ }
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+
+protected:
+ member_ptr<AlgorithmParametersBase> m_next;
+ bool m_defaultThrowIfNotUsed;
+};
+
+//! Create an object that implements NameValuePairs for passing parameters
+/*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
+ \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
+ such as MSVC 7.0 and earlier.
+ \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
+ repeatedly using operator() on the object returned by MakeParameters, for example:
+ AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
+*/
+#ifdef __BORLANDC__
+typedef AlgorithmParameters MakeParameters;
+#else
+template <class T>
+AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
+{
+ return AlgorithmParameters()(name, value, throwIfNotUsed);
+}
+#endif
+
+#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
+#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
+#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/argnames.h b/lib/cryptopp/argnames.h
new file mode 100644
index 000000000..e96172521
--- /dev/null
+++ b/lib/cryptopp/argnames.h
@@ -0,0 +1,81 @@
+#ifndef CRYPTOPP_ARGNAMES_H
+#define CRYPTOPP_ARGNAMES_H
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+DOCUMENTED_NAMESPACE_BEGIN(Name)
+
+#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;}
+
+CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name
+CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int
+CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility
+CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte *
+CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int
+CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int
+CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes
+CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes
+CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits
+CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits
+CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits
+CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits
+CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits
+CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point
+CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N
+CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID
+CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector *
+CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer
+CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool
+CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int
+CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme
+CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32
+CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32
+CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32
+CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char *
+CRYPTOPP_DEFINE_NAME_STRING(InputFileNameWide) //!< const wchar_t *
+CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream *
+CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool
+CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char *
+CRYPTOPP_DEFINE_NAME_STRING(OutputFileNameWide) //!< const wchar_t *
+CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream *
+CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool
+CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter
+CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool
+CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int
+CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool
+CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte
+CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int
+CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte *
+CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte *
+CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool
+CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int
+CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes
+CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes
+CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes
+
+DOCUMENTED_NAMESPACE_END
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/asn.cpp b/lib/cryptopp/asn.cpp
new file mode 100644
index 000000000..8ae1ad65a
--- /dev/null
+++ b/lib/cryptopp/asn.cpp
@@ -0,0 +1,597 @@
+// asn.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "asn.h"
+
+#include <iomanip>
+#include <time.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+USING_NAMESPACE(std)
+
+/// DER Length
+size_t DERLengthEncode(BufferedTransformation &bt, lword length)
+{
+ size_t i=0;
+ if (length <= 0x7f)
+ {
+ bt.Put(byte(length));
+ i++;
+ }
+ else
+ {
+ bt.Put(byte(BytePrecision(length) | 0x80));
+ i++;
+ for (int j=BytePrecision(length); j; --j)
+ {
+ bt.Put(byte(length >> (j-1)*8));
+ i++;
+ }
+ }
+ return i;
+}
+
+bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)
+{
+ byte b;
+
+ if (!bt.Get(b))
+ return false;
+
+ if (!(b & 0x80))
+ {
+ definiteLength = true;
+ length = b;
+ }
+ else
+ {
+ unsigned int lengthBytes = b & 0x7f;
+
+ if (lengthBytes == 0)
+ {
+ definiteLength = false;
+ return true;
+ }
+
+ definiteLength = true;
+ length = 0;
+ while (lengthBytes--)
+ {
+ if (length >> (8*(sizeof(length)-1)))
+ BERDecodeError(); // length about to overflow
+
+ if (!bt.Get(b))
+ return false;
+
+ length = (length << 8) | b;
+ }
+ }
+ return true;
+}
+
+bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
+{
+ lword lw;
+ bool definiteLength;
+ if (!BERLengthDecode(bt, lw, definiteLength))
+ BERDecodeError();
+ if (!SafeConvert(lw, length))
+ BERDecodeError();
+ return definiteLength;
+}
+
+void DEREncodeNull(BufferedTransformation &out)
+{
+ out.Put(TAG_NULL);
+ out.Put(0);
+}
+
+void BERDecodeNull(BufferedTransformation &in)
+{
+ byte b;
+ if (!in.Get(b) || b != TAG_NULL)
+ BERDecodeError();
+ size_t length;
+ if (!BERLengthDecode(in, length) || length != 0)
+ BERDecodeError();
+}
+
+/// ASN Strings
+size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
+{
+ bt.Put(OCTET_STRING);
+ size_t lengthBytes = DERLengthEncode(bt, strLen);
+ bt.Put(str, strLen);
+ return 1+lengthBytes+strLen;
+}
+
+size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
+{
+ return DEREncodeOctetString(bt, str.begin(), str.size());
+}
+
+size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
+{
+ byte b;
+ if (!bt.Get(b) || b != OCTET_STRING)
+ BERDecodeError();
+
+ size_t bc;
+ if (!BERLengthDecode(bt, bc))
+ BERDecodeError();
+
+ str.resize(bc);
+ if (bc != bt.Get(str, bc))
+ BERDecodeError();
+ return bc;
+}
+
+size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
+{
+ byte b;
+ if (!bt.Get(b) || b != OCTET_STRING)
+ BERDecodeError();
+
+ size_t bc;
+ if (!BERLengthDecode(bt, bc))
+ BERDecodeError();
+
+ bt.TransferTo(str, bc);
+ return bc;
+}
+
+size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
+{
+ bt.Put(asnTag);
+ size_t lengthBytes = DERLengthEncode(bt, str.size());
+ bt.Put((const byte *)str.data(), str.size());
+ return 1+lengthBytes+str.size();
+}
+
+size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
+{
+ byte b;
+ if (!bt.Get(b) || b != asnTag)
+ BERDecodeError();
+
+ size_t bc;
+ if (!BERLengthDecode(bt, bc))
+ BERDecodeError();
+
+ SecByteBlock temp(bc);
+ if (bc != bt.Get(temp, bc))
+ BERDecodeError();
+ str.assign((char *)temp.begin(), bc);
+ return bc;
+}
+
+/// ASN BitString
+size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
+{
+ bt.Put(BIT_STRING);
+ size_t lengthBytes = DERLengthEncode(bt, strLen+1);
+ bt.Put((byte)unusedBits);
+ bt.Put(str, strLen);
+ return 2+lengthBytes+strLen;
+}
+
+size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
+{
+ byte b;
+ if (!bt.Get(b) || b != BIT_STRING)
+ BERDecodeError();
+
+ size_t bc;
+ if (!BERLengthDecode(bt, bc))
+ BERDecodeError();
+
+ byte unused;
+ if (!bt.Get(unused))
+ BERDecodeError();
+ unusedBits = unused;
+ str.resize(bc-1);
+ if ((bc-1) != bt.Get(str, bc-1))
+ BERDecodeError();
+ return bc-1;
+}
+
+void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)
+{
+ byte tag;
+ source.Peek(tag);
+ BERGeneralDecoder decoder(source, tag);
+ DERGeneralEncoder encoder(dest, tag);
+ if (decoder.IsDefiniteLength())
+ decoder.TransferTo(encoder, decoder.RemainingLength());
+ else
+ {
+ while (!decoder.EndReached())
+ DERReencode(decoder, encoder);
+ }
+ decoder.MessageEnd();
+ encoder.MessageEnd();
+}
+
+void OID::EncodeValue(BufferedTransformation &bt, word32 v)
+{
+ for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
+ bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
+ bt.Put((byte)(v & 0x7f));
+}
+
+size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
+{
+ byte b;
+ size_t i=0;
+ v = 0;
+ while (true)
+ {
+ if (!bt.Get(b))
+ BERDecodeError();
+ i++;
+ if (v >> (8*sizeof(v)-7)) // v about to overflow
+ BERDecodeError();
+ v <<= 7;
+ v += b & 0x7f;
+ if (!(b & 0x80))
+ return i;
+ }
+}
+
+void OID::DEREncode(BufferedTransformation &bt) const
+{
+ assert(m_values.size() >= 2);
+ ByteQueue temp;
+ temp.Put(byte(m_values[0] * 40 + m_values[1]));
+ for (size_t i=2; i<m_values.size(); i++)
+ EncodeValue(temp, m_values[i]);
+ bt.Put(OBJECT_IDENTIFIER);
+ DERLengthEncode(bt, temp.CurrentSize());
+ temp.TransferTo(bt);
+}
+
+void OID::BERDecode(BufferedTransformation &bt)
+{
+ byte b;
+ if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
+ BERDecodeError();
+
+ size_t length;
+ if (!BERLengthDecode(bt, length) || length < 1)
+ BERDecodeError();
+
+ if (!bt.Get(b))
+ BERDecodeError();
+
+ length--;
+ m_values.resize(2);
+ m_values[0] = b / 40;
+ m_values[1] = b % 40;
+
+ while (length > 0)
+ {
+ word32 v;
+ size_t valueLen = DecodeValue(bt, v);
+ if (valueLen > length)
+ BERDecodeError();
+ m_values.push_back(v);
+ length -= valueLen;
+ }
+}
+
+void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
+{
+ OID oid(bt);
+ if (*this != oid)
+ BERDecodeError();
+}
+
+inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
+{
+ if (m_flags & PUT_OBJECTS)
+ return *AttachedTransformation();
+ else
+ return TheBitBucket();
+}
+
+void EncodedObjectFilter::Put(const byte *inString, size_t length)
+{
+ if (m_nCurrentObject == m_nObjects)
+ {
+ AttachedTransformation()->Put(inString, length);
+ return;
+ }
+
+ LazyPutter lazyPutter(m_queue, inString, length);
+
+ while (m_queue.AnyRetrievable())
+ {
+ switch (m_state)
+ {
+ case IDENTIFIER:
+ if (!m_queue.Get(m_id))
+ return;
+ m_queue.TransferTo(CurrentTarget(), 1);
+ m_state = LENGTH; // fall through
+ case LENGTH:
+ {
+ byte b;
+ if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
+ {
+ m_queue.TransferTo(CurrentTarget(), 1);
+ m_level--;
+ m_state = IDENTIFIER;
+ break;
+ }
+ ByteQueue::Walker walker(m_queue);
+ bool definiteLength;
+ if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
+ return;
+ m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
+ if (!((m_id & CONSTRUCTED) || definiteLength))
+ BERDecodeError();
+ if (!definiteLength)
+ {
+ if (!(m_id & CONSTRUCTED))
+ BERDecodeError();
+ m_level++;
+ m_state = IDENTIFIER;
+ break;
+ }
+ m_state = BODY; // fall through
+ }
+ case BODY:
+ m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
+
+ if (m_lengthRemaining == 0)
+ m_state = IDENTIFIER;
+ }
+
+ if (m_state == IDENTIFIER && m_level == 0)
+ {
+ // just finished processing a level 0 object
+ ++m_nCurrentObject;
+
+ if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
+ AttachedTransformation()->MessageEnd();
+
+ if (m_nCurrentObject == m_nObjects)
+ {
+ if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
+ AttachedTransformation()->MessageEnd();
+
+ if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
+ AttachedTransformation()->MessageSeriesEnd();
+
+ m_queue.TransferAllTo(*AttachedTransformation());
+ return;
+ }
+ }
+ }
+}
+
+BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
+ : m_inQueue(inQueue), m_finished(false)
+{
+ Init(asnTag);
+}
+
+BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
+ : m_inQueue(inQueue), m_finished(false)
+{
+ Init(asnTag);
+}
+
+void BERGeneralDecoder::Init(byte asnTag)
+{
+ byte b;
+ if (!m_inQueue.Get(b) || b != asnTag)
+ BERDecodeError();
+
+ if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
+ BERDecodeError();
+
+ if (!m_definiteLength && !(asnTag & CONSTRUCTED))
+ BERDecodeError(); // cannot be primitive and have indefinite length
+}
+
+BERGeneralDecoder::~BERGeneralDecoder()
+{
+ try // avoid throwing in constructor
+ {
+ if (!m_finished)
+ MessageEnd();
+ }
+ catch (...)
+ {
+ }
+}
+
+bool BERGeneralDecoder::EndReached() const
+{
+ if (m_definiteLength)
+ return m_length == 0;
+ else
+ { // check end-of-content octets
+ word16 i;
+ return (m_inQueue.PeekWord16(i)==2 && i==0);
+ }
+}
+
+byte BERGeneralDecoder::PeekByte() const
+{
+ byte b;
+ if (!Peek(b))
+ BERDecodeError();
+ return b;
+}
+
+void BERGeneralDecoder::CheckByte(byte check)
+{
+ byte b;
+ if (!Get(b) || b != check)
+ BERDecodeError();
+}
+
+void BERGeneralDecoder::MessageEnd()
+{
+ m_finished = true;
+ if (m_definiteLength)
+ {
+ if (m_length != 0)
+ BERDecodeError();
+ }
+ else
+ { // remove end-of-content octets
+ word16 i;
+ if (m_inQueue.GetWord16(i) != 2 || i != 0)
+ BERDecodeError();
+ }
+}
+
+size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ if (m_definiteLength && transferBytes > m_length)
+ transferBytes = m_length;
+ size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
+ ReduceLength(transferBytes);
+ return blockedBytes;
+}
+
+size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ if (m_definiteLength)
+ end = STDMIN(m_length, end);
+ return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
+}
+
+lword BERGeneralDecoder::ReduceLength(lword delta)
+{
+ if (m_definiteLength)
+ {
+ if (m_length < delta)
+ BERDecodeError();
+ m_length -= delta;
+ }
+ return delta;
+}
+
+DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
+ : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
+{
+}
+
+DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
+ : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
+{
+}
+
+DERGeneralEncoder::~DERGeneralEncoder()
+{
+ try // avoid throwing in constructor
+ {
+ if (!m_finished)
+ MessageEnd();
+ }
+ catch (...)
+ {
+ }
+}
+
+void DERGeneralEncoder::MessageEnd()
+{
+ m_finished = true;
+ lword length = CurrentSize();
+ m_outQueue.Put(m_asnTag);
+ DERLengthEncode(m_outQueue, length);
+ TransferTo(m_outQueue);
+}
+
+// *************************************************************
+
+void X509PublicKey::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder subjectPublicKeyInfo(bt);
+ BERSequenceDecoder algorithm(subjectPublicKeyInfo);
+ GetAlgorithmID().BERDecodeAndCheck(algorithm);
+ bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
+ algorithm.MessageEnd();
+
+ BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
+ subjectPublicKey.CheckByte(0); // unused bits
+ BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
+ subjectPublicKey.MessageEnd();
+ subjectPublicKeyInfo.MessageEnd();
+}
+
+void X509PublicKey::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder subjectPublicKeyInfo(bt);
+
+ DERSequenceEncoder algorithm(subjectPublicKeyInfo);
+ GetAlgorithmID().DEREncode(algorithm);
+ DEREncodeAlgorithmParameters(algorithm);
+ algorithm.MessageEnd();
+
+ DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
+ subjectPublicKey.Put(0); // unused bits
+ DEREncodePublicKey(subjectPublicKey);
+ subjectPublicKey.MessageEnd();
+
+ subjectPublicKeyInfo.MessageEnd();
+}
+
+void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder privateKeyInfo(bt);
+ word32 version;
+ BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
+
+ BERSequenceDecoder algorithm(privateKeyInfo);
+ GetAlgorithmID().BERDecodeAndCheck(algorithm);
+ bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
+ algorithm.MessageEnd();
+
+ BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
+ BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
+ octetString.MessageEnd();
+
+ if (!privateKeyInfo.EndReached())
+ BERDecodeOptionalAttributes(privateKeyInfo);
+ privateKeyInfo.MessageEnd();
+}
+
+void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder privateKeyInfo(bt);
+ DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
+
+ DERSequenceEncoder algorithm(privateKeyInfo);
+ GetAlgorithmID().DEREncode(algorithm);
+ DEREncodeAlgorithmParameters(algorithm);
+ algorithm.MessageEnd();
+
+ DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
+ DEREncodePrivateKey(octetString);
+ octetString.MessageEnd();
+
+ DEREncodeOptionalAttributes(privateKeyInfo);
+ privateKeyInfo.MessageEnd();
+}
+
+void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)
+{
+ DERReencode(bt, m_optionalAttributes);
+}
+
+void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const
+{
+ m_optionalAttributes.CopyTo(bt);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/asn.h b/lib/cryptopp/asn.h
new file mode 100644
index 000000000..c35126bc3
--- /dev/null
+++ b/lib/cryptopp/asn.h
@@ -0,0 +1,369 @@
+#ifndef CRYPTOPP_ASN_H
+#define CRYPTOPP_ASN_H
+
+#include "filters.h"
+#include "queue.h"
+#include <vector>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// these tags and flags are not complete
+enum ASNTag
+{
+ BOOLEAN = 0x01,
+ INTEGER = 0x02,
+ BIT_STRING = 0x03,
+ OCTET_STRING = 0x04,
+ TAG_NULL = 0x05,
+ OBJECT_IDENTIFIER = 0x06,
+ OBJECT_DESCRIPTOR = 0x07,
+ EXTERNAL = 0x08,
+ REAL = 0x09,
+ ENUMERATED = 0x0a,
+ UTF8_STRING = 0x0c,
+ SEQUENCE = 0x10,
+ SET = 0x11,
+ NUMERIC_STRING = 0x12,
+ PRINTABLE_STRING = 0x13,
+ T61_STRING = 0x14,
+ VIDEOTEXT_STRING = 0x15,
+ IA5_STRING = 0x16,
+ UTC_TIME = 0x17,
+ GENERALIZED_TIME = 0x18,
+ GRAPHIC_STRING = 0x19,
+ VISIBLE_STRING = 0x1a,
+ GENERAL_STRING = 0x1b
+};
+
+enum ASNIdFlag
+{
+ UNIVERSAL = 0x00,
+// DATA = 0x01,
+// HEADER = 0x02,
+ CONSTRUCTED = 0x20,
+ APPLICATION = 0x40,
+ CONTEXT_SPECIFIC = 0x80,
+ PRIVATE = 0xc0
+};
+
+inline void BERDecodeError() {throw BERDecodeErr();}
+
+class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
+{
+public:
+ UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
+ UnknownOID(const char *err) : BERDecodeErr(err) {}
+};
+
+// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
+CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length);
+// returns false if indefinite length
+CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length);
+
+CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out);
+CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in);
+
+CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen);
+CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
+CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
+CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
+
+// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
+CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
+CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
+
+CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0);
+CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
+
+// BER decode from source and DER reencode into dest
+CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest);
+
+//! Object Identifier
+class CRYPTOPP_DLL OID
+{
+public:
+ OID() {}
+ OID(word32 v) : m_values(1, v) {}
+ OID(BufferedTransformation &bt) {BERDecode(bt);}
+
+ inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
+
+ void DEREncode(BufferedTransformation &bt) const;
+ void BERDecode(BufferedTransformation &bt);
+
+ // throw BERDecodeErr() if decoded value doesn't equal this OID
+ void BERDecodeAndCheck(BufferedTransformation &bt) const;
+
+ std::vector<word32> m_values;
+
+private:
+ static void EncodeValue(BufferedTransformation &bt, word32 v);
+ static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
+};
+
+class EncodedObjectFilter : public Filter
+{
+public:
+ enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
+ EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
+
+ void Put(const byte *inString, size_t length);
+
+ unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
+ unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
+
+private:
+ BufferedTransformation & CurrentTarget();
+
+ word32 m_flags;
+ unsigned int m_nObjects, m_nCurrentObject, m_level;
+ std::vector<unsigned int> m_positions;
+ ByteQueue m_queue;
+ enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
+ byte m_id;
+ lword m_lengthRemaining;
+};
+
+//! BER General Decoder
+class CRYPTOPP_DLL BERGeneralDecoder : public Store
+{
+public:
+ explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
+ explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
+ ~BERGeneralDecoder();
+
+ bool IsDefiniteLength() const {return m_definiteLength;}
+ lword RemainingLength() const {assert(m_definiteLength); return m_length;}
+ bool EndReached() const;
+ byte PeekByte() const;
+ void CheckByte(byte b);
+
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+
+ // call this to denote end of sequence
+ void MessageEnd();
+
+protected:
+ BufferedTransformation &m_inQueue;
+ bool m_finished, m_definiteLength;
+ lword m_length;
+
+private:
+ void Init(byte asnTag);
+ void StoreInitialize(const NameValuePairs &parameters) {assert(false);}
+ lword ReduceLength(lword delta);
+};
+
+//! DER General Encoder
+class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
+{
+public:
+ explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
+ explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
+ ~DERGeneralEncoder();
+
+ // call this to denote end of sequence
+ void MessageEnd();
+
+private:
+ BufferedTransformation &m_outQueue;
+ bool m_finished;
+
+ byte m_asnTag;
+};
+
+//! BER Sequence Decoder
+class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
+{
+public:
+ explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+ : BERGeneralDecoder(inQueue, asnTag) {}
+ explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+ : BERGeneralDecoder(inQueue, asnTag) {}
+};
+
+//! DER Sequence Encoder
+class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
+{
+public:
+ explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+ : DERGeneralEncoder(outQueue, asnTag) {}
+ explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
+ : DERGeneralEncoder(outQueue, asnTag) {}
+};
+
+//! BER Set Decoder
+class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
+{
+public:
+ explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
+ : BERGeneralDecoder(inQueue, asnTag) {}
+ explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
+ : BERGeneralDecoder(inQueue, asnTag) {}
+};
+
+//! DER Set Encoder
+class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
+{
+public:
+ explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
+ : DERGeneralEncoder(outQueue, asnTag) {}
+ explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
+ : DERGeneralEncoder(outQueue, asnTag) {}
+};
+
+template <class T>
+class ASNOptional : public member_ptr<T>
+{
+public:
+ void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
+ {
+ byte b;
+ if (seqDecoder.Peek(b) && (b & mask) == tag)
+ reset(new T(seqDecoder));
+ }
+ void DEREncode(BufferedTransformation &out)
+ {
+ if (this->get() != NULL)
+ this->get()->DEREncode(out);
+ }
+};
+
+//! _
+template <class BASE>
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
+{
+public:
+ void Save(BufferedTransformation &bt) const
+ {BEREncode(bt);}
+ void Load(BufferedTransformation &bt)
+ {BERDecode(bt);}
+};
+
+//! encodes/decodes subjectPublicKeyInfo
+class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
+{
+public:
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ virtual OID GetAlgorithmID() const =0;
+ virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
+ {BERDecodeNull(bt); return false;}
+ virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
+ {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
+
+ //! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
+ virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
+ //! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
+ virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
+};
+
+//! encodes/decodes privateKeyInfo
+class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
+{
+public:
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ virtual OID GetAlgorithmID() const =0;
+ virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
+ {BERDecodeNull(bt); return false;}
+ virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
+ {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
+
+ //! decode privateKey part of privateKeyInfo, without the OCTET STRING header
+ virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
+ //! encode privateKey part of privateKeyInfo, without the OCTET STRING header
+ virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
+
+ //! decode optional attributes including context-specific tag
+ /*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
+ virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
+ //! encode optional attributes including context-specific tag
+ virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
+
+protected:
+ ByteQueue m_optionalAttributes;
+};
+
+// ********************************************************
+
+//! DER Encode Unsigned
+/*! for INTEGER, BOOLEAN, and ENUM */
+template <class T>
+size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
+{
+ byte buf[sizeof(w)+1];
+ unsigned int bc;
+ if (asnTag == BOOLEAN)
+ {
+ buf[sizeof(w)] = w ? 0xff : 0;
+ bc = 1;
+ }
+ else
+ {
+ buf[0] = 0;
+ for (unsigned int i=0; i<sizeof(w); i++)
+ buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
+ bc = sizeof(w);
+ while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
+ --bc;
+ if (buf[sizeof(w)+1-bc] & 0x80)
+ ++bc;
+ }
+ out.Put(asnTag);
+ size_t lengthBytes = DERLengthEncode(out, bc);
+ out.Put(buf+sizeof(w)+1-bc, bc);
+ return 1+lengthBytes+bc;
+}
+
+//! BER Decode Unsigned
+// VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro
+// CW41 workaround: std::numeric_limits<T>::max causes a template error
+template <class T>
+void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
+ T minValue = 0, T maxValue = 0xffffffff)
+{
+ byte b;
+ if (!in.Get(b) || b != asnTag)
+ BERDecodeError();
+
+ size_t bc;
+ BERLengthDecode(in, bc);
+
+ SecByteBlock buf(bc);
+
+ if (bc != in.Get(buf, bc))
+ BERDecodeError();
+
+ const byte *ptr = buf;
+ while (bc > sizeof(w) && *ptr == 0)
+ {
+ bc--;
+ ptr++;
+ }
+ if (bc > sizeof(w))
+ BERDecodeError();
+
+ w = 0;
+ for (unsigned int i=0; i<bc; i++)
+ w = (w << 8) | ptr[i];
+
+ if (w < minValue || w > maxValue)
+ BERDecodeError();
+}
+
+inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
+ {return lhs.m_values == rhs.m_values;}
+inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
+ {return lhs.m_values != rhs.m_values;}
+inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
+ {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
+inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
+ {return ::CryptoPP::OID(lhs)+=rhs;}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/authenc.cpp b/lib/cryptopp/authenc.cpp
new file mode 100644
index 000000000..f93662efb
--- /dev/null
+++ b/lib/cryptopp/authenc.cpp
@@ -0,0 +1,180 @@
+// authenc.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "authenc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
+{
+ unsigned int blockSize = AuthenticationBlockSize();
+ unsigned int &num = m_bufferedDataLength;
+ byte* data = m_buffer.begin();
+
+ if (num != 0) // process left over data
+ {
+ if (num+len >= blockSize)
+ {
+ memcpy(data+num, input, blockSize-num);
+ AuthenticateBlocks(data, blockSize);
+ input += (blockSize-num);
+ len -= (blockSize-num);
+ num = 0;
+ // drop through and do the rest
+ }
+ else
+ {
+ memcpy(data+num, input, len);
+ num += (unsigned int)len;
+ return;
+ }
+ }
+
+ // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
+ if (len >= blockSize)
+ {
+ size_t leftOver = AuthenticateBlocks(input, len);
+ input += (len - leftOver);
+ len = leftOver;
+ }
+
+ memcpy(data, input, len);
+ num = (unsigned int)len;
+}
+
+void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params)
+{
+ m_bufferedDataLength = 0;
+ m_state = State_Start;
+
+ SetKeyWithoutResync(userKey, keylength, params);
+ m_state = State_KeySet;
+
+ size_t length;
+ const byte *iv = GetIVAndThrowIfInvalid(params, length);
+ if (iv)
+ Resynchronize(iv, (int)length);
+}
+
+void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
+{
+ if (m_state < State_KeySet)
+ throw BadState(AlgorithmName(), "Resynchronize", "key is set");
+
+ m_bufferedDataLength = 0;
+ m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
+ m_state = State_KeySet;
+
+ Resync(iv, this->ThrowIfInvalidIVLength(length));
+ m_state = State_IVSet;
+}
+
+void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
+{
+ if (length == 0)
+ return;
+
+ switch (m_state)
+ {
+ case State_Start:
+ case State_KeySet:
+ throw BadState(AlgorithmName(), "Update", "setting key and IV");
+ case State_IVSet:
+ AuthenticateData(input, length);
+ m_totalHeaderLength += length;
+ break;
+ case State_AuthUntransformed:
+ case State_AuthTransformed:
+ AuthenticateLastConfidentialBlock();
+ m_bufferedDataLength = 0;
+ m_state = State_AuthFooter;
+ // fall through
+ case State_AuthFooter:
+ AuthenticateData(input, length);
+ m_totalFooterLength += length;
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
+{
+ m_totalMessageLength += length;
+ if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
+ throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
+
+reswitch:
+ switch (m_state)
+ {
+ case State_Start:
+ case State_KeySet:
+ throw BadState(AlgorithmName(), "ProcessData", "setting key and IV");
+ case State_AuthFooter:
+ throw BadState(AlgorithmName(), "ProcessData was called after footer input has started");
+ case State_IVSet:
+ AuthenticateLastHeaderBlock();
+ m_bufferedDataLength = 0;
+ m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
+ goto reswitch;
+ case State_AuthUntransformed:
+ AuthenticateData(inString, length);
+ AccessSymmetricCipher().ProcessData(outString, inString, length);
+ break;
+ case State_AuthTransformed:
+ AccessSymmetricCipher().ProcessData(outString, inString, length);
+ AuthenticateData(outString, length);
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
+{
+ if (m_totalHeaderLength > MaxHeaderLength())
+ throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
+
+ if (m_totalFooterLength > MaxFooterLength())
+ {
+ if (MaxFooterLength() == 0)
+ throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted");
+ else
+ throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
+ }
+
+ switch (m_state)
+ {
+ case State_Start:
+ case State_KeySet:
+ throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV");
+
+ case State_IVSet:
+ AuthenticateLastHeaderBlock();
+ m_bufferedDataLength = 0;
+ // fall through
+
+ case State_AuthUntransformed:
+ case State_AuthTransformed:
+ AuthenticateLastConfidentialBlock();
+ m_bufferedDataLength = 0;
+ // fall through
+
+ case State_AuthFooter:
+ AuthenticateLastFooterBlock(mac, macSize);
+ m_bufferedDataLength = 0;
+ break;
+
+ default:
+ assert(false);
+ }
+
+ m_state = State_KeySet;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/authenc.h b/lib/cryptopp/authenc.h
new file mode 100644
index 000000000..5bb2a51c8
--- /dev/null
+++ b/lib/cryptopp/authenc.h
@@ -0,0 +1,49 @@
+#ifndef CRYPTOPP_AUTHENC_H
+#define CRYPTOPP_AUTHENC_H
+
+#include "cryptlib.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! .
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher
+{
+public:
+ AuthenticatedSymmetricCipherBase() : m_state(State_Start) {}
+
+ bool IsRandomAccess() const {return false;}
+ bool IsSelfInverting() const {return true;}
+ void UncheckedSetKey(const byte *,unsigned int,const CryptoPP::NameValuePairs &) {assert(false);}
+
+ void SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params);
+ void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;}
+ void Resynchronize(const byte *iv, int length=-1);
+ void Update(const byte *input, size_t length);
+ void ProcessData(byte *outString, const byte *inString, size_t length);
+ void TruncatedFinal(byte *mac, size_t macSize);
+
+protected:
+ void AuthenticateData(const byte *data, size_t len);
+ const SymmetricCipher & GetSymmetricCipher() const {return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
+
+ virtual SymmetricCipher & AccessSymmetricCipher() =0;
+ virtual bool AuthenticationIsOnPlaintext() const =0;
+ virtual unsigned int AuthenticationBlockSize() const =0;
+ virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params) =0;
+ virtual void Resync(const byte *iv, size_t len) =0;
+ virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0;
+ virtual void AuthenticateLastHeaderBlock() =0;
+ virtual void AuthenticateLastConfidentialBlock() {}
+ virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0;
+
+ enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter};
+ State m_state;
+ unsigned int m_bufferedDataLength;
+ lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength;
+ AlignedSecByteBlock m_buffer;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/base32.cpp b/lib/cryptopp/base32.cpp
new file mode 100644
index 000000000..0568f0729
--- /dev/null
+++ b/lib/cryptopp/base32.cpp
@@ -0,0 +1,39 @@
+// base32.cpp - written and placed in the public domain by Frank Palazzolo, based on hex.cpp by Wei Dai
+
+#include "pch.h"
+#include "base32.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const byte s_vecUpper[] = "ABCDEFGHIJKMNPQRSTUVWXYZ23456789";
+static const byte s_vecLower[] = "abcdefghijkmnpqrstuvwxyz23456789";
+
+void Base32Encoder::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true);
+ m_filter->Initialize(CombinedNameValuePairs(
+ parameters,
+ MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 5, true)));
+}
+
+void Base32Decoder::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ BaseN_Decoder::Initialize(CombinedNameValuePairs(
+ parameters,
+ MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 5, true)));
+}
+
+const int *Base32Decoder::GetDefaultDecodingLookupArray()
+{
+ static volatile bool s_initialized = false;
+ static int s_array[256];
+
+ if (!s_initialized)
+ {
+ InitializeDecodingLookupArray(s_array, s_vecUpper, 32, true);
+ s_initialized = true;
+ }
+ return s_array;
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/base32.h b/lib/cryptopp/base32.h
new file mode 100644
index 000000000..cb1e1af8d
--- /dev/null
+++ b/lib/cryptopp/base32.h
@@ -0,0 +1,38 @@
+#ifndef CRYPTOPP_BASE32_H
+#define CRYPTOPP_BASE32_H
+
+#include "basecode.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Converts given data to base 32, the default code is based on draft-ietf-idn-dude-02.txt
+/*! To specify alternative code, call Initialize() with EncodingLookupArray parameter. */
+class Base32Encoder : public SimpleProxyFilter
+{
+public:
+ Base32Encoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
+ : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
+ {
+ IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator)));
+ }
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+};
+
+//! Decode base 32 data back to bytes, the default code is based on draft-ietf-idn-dude-02.txt
+/*! To specify alternative code, call Initialize() with DecodingLookupArray parameter. */
+class Base32Decoder : public BaseN_Decoder
+{
+public:
+ Base32Decoder(BufferedTransformation *attachment = NULL)
+ : BaseN_Decoder(GetDefaultDecodingLookupArray(), 5, attachment) {}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+
+private:
+ static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/base64.cpp b/lib/cryptopp/base64.cpp
new file mode 100644
index 000000000..7571f2b8c
--- /dev/null
+++ b/lib/cryptopp/base64.cpp
@@ -0,0 +1,42 @@
+// base64.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "base64.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const byte s_vec[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const byte s_padding = '=';
+
+void Base64Encoder::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ bool insertLineBreaks = parameters.GetValueWithDefault(Name::InsertLineBreaks(), true);
+ int maxLineLength = parameters.GetIntValueWithDefault(Name::MaxLineLength(), 72);
+
+ const char *lineBreak = insertLineBreaks ? "\n" : "";
+
+ m_filter->Initialize(CombinedNameValuePairs(
+ parameters,
+ MakeParameters(Name::EncodingLookupArray(), &s_vec[0], false)
+ (Name::PaddingByte(), s_padding)
+ (Name::GroupSize(), insertLineBreaks ? maxLineLength : 0)
+ (Name::Separator(), ConstByteArrayParameter(lineBreak))
+ (Name::Terminator(), ConstByteArrayParameter(lineBreak))
+ (Name::Log2Base(), 6, true)));
+}
+
+const int *Base64Decoder::GetDecodingLookupArray()
+{
+ static volatile bool s_initialized = false;
+ static int s_array[256];
+
+ if (!s_initialized)
+ {
+ InitializeDecodingLookupArray(s_array, s_vec, 64, false);
+ s_initialized = true;
+ }
+ return s_array;
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/base64.h b/lib/cryptopp/base64.h
new file mode 100644
index 000000000..5a9e184b2
--- /dev/null
+++ b/lib/cryptopp/base64.h
@@ -0,0 +1,36 @@
+#ifndef CRYPTOPP_BASE64_H
+#define CRYPTOPP_BASE64_H
+
+#include "basecode.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Base64 Encoder Class
+class Base64Encoder : public SimpleProxyFilter
+{
+public:
+ Base64Encoder(BufferedTransformation *attachment = NULL, bool insertLineBreaks = true, int maxLineLength = 72)
+ : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
+ {
+ IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), insertLineBreaks)(Name::MaxLineLength(), maxLineLength));
+ }
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+};
+
+//! Base64 Decoder Class
+class Base64Decoder : public BaseN_Decoder
+{
+public:
+ Base64Decoder(BufferedTransformation *attachment = NULL)
+ : BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {}
+
+ void IsolatedInitialize(const NameValuePairs &parameters) {}
+
+private:
+ static const int * CRYPTOPP_API GetDecodingLookupArray();
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/basecode.cpp b/lib/cryptopp/basecode.cpp
new file mode 100644
index 000000000..0c98b2271
--- /dev/null
+++ b/lib/cryptopp/basecode.cpp
@@ -0,0 +1,238 @@
+// basecode.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "basecode.h"
+#include "fltrimpl.h"
+#include <ctype.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void BaseN_Encoder::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet);
+
+ parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar);
+ if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
+ throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive");
+
+ byte padding;
+ bool pad;
+ if (parameters.GetValue(Name::PaddingByte(), padding))
+ pad = parameters.GetValueWithDefault(Name::Pad(), true);
+ else
+ pad = false;
+ m_padding = pad ? padding : -1;
+
+ m_bytePos = m_bitPos = 0;
+
+ int i = 8;
+ while (i%m_bitsPerChar != 0)
+ i += 8;
+ m_outputBlockSize = i/m_bitsPerChar;
+
+ m_outBuf.New(m_outputBlockSize);
+}
+
+size_t BaseN_Encoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ FILTER_BEGIN;
+ while (m_inputPosition < length)
+ {
+ if (m_bytePos == 0)
+ memset(m_outBuf, 0, m_outputBlockSize);
+
+ {
+ unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8;
+ while (true)
+ {
+ assert(m_bitPos < m_bitsPerChar);
+ unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos;
+ m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget);
+ if (bitsLeftInSource >= bitsLeftInTarget)
+ {
+ m_bitPos = 0;
+ ++m_bytePos;
+ bitsLeftInSource -= bitsLeftInTarget;
+ if (bitsLeftInSource == 0)
+ break;
+ b <<= bitsLeftInTarget;
+ b &= 0xff;
+ }
+ else
+ {
+ m_bitPos += bitsLeftInSource;
+ break;
+ }
+ }
+ }
+
+ assert(m_bytePos <= m_outputBlockSize);
+ if (m_bytePos == m_outputBlockSize)
+ {
+ int i;
+ for (i=0; i<m_bytePos; i++)
+ {
+ assert(m_outBuf[i] < (1 << m_bitsPerChar));
+ m_outBuf[i] = m_alphabet[m_outBuf[i]];
+ }
+ FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
+
+ m_bytePos = m_bitPos = 0;
+ }
+ }
+ if (messageEnd)
+ {
+ if (m_bitPos > 0)
+ ++m_bytePos;
+
+ int i;
+ for (i=0; i<m_bytePos; i++)
+ m_outBuf[i] = m_alphabet[m_outBuf[i]];
+
+ if (m_padding != -1 && m_bytePos > 0)
+ {
+ memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos);
+ m_bytePos = m_outputBlockSize;
+ }
+ FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
+ m_bytePos = m_bitPos = 0;
+ }
+ FILTER_END_NO_MESSAGE_END;
+}
+
+void BaseN_Decoder::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup);
+
+ parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar);
+ if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
+ throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive");
+
+ m_bytePos = m_bitPos = 0;
+
+ int i = m_bitsPerChar;
+ while (i%8 != 0)
+ i += m_bitsPerChar;
+ m_outputBlockSize = i/8;
+
+ m_outBuf.New(m_outputBlockSize);
+}
+
+size_t BaseN_Decoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ FILTER_BEGIN;
+ while (m_inputPosition < length)
+ {
+ unsigned int value;
+ value = m_lookup[begin[m_inputPosition++]];
+ if (value >= 256)
+ continue;
+
+ if (m_bytePos == 0 && m_bitPos == 0)
+ memset(m_outBuf, 0, m_outputBlockSize);
+
+ {
+ int newBitPos = m_bitPos + m_bitsPerChar;
+ if (newBitPos <= 8)
+ m_outBuf[m_bytePos] |= value << (8-newBitPos);
+ else
+ {
+ m_outBuf[m_bytePos] |= value >> (newBitPos-8);
+ m_outBuf[m_bytePos+1] |= value << (16-newBitPos);
+ }
+
+ m_bitPos = newBitPos;
+ while (m_bitPos >= 8)
+ {
+ m_bitPos -= 8;
+ ++m_bytePos;
+ }
+ }
+
+ if (m_bytePos == m_outputBlockSize)
+ {
+ FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
+ m_bytePos = m_bitPos = 0;
+ }
+ }
+ if (messageEnd)
+ {
+ FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
+ m_bytePos = m_bitPos = 0;
+ }
+ FILTER_END_NO_MESSAGE_END;
+}
+
+void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive)
+{
+ std::fill(lookup, lookup+256, -1);
+
+ for (unsigned int i=0; i<base; i++)
+ {
+ if (caseInsensitive && isalpha(alphabet[i]))
+ {
+ assert(lookup[toupper(alphabet[i])] == -1);
+ lookup[toupper(alphabet[i])] = i;
+ assert(lookup[tolower(alphabet[i])] == -1);
+ lookup[tolower(alphabet[i])] = i;
+ }
+ else
+ {
+ assert(lookup[alphabet[i]] == -1);
+ lookup[alphabet[i]] = i;
+ }
+ }
+}
+
+void Grouper::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_groupSize = parameters.GetIntValueWithDefault(Name::GroupSize(), 0);
+ ConstByteArrayParameter separator, terminator;
+ if (m_groupSize)
+ parameters.GetRequiredParameter("Grouper", Name::Separator(), separator);
+ else
+ parameters.GetValue(Name::Separator(), separator);
+ parameters.GetValue(Name::Terminator(), terminator);
+
+ m_separator.Assign(separator.begin(), separator.size());
+ m_terminator.Assign(terminator.begin(), terminator.size());
+ m_counter = 0;
+}
+
+size_t Grouper::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ FILTER_BEGIN;
+ if (m_groupSize)
+ {
+ while (m_inputPosition < length)
+ {
+ if (m_counter == m_groupSize)
+ {
+ FILTER_OUTPUT(1, m_separator, m_separator.size(), 0);
+ m_counter = 0;
+ }
+
+ size_t len;
+ FILTER_OUTPUT2(2, len = STDMIN(length-m_inputPosition, m_groupSize-m_counter),
+ begin+m_inputPosition, len, 0);
+ m_inputPosition += len;
+ m_counter += len;
+ }
+ }
+ else
+ FILTER_OUTPUT(3, begin, length, 0);
+
+ if (messageEnd)
+ {
+ FILTER_OUTPUT(4, m_terminator, m_terminator.size(), messageEnd);
+ m_counter = 0;
+ }
+ FILTER_END_NO_MESSAGE_END
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/basecode.h b/lib/cryptopp/basecode.h
new file mode 100644
index 000000000..cc44c4342
--- /dev/null
+++ b/lib/cryptopp/basecode.h
@@ -0,0 +1,86 @@
+#ifndef CRYPTOPP_BASECODE_H
+#define CRYPTOPP_BASECODE_H
+
+#include "filters.h"
+#include "algparam.h"
+#include "argnames.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! base n encoder, where n is a power of 2
+class CRYPTOPP_DLL BaseN_Encoder : public Unflushable<Filter>
+{
+public:
+ BaseN_Encoder(BufferedTransformation *attachment=NULL)
+ {Detach(attachment);}
+
+ BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1)
+ {
+ Detach(attachment);
+ IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet)
+ (Name::Log2Base(), log2base)
+ (Name::Pad(), padding != -1)
+ (Name::PaddingByte(), byte(padding)));
+ }
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+
+private:
+ const byte *m_alphabet;
+ int m_padding, m_bitsPerChar, m_outputBlockSize;
+ int m_bytePos, m_bitPos;
+ SecByteBlock m_outBuf;
+};
+
+//! base n decoder, where n is a power of 2
+class CRYPTOPP_DLL BaseN_Decoder : public Unflushable<Filter>
+{
+public:
+ BaseN_Decoder(BufferedTransformation *attachment=NULL)
+ {Detach(attachment);}
+
+ BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL)
+ {
+ Detach(attachment);
+ IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base));
+ }
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+
+ static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive);
+
+private:
+ const int *m_lookup;
+ int m_padding, m_bitsPerChar, m_outputBlockSize;
+ int m_bytePos, m_bitPos;
+ SecByteBlock m_outBuf;
+};
+
+//! filter that breaks input stream into groups of fixed size
+class CRYPTOPP_DLL Grouper : public Bufferless<Filter>
+{
+public:
+ Grouper(BufferedTransformation *attachment=NULL)
+ {Detach(attachment);}
+
+ Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL)
+ {
+ Detach(attachment);
+ IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize)
+ (Name::Separator(), ConstByteArrayParameter(separator))
+ (Name::Terminator(), ConstByteArrayParameter(terminator)));
+ }
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+
+private:
+ SecByteBlock m_separator, m_terminator;
+ size_t m_groupSize, m_counter;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/cbcmac.cpp b/lib/cryptopp/cbcmac.cpp
new file mode 100644
index 000000000..6b0e8858e
--- /dev/null
+++ b/lib/cryptopp/cbcmac.cpp
@@ -0,0 +1,62 @@
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cbcmac.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void CBC_MAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+{
+ AccessCipher().SetKey(key, length, params);
+ m_reg.CleanNew(AccessCipher().BlockSize());
+ m_counter = 0;
+}
+
+void CBC_MAC_Base::Update(const byte *input, size_t length)
+{
+ unsigned int blockSize = AccessCipher().BlockSize();
+
+ while (m_counter && length)
+ {
+ m_reg[m_counter++] ^= *input++;
+ if (m_counter == blockSize)
+ ProcessBuf();
+ length--;
+ }
+
+ if (length >= blockSize)
+ {
+ size_t leftOver = AccessCipher().AdvancedProcessBlocks(m_reg, input, m_reg, length, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+ input += (length - leftOver);
+ length = leftOver;
+ }
+
+ while (length--)
+ {
+ m_reg[m_counter++] ^= *input++;
+ if (m_counter == blockSize)
+ ProcessBuf();
+ }
+}
+
+void CBC_MAC_Base::TruncatedFinal(byte *mac, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ if (m_counter)
+ ProcessBuf();
+
+ memcpy(mac, m_reg, size);
+ memset(m_reg, 0, AccessCipher().BlockSize());
+}
+
+void CBC_MAC_Base::ProcessBuf()
+{
+ AccessCipher().ProcessBlock(m_reg);
+ m_counter = 0;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/cbcmac.h b/lib/cryptopp/cbcmac.h
new file mode 100644
index 000000000..4675dcb3d
--- /dev/null
+++ b/lib/cryptopp/cbcmac.h
@@ -0,0 +1,50 @@
+#ifndef CRYPTOPP_CBCMAC_H
+#define CRYPTOPP_CBCMAC_H
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode
+{
+public:
+ CBC_MAC_Base() {}
+
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *mac, size_t size);
+ unsigned int DigestSize() const {return const_cast<CBC_MAC_Base*>(this)->AccessCipher().BlockSize();}
+
+protected:
+ virtual BlockCipher & AccessCipher() =0;
+
+private:
+ void ProcessBuf();
+ SecByteBlock m_reg;
+ unsigned int m_counter;
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/mac.html#CBC-MAC">CBC-MAC</a>
+/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation.
+ Secure only for fixed length messages. For variable length messages use CMAC or DMAC.
+*/
+template <class T>
+class CBC_MAC : public MessageAuthenticationCodeImpl<CBC_MAC_Base, CBC_MAC<T> >, public SameKeyLengthAs<T>
+{
+public:
+ CBC_MAC() {}
+ CBC_MAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
+ {this->SetKey(key, length);}
+
+ static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";}
+
+private:
+ BlockCipher & AccessCipher() {return m_cipher;}
+ typename T::Encryption m_cipher;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/ccm.cpp b/lib/cryptopp/ccm.cpp
new file mode 100644
index 000000000..030828ad8
--- /dev/null
+++ b/lib/cryptopp/ccm.cpp
@@ -0,0 +1,140 @@
+// ccm.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "ccm.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
+{
+ BlockCipher &blockCipher = AccessBlockCipher();
+
+ blockCipher.SetKey(userKey, keylength, params);
+
+ if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
+ throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
+
+ m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
+ if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
+ throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
+
+ m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
+ m_L = 8;
+}
+
+void CCM_Base::Resync(const byte *iv, size_t len)
+{
+ BlockCipher &cipher = AccessBlockCipher();
+
+ m_L = REQUIRED_BLOCKSIZE-1-(int)len;
+ assert(m_L >= 2);
+ if (m_L > 8)
+ m_L = 8;
+
+ m_buffer[0] = byte(m_L-1); // flag
+ memcpy(m_buffer+1, iv, len);
+ memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
+
+ if (m_state >= State_IVSet)
+ m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
+ else
+ m_ctr.SetCipherWithIV(cipher, m_buffer);
+
+ m_ctr.Seek(REQUIRED_BLOCKSIZE);
+ m_aadLength = 0;
+ m_messageLength = 0;
+}
+
+void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
+{
+ if (m_state != State_IVSet)
+ throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
+
+ m_aadLength = headerLength;
+ m_messageLength = messageLength;
+
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+
+ cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag
+ PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
+ memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
+ cipher.ProcessBlock(cbcBuffer);
+
+ if (headerLength>0)
+ {
+ assert(m_bufferedDataLength == 0);
+
+ if (headerLength < ((1<<16) - (1<<8)))
+ {
+ PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
+ m_bufferedDataLength = 2;
+ }
+ else if (headerLength < (W64LIT(1)<<32))
+ {
+ m_buffer[0] = 0xff;
+ m_buffer[1] = 0xfe;
+ PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
+ m_bufferedDataLength = 6;
+ }
+ else
+ {
+ m_buffer[0] = 0xff;
+ m_buffer[1] = 0xff;
+ PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
+ m_bufferedDataLength = 10;
+ }
+ }
+}
+
+size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
+{
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+ return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+}
+
+void CCM_Base::AuthenticateLastHeaderBlock()
+{
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+
+ if (m_aadLength != m_totalHeaderLength)
+ throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
+
+ if (m_bufferedDataLength > 0)
+ {
+ xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
+ cipher.ProcessBlock(cbcBuffer);
+ m_bufferedDataLength = 0;
+ }
+}
+
+void CCM_Base::AuthenticateLastConfidentialBlock()
+{
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+
+ if (m_messageLength != m_totalMessageLength)
+ throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
+
+ if (m_bufferedDataLength > 0)
+ {
+ xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
+ cipher.ProcessBlock(cbcBuffer);
+ m_bufferedDataLength = 0;
+ }
+}
+
+void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
+{
+ m_ctr.Seek(0);
+ m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/ccm.h b/lib/cryptopp/ccm.h
new file mode 100644
index 000000000..b1e5f00b9
--- /dev/null
+++ b/lib/cryptopp/ccm.h
@@ -0,0 +1,101 @@
+#ifndef CRYPTOPP_CCM_H
+#define CRYPTOPP_CCM_H
+
+#include "authenc.h"
+#include "modes.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! .
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase
+{
+public:
+ CCM_Base()
+ : m_digestSize(0), m_L(0) {}
+
+ // AuthenticatedSymmetricCipher
+ std::string AlgorithmName() const
+ {return GetBlockCipher().AlgorithmName() + std::string("/CCM");}
+ size_t MinKeyLength() const
+ {return GetBlockCipher().MinKeyLength();}
+ size_t MaxKeyLength() const
+ {return GetBlockCipher().MaxKeyLength();}
+ size_t DefaultKeyLength() const
+ {return GetBlockCipher().DefaultKeyLength();}
+ size_t GetValidKeyLength(size_t n) const
+ {return GetBlockCipher().GetValidKeyLength(n);}
+ bool IsValidKeyLength(size_t n) const
+ {return GetBlockCipher().IsValidKeyLength(n);}
+ unsigned int OptimalDataAlignment() const
+ {return GetBlockCipher().OptimalDataAlignment();}
+ IV_Requirement IVRequirement() const
+ {return UNIQUE_IV;}
+ unsigned int IVSize() const
+ {return 8;}
+ unsigned int MinIVLength() const
+ {return 7;}
+ unsigned int MaxIVLength() const
+ {return 13;}
+ unsigned int DigestSize() const
+ {return m_digestSize;}
+ lword MaxHeaderLength() const
+ {return W64LIT(0)-1;}
+ lword MaxMessageLength() const
+ {return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;}
+ bool NeedsPrespecifiedDataLengths() const
+ {return true;}
+ void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength);
+
+protected:
+ // AuthenticatedSymmetricCipherBase
+ bool AuthenticationIsOnPlaintext() const
+ {return true;}
+ unsigned int AuthenticationBlockSize() const
+ {return GetBlockCipher().BlockSize();}
+ void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
+ void Resync(const byte *iv, size_t len);
+ size_t AuthenticateBlocks(const byte *data, size_t len);
+ void AuthenticateLastHeaderBlock();
+ void AuthenticateLastConfidentialBlock();
+ void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
+ SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
+
+ virtual BlockCipher & AccessBlockCipher() =0;
+ virtual int DefaultDigestSize() const =0;
+
+ const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
+ byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
+
+ enum {REQUIRED_BLOCKSIZE = 16};
+ int m_digestSize, m_L;
+ word64 m_messageLength, m_aadLength;
+ CTR_Mode_ExternalCipher::Encryption m_ctr;
+};
+
+//! .
+template <class T_BlockCipher, int T_DefaultDigestSize, bool T_IsEncryption>
+class CCM_Final : public CCM_Base
+{
+public:
+ static std::string StaticAlgorithmName()
+ {return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");}
+ bool IsForwardTransformation() const
+ {return T_IsEncryption;}
+
+private:
+ BlockCipher & AccessBlockCipher() {return m_cipher;}
+ int DefaultDigestSize() const {return T_DefaultDigestSize;}
+ typename T_BlockCipher::Encryption m_cipher;
+};
+
+/// <a href="http://www.cryptolounge.org/wiki/CCM">CCM</a>
+template <class T_BlockCipher, int T_DefaultDigestSize = 16>
+struct CCM : public AuthenticatedSymmetricCipherDocumentation
+{
+ typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, true> Encryption;
+ typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, false> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/channels.cpp b/lib/cryptopp/channels.cpp
new file mode 100644
index 000000000..7359f54f7
--- /dev/null
+++ b/lib/cryptopp/channels.cpp
@@ -0,0 +1,309 @@
+// channels.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "channels.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+USING_NAMESPACE(std)
+
+#if 0
+void MessageSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &channel)
+{
+ m_defaultRoutes.push_back(Route(&destination, channel));
+}
+
+void MessageSwitch::AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel)
+{
+ RangeRoute route(begin, end, Route(&destination, channel));
+ RouteList::iterator it = upper_bound(m_routes.begin(), m_routes.end(), route);
+ m_routes.insert(it, route);
+}
+
+/*
+class MessageRouteIterator
+{
+public:
+ typedef MessageSwitch::RouteList::const_iterator RouteIterator;
+ typedef MessageSwitch::DefaultRouteList::const_iterator DefaultIterator;
+
+ bool m_useDefault;
+ RouteIterator m_itRouteCurrent, m_itRouteEnd;
+ DefaultIterator m_itDefaultCurrent, m_itDefaultEnd;
+
+ MessageRouteIterator(MessageSwitch &ms, const std::string &channel)
+ : m_channel(channel)
+ {
+ pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel);
+ if (range.first == range.second)
+ {
+ m_useDefault = true;
+ m_itListCurrent = cs.m_defaultRoutes.begin();
+ m_itListEnd = cs.m_defaultRoutes.end();
+ }
+ else
+ {
+ m_useDefault = false;
+ m_itMapCurrent = range.first;
+ m_itMapEnd = range.second;
+ }
+ }
+
+ bool End() const
+ {
+ return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
+ }
+
+ void Next()
+ {
+ if (m_useDefault)
+ ++m_itListCurrent;
+ else
+ ++m_itMapCurrent;
+ }
+
+ BufferedTransformation & Destination()
+ {
+ return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
+ }
+
+ const std::string & Message()
+ {
+ if (m_useDefault)
+ return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
+ else
+ return m_itMapCurrent->second.second;
+ }
+};
+
+void MessageSwitch::Put(byte inByte);
+void MessageSwitch::Put(const byte *inString, unsigned int length);
+
+void MessageSwitch::Flush(bool completeFlush, int propagation=-1);
+void MessageSwitch::MessageEnd(int propagation=-1);
+void MessageSwitch::PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
+void MessageSwitch::MessageSeriesEnd(int propagation=-1);
+*/
+#endif
+
+
+//
+// ChannelRouteIterator
+//////////////////////////
+
+void ChannelRouteIterator::Reset(const std::string &channel)
+{
+ m_channel = channel;
+ pair<MapIterator, MapIterator> range = m_cs.m_routeMap.equal_range(channel);
+ if (range.first == range.second)
+ {
+ m_useDefault = true;
+ m_itListCurrent = m_cs.m_defaultRoutes.begin();
+ m_itListEnd = m_cs.m_defaultRoutes.end();
+ }
+ else
+ {
+ m_useDefault = false;
+ m_itMapCurrent = range.first;
+ m_itMapEnd = range.second;
+ }
+}
+
+bool ChannelRouteIterator::End() const
+{
+ return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
+}
+
+void ChannelRouteIterator::Next()
+{
+ if (m_useDefault)
+ ++m_itListCurrent;
+ else
+ ++m_itMapCurrent;
+}
+
+BufferedTransformation & ChannelRouteIterator::Destination()
+{
+ return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
+}
+
+const std::string & ChannelRouteIterator::Channel()
+{
+ if (m_useDefault)
+ return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
+ else
+ return m_itMapCurrent->second.second;
+}
+
+
+//
+// ChannelSwitch
+///////////////////
+
+size_t ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (m_blocked)
+ {
+ m_blocked = false;
+ goto WasBlocked;
+ }
+
+ m_it.Reset(channel);
+
+ while (!m_it.End())
+ {
+WasBlocked:
+ if (m_it.Destination().ChannelPut2(m_it.Channel(), begin, length, messageEnd, blocking))
+ {
+ m_blocked = true;
+ return 1;
+ }
+
+ m_it.Next();
+ }
+
+ return 0;
+}
+
+void ChannelSwitch::IsolatedInitialize(const NameValuePairs &parameters/* =g_nullNameValuePairs */)
+{
+ m_routeMap.clear();
+ m_defaultRoutes.clear();
+ m_blocked = false;
+}
+
+bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
+{
+ if (m_blocked)
+ {
+ m_blocked = false;
+ goto WasBlocked;
+ }
+
+ m_it.Reset(channel);
+
+ while (!m_it.End())
+ {
+ WasBlocked:
+ if (m_it.Destination().ChannelFlush(m_it.Channel(), completeFlush, propagation, blocking))
+ {
+ m_blocked = true;
+ return true;
+ }
+
+ m_it.Next();
+ }
+
+ return false;
+}
+
+bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
+{
+ if (m_blocked)
+ {
+ m_blocked = false;
+ goto WasBlocked;
+ }
+
+ m_it.Reset(channel);
+
+ while (!m_it.End())
+ {
+ WasBlocked:
+ if (m_it.Destination().ChannelMessageSeriesEnd(m_it.Channel(), propagation))
+ {
+ m_blocked = true;
+ return true;
+ }
+
+ m_it.Next();
+ }
+
+ return false;
+}
+
+byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, size_t &size)
+{
+ m_it.Reset(channel);
+ if (!m_it.End())
+ {
+ BufferedTransformation &target = m_it.Destination();
+ const std::string &channel = m_it.Channel();
+ m_it.Next();
+ if (m_it.End()) // there is only one target channel
+ return target.ChannelCreatePutSpace(channel, size);
+ }
+ size = 0;
+ return NULL;
+}
+
+size_t ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ ChannelRouteIterator it(*this);
+ it.Reset(channel);
+
+ if (!it.End())
+ {
+ BufferedTransformation &target = it.Destination();
+ const std::string &targetChannel = it.Channel();
+ it.Next();
+ if (it.End()) // there is only one target channel
+ return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking);
+ }
+
+ return ChannelPut2(channel, inString, length, messageEnd, blocking);
+}
+
+void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination)
+{
+ m_defaultRoutes.push_back(DefaultRoute(&destination, value_ptr<std::string>(NULL)));
+}
+
+void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination)
+{
+ for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
+ if (it->first == &destination && !it->second.get())
+ {
+ m_defaultRoutes.erase(it);
+ break;
+ }
+}
+
+void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
+{
+ m_defaultRoutes.push_back(DefaultRoute(&destination, outChannel));
+}
+
+void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
+{
+ for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
+ if (it->first == &destination && (it->second.get() && *it->second == outChannel))
+ {
+ m_defaultRoutes.erase(it);
+ break;
+ }
+}
+
+void ChannelSwitch::AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
+{
+ m_routeMap.insert(RouteMap::value_type(inChannel, Route(&destination, outChannel)));
+}
+
+void ChannelSwitch::RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
+{
+ typedef ChannelSwitch::RouteMap::iterator MapIterator;
+ pair<MapIterator, MapIterator> range = m_routeMap.equal_range(inChannel);
+
+ for (MapIterator it = range.first; it != range.second; ++it)
+ if (it->second.first == &destination && it->second.second == outChannel)
+ {
+ m_routeMap.erase(it);
+ break;
+ }
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/channels.h b/lib/cryptopp/channels.h
new file mode 100644
index 000000000..837415615
--- /dev/null
+++ b/lib/cryptopp/channels.h
@@ -0,0 +1,123 @@
+#ifndef CRYPTOPP_CHANNELS_H
+#define CRYPTOPP_CHANNELS_H
+
+#include "simple.h"
+#include "smartptr.h"
+#include <map>
+#include <list>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if 0
+//! Route input on default channel to different and/or multiple channels based on message sequence number
+class MessageSwitch : public Sink
+{
+public:
+ void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel);
+ void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel);
+
+ void Put(byte inByte);
+ void Put(const byte *inString, unsigned int length);
+
+ void Flush(bool completeFlush, int propagation=-1);
+ void MessageEnd(int propagation=-1);
+ void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
+ void MessageSeriesEnd(int propagation=-1);
+
+private:
+ typedef std::pair<BufferedTransformation *, std::string> Route;
+ struct RangeRoute
+ {
+ RangeRoute(unsigned int begin, unsigned int end, const Route &route)
+ : begin(begin), end(end), route(route) {}
+ bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;}
+ unsigned int begin, end;
+ Route route;
+ };
+
+ typedef std::list<RangeRoute> RouteList;
+ typedef std::list<Route> DefaultRouteList;
+
+ RouteList m_routes;
+ DefaultRouteList m_defaultRoutes;
+ unsigned int m_nCurrentMessage;
+};
+#endif
+
+class ChannelSwitchTypedefs
+{
+public:
+ typedef std::pair<BufferedTransformation *, std::string> Route;
+ typedef std::multimap<std::string, Route> RouteMap;
+
+ typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute;
+ typedef std::list<DefaultRoute> DefaultRouteList;
+
+ // SunCC workaround: can't use const_iterator here
+ typedef RouteMap::iterator MapIterator;
+ typedef DefaultRouteList::iterator ListIterator;
+};
+
+class ChannelSwitch;
+
+class ChannelRouteIterator : public ChannelSwitchTypedefs
+{
+public:
+ ChannelSwitch& m_cs;
+ std::string m_channel;
+ bool m_useDefault;
+ MapIterator m_itMapCurrent, m_itMapEnd;
+ ListIterator m_itListCurrent, m_itListEnd;
+
+ ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs) {}
+ void Reset(const std::string &channel);
+ bool End() const;
+ void Next();
+ BufferedTransformation & Destination();
+ const std::string & Channel();
+};
+
+//! Route input to different and/or multiple channels based on channel ID
+class CRYPTOPP_DLL ChannelSwitch : public Multichannel<Sink>, public ChannelSwitchTypedefs
+{
+public:
+ ChannelSwitch() : m_it(*this), m_blocked(false) {}
+ ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false)
+ {
+ AddDefaultRoute(destination);
+ }
+ ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false)
+ {
+ AddDefaultRoute(destination, outChannel);
+ }
+
+ void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
+
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+ size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
+
+ bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true);
+ bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
+
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+
+ void AddDefaultRoute(BufferedTransformation &destination);
+ void RemoveDefaultRoute(BufferedTransformation &destination);
+ void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
+ void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
+ void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
+ void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
+
+private:
+ RouteMap m_routeMap;
+ DefaultRouteList m_defaultRoutes;
+
+ ChannelRouteIterator m_it;
+ bool m_blocked;
+
+ friend class ChannelRouteIterator;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/cmac.cpp b/lib/cryptopp/cmac.cpp
new file mode 100644
index 000000000..a31d5f8b0
--- /dev/null
+++ b/lib/cryptopp/cmac.cpp
@@ -0,0 +1,122 @@
+// cmac.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cmac.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static void MulU(byte *k, unsigned int length)
+{
+ byte carry = 0;
+
+ for (int i=length-1; i>=1; i-=2)
+ {
+ byte carry2 = k[i] >> 7;
+ k[i] += k[i] + carry;
+ carry = k[i-1] >> 7;
+ k[i-1] += k[i-1] + carry2;
+ }
+
+ if (carry)
+ {
+ switch (length)
+ {
+ case 8:
+ k[7] ^= 0x1b;
+ break;
+ case 16:
+ k[15] ^= 0x87;
+ break;
+ case 32:
+ k[30] ^= 4;
+ k[31] ^= 0x23;
+ break;
+ default:
+ throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
+ }
+ }
+}
+
+void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+{
+ BlockCipher &cipher = AccessCipher();
+ unsigned int blockSize = cipher.BlockSize();
+
+ cipher.SetKey(key, length, params);
+ m_reg.CleanNew(3*blockSize);
+ m_counter = 0;
+
+ cipher.ProcessBlock(m_reg, m_reg+blockSize);
+ MulU(m_reg+blockSize, blockSize);
+ memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
+ MulU(m_reg+2*blockSize, blockSize);
+}
+
+void CMAC_Base::Update(const byte *input, size_t length)
+{
+ if (!length)
+ return;
+
+ BlockCipher &cipher = AccessCipher();
+ unsigned int blockSize = cipher.BlockSize();
+
+ if (m_counter > 0)
+ {
+ unsigned int len = UnsignedMin(blockSize - m_counter, length);
+ xorbuf(m_reg+m_counter, input, len);
+ length -= len;
+ input += len;
+ m_counter += len;
+
+ if (m_counter == blockSize && length > 0)
+ {
+ cipher.ProcessBlock(m_reg);
+ m_counter = 0;
+ }
+ }
+
+ if (length > blockSize)
+ {
+ assert(m_counter == 0);
+ size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+ input += (length - leftOver);
+ length = leftOver;
+ }
+
+ if (length > 0)
+ {
+ assert(m_counter + length <= blockSize);
+ xorbuf(m_reg+m_counter, input, length);
+ m_counter += (unsigned int)length;
+ }
+
+ assert(m_counter > 0);
+}
+
+void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ BlockCipher &cipher = AccessCipher();
+ unsigned int blockSize = cipher.BlockSize();
+
+ if (m_counter < blockSize)
+ {
+ m_reg[m_counter] ^= 0x80;
+ cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+ }
+ else
+ cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+
+ memcpy(mac, m_reg, size);
+
+ m_counter = 0;
+ memset(m_reg, 0, blockSize);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/cmac.h b/lib/cryptopp/cmac.h
new file mode 100644
index 000000000..d8a1b391d
--- /dev/null
+++ b/lib/cryptopp/cmac.h
@@ -0,0 +1,52 @@
+#ifndef CRYPTOPP_CMAC_H
+#define CRYPTOPP_CMAC_H
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode
+{
+public:
+ CMAC_Base() {}
+
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *mac, size_t size);
+ unsigned int DigestSize() const {return GetCipher().BlockSize();}
+ unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();}
+ unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();}
+
+protected:
+ friend class EAX_Base;
+
+ const BlockCipher & GetCipher() const {return const_cast<CMAC_Base*>(this)->AccessCipher();}
+ virtual BlockCipher & AccessCipher() =0;
+
+ void ProcessBuf();
+ SecByteBlock m_reg;
+ unsigned int m_counter;
+};
+
+/// <a href="http://www.cryptolounge.org/wiki/CMAC">CMAC</a>
+/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */
+template <class T>
+class CMAC : public MessageAuthenticationCodeImpl<CMAC_Base, CMAC<T> >, public SameKeyLengthAs<T>
+{
+public:
+ CMAC() {}
+ CMAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
+ {this->SetKey(key, length);}
+
+ static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";}
+
+private:
+ BlockCipher & AccessCipher() {return m_cipher;}
+ typename T::Encryption m_cipher;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/config.h b/lib/cryptopp/config.h
new file mode 100644
index 000000000..edbfd00ef
--- /dev/null
+++ b/lib/cryptopp/config.h
@@ -0,0 +1,462 @@
+#ifndef CRYPTOPP_CONFIG_H
+#define CRYPTOPP_CONFIG_H
+
+// ***************** Important Settings ********************
+
+// define this if running on a big-endian CPU
+#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__MIPSEB__) || defined(__ARMEB__) || (defined(__MWERKS__) && !defined(__INTEL__)))
+# define IS_BIG_ENDIAN
+#endif
+
+// define this if running on a little-endian CPU
+// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
+#ifndef IS_BIG_ENDIAN
+# define IS_LITTLE_ENDIAN
+#endif
+
+// define this if you want to disable all OS-dependent features,
+// such as sockets and OS-provided random number generators
+#define NO_OS_DEPENDENCE
+
+// Define this to use features provided by Microsoft's CryptoAPI.
+// Currently the only feature used is random number generation.
+// This macro will be ignored if NO_OS_DEPENDENCE is defined.
+// #define USE_MS_CRYPTOAPI
+
+// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used
+#ifndef DSA_1024_BIT_MODULUS_ONLY
+# define DSA_1024_BIT_MODULUS_ONLY 1
+#endif
+
+// ***************** Less Important Settings ***************
+
+// define this to retain (as much as possible) old deprecated function and class names
+// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+
+#define GZIP_OS_CODE 0
+
+// Try this if your CPU has 256K internal cache or a slow multiply instruction
+// and you want a (possibly) faster IDEA implementation using log tables
+// #define IDEA_LARGECACHE
+
+// Define this if, for the linear congruential RNG, you want to use
+// the original constants as specified in S.K. Park and K.W. Miller's
+// CACM paper.
+// #define LCRNG_ORIGINAL_NUMBERS
+
+// choose which style of sockets to wrap (mostly useful for cygwin which has both)
+#define PREFER_BERKELEY_STYLE_SOCKETS
+// #define PREFER_WINDOWS_STYLE_SOCKETS
+
+// set the name of Rijndael cipher, was "Rijndael" before version 5.3
+#define CRYPTOPP_RIJNDAEL_NAME "AES"
+
+// ***************** Important Settings Again ********************
+// But the defaults should be ok.
+
+// namespace support is now required
+#ifdef NO_NAMESPACE
+# error namespace support is now required
+#endif
+
+// Define this to workaround a Microsoft CryptoAPI bug where
+// each call to CryptAcquireContext causes a 100 KB memory leak.
+// Defining this will cause Crypto++ to make only one call to CryptAcquireContext.
+#define WORKAROUND_MS_BUG_Q258000
+
+#ifdef CRYPTOPP_DOXYGEN_PROCESSING
+// Avoid putting "CryptoPP::" in front of everything in Doxygen output
+# define CryptoPP
+# define NAMESPACE_BEGIN(x)
+# define NAMESPACE_END
+// Get Doxygen to generate better documentation for these typedefs
+# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
+#else
+# define NAMESPACE_BEGIN(x) namespace x {
+# define NAMESPACE_END }
+# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
+#endif
+#define ANONYMOUS_NAMESPACE_BEGIN namespace {
+#define USING_NAMESPACE(x) using namespace x;
+#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
+#define DOCUMENTED_NAMESPACE_END }
+
+// What is the type of the third parameter to bind?
+// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
+// Unfortunately there is no way to tell whether or not socklen_t is defined.
+// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
+#ifndef TYPE_OF_SOCKLEN_T
+# if defined(_WIN32) || defined(__CYGWIN__)
+# define TYPE_OF_SOCKLEN_T int
+# else
+# define TYPE_OF_SOCKLEN_T ::socklen_t
+# endif
+#endif
+
+#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
+# define __USE_W32_SOCKETS
+#endif
+
+typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs
+
+NAMESPACE_BEGIN(CryptoPP)
+
+typedef unsigned short word16;
+typedef unsigned int word32;
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 word64;
+ #define W64LIT(x) x##ui64
+#else
+ typedef unsigned long long word64;
+ #define W64LIT(x) x##ULL
+#endif
+
+// define large word type, used for file offsets and such
+typedef word64 lword;
+const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
+
+#ifdef __GNUC__
+ #define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+// define hword, word, and dword. these are used for multiprecision integer arithmetic
+// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
+#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
+ typedef word32 hword;
+ typedef word64 word;
+#else
+ #define CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ #if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
+ #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400
+ // GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
+ // mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
+ typedef word32 hword;
+ typedef word64 word;
+ typedef __uint128_t dword;
+ typedef __uint128_t word128;
+ #define CRYPTOPP_WORD128_AVAILABLE
+ #else
+ // if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
+ typedef word16 hword;
+ typedef word32 word;
+ typedef word64 dword;
+ #endif
+ #else
+ // being here means the native register size is probably 32 bits or less
+ #define CRYPTOPP_BOOL_SLOW_WORD64 1
+ typedef word16 hword;
+ typedef word32 word;
+ typedef word64 dword;
+ #endif
+#endif
+#ifndef CRYPTOPP_BOOL_SLOW_WORD64
+ #define CRYPTOPP_BOOL_SLOW_WORD64 0
+#endif
+
+const unsigned int WORD_SIZE = sizeof(word);
+const unsigned int WORD_BITS = WORD_SIZE * 8;
+
+NAMESPACE_END
+
+#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
+ // This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
+ #if defined(_M_X64) || defined(__x86_64__)
+ #define CRYPTOPP_L1_CACHE_LINE_SIZE 64
+ #else
+ // L1 cache line size is 32 on Pentium III and earlier
+ #define CRYPTOPP_L1_CACHE_LINE_SIZE 32
+ #endif
+#endif
+
+#if defined(_MSC_VER)
+ #if _MSC_VER == 1200
+ #include <malloc.h>
+ #endif
+ #if _MSC_VER > 1200 || defined(_mm_free)
+ #define CRYPTOPP_MSVC6PP_OR_LATER // VC 6 processor pack or later
+ #else
+ #define CRYPTOPP_MSVC6_NO_PP // VC 6 without processor pack
+ #endif
+#endif
+
+#ifndef CRYPTOPP_ALIGN_DATA
+ #if defined(CRYPTOPP_MSVC6PP_OR_LATER)
+ #define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
+ #elif defined(__GNUC__)
+ #define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
+ #else
+ #define CRYPTOPP_ALIGN_DATA(x)
+ #endif
+#endif
+
+#ifndef CRYPTOPP_SECTION_ALIGN16
+ #if defined(__GNUC__) && !defined(__APPLE__)
+ // the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on
+ #define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16")))
+ #else
+ #define CRYPTOPP_SECTION_ALIGN16
+ #endif
+#endif
+
+#if defined(_MSC_VER) || defined(__fastcall)
+ #define CRYPTOPP_FASTCALL __fastcall
+#else
+ #define CRYPTOPP_FASTCALL
+#endif
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+#define CPP_TYPENAME
+#else
+#define CPP_TYPENAME typename
+#endif
+
+// VC60 workaround: can't cast unsigned __int64 to float or double
+#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER)
+#define CRYPTOPP_VC6_INT64 (__int64)
+#else
+#define CRYPTOPP_VC6_INT64
+#endif
+
+#ifdef _MSC_VER
+#define CRYPTOPP_NO_VTABLE __declspec(novtable)
+#else
+#define CRYPTOPP_NO_VTABLE
+#endif
+
+#ifdef _MSC_VER
+ // 4231: nonstandard extension used : 'extern' before template explicit instantiation
+ // 4250: dominance
+ // 4251: member needs to have dll-interface
+ // 4275: base needs to have dll-interface
+ // 4660: explicitly instantiating a class that's already implicitly instantiated
+ // 4661: no suitable definition provided for explicit template instantiation request
+ // 4786: identifer was truncated in debug information
+ // 4355: 'this' : used in base member initializer list
+ // 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
+# pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910)
+#endif
+
+#ifdef __BORLANDC__
+// 8037: non-const function called for const object. needed to work around BCB2006 bug
+# pragma warn -8037
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION) || defined(ANDROID_NDK)
+#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+#endif
+
+#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_DISABLE_X86ASM // for backwards compatibility: this macro had both meanings
+#define CRYPTOPP_DISABLE_ASM
+#define CRYPTOPP_DISABLE_SSE2
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
+ // C++Builder 2010 does not allow "call label" where label is defined within inline assembly
+ #define CRYPTOPP_X86_ASM_AVAILABLE
+
+ #if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300)
+ #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
+ #else
+ #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0
+ #endif
+
+ // SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed.
+ // GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version.
+ #if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102)
+ #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1
+ #else
+ #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0
+ #endif
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
+ #define CRYPTOPP_X64_MASM_AVAILABLE
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
+ #define CRYPTOPP_X64_ASM_AVAILABLE
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__))
+ #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1
+#else
+ #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_SSSE3) && !defined(CRYPTOPP_DISABLE_AESNI) && CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE && (CRYPTOPP_GCC_VERSION >= 40400 || _MSC_FULL_VER >= 150030729 || __INTEL_COMPILER >= 1110)
+ #define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 1
+#else
+ #define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 0
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ #define CRYPTOPP_BOOL_ALIGN16_ENABLED 1
+#else
+ #define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
+#endif
+
+// how to allocate 16-byte aligned memory (for SSE2)
+#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
+ #define CRYPTOPP_MM_MALLOC_AVAILABLE
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+ #define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
+#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
+ #define CRYPTOPP_MEMALIGN_AVAILABLE
+#else
+ #define CRYPTOPP_NO_ALIGNED_ALLOC
+#endif
+
+// how to disable inlining
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+# define CRYPTOPP_NOINLINE_DOTDOTDOT
+# define CRYPTOPP_NOINLINE __declspec(noinline)
+#elif defined(__GNUC__)
+# define CRYPTOPP_NOINLINE_DOTDOTDOT
+# define CRYPTOPP_NOINLINE __attribute__((noinline))
+#else
+# define CRYPTOPP_NOINLINE_DOTDOTDOT ...
+# define CRYPTOPP_NOINLINE
+#endif
+
+// how to declare class constants
+#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER)
+# define CRYPTOPP_CONSTANT(x) enum {x};
+#else
+# define CRYPTOPP_CONSTANT(x) static const int x;
+#endif
+
+#if defined(_M_X64) || defined(__x86_64__)
+ #define CRYPTOPP_BOOL_X64 1
+#else
+ #define CRYPTOPP_BOOL_X64 0
+#endif
+
+// see http://predef.sourceforge.net/prearch.html
+#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)
+ #define CRYPTOPP_BOOL_X86 1
+#else
+ #define CRYPTOPP_BOOL_X86 0
+#endif
+
+#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__)
+ #define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+#endif
+
+#define CRYPTOPP_VERSION 562
+
+// ***************** determine availability of OS features ********************
+
+#ifndef NO_OS_DEPENDENCE
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define CRYPTOPP_WIN32_AVAILABLE
+#endif
+
+#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
+#define CRYPTOPP_UNIX_AVAILABLE
+#endif
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
+# define HIGHRES_TIMER_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_UNIX_AVAILABLE
+# define HAS_BERKELEY_STYLE_SOCKETS
+#endif
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+# define HAS_WINDOWS_STYLE_SOCKETS
+#endif
+
+#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS))
+# define SOCKETS_AVAILABLE
+#endif
+
+#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
+# define USE_WINDOWS_STYLE_SOCKETS
+#else
+# define USE_BERKELEY_STYLE_SOCKETS
+#endif
+
+#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
+# define WINDOWS_PIPES_AVAILABLE
+#endif
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI)
+# define NONBLOCKING_RNG_AVAILABLE
+# define OS_RNG_AVAILABLE
+#endif
+
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+# define NONBLOCKING_RNG_AVAILABLE
+# define BLOCKING_RNG_AVAILABLE
+# define OS_RNG_AVAILABLE
+# define HAS_PTHREADS
+# define THREADS_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+# define HAS_WINTHREADS
+# define THREADS_AVAILABLE
+#endif
+
+#endif // NO_OS_DEPENDENCE
+
+// ***************** DLL related ********************
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+#ifdef CRYPTOPP_EXPORTS
+#define CRYPTOPP_IS_DLL
+#define CRYPTOPP_DLL __declspec(dllexport)
+#elif defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_IS_DLL
+#define CRYPTOPP_DLL __declspec(dllimport)
+#else
+#define CRYPTOPP_DLL
+#endif
+
+#define CRYPTOPP_API __cdecl
+
+#else // CRYPTOPP_WIN32_AVAILABLE
+
+#define CRYPTOPP_DLL
+#define CRYPTOPP_API
+
+#endif // CRYPTOPP_WIN32_AVAILABLE
+
+#if defined(__MWERKS__)
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
+#endif
+
+#if defined(__MWERKS__)
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
+#else
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
+#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
+#else
+#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
+#endif
+
+#endif
diff --git a/lib/cryptopp/cpu.cpp b/lib/cryptopp/cpu.cpp
new file mode 100644
index 000000000..3610a7c8e
--- /dev/null
+++ b/lib/cryptopp/cpu.cpp
@@ -0,0 +1,199 @@
+// cpu.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cpu.h"
+#include "misc.h"
+#include <algorithm>
+
+#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
+#include <signal.h>
+#include <setjmp.h>
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+#include <emmintrin.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef CRYPTOPP_CPUID_AVAILABLE
+
+#if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
+
+bool CpuId(word32 input, word32 *output)
+{
+ __cpuid((int *)output, input);
+ return true;
+}
+
+#else
+
+#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
+extern "C" {
+typedef void (*SigHandler)(int);
+
+static jmp_buf s_jmpNoCPUID;
+static void SigIllHandlerCPUID(int)
+{
+ longjmp(s_jmpNoCPUID, 1);
+}
+
+static jmp_buf s_jmpNoSSE2;
+static void SigIllHandlerSSE2(int)
+{
+ longjmp(s_jmpNoSSE2, 1);
+}
+}
+#endif
+
+bool CpuId(word32 input, word32 *output)
+{
+#ifdef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
+ __try
+ {
+ __asm
+ {
+ mov eax, input
+ cpuid
+ mov edi, output
+ mov [edi], eax
+ mov [edi+4], ebx
+ mov [edi+8], ecx
+ mov [edi+12], edx
+ }
+ }
+ __except (1)
+ {
+ return false;
+ }
+ return true;
+#else
+ SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ bool result = true;
+ if (setjmp(s_jmpNoCPUID))
+ result = false;
+ else
+ {
+ asm
+ (
+ // save ebx in case -fPIC is being used
+#if CRYPTOPP_BOOL_X86
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+#else
+ "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
+#endif
+ : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
+ : "a" (input)
+ );
+ }
+
+ signal(SIGILL, oldHandler);
+ return result;
+#endif
+}
+
+#endif
+
+static bool TrySSE2()
+{
+#if CRYPTOPP_BOOL_X64
+ return true;
+#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
+ __try
+ {
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ AS2(por xmm0, xmm0) // executing SSE2 instruction
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+ __m128i x = _mm_setzero_si128();
+ return _mm_cvtsi128_si32(x) == 0;
+#endif
+ }
+ __except (1)
+ {
+ return false;
+ }
+ return true;
+#else
+ SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ bool result = true;
+ if (setjmp(s_jmpNoSSE2))
+ result = false;
+ else
+ {
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ __asm __volatile ("por %xmm0, %xmm0");
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+ __m128i x = _mm_setzero_si128();
+ result = _mm_cvtsi128_si32(x) == 0;
+#endif
+ }
+
+ signal(SIGILL, oldHandler);
+ return result;
+#endif
+}
+
+bool g_x86DetectionDone = false;
+bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_hasAESNI = false, g_hasCLMUL = false, g_isP4 = false;
+word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+void DetectX86Features()
+{
+ word32 cpuid[4], cpuid1[4];
+ if (!CpuId(0, cpuid))
+ return;
+ if (!CpuId(1, cpuid1))
+ return;
+
+ g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
+ if ((cpuid1[3] & (1 << 26)) != 0)
+ g_hasSSE2 = TrySSE2();
+ g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
+ g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
+ g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
+
+ if ((cpuid1[3] & (1 << 25)) != 0)
+ g_hasISSE = true;
+ else
+ {
+ word32 cpuid2[4];
+ CpuId(0x080000000, cpuid2);
+ if (cpuid2[0] >= 0x080000001)
+ {
+ CpuId(0x080000001, cpuid2);
+ g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
+ }
+ }
+
+ std::swap(cpuid[2], cpuid[3]);
+ if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
+ {
+ g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
+ g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
+ }
+ else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
+ {
+ CpuId(0x80000005, cpuid);
+ g_cacheLineSize = GETBYTE(cpuid[2], 0);
+ }
+
+ if (!g_cacheLineSize)
+ g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+ g_x86DetectionDone = true;
+}
+
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/cpu.h b/lib/cryptopp/cpu.h
new file mode 100644
index 000000000..65029d338
--- /dev/null
+++ b/lib/cryptopp/cpu.h
@@ -0,0 +1,345 @@
+#ifndef CRYPTOPP_CPU_H
+#define CRYPTOPP_CPU_H
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+
+#define CRYPTOPP_X86_ASM_AVAILABLE
+#define CRYPTOPP_BOOL_X64 1
+#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
+#define NAMESPACE_END
+
+#else
+
+#include "config.h"
+
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+#include <emmintrin.h>
+#endif
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+#if !defined(__GNUC__) || defined(__SSSE3__) || defined(__INTEL_COMPILER)
+#include <tmmintrin.h>
+#else
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_shuffle_epi8 (__m128i a, __m128i b)
+{
+ asm ("pshufb %1, %0" : "+x"(a) : "xm"(b));
+ return a;
+}
+#endif
+#if !defined(__GNUC__) || defined(__SSE4_1__) || defined(__INTEL_COMPILER)
+#include <smmintrin.h>
+#else
+__inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_extract_epi32 (__m128i a, const int i)
+{
+ int r;
+ asm ("pextrd %2, %1, %0" : "=rm"(r) : "x"(a), "i"(i));
+ return r;
+}
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_insert_epi32 (__m128i a, int b, const int i)
+{
+ asm ("pinsrd %2, %1, %0" : "+x"(a) : "rm"(b), "i"(i));
+ return a;
+}
+#endif
+#if !defined(__GNUC__) || (defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER)
+#include <wmmintrin.h>
+#else
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_clmulepi64_si128 (__m128i a, __m128i b, const int i)
+{
+ asm ("pclmulqdq %2, %1, %0" : "+x"(a) : "xm"(b), "i"(i));
+ return a;
+}
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aeskeygenassist_si128 (__m128i a, const int i)
+{
+ __m128i r;
+ asm ("aeskeygenassist %2, %1, %0" : "=x"(r) : "xm"(a), "i"(i));
+ return r;
+}
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesimc_si128 (__m128i a)
+{
+ __m128i r;
+ asm ("aesimc %1, %0" : "=x"(r) : "xm"(a));
+ return r;
+}
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesenc_si128 (__m128i a, __m128i b)
+{
+ asm ("aesenc %1, %0" : "+x"(a) : "xm"(b));
+ return a;
+}
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesenclast_si128 (__m128i a, __m128i b)
+{
+ asm ("aesenclast %1, %0" : "+x"(a) : "xm"(b));
+ return a;
+}
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesdec_si128 (__m128i a, __m128i b)
+{
+ asm ("aesdec %1, %0" : "+x"(a) : "xm"(b));
+ return a;
+}
+__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_aesdeclast_si128 (__m128i a, __m128i b)
+{
+ asm ("aesdeclast %1, %0" : "+x"(a) : "xm"(b));
+ return a;
+}
+#endif
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64
+
+#define CRYPTOPP_CPUID_AVAILABLE
+
+// these should not be used directly
+extern CRYPTOPP_DLL bool g_x86DetectionDone;
+extern CRYPTOPP_DLL bool g_hasSSSE3;
+extern CRYPTOPP_DLL bool g_hasAESNI;
+extern CRYPTOPP_DLL bool g_hasCLMUL;
+extern CRYPTOPP_DLL bool g_isP4;
+extern CRYPTOPP_DLL word32 g_cacheLineSize;
+CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
+CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output);
+
+#if CRYPTOPP_BOOL_X64
+inline bool HasSSE2() {return true;}
+inline bool HasISSE() {return true;}
+inline bool HasMMX() {return true;}
+#else
+
+extern CRYPTOPP_DLL bool g_hasSSE2;
+extern CRYPTOPP_DLL bool g_hasISSE;
+extern CRYPTOPP_DLL bool g_hasMMX;
+
+inline bool HasSSE2()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_hasSSE2;
+}
+
+inline bool HasISSE()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_hasISSE;
+}
+
+inline bool HasMMX()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_hasMMX;
+}
+
+#endif
+
+inline bool HasSSSE3()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_hasSSSE3;
+}
+
+inline bool HasAESNI()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_hasAESNI;
+}
+
+inline bool HasCLMUL()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_hasCLMUL;
+}
+
+inline bool IsP4()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_isP4;
+}
+
+inline int GetCacheLineSize()
+{
+ if (!g_x86DetectionDone)
+ DetectX86Features();
+ return g_cacheLineSize;
+}
+
+#else
+
+inline int GetCacheLineSize()
+{
+ return CRYPTOPP_L1_CACHE_LINE_SIZE;
+}
+
+#endif
+
+#endif
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+ #define AS1(x) x*newline*
+ #define AS2(x, y) x, y*newline*
+ #define AS3(x, y, z) x, y, z*newline*
+ #define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline*
+ #define ASL(x) label##x:*newline*
+ #define ASJ(x, y, z) x label##y*newline*
+ #define ASC(x, y) x label##y*newline*
+ #define AS_HEX(y) 0##y##h
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+ #define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
+ #define AS1(x) __asm {x}
+ #define AS2(x, y) __asm {x, y}
+ #define AS3(x, y, z) __asm {x, y, z}
+ #define ASS(x, y, a, b, c, d) __asm {x, y, (a)*64+(b)*16+(c)*4+(d)}
+ #define ASL(x) __asm {label##x:}
+ #define ASJ(x, y, z) __asm {x label##y}
+ #define ASC(x, y) __asm {x label##y}
+ #define CRYPTOPP_NAKED __declspec(naked)
+ #define AS_HEX(y) 0x##y
+#else
+ #define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
+ // define these in two steps to allow arguments to be expanded
+ #define GNU_AS1(x) #x ";"
+ #define GNU_AS2(x, y) #x ", " #y ";"
+ #define GNU_AS3(x, y, z) #x ", " #y ", " #z ";"
+ #define GNU_ASL(x) "\n" #x ":"
+ #define GNU_ASJ(x, y, z) #x " " #y #z ";"
+ #define AS1(x) GNU_AS1(x)
+ #define AS2(x, y) GNU_AS2(x, y)
+ #define AS3(x, y, z) GNU_AS3(x, y, z)
+ #define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";"
+ #define ASL(x) GNU_ASL(x)
+ #define ASJ(x, y, z) GNU_ASJ(x, y, z)
+ #define ASC(x, y) #x " " #y ";"
+ #define CRYPTOPP_NAKED
+ #define AS_HEX(y) 0x##y
+#endif
+
+#define IF0(y)
+#define IF1(y) y
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+#define ASM_MOD(x, y) ((x) MOD (y))
+#define XMMWORD_PTR XMMWORD PTR
+#else
+// GNU assembler doesn't seem to have mod operator
+#define ASM_MOD(x, y) ((x)-((x)/(y))*(y))
+// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM
+#define XMMWORD_PTR
+#endif
+
+#if CRYPTOPP_BOOL_X86
+ #define AS_REG_1 ecx
+ #define AS_REG_2 edx
+ #define AS_REG_3 esi
+ #define AS_REG_4 edi
+ #define AS_REG_5 eax
+ #define AS_REG_6 ebx
+ #define AS_REG_7 ebp
+ #define AS_REG_1d ecx
+ #define AS_REG_2d edx
+ #define AS_REG_3d esi
+ #define AS_REG_4d edi
+ #define AS_REG_5d eax
+ #define AS_REG_6d ebx
+ #define AS_REG_7d ebp
+ #define WORD_SZ 4
+ #define WORD_REG(x) e##x
+ #define WORD_PTR DWORD PTR
+ #define AS_PUSH_IF86(x) AS1(push e##x)
+ #define AS_POP_IF86(x) AS1(pop e##x)
+ #define AS_JCXZ jecxz
+#elif CRYPTOPP_BOOL_X64
+ #ifdef CRYPTOPP_GENERATE_X64_MASM
+ #define AS_REG_1 rcx
+ #define AS_REG_2 rdx
+ #define AS_REG_3 r8
+ #define AS_REG_4 r9
+ #define AS_REG_5 rax
+ #define AS_REG_6 r10
+ #define AS_REG_7 r11
+ #define AS_REG_1d ecx
+ #define AS_REG_2d edx
+ #define AS_REG_3d r8d
+ #define AS_REG_4d r9d
+ #define AS_REG_5d eax
+ #define AS_REG_6d r10d
+ #define AS_REG_7d r11d
+ #else
+ #define AS_REG_1 rdi
+ #define AS_REG_2 rsi
+ #define AS_REG_3 rdx
+ #define AS_REG_4 rcx
+ #define AS_REG_5 r8
+ #define AS_REG_6 r9
+ #define AS_REG_7 r10
+ #define AS_REG_1d edi
+ #define AS_REG_2d esi
+ #define AS_REG_3d edx
+ #define AS_REG_4d ecx
+ #define AS_REG_5d r8d
+ #define AS_REG_6d r9d
+ #define AS_REG_7d r10d
+ #endif
+ #define WORD_SZ 8
+ #define WORD_REG(x) r##x
+ #define WORD_PTR QWORD PTR
+ #define AS_PUSH_IF86(x)
+ #define AS_POP_IF86(x)
+ #define AS_JCXZ jrcxz
+#endif
+
+// helper macro for stream cipher output
+#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\
+ AS2( test inputPtr, inputPtr)\
+ ASC( jz, labelPrefix##3)\
+ AS2( test inputPtr, 15)\
+ ASC( jnz, labelPrefix##7)\
+ AS2( pxor xmm##x0, [inputPtr+p0*16])\
+ AS2( pxor xmm##x1, [inputPtr+p1*16])\
+ AS2( pxor xmm##x2, [inputPtr+p2*16])\
+ AS2( pxor xmm##x3, [inputPtr+p3*16])\
+ AS2( add inputPtr, increment*16)\
+ ASC( jmp, labelPrefix##3)\
+ ASL(labelPrefix##7)\
+ AS2( movdqu xmm##t, [inputPtr+p0*16])\
+ AS2( pxor xmm##x0, xmm##t)\
+ AS2( movdqu xmm##t, [inputPtr+p1*16])\
+ AS2( pxor xmm##x1, xmm##t)\
+ AS2( movdqu xmm##t, [inputPtr+p2*16])\
+ AS2( pxor xmm##x2, xmm##t)\
+ AS2( movdqu xmm##t, [inputPtr+p3*16])\
+ AS2( pxor xmm##x3, xmm##t)\
+ AS2( add inputPtr, increment*16)\
+ ASL(labelPrefix##3)\
+ AS2( test outputPtr, 15)\
+ ASC( jnz, labelPrefix##8)\
+ AS2( movdqa [outputPtr+p0*16], xmm##x0)\
+ AS2( movdqa [outputPtr+p1*16], xmm##x1)\
+ AS2( movdqa [outputPtr+p2*16], xmm##x2)\
+ AS2( movdqa [outputPtr+p3*16], xmm##x3)\
+ ASC( jmp, labelPrefix##9)\
+ ASL(labelPrefix##8)\
+ AS2( movdqu [outputPtr+p0*16], xmm##x0)\
+ AS2( movdqu [outputPtr+p1*16], xmm##x1)\
+ AS2( movdqu [outputPtr+p2*16], xmm##x2)\
+ AS2( movdqu [outputPtr+p3*16], xmm##x3)\
+ ASL(labelPrefix##9)\
+ AS2( add outputPtr, increment*16)
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/crc.cpp b/lib/cryptopp/crc.cpp
new file mode 100644
index 000000000..10c25c257
--- /dev/null
+++ b/lib/cryptopp/crc.cpp
@@ -0,0 +1,160 @@
+// crc.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "crc.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/* Table of CRC-32's of all single byte values (made by makecrc.c) */
+const word32 CRC32::m_tab[] = {
+#ifdef IS_LITTLE_ENDIAN
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+#else
+ 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,
+ 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,
+ 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,
+ 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,
+ 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,
+ 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,
+ 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,
+ 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,
+ 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,
+ 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,
+ 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,
+ 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,
+ 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,
+ 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,
+ 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,
+ 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,
+ 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,
+ 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,
+ 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,
+ 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,
+ 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,
+ 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,
+ 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,
+ 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,
+ 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,
+ 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,
+ 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,
+ 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,
+ 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,
+ 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,
+ 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,
+ 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,
+ 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,
+ 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,
+ 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,
+ 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,
+ 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,
+ 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,
+ 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,
+ 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,
+ 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,
+ 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,
+ 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,
+ 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,
+ 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,
+ 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,
+ 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,
+ 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,
+ 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,
+ 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,
+ 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,
+ 0x8def022dL
+#endif
+};
+
+CRC32::CRC32()
+{
+ Reset();
+}
+
+void CRC32::Update(const byte *s, size_t n)
+{
+ word32 crc = m_crc;
+
+ for(; !IsAligned<word32>(s) && n > 0; n--)
+ crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
+
+ while (n >= 4)
+ {
+ crc ^= *(const word32 *)s;
+ crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
+ crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
+ crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
+ crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
+ n -= 4;
+ s += 4;
+ }
+
+ while (n--)
+ crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
+
+ m_crc = crc;
+}
+
+void CRC32::TruncatedFinal(byte *hash, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ m_crc ^= CRC32_NEGL;
+ for (size_t i=0; i<size; i++)
+ hash[i] = GetCrcByte(i);
+
+ Reset();
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/crc.h b/lib/cryptopp/crc.h
new file mode 100644
index 000000000..f75ea384c
--- /dev/null
+++ b/lib/cryptopp/crc.h
@@ -0,0 +1,42 @@
+#ifndef CRYPTOPP_CRC32_H
+#define CRYPTOPP_CRC32_H
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+const word32 CRC32_NEGL = 0xffffffffL;
+
+#ifdef IS_LITTLE_ENDIAN
+#define CRC32_INDEX(c) (c & 0xff)
+#define CRC32_SHIFTED(c) (c >> 8)
+#else
+#define CRC32_INDEX(c) (c >> 24)
+#define CRC32_SHIFTED(c) (c << 8)
+#endif
+
+//! CRC Checksum Calculation
+class CRC32 : public HashTransformation
+{
+public:
+ CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
+ CRC32();
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *hash, size_t size);
+ unsigned int DigestSize() const {return DIGESTSIZE;}
+ static const char * StaticAlgorithmName() {return "CRC32";}
+ std::string AlgorithmName() const {return StaticAlgorithmName();}
+
+ void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
+ byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
+
+private:
+ void Reset() {m_crc = CRC32_NEGL;}
+
+ static const word32 m_tab[256];
+ word32 m_crc;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/cryptlib.cpp b/lib/cryptopp/cryptlib.cpp
new file mode 100644
index 000000000..df138ddb0
--- /dev/null
+++ b/lib/cryptopp/cryptlib.cpp
@@ -0,0 +1,828 @@
+// cryptlib.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cryptlib.h"
+#include "misc.h"
+#include "filters.h"
+#include "algparam.h"
+#include "fips140.h"
+#include "argnames.h"
+#include "fltrimpl.h"
+#include "trdlocal.h"
+#include "osrng.h"
+
+#include <memory>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
+CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2);
+CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4);
+CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
+#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
+#endif
+
+const std::string DEFAULT_CHANNEL;
+const std::string AAD_CHANNEL = "AAD";
+const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL;
+
+class NullNameValuePairs : public NameValuePairs
+{
+public:
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;}
+};
+
+simple_ptr<NullNameValuePairs> s_pNullNameValuePairs(new NullNameValuePairs);
+const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p;
+
+BufferedTransformation & TheBitBucket()
+{
+ static BitBucket bitBucket;
+ return bitBucket;
+}
+
+Algorithm::Algorithm(bool checkSelfTestStatus)
+{
+ if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled())
+ {
+ if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread())
+ throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed.");
+
+ if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED)
+ throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed.");
+ }
+}
+
+void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs &params)
+{
+ this->ThrowIfInvalidKeyLength(length);
+ this->UncheckedSetKey(key, (unsigned int)length, params);
+}
+
+void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds)
+{
+ SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
+}
+
+void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength)
+{
+ SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength)));
+}
+
+void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length)
+{
+ if (!IsValidKeyLength(length))
+ throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length);
+}
+
+void SimpleKeyingInterface::ThrowIfResynchronizable()
+{
+ if (IsResynchronizable())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV");
+}
+
+void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv)
+{
+ if (!iv && IVRequirement() == UNPREDICTABLE_RANDOM_IV)
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV");
+}
+
+size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int size)
+{
+ if (size < 0)
+ return IVSize();
+ else if ((size_t)size < MinIVLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " is less than the minimum of " + IntToString(MinIVLength()));
+ else if ((size_t)size > MaxIVLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " exceeds the maximum of " + IntToString(MaxIVLength()));
+ else
+ return size;
+}
+
+const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size)
+{
+ ConstByteArrayParameter ivWithLength;
+ const byte *iv;
+ bool found = false;
+
+ try {found = params.GetValue(Name::IV(), ivWithLength);}
+ catch (const NameValuePairs::ValueTypeMismatch &) {}
+
+ if (found)
+ {
+ iv = ivWithLength.begin();
+ ThrowIfInvalidIV(iv);
+ size = ThrowIfInvalidIVLength((int)ivWithLength.size());
+ return iv;
+ }
+ else if (params.GetValue(Name::IV(), iv))
+ {
+ ThrowIfInvalidIV(iv);
+ size = IVSize();
+ return iv;
+ }
+ else
+ {
+ ThrowIfResynchronizable();
+ size = 0;
+ return NULL;
+ }
+}
+
+void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV)
+{
+ rng.GenerateBlock(IV, IVSize());
+}
+
+size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
+{
+ size_t blockSize = BlockSize();
+ size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+ size_t xorIncrement = xorBlocks ? blockSize : 0;
+ size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize;
+
+ if (flags & BT_ReverseDirection)
+ {
+ assert(length % blockSize == 0);
+ inBlocks += length - blockSize;
+ xorBlocks += length - blockSize;
+ outBlocks += length - blockSize;
+ inIncrement = 0-inIncrement;
+ xorIncrement = 0-xorIncrement;
+ outIncrement = 0-outIncrement;
+ }
+
+ while (length >= blockSize)
+ {
+ if (flags & BT_XorInput)
+ {
+ xorbuf(outBlocks, xorBlocks, inBlocks, blockSize);
+ ProcessBlock(outBlocks);
+ }
+ else
+ ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
+ if (flags & BT_InBlockIsCounter)
+ const_cast<byte *>(inBlocks)[blockSize-1]++;
+ inBlocks += inIncrement;
+ outBlocks += outIncrement;
+ xorBlocks += xorIncrement;
+ length -= blockSize;
+ }
+
+ return length;
+}
+
+unsigned int BlockTransformation::OptimalDataAlignment() const
+{
+ return GetAlignmentOf<word32>();
+}
+
+unsigned int StreamTransformation::OptimalDataAlignment() const
+{
+ return GetAlignmentOf<word32>();
+}
+
+unsigned int HashTransformation::OptimalDataAlignment() const
+{
+ return GetAlignmentOf<word32>();
+}
+
+void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
+{
+ assert(MinLastBlockSize() == 0); // this function should be overriden otherwise
+
+ if (length == MandatoryBlockSize())
+ ProcessData(outString, inString, length);
+ else if (length != 0)
+ throw NotImplemented(AlgorithmName() + ": this object does't support a special last block");
+}
+
+void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
+{
+ if (headerLength > MaxHeaderLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
+
+ if (messageLength > MaxMessageLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength()));
+
+ if (footerLength > MaxFooterLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
+
+ UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength);
+}
+
+void AuthenticatedSymmetricCipher::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength)
+{
+ Resynchronize(iv, ivLength);
+ SpecifyDataLengths(headerLength, messageLength);
+ Update(header, headerLength);
+ ProcessString(ciphertext, message, messageLength);
+ TruncatedFinal(mac, macSize);
+}
+
+bool AuthenticatedSymmetricCipher::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength)
+{
+ Resynchronize(iv, ivLength);
+ SpecifyDataLengths(headerLength, ciphertextLength);
+ Update(header, headerLength);
+ ProcessString(message, ciphertext, ciphertextLength);
+ return TruncatedVerify(mac, macLength);
+}
+
+unsigned int RandomNumberGenerator::GenerateBit()
+{
+ return GenerateByte() & 1;
+}
+
+byte RandomNumberGenerator::GenerateByte()
+{
+ byte b;
+ GenerateBlock(&b, 1);
+ return b;
+}
+
+word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)
+{
+ word32 range = max-min;
+ const int maxBits = BitPrecision(range);
+
+ word32 value;
+
+ do
+ {
+ GenerateBlock((byte *)&value, sizeof(value));
+ value = Crop(value, maxBits);
+ } while (value > range);
+
+ return value+min;
+}
+
+void RandomNumberGenerator::GenerateBlock(byte *output, size_t size)
+{
+ ArraySink s(output, size);
+ GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size);
+}
+
+void RandomNumberGenerator::DiscardBytes(size_t n)
+{
+ GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n);
+}
+
+void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
+{
+ FixedSizeSecBlock<byte, 256> buffer;
+ while (length)
+ {
+ size_t len = UnsignedMin(buffer.size(), length);
+ GenerateBlock(buffer, len);
+ target.ChannelPut(channel, buffer, len);
+ length -= len;
+ }
+}
+
+//! see NullRNG()
+class ClassNullRNG : public RandomNumberGenerator
+{
+public:
+ std::string AlgorithmName() const {return "NullRNG";}
+ void GenerateBlock(byte *output, size_t size) {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");}
+};
+
+RandomNumberGenerator & NullRNG()
+{
+ static ClassNullRNG s_nullRNG;
+ return s_nullRNG;
+}
+
+bool HashTransformation::TruncatedVerify(const byte *digestIn, size_t digestLength)
+{
+ ThrowIfInvalidTruncatedSize(digestLength);
+ SecByteBlock digest(digestLength);
+ TruncatedFinal(digest, digestLength);
+ return VerifyBufsEqual(digest, digestIn, digestLength);
+}
+
+void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const
+{
+ if (size > DigestSize())
+ throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes");
+}
+
+unsigned int BufferedTransformation::GetMaxWaitObjectCount() const
+{
+ const BufferedTransformation *t = AttachedTransformation();
+ return t ? t->GetMaxWaitObjectCount() : 0;
+}
+
+void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ BufferedTransformation *t = AttachedTransformation();
+ if (t)
+ t->GetWaitObjects(container, callStack); // reduce clutter by not adding to stack here
+}
+
+void BufferedTransformation::Initialize(const NameValuePairs &parameters, int propagation)
+{
+ assert(!AttachedTransformation());
+ IsolatedInitialize(parameters);
+}
+
+bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking)
+{
+ assert(!AttachedTransformation());
+ return IsolatedFlush(hardFlush, blocking);
+}
+
+bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking)
+{
+ assert(!AttachedTransformation());
+ return IsolatedMessageSeriesEnd(blocking);
+}
+
+byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size)
+{
+ if (channel.empty())
+ return CreatePutSpace(size);
+ else
+ throw NoChannelSupport(AlgorithmName());
+}
+
+size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (channel.empty())
+ return Put2(begin, length, messageEnd, blocking);
+ else
+ throw NoChannelSupport(AlgorithmName());
+}
+
+size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (channel.empty())
+ return PutModifiable2(begin, length, messageEnd, blocking);
+ else
+ return ChannelPut2(channel, begin, length, messageEnd, blocking);
+}
+
+bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
+{
+ if (channel.empty())
+ return Flush(completeFlush, propagation, blocking);
+ else
+ throw NoChannelSupport(AlgorithmName());
+}
+
+bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
+{
+ if (channel.empty())
+ return MessageSeriesEnd(propagation, blocking);
+ else
+ throw NoChannelSupport(AlgorithmName());
+}
+
+lword BufferedTransformation::MaxRetrievable() const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->MaxRetrievable();
+ else
+ return CopyTo(TheBitBucket());
+}
+
+bool BufferedTransformation::AnyRetrievable() const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->AnyRetrievable();
+ else
+ {
+ byte b;
+ return Peek(b) != 0;
+ }
+}
+
+size_t BufferedTransformation::Get(byte &outByte)
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->Get(outByte);
+ else
+ return Get(&outByte, 1);
+}
+
+size_t BufferedTransformation::Get(byte *outString, size_t getMax)
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->Get(outString, getMax);
+ else
+ {
+ ArraySink arraySink(outString, getMax);
+ return (size_t)TransferTo(arraySink, getMax);
+ }
+}
+
+size_t BufferedTransformation::Peek(byte &outByte) const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->Peek(outByte);
+ else
+ return Peek(&outByte, 1);
+}
+
+size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->Peek(outString, peekMax);
+ else
+ {
+ ArraySink arraySink(outString, peekMax);
+ return (size_t)CopyTo(arraySink, peekMax);
+ }
+}
+
+lword BufferedTransformation::Skip(lword skipMax)
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->Skip(skipMax);
+ else
+ return TransferTo(TheBitBucket(), skipMax);
+}
+
+lword BufferedTransformation::TotalBytesRetrievable() const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->TotalBytesRetrievable();
+ else
+ return MaxRetrievable();
+}
+
+unsigned int BufferedTransformation::NumberOfMessages() const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->NumberOfMessages();
+ else
+ return CopyMessagesTo(TheBitBucket());
+}
+
+bool BufferedTransformation::AnyMessages() const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->AnyMessages();
+ else
+ return NumberOfMessages() != 0;
+}
+
+bool BufferedTransformation::GetNextMessage()
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->GetNextMessage();
+ else
+ {
+ assert(!AnyMessages());
+ return false;
+ }
+}
+
+unsigned int BufferedTransformation::SkipMessages(unsigned int count)
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->SkipMessages(count);
+ else
+ return TransferMessagesTo(TheBitBucket(), count);
+}
+
+size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking)
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking);
+ else
+ {
+ unsigned int maxMessages = messageCount;
+ for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++)
+ {
+ size_t blockedBytes;
+ lword transferredBytes;
+
+ while (AnyRetrievable())
+ {
+ transferredBytes = LWORD_MAX;
+ blockedBytes = TransferTo2(target, transferredBytes, channel, blocking);
+ if (blockedBytes > 0)
+ return blockedBytes;
+ }
+
+ if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking))
+ return 1;
+
+ bool result = GetNextMessage();
+ assert(result);
+ }
+ return 0;
+ }
+}
+
+unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->CopyMessagesTo(target, count, channel);
+ else
+ return 0;
+}
+
+void BufferedTransformation::SkipAll()
+{
+ if (AttachedTransformation())
+ AttachedTransformation()->SkipAll();
+ else
+ {
+ while (SkipMessages()) {}
+ while (Skip()) {}
+ }
+}
+
+size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking)
+{
+ if (AttachedTransformation())
+ return AttachedTransformation()->TransferAllTo2(target, channel, blocking);
+ else
+ {
+ assert(!NumberOfMessageSeries());
+
+ unsigned int messageCount;
+ do
+ {
+ messageCount = UINT_MAX;
+ size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking);
+ if (blockedBytes)
+ return blockedBytes;
+ }
+ while (messageCount != 0);
+
+ lword byteCount;
+ do
+ {
+ byteCount = ULONG_MAX;
+ size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking);
+ if (blockedBytes)
+ return blockedBytes;
+ }
+ while (byteCount != 0);
+
+ return 0;
+ }
+}
+
+void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const
+{
+ if (AttachedTransformation())
+ AttachedTransformation()->CopyAllTo(target, channel);
+ else
+ {
+ assert(!NumberOfMessageSeries());
+ while (CopyMessagesTo(target, UINT_MAX, channel)) {}
+ }
+}
+
+void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
+{
+ if (AttachedTransformation())
+ AttachedTransformation()->SetRetrievalChannel(channel);
+}
+
+size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking)
+{
+ PutWord(false, order, m_buf, value);
+ return ChannelPut(channel, m_buf, 2, blocking);
+}
+
+size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking)
+{
+ PutWord(false, order, m_buf, value);
+ return ChannelPut(channel, m_buf, 4, blocking);
+}
+
+size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking)
+{
+ return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking);
+}
+
+size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking)
+{
+ return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking);
+}
+
+size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const
+{
+ byte buf[2] = {0, 0};
+ size_t len = Peek(buf, 2);
+
+ if (order)
+ value = (buf[0] << 8) | buf[1];
+ else
+ value = (buf[1] << 8) | buf[0];
+
+ return len;
+}
+
+size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const
+{
+ byte buf[4] = {0, 0, 0, 0};
+ size_t len = Peek(buf, 4);
+
+ if (order)
+ value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3];
+ else
+ value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0];
+
+ return len;
+}
+
+size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order)
+{
+ return (size_t)Skip(PeekWord16(value, order));
+}
+
+size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order)
+{
+ return (size_t)Skip(PeekWord32(value, order));
+}
+
+void BufferedTransformation::Attach(BufferedTransformation *newOut)
+{
+ if (AttachedTransformation() && AttachedTransformation()->Attachable())
+ AttachedTransformation()->Attach(newOut);
+ else
+ Detach(newOut);
+}
+
+void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
+{
+ GenerateRandom(rng, MakeParameters("KeySize", (int)keySize));
+}
+
+class PK_DefaultEncryptionFilter : public Unflushable<Filter>
+{
+public:
+ PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs &parameters)
+ : m_rng(rng), m_encryptor(encryptor), m_parameters(parameters)
+ {
+ Detach(attachment);
+ }
+
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+ {
+ FILTER_BEGIN;
+ m_plaintextQueue.Put(inString, length);
+
+ if (messageEnd)
+ {
+ {
+ size_t plaintextLength;
+ if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength))
+ throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long");
+ size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength);
+
+ SecByteBlock plaintext(plaintextLength);
+ m_plaintextQueue.Get(plaintext, plaintextLength);
+ m_ciphertext.resize(ciphertextLength);
+ m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters);
+ }
+
+ FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd);
+ }
+ FILTER_END_NO_MESSAGE_END;
+ }
+
+ RandomNumberGenerator &m_rng;
+ const PK_Encryptor &m_encryptor;
+ const NameValuePairs &m_parameters;
+ ByteQueue m_plaintextQueue;
+ SecByteBlock m_ciphertext;
+};
+
+BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs &parameters) const
+{
+ return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters);
+}
+
+class PK_DefaultDecryptionFilter : public Unflushable<Filter>
+{
+public:
+ PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs &parameters)
+ : m_rng(rng), m_decryptor(decryptor), m_parameters(parameters)
+ {
+ Detach(attachment);
+ }
+
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+ {
+ FILTER_BEGIN;
+ m_ciphertextQueue.Put(inString, length);
+
+ if (messageEnd)
+ {
+ {
+ size_t ciphertextLength;
+ if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength))
+ throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long");
+ size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength);
+
+ SecByteBlock ciphertext(ciphertextLength);
+ m_ciphertextQueue.Get(ciphertext, ciphertextLength);
+ m_plaintext.resize(maxPlaintextLength);
+ m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters);
+ if (!m_result.isValidCoding)
+ throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext");
+ }
+
+ FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd);
+ }
+ FILTER_END_NO_MESSAGE_END;
+ }
+
+ RandomNumberGenerator &m_rng;
+ const PK_Decryptor &m_decryptor;
+ const NameValuePairs &m_parameters;
+ ByteQueue m_ciphertextQueue;
+ SecByteBlock m_plaintext;
+ DecodingResult m_result;
+};
+
+BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs &parameters) const
+{
+ return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters);
+}
+
+size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const
+{
+ std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
+ return SignAndRestart(rng, *m, signature, false);
+}
+
+size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const
+{
+ std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
+ m->Update(message, messageLen);
+ return SignAndRestart(rng, *m, signature, false);
+}
+
+size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength,
+ const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const
+{
+ std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
+ InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength);
+ m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
+ return SignAndRestart(rng, *m, signature, false);
+}
+
+bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const
+{
+ std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
+ return VerifyAndRestart(*m);
+}
+
+bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLength) const
+{
+ std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
+ InputSignature(*m, signature, signatureLength);
+ m->Update(message, messageLen);
+ return VerifyAndRestart(*m);
+}
+
+DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const
+{
+ std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
+ return RecoverAndRestart(recoveredMessage, *m);
+}
+
+DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage,
+ const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength,
+ const byte *signature, size_t signatureLength) const
+{
+ std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
+ InputSignature(*m, signature, signatureLength);
+ m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
+ return RecoverAndRestart(recoveredMessage, *m);
+}
+
+void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
+{
+ GeneratePrivateKey(rng, privateKey);
+ GeneratePublicKey(rng, privateKey, publicKey);
+}
+
+void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
+{
+ GenerateStaticPrivateKey(rng, privateKey);
+ GenerateStaticPublicKey(rng, privateKey, publicKey);
+}
+
+void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
+{
+ GenerateEphemeralPrivateKey(rng, privateKey);
+ GenerateEphemeralPublicKey(rng, privateKey, publicKey);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/cryptlib.h b/lib/cryptopp/cryptlib.h
new file mode 100644
index 000000000..406872232
--- /dev/null
+++ b/lib/cryptopp/cryptlib.h
@@ -0,0 +1,1655 @@
+// cryptlib.h - written and placed in the public domain by Wei Dai
+/*! \file
+ This file contains the declarations for the abstract base
+ classes that provide a uniform interface to this library.
+*/
+
+/*! \mainpage Crypto++ Library 5.6.2 API Reference
+<dl>
+<dt>Abstract Base Classes<dd>
+ cryptlib.h
+<dt>Authenticated Encryption<dd>
+ AuthenticatedSymmetricCipherDocumentation
+<dt>Symmetric Ciphers<dd>
+ SymmetricCipherDocumentation
+<dt>Hash Functions<dd>
+ SHA1, SHA224, SHA256, SHA384, SHA512, Tiger, Whirlpool, RIPEMD160, RIPEMD320, RIPEMD128, RIPEMD256, Weak1::MD2, Weak1::MD4, Weak1::MD5
+<dt>Non-Cryptographic Checksums<dd>
+ CRC32, Adler32
+<dt>Message Authentication Codes<dd>
+ VMAC, HMAC, CBC_MAC, CMAC, DMAC, TTMAC, GCM (GMAC)
+<dt>Random Number Generators<dd>
+ NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, #DefaultAutoSeededRNG
+<dt>Password-based Cryptography<dd>
+ PasswordBasedKeyDerivationFunction
+<dt>Public Key Cryptosystems<dd>
+ DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES
+<dt>Public Key Signature Schemes<dd>
+ DSA2, GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RSASS_ISO, RabinSS, RWSS, ESIGN
+<dt>Key Agreement<dd>
+ #DH, DH2, #MQV, ECDH, ECMQV, XTR_DH
+<dt>Algebraic Structures<dd>
+ Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver,
+ ModularArithmetic, MontgomeryRepresentation, GFP2_ONB,
+ GF2NP, GF256, GF2_32, EC2N, ECP
+<dt>Secret Sharing and Information Dispersal<dd>
+ SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery
+<dt>Compression<dd>
+ Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor
+<dt>Input Source Classes<dd>
+ StringSource, #ArraySource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource
+<dt>Output Sink Classes<dd>
+ StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink, RandomNumberSink
+<dt>Filter Wrappers<dd>
+ StreamTransformationFilter, HashFilter, HashVerificationFilter, SignerFilter, SignatureVerificationFilter
+<dt>Binary to Text Encoders and Decoders<dd>
+ HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base32Encoder, Base32Decoder
+<dt>Wrappers for OS features<dd>
+ Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer
+<dt>FIPS 140 related<dd>
+ fips140.h
+</dl>
+
+In the DLL version of Crypto++, only the following implementation class are available.
+<dl>
+<dt>Block Ciphers<dd>
+ AES, DES_EDE2, DES_EDE3, SKIPJACK
+<dt>Cipher Modes (replace template parameter BC with one of the block ciphers above)<dd>
+ ECB_Mode\<BC\>, CTR_Mode\<BC\>, CBC_Mode\<BC\>, CFB_FIPS_Mode\<BC\>, OFB_Mode\<BC\>, GCM\<AES\>
+<dt>Hash Functions<dd>
+ SHA1, SHA224, SHA256, SHA384, SHA512
+<dt>Public Key Signature Schemes (replace template parameter H with one of the hash functions above)<dd>
+ RSASS\<PKCS1v15, H\>, RSASS\<PSS, H\>, RSASS_ISO\<H\>, RWSS\<P1363_EMSA2, H\>, DSA, ECDSA\<ECP, H\>, ECDSA\<EC2N, H\>
+<dt>Message Authentication Codes (replace template parameter H with one of the hash functions above)<dd>
+ HMAC\<H\>, CBC_MAC\<DES_EDE2\>, CBC_MAC\<DES_EDE3\>, GCM\<AES\>
+<dt>Random Number Generators<dd>
+ #DefaultAutoSeededRNG (AutoSeededX917RNG\<AES\>)
+<dt>Key Agreement<dd>
+ #DH
+<dt>Public Key Cryptosystems<dd>
+ RSAES\<OAEP\<SHA1\> \>
+</dl>
+
+<p>This reference manual is a work in progress. Some classes are still lacking detailed descriptions.
+<p>Click <a href="CryptoPPRef.zip">here</a> to download a zip archive containing this manual.
+<p>Thanks to Ryan Phillips for providing the Doxygen configuration file
+and getting me started with this manual.
+*/
+
+#ifndef CRYPTOPP_CRYPTLIB_H
+#define CRYPTOPP_CRYPTLIB_H
+
+#include "config.h"
+#include "stdcpp.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// forward declarations
+class Integer;
+class RandomNumberGenerator;
+class BufferedTransformation;
+
+//! used to specify a direction for a cipher to operate in (encrypt or decrypt)
+enum CipherDir {ENCRYPTION, DECRYPTION};
+
+//! used to represent infinite time
+const unsigned long INFINITE_TIME = ULONG_MAX;
+
+// VC60 workaround: using enums as template parameters causes problems
+template <typename ENUM_TYPE, int VALUE>
+struct EnumToType
+{
+ static ENUM_TYPE ToEnum() {return (ENUM_TYPE)VALUE;}
+};
+
+enum ByteOrder {LITTLE_ENDIAN_ORDER = 0, BIG_ENDIAN_ORDER = 1};
+typedef EnumToType<ByteOrder, LITTLE_ENDIAN_ORDER> LittleEndian;
+typedef EnumToType<ByteOrder, BIG_ENDIAN_ORDER> BigEndian;
+
+//! base class for all exceptions thrown by Crypto++
+class CRYPTOPP_DLL Exception : public std::exception
+{
+public:
+ //! error types
+ enum ErrorType {
+ //! a method is not implemented
+ NOT_IMPLEMENTED,
+ //! invalid function argument
+ INVALID_ARGUMENT,
+ //! BufferedTransformation received a Flush(true) signal but can't flush buffers
+ CANNOT_FLUSH,
+ //! data integerity check (such as CRC or MAC) failed
+ DATA_INTEGRITY_CHECK_FAILED,
+ //! received input data that doesn't conform to expected format
+ INVALID_DATA_FORMAT,
+ //! error reading from input device or writing to output device
+ IO_ERROR,
+ //! some error not belong to any of the above categories
+ OTHER_ERROR
+ };
+
+ explicit Exception(ErrorType errorType, const std::string &s) : m_errorType(errorType), m_what(s) {}
+ virtual ~Exception() throw() {}
+ const char *what() const throw() {return (m_what.c_str());}
+ const std::string &GetWhat() const {return m_what;}
+ void SetWhat(const std::string &s) {m_what = s;}
+ ErrorType GetErrorType() const {return m_errorType;}
+ void SetErrorType(ErrorType errorType) {m_errorType = errorType;}
+
+private:
+ ErrorType m_errorType;
+ std::string m_what;
+};
+
+//! exception thrown when an invalid argument is detected
+class CRYPTOPP_DLL InvalidArgument : public Exception
+{
+public:
+ explicit InvalidArgument(const std::string &s) : Exception(INVALID_ARGUMENT, s) {}
+};
+
+//! exception thrown when input data is received that doesn't conform to expected format
+class CRYPTOPP_DLL InvalidDataFormat : public Exception
+{
+public:
+ explicit InvalidDataFormat(const std::string &s) : Exception(INVALID_DATA_FORMAT, s) {}
+};
+
+//! exception thrown by decryption filters when trying to decrypt an invalid ciphertext
+class CRYPTOPP_DLL InvalidCiphertext : public InvalidDataFormat
+{
+public:
+ explicit InvalidCiphertext(const std::string &s) : InvalidDataFormat(s) {}
+};
+
+//! exception thrown by a class if a non-implemented method is called
+class CRYPTOPP_DLL NotImplemented : public Exception
+{
+public:
+ explicit NotImplemented(const std::string &s) : Exception(NOT_IMPLEMENTED, s) {}
+};
+
+//! exception thrown by a class when Flush(true) is called but it can't completely flush its buffers
+class CRYPTOPP_DLL CannotFlush : public Exception
+{
+public:
+ explicit CannotFlush(const std::string &s) : Exception(CANNOT_FLUSH, s) {}
+};
+
+//! error reported by the operating system
+class CRYPTOPP_DLL OS_Error : public Exception
+{
+public:
+ OS_Error(ErrorType errorType, const std::string &s, const std::string& operation, int errorCode)
+ : Exception(errorType, s), m_operation(operation), m_errorCode(errorCode) {}
+ ~OS_Error() throw() {}
+
+ // the operating system API that reported the error
+ const std::string & GetOperation() const {return m_operation;}
+ // the error code return by the operating system
+ int GetErrorCode() const {return m_errorCode;}
+
+protected:
+ std::string m_operation;
+ int m_errorCode;
+};
+
+//! used to return decoding results
+struct CRYPTOPP_DLL DecodingResult
+{
+ explicit DecodingResult() : isValidCoding(false), messageLength(0) {}
+ explicit DecodingResult(size_t len) : isValidCoding(true), messageLength(len) {}
+
+ bool operator==(const DecodingResult &rhs) const {return isValidCoding == rhs.isValidCoding && messageLength == rhs.messageLength;}
+ bool operator!=(const DecodingResult &rhs) const {return !operator==(rhs);}
+
+ bool isValidCoding;
+ size_t messageLength;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ operator size_t() const {return isValidCoding ? messageLength : 0;}
+#endif
+};
+
+//! interface for retrieving values given their names
+/*! \note This class is used to safely pass a variable number of arbitrarily typed arguments to functions
+ and to read values from keys and crypto parameters.
+ \note To obtain an object that implements NameValuePairs for the purpose of parameter
+ passing, use the MakeParameters() function.
+ \note To get a value from NameValuePairs, you need to know the name and the type of the value.
+ Call GetValueNames() on a NameValuePairs object to obtain a list of value names that it supports.
+ Then look at the Name namespace documentation to see what the type of each value is, or
+ alternatively, call GetIntValue() with the value name, and if the type is not int, a
+ ValueTypeMismatch exception will be thrown and you can get the actual type from the exception object.
+*/
+class CRYPTOPP_NO_VTABLE NameValuePairs
+{
+public:
+ virtual ~NameValuePairs() {}
+
+ //! exception thrown when trying to retrieve a value using a different type than expected
+ class CRYPTOPP_DLL ValueTypeMismatch : public InvalidArgument
+ {
+ public:
+ ValueTypeMismatch(const std::string &name, const std::type_info &stored, const std::type_info &retrieving)
+ : InvalidArgument("NameValuePairs: type mismatch for '" + name + "', stored '" + stored.name() + "', trying to retrieve '" + retrieving.name() + "'")
+ , m_stored(stored), m_retrieving(retrieving) {}
+
+ const std::type_info & GetStoredTypeInfo() const {return m_stored;}
+ const std::type_info & GetRetrievingTypeInfo() const {return m_retrieving;}
+
+ private:
+ const std::type_info &m_stored;
+ const std::type_info &m_retrieving;
+ };
+
+ //! get a copy of this object or a subobject of it
+ template <class T>
+ bool GetThisObject(T &object) const
+ {
+ return GetValue((std::string("ThisObject:")+typeid(T).name()).c_str(), object);
+ }
+
+ //! get a pointer to this object, as a pointer to T
+ template <class T>
+ bool GetThisPointer(T *&p) const
+ {
+ return GetValue((std::string("ThisPointer:")+typeid(T).name()).c_str(), p);
+ }
+
+ //! get a named value, returns true if the name exists
+ template <class T>
+ bool GetValue(const char *name, T &value) const
+ {
+ return GetVoidValue(name, typeid(T), &value);
+ }
+
+ //! get a named value, returns the default if the name doesn't exist
+ template <class T>
+ T GetValueWithDefault(const char *name, T defaultValue) const
+ {
+ GetValue(name, defaultValue);
+ return defaultValue;
+ }
+
+ //! get a list of value names that can be retrieved
+ CRYPTOPP_DLL std::string GetValueNames() const
+ {std::string result; GetValue("ValueNames", result); return result;}
+
+ //! get a named value with type int
+ /*! used to ensure we don't accidentally try to get an unsigned int
+ or some other type when we mean int (which is the most common case) */
+ CRYPTOPP_DLL bool GetIntValue(const char *name, int &value) const
+ {return GetValue(name, value);}
+
+ //! get a named value with type int, with default
+ CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
+ {return GetValueWithDefault(name, defaultValue);}
+
+ //! used by derived classes to check for type mismatch
+ CRYPTOPP_DLL static void CRYPTOPP_API ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving)
+ {if (stored != retrieving) throw ValueTypeMismatch(name, stored, retrieving);}
+
+ template <class T>
+ void GetRequiredParameter(const char *className, const char *name, T &value) const
+ {
+ if (!GetValue(name, value))
+ throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'");
+ }
+
+ CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const
+ {
+ if (!GetIntValue(name, value))
+ throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'");
+ }
+
+ //! to be implemented by derived classes, users should use one of the above functions instead
+ CRYPTOPP_DLL virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
+};
+
+//! namespace containing value name definitions
+/*! value names, types and semantics:
+
+ ThisObject:ClassName (ClassName, copy of this object or a subobject)
+ ThisPointer:ClassName (const ClassName *, pointer to this object or a subobject)
+*/
+DOCUMENTED_NAMESPACE_BEGIN(Name)
+// more names defined in argnames.h
+DOCUMENTED_NAMESPACE_END
+
+//! empty set of name-value pairs
+extern CRYPTOPP_DLL const NameValuePairs &g_nullNameValuePairs;
+
+// ********************************************************
+
+//! interface for cloning objects, this is not implemented by most classes yet
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Clonable
+{
+public:
+ virtual ~Clonable() {}
+ //! this is not implemented by most classes yet
+ virtual Clonable* Clone() const {throw NotImplemented("Clone() is not implemented yet.");} // TODO: make this =0
+};
+
+//! interface for all crypto algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Algorithm : public Clonable
+{
+public:
+ /*! When FIPS 140-2 compliance is enabled and checkSelfTestStatus == true,
+ this constructor throws SelfTestFailure if the self test hasn't been run or fails. */
+ Algorithm(bool checkSelfTestStatus = true);
+ //! returns name of this algorithm, not universally implemented yet
+ virtual std::string AlgorithmName() const {return "unknown";}
+};
+
+//! keying interface for crypto algorithms that take byte strings as keys
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface
+{
+public:
+ virtual ~SimpleKeyingInterface() {}
+
+ //! returns smallest valid key length in bytes */
+ virtual size_t MinKeyLength() const =0;
+ //! returns largest valid key length in bytes */
+ virtual size_t MaxKeyLength() const =0;
+ //! returns default (recommended) key length in bytes */
+ virtual size_t DefaultKeyLength() const =0;
+
+ //! returns the smallest valid key length in bytes that is >= min(n, GetMaxKeyLength())
+ virtual size_t GetValidKeyLength(size_t n) const =0;
+
+ //! returns whether n is a valid key length
+ virtual bool IsValidKeyLength(size_t n) const
+ {return n == GetValidKeyLength(n);}
+
+ //! set or reset the key of this object
+ /*! \param params is used to specify Rounds, BlockSize, etc. */
+ virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs);
+
+ //! calls SetKey() with an NameValuePairs object that just specifies "Rounds"
+ void SetKeyWithRounds(const byte *key, size_t length, int rounds);
+
+ //! calls SetKey() with an NameValuePairs object that just specifies "IV"
+ void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength);
+
+ //! calls SetKey() with an NameValuePairs object that just specifies "IV"
+ void SetKeyWithIV(const byte *key, size_t length, const byte *iv)
+ {SetKeyWithIV(key, length, iv, IVSize());}
+
+ enum IV_Requirement {UNIQUE_IV = 0, RANDOM_IV, UNPREDICTABLE_RANDOM_IV, INTERNALLY_GENERATED_IV, NOT_RESYNCHRONIZABLE};
+ //! returns the minimal requirement for secure IVs
+ virtual IV_Requirement IVRequirement() const =0;
+
+ //! returns whether this object can be resynchronized (i.e. supports initialization vectors)
+ /*! If this function returns true, and no IV is passed to SetKey() and CanUseStructuredIVs()==true, an IV of all 0's will be assumed. */
+ bool IsResynchronizable() const {return IVRequirement() < NOT_RESYNCHRONIZABLE;}
+ //! returns whether this object can use random IVs (in addition to ones returned by GetNextIV)
+ bool CanUseRandomIVs() const {return IVRequirement() <= UNPREDICTABLE_RANDOM_IV;}
+ //! returns whether this object can use random but possibly predictable IVs (in addition to ones returned by GetNextIV)
+ bool CanUsePredictableIVs() const {return IVRequirement() <= RANDOM_IV;}
+ //! returns whether this object can use structured IVs, for example a counter (in addition to ones returned by GetNextIV)
+ bool CanUseStructuredIVs() const {return IVRequirement() <= UNIQUE_IV;}
+
+ virtual unsigned int IVSize() const {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
+ //! returns default length of IVs accepted by this object
+ unsigned int DefaultIVLength() const {return IVSize();}
+ //! returns minimal length of IVs accepted by this object
+ virtual unsigned int MinIVLength() const {return IVSize();}
+ //! returns maximal length of IVs accepted by this object
+ virtual unsigned int MaxIVLength() const {return IVSize();}
+ //! resynchronize with an IV. ivLength=-1 means use IVSize()
+ virtual void Resynchronize(const byte *iv, int ivLength=-1) {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
+ //! get a secure IV for the next message
+ /*! This method should be called after you finish encrypting one message and are ready to start the next one.
+ After calling it, you must call SetKey() or Resynchronize() before using this object again.
+ This method is not implemented on decryption objects. */
+ virtual void GetNextIV(RandomNumberGenerator &rng, byte *IV);
+
+protected:
+ virtual const Algorithm & GetAlgorithm() const =0;
+ virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params) =0;
+
+ void ThrowIfInvalidKeyLength(size_t length);
+ void ThrowIfResynchronizable(); // to be called when no IV is passed
+ void ThrowIfInvalidIV(const byte *iv); // check for NULL IV if it can't be used
+ size_t ThrowIfInvalidIVLength(int size);
+ const byte * GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size);
+ inline void AssertValidKeyLength(size_t length) const
+ {assert(IsValidKeyLength(length));}
+};
+
+//! interface for the data processing part of block ciphers
+
+/*! Classes derived from BlockTransformation are block ciphers
+ in ECB mode (for example the DES::Encryption class), which are stateless.
+ These classes should not be used directly, but only in combination with
+ a mode class (see CipherModeDocumentation in modes.h).
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockTransformation : public Algorithm
+{
+public:
+ //! encrypt or decrypt inBlock, xor with xorBlock, and write to outBlock
+ virtual void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const =0;
+
+ //! encrypt or decrypt one block
+ /*! \pre size of inBlock and outBlock == BlockSize() */
+ void ProcessBlock(const byte *inBlock, byte *outBlock) const
+ {ProcessAndXorBlock(inBlock, NULL, outBlock);}
+
+ //! encrypt or decrypt one block in place
+ void ProcessBlock(byte *inoutBlock) const
+ {ProcessAndXorBlock(inoutBlock, NULL, inoutBlock);}
+
+ //! block size of the cipher in bytes
+ virtual unsigned int BlockSize() const =0;
+
+ //! returns how inputs and outputs should be aligned for optimal performance
+ virtual unsigned int OptimalDataAlignment() const;
+
+ //! returns true if this is a permutation (i.e. there is an inverse transformation)
+ virtual bool IsPermutation() const {return true;}
+
+ //! returns true if this is an encryption object
+ virtual bool IsForwardTransformation() const =0;
+
+ //! return number of blocks that can be processed in parallel, for bit-slicing implementations
+ virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;}
+
+ enum {BT_InBlockIsCounter=1, BT_DontIncrementInOutPointers=2, BT_XorInput=4, BT_ReverseDirection=8, BT_AllowParallel=16} FlagsForAdvancedProcessBlocks;
+
+ //! encrypt and xor blocks according to flags (see FlagsForAdvancedProcessBlocks)
+ /*! /note If BT_InBlockIsCounter is set, last byte of inBlocks may be modified. */
+ virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+
+ inline CipherDir GetCipherDirection() const {return IsForwardTransformation() ? ENCRYPTION : DECRYPTION;}
+};
+
+//! interface for the data processing part of stream ciphers
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE StreamTransformation : public Algorithm
+{
+public:
+ //! return a reference to this object, useful for passing a temporary object to a function that takes a non-const reference
+ StreamTransformation& Ref() {return *this;}
+
+ //! returns block size, if input must be processed in blocks, otherwise 1
+ virtual unsigned int MandatoryBlockSize() const {return 1;}
+
+ //! returns the input block size that is most efficient for this cipher
+ /*! \note optimal input length is n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n > 0 */
+ virtual unsigned int OptimalBlockSize() const {return MandatoryBlockSize();}
+ //! returns how much of the current block is used up
+ virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;}
+
+ //! returns how input should be aligned for optimal performance
+ virtual unsigned int OptimalDataAlignment() const;
+
+ //! encrypt or decrypt an array of bytes of specified length
+ /*! \note either inString == outString, or they don't overlap */
+ virtual void ProcessData(byte *outString, const byte *inString, size_t length) =0;
+
+ //! for ciphers where the last block of data is special, encrypt or decrypt the last block of data
+ /*! For now the only use of this function is for CBC-CTS mode. */
+ virtual void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
+ //! returns the minimum size of the last block, 0 indicating the last block is not special
+ virtual unsigned int MinLastBlockSize() const {return 0;}
+
+ //! same as ProcessData(inoutString, inoutString, length)
+ inline void ProcessString(byte *inoutString, size_t length)
+ {ProcessData(inoutString, inoutString, length);}
+ //! same as ProcessData(outString, inString, length)
+ inline void ProcessString(byte *outString, const byte *inString, size_t length)
+ {ProcessData(outString, inString, length);}
+ //! implemented as {ProcessData(&input, &input, 1); return input;}
+ inline byte ProcessByte(byte input)
+ {ProcessData(&input, &input, 1); return input;}
+
+ //! returns whether this cipher supports random access
+ virtual bool IsRandomAccess() const =0;
+ //! for random access ciphers, seek to an absolute position
+ virtual void Seek(lword n)
+ {
+ assert(!IsRandomAccess());
+ throw NotImplemented("StreamTransformation: this object doesn't support random access");
+ }
+
+ //! returns whether this transformation is self-inverting (e.g. xor with a keystream)
+ virtual bool IsSelfInverting() const =0;
+ //! returns whether this is an encryption object
+ virtual bool IsForwardTransformation() const =0;
+};
+
+//! interface for hash functions and data processing part of MACs
+
+/*! HashTransformation objects are stateful. They are created in an initial state,
+ change state as Update() is called, and return to the initial
+ state when Final() is called. This interface allows a large message to
+ be hashed in pieces by calling Update() on each piece followed by
+ calling Final().
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HashTransformation : public Algorithm
+{
+public:
+ //! return a reference to this object, useful for passing a temporary object to a function that takes a non-const reference
+ HashTransformation& Ref() {return *this;}
+
+ //! process more input
+ virtual void Update(const byte *input, size_t length) =0;
+
+ //! request space to write input into
+ virtual byte * CreateUpdateSpace(size_t &size) {size=0; return NULL;}
+
+ //! compute hash for current message, then restart for a new message
+ /*! \pre size of digest == DigestSize(). */
+ virtual void Final(byte *digest)
+ {TruncatedFinal(digest, DigestSize());}
+
+ //! discard the current state, and restart with a new message
+ virtual void Restart()
+ {TruncatedFinal(NULL, 0);}
+
+ //! size of the hash/digest/MAC returned by Final()
+ virtual unsigned int DigestSize() const =0;
+
+ //! same as DigestSize()
+ unsigned int TagSize() const {return DigestSize();}
+
+
+ //! block size of underlying compression function, or 0 if not block based
+ virtual unsigned int BlockSize() const {return 0;}
+
+ //! input to Update() should have length a multiple of this for optimal speed
+ virtual unsigned int OptimalBlockSize() const {return 1;}
+
+ //! returns how input should be aligned for optimal performance
+ virtual unsigned int OptimalDataAlignment() const;
+
+ //! use this if your input is in one piece and you don't want to call Update() and Final() separately
+ virtual void CalculateDigest(byte *digest, const byte *input, size_t length)
+ {Update(input, length); Final(digest);}
+
+ //! verify that digest is a valid digest for the current message, then reinitialize the object
+ /*! Default implementation is to call Final() and do a bitwise comparison
+ between its output and digest. */
+ virtual bool Verify(const byte *digest)
+ {return TruncatedVerify(digest, DigestSize());}
+
+ //! use this if your input is in one piece and you don't want to call Update() and Verify() separately
+ virtual bool VerifyDigest(const byte *digest, const byte *input, size_t length)
+ {Update(input, length); return Verify(digest);}
+
+ //! truncated version of Final()
+ virtual void TruncatedFinal(byte *digest, size_t digestSize) =0;
+
+ //! truncated version of CalculateDigest()
+ virtual void CalculateTruncatedDigest(byte *digest, size_t digestSize, const byte *input, size_t length)
+ {Update(input, length); TruncatedFinal(digest, digestSize);}
+
+ //! truncated version of Verify()
+ virtual bool TruncatedVerify(const byte *digest, size_t digestLength);
+
+ //! truncated version of VerifyDigest()
+ virtual bool VerifyTruncatedDigest(const byte *digest, size_t digestLength, const byte *input, size_t length)
+ {Update(input, length); return TruncatedVerify(digest, digestLength);}
+
+protected:
+ void ThrowIfInvalidTruncatedSize(size_t size) const;
+};
+
+typedef HashTransformation HashFunction;
+
+//! interface for one direction (encryption or decryption) of a block cipher
+/*! \note These objects usually should not be used directly. See BlockTransformation for more details. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockCipher : public SimpleKeyingInterface, public BlockTransformation
+{
+protected:
+ const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for one direction (encryption or decryption) of a stream cipher or cipher mode
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SymmetricCipher : public SimpleKeyingInterface, public StreamTransformation
+{
+protected:
+ const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for message authentication codes
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE MessageAuthenticationCode : public SimpleKeyingInterface, public HashTransformation
+{
+protected:
+ const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for for one direction (encryption or decryption) of a stream cipher or block cipher mode with authentication
+/*! The StreamTransformation part of this interface is used to encrypt/decrypt the data, and the MessageAuthenticationCode part of this
+ interface is used to input additional authenticated data (AAD, which is MAC'ed but not encrypted), and to generate/verify the MAC. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipher : public MessageAuthenticationCode, public StreamTransformation
+{
+public:
+ //! this indicates that a member function was called in the wrong state, for example trying to encrypt a message before having set the key or IV
+ class BadState : public Exception
+ {
+ public:
+ explicit BadState(const std::string &name, const char *message) : Exception(OTHER_ERROR, name + ": " + message) {}
+ explicit BadState(const std::string &name, const char *function, const char *state) : Exception(OTHER_ERROR, name + ": " + function + " was called before " + state) {}
+ };
+
+ //! the maximum length of AAD that can be input before the encrypted data
+ virtual lword MaxHeaderLength() const =0;
+ //! the maximum length of encrypted data
+ virtual lword MaxMessageLength() const =0;
+ //! the maximum length of AAD that can be input after the encrypted data
+ virtual lword MaxFooterLength() const {return 0;}
+ //! if this function returns true, SpecifyDataLengths() must be called before attempting to input data
+ /*! This is the case for some schemes, such as CCM. */
+ virtual bool NeedsPrespecifiedDataLengths() const {return false;}
+ //! this function only needs to be called if NeedsPrespecifiedDataLengths() returns true
+ void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0);
+ //! encrypt and generate MAC in one call. will truncate MAC if macSize < TagSize()
+ virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength);
+ //! decrypt and verify MAC in one call, returning true iff MAC is valid. will assume MAC is truncated if macLength < TagSize()
+ virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength);
+
+ // redeclare this to avoid compiler ambiguity errors
+ virtual std::string AlgorithmName() const =0;
+
+protected:
+ const Algorithm & GetAlgorithm() const {return *static_cast<const MessageAuthenticationCode *>(this);}
+ virtual void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) {}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef SymmetricCipher StreamCipher;
+#endif
+
+//! interface for random number generators
+/*! All return values are uniformly distributed over the range specified.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm
+{
+public:
+ //! update RNG state with additional unpredictable values
+ virtual void IncorporateEntropy(const byte *input, size_t length) {throw NotImplemented("RandomNumberGenerator: IncorporateEntropy not implemented");}
+
+ //! returns true if IncorporateEntropy is implemented
+ virtual bool CanIncorporateEntropy() const {return false;}
+
+ //! generate new random byte and return it
+ virtual byte GenerateByte();
+
+ //! generate new random bit and return it
+ /*! Default implementation is to call GenerateByte() and return its lowest bit. */
+ virtual unsigned int GenerateBit();
+
+ //! generate a random 32 bit word in the range min to max, inclusive
+ virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL);
+
+ //! generate random array of bytes
+ virtual void GenerateBlock(byte *output, size_t size);
+
+ //! generate and discard n bytes
+ virtual void DiscardBytes(size_t n);
+
+ //! generate random bytes as input to a BufferedTransformation
+ virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length);
+
+ //! randomly shuffle the specified array, resulting permutation is uniformly distributed
+ template <class IT> void Shuffle(IT begin, IT end)
+ {
+ for (; begin != end; ++begin)
+ std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1));
+ }
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ byte GetByte() {return GenerateByte();}
+ unsigned int GetBit() {return GenerateBit();}
+ word32 GetLong(word32 a=0, word32 b=0xffffffffL) {return GenerateWord32(a, b);}
+ word16 GetShort(word16 a=0, word16 b=0xffff) {return (word16)GenerateWord32(a, b);}
+ void GetBlock(byte *output, size_t size) {GenerateBlock(output, size);}
+#endif
+};
+
+//! returns a reference that can be passed to functions that ask for a RNG but doesn't actually use it
+CRYPTOPP_DLL RandomNumberGenerator & CRYPTOPP_API NullRNG();
+
+class WaitObjectContainer;
+class CallStack;
+
+//! interface for objects that you can wait for
+
+class CRYPTOPP_NO_VTABLE Waitable
+{
+public:
+ virtual ~Waitable() {}
+
+ //! maximum number of wait objects that this object can return
+ virtual unsigned int GetMaxWaitObjectCount() const =0;
+ //! put wait objects into container
+ /*! \param callStack is used for tracing no wait loops, example:
+ something.GetWaitObjects(c, CallStack("my func after X", 0));
+ - or in an outer GetWaitObjects() method that itself takes a callStack parameter:
+ innerThing.GetWaitObjects(c, CallStack("MyClass::GetWaitObjects at X", &callStack)); */
+ virtual void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) =0;
+ //! wait on this object
+ /*! same as creating an empty container, calling GetWaitObjects(), and calling Wait() on the container */
+ bool Wait(unsigned long milliseconds, CallStack const& callStack);
+};
+
+//! the default channel for BufferedTransformation, equal to the empty string
+extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
+
+//! channel for additional authenticated data, equal to "AAD"
+extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
+
+//! interface for buffered transformations
+
+/*! BufferedTransformation is a generalization of BlockTransformation,
+ StreamTransformation, and HashTransformation.
+
+ A buffered transformation is an object that takes a stream of bytes
+ as input (this may be done in stages), does some computation on them, and
+ then places the result into an internal buffer for later retrieval. Any
+ partial result already in the output buffer is not modified by further
+ input.
+
+ If a method takes a "blocking" parameter, and you
+ pass "false" for it, the method will return before all input has been processed if
+ the input cannot be processed without waiting (for network buffers to become available, for example).
+ In this case the method will return true
+ or a non-zero integer value. When this happens you must continue to call the method with the same
+ parameters until it returns false or zero, before calling any other method on it or
+ attached BufferedTransformation. The integer return value in this case is approximately
+ the number of bytes left to be processed, and can be used to implement a progress bar.
+
+ For functions that take a "propagation" parameter, propagation != 0 means pass on the signal to attached
+ BufferedTransformation objects, with propagation decremented at each step until it reaches 0.
+ -1 means unlimited propagation.
+
+ \nosubgrouping
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable
+{
+public:
+ // placed up here for CW8
+ static const std::string &NULL_CHANNEL; // same as DEFAULT_CHANNEL, for backwards compatibility
+
+ BufferedTransformation() : Algorithm(false) {}
+
+ //! return a reference to this object, useful for passing a temporary object to a function that takes a non-const reference
+ BufferedTransformation& Ref() {return *this;}
+
+ //! \name INPUT
+ //@{
+ //! input a byte for processing
+ size_t Put(byte inByte, bool blocking=true)
+ {return Put(&inByte, 1, blocking);}
+ //! input multiple bytes
+ size_t Put(const byte *inString, size_t length, bool blocking=true)
+ {return Put2(inString, length, 0, blocking);}
+
+ //! input a 16-bit word
+ size_t PutWord16(word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+ //! input a 32-bit word
+ size_t PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+
+ //! request space which can be written into by the caller, and then used as input to Put()
+ /*! \param size is requested size (as a hint) for input, and size of the returned space for output */
+ /*! \note The purpose of this method is to help avoid doing extra memory allocations. */
+ virtual byte * CreatePutSpace(size_t &size) {size=0; return NULL;}
+
+ virtual bool CanModifyInput() const {return false;}
+
+ //! input multiple bytes that may be modified by callee
+ size_t PutModifiable(byte *inString, size_t length, bool blocking=true)
+ {return PutModifiable2(inString, length, 0, blocking);}
+
+ bool MessageEnd(int propagation=-1, bool blocking=true)
+ {return !!Put2(NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);}
+ size_t PutMessageEnd(const byte *inString, size_t length, int propagation=-1, bool blocking=true)
+ {return Put2(inString, length, propagation < 0 ? -1 : propagation+1, blocking);}
+
+ //! input multiple bytes for blocking or non-blocking processing
+ /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */
+ virtual size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) =0;
+ //! input multiple bytes that may be modified by callee for blocking or non-blocking processing
+ /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */
+ virtual size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
+ {return Put2(inString, length, messageEnd, blocking);}
+
+ //! thrown by objects that have not implemented nonblocking input processing
+ struct BlockingInputOnly : public NotImplemented
+ {BlockingInputOnly(const std::string &s) : NotImplemented(s + ": Nonblocking input is not implemented by this object.") {}};
+ //@}
+
+ //! \name WAITING
+ //@{
+ unsigned int GetMaxWaitObjectCount() const;
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+ //@}
+
+ //! \name SIGNALS
+ //@{
+ virtual void IsolatedInitialize(const NameValuePairs &parameters) {throw NotImplemented("BufferedTransformation: this object can't be reinitialized");}
+ virtual bool IsolatedFlush(bool hardFlush, bool blocking) =0;
+ virtual bool IsolatedMessageSeriesEnd(bool blocking) {return false;}
+
+ //! initialize or reinitialize this object
+ virtual void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1);
+ //! flush buffered input and/or output
+ /*! \param hardFlush is used to indicate whether all data should be flushed
+ \note Hard flushes must be used with care. It means try to process and output everything, even if
+ there may not be enough data to complete the action. For example, hard flushing a HexDecoder would
+ cause an error if you do it after inputing an odd number of hex encoded characters.
+ For some types of filters, for example ZlibDecompressor, hard flushes can only
+ be done at "synchronization points". These synchronization points are positions in the data
+ stream that are created by hard flushes on the corresponding reverse filters, in this
+ example ZlibCompressor. This is useful when zlib compressed data is moved across a
+ network in packets and compression state is preserved across packets, as in the ssh2 protocol.
+ */
+ virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
+ //! mark end of a series of messages
+ /*! There should be a MessageEnd immediately before MessageSeriesEnd. */
+ virtual bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
+
+ //! set propagation of automatically generated and transferred signals
+ /*! propagation == 0 means do not automaticly generate signals */
+ virtual void SetAutoSignalPropagation(int propagation) {}
+
+ //!
+ virtual int GetAutoSignalPropagation() const {return 0;}
+public:
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ void Close() {MessageEnd();}
+#endif
+ //@}
+
+ //! \name RETRIEVAL OF ONE MESSAGE
+ //@{
+ //! returns number of bytes that is currently ready for retrieval
+ /*! All retrieval functions return the actual number of bytes
+ retrieved, which is the lesser of the request number and
+ MaxRetrievable(). */
+ virtual lword MaxRetrievable() const;
+
+ //! returns whether any bytes are currently ready for retrieval
+ virtual bool AnyRetrievable() const;
+
+ //! try to retrieve a single byte
+ virtual size_t Get(byte &outByte);
+ //! try to retrieve multiple bytes
+ virtual size_t Get(byte *outString, size_t getMax);
+
+ //! peek at the next byte without removing it from the output buffer
+ virtual size_t Peek(byte &outByte) const;
+ //! peek at multiple bytes without removing them from the output buffer
+ virtual size_t Peek(byte *outString, size_t peekMax) const;
+
+ //! try to retrieve a 16-bit word
+ size_t GetWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER);
+ //! try to retrieve a 32-bit word
+ size_t GetWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER);
+
+ //! try to peek at a 16-bit word
+ size_t PeekWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER) const;
+ //! try to peek at a 32-bit word
+ size_t PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER) const;
+
+ //! move transferMax bytes of the buffered output to target as input
+ lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL)
+ {TransferTo2(target, transferMax, channel); return transferMax;}
+
+ //! discard skipMax bytes from the output buffer
+ virtual lword Skip(lword skipMax=LWORD_MAX);
+
+ //! copy copyMax bytes of the buffered output to target as input
+ lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+ {return CopyRangeTo(target, 0, copyMax, channel);}
+
+ //! copy copyMax bytes of the buffered output, starting at position (relative to current position), to target as input
+ lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+ {lword i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ unsigned long MaxRetrieveable() const {return MaxRetrievable();}
+#endif
+ //@}
+
+ //! \name RETRIEVAL OF MULTIPLE MESSAGES
+ //@{
+ //!
+ virtual lword TotalBytesRetrievable() const;
+ //! number of times MessageEnd() has been received minus messages retrieved or skipped
+ virtual unsigned int NumberOfMessages() const;
+ //! returns true if NumberOfMessages() > 0
+ virtual bool AnyMessages() const;
+ //! start retrieving the next message
+ /*!
+ Returns false if no more messages exist or this message
+ is not completely retrieved.
+ */
+ virtual bool GetNextMessage();
+ //! skip count number of messages
+ virtual unsigned int SkipMessages(unsigned int count=UINT_MAX);
+ //!
+ unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL)
+ {TransferMessagesTo2(target, count, channel); return count;}
+ //!
+ unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
+
+ //!
+ virtual void SkipAll();
+ //!
+ void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
+ {TransferAllTo2(target, channel);}
+ //!
+ void CopyAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const;
+
+ virtual bool GetNextMessageSeries() {return false;}
+ virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();}
+ virtual unsigned int NumberOfMessageSeries() const {return 0;}
+ //@}
+
+ //! \name NON-BLOCKING TRANSFER OF OUTPUT
+ //@{
+ //! upon return, byteCount contains number of bytes that have finished being transfered, and returns the number of bytes left in the current transfer block
+ virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) =0;
+ //! upon return, begin contains the start position of data yet to be finished copying, and returns the number of bytes left in the current transfer block
+ virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0;
+ //! upon return, messageCount contains number of messages that have finished being transfered, and returns the number of bytes left in the current transfer block
+ size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ //! returns the number of bytes left in the current transfer block
+ size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ //@}
+
+ //! \name CHANNELS
+ //@{
+ struct NoChannelSupport : public NotImplemented
+ {NoChannelSupport(const std::string &name) : NotImplemented(name + ": this object doesn't support multiple channels") {}};
+ struct InvalidChannelName : public InvalidArgument
+ {InvalidChannelName(const std::string &name, const std::string &channel) : InvalidArgument(name + ": unexpected channel name \"" + channel + "\"") {}};
+
+ size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
+ {return ChannelPut(channel, &inByte, 1, blocking);}
+ size_t ChannelPut(const std::string &channel, const byte *inString, size_t length, bool blocking=true)
+ {return ChannelPut2(channel, inString, length, 0, blocking);}
+
+ size_t ChannelPutModifiable(const std::string &channel, byte *inString, size_t length, bool blocking=true)
+ {return ChannelPutModifiable2(channel, inString, length, 0, blocking);}
+
+ size_t ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+ size_t ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+
+ bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true)
+ {return !!ChannelPut2(channel, NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);}
+ size_t ChannelPutMessageEnd(const std::string &channel, const byte *inString, size_t length, int propagation=-1, bool blocking=true)
+ {return ChannelPut2(channel, inString, length, propagation < 0 ? -1 : propagation+1, blocking);}
+
+ virtual byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+
+ virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+ virtual size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
+
+ virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true);
+ virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
+
+ virtual void SetRetrievalChannel(const std::string &channel);
+ //@}
+
+ //! \name ATTACHMENT
+ /*! Some BufferedTransformation objects (e.g. Filter objects)
+ allow other BufferedTransformation objects to be attached. When
+ this is done, the first object instead of buffering its output,
+ sents that output to the attached object as input. The entire
+ attachment chain is deleted when the anchor object is destructed.
+ */
+ //@{
+ //! returns whether this object allows attachment
+ virtual bool Attachable() {return false;}
+ //! returns the object immediately attached to this object or NULL for no attachment
+ virtual BufferedTransformation *AttachedTransformation() {assert(!Attachable()); return 0;}
+ //!
+ virtual const BufferedTransformation *AttachedTransformation() const
+ {return const_cast<BufferedTransformation *>(this)->AttachedTransformation();}
+ //! delete the current attachment chain and replace it with newAttachment
+ virtual void Detach(BufferedTransformation *newAttachment = 0)
+ {assert(!Attachable()); throw NotImplemented("BufferedTransformation: this object is not attachable");}
+ //! add newAttachment to the end of attachment chain
+ virtual void Attach(BufferedTransformation *newAttachment);
+ //@}
+
+protected:
+ static int DecrementPropagation(int propagation)
+ {return propagation != 0 ? propagation - 1 : 0;}
+
+private:
+ byte m_buf[4]; // for ChannelPutWord16 and ChannelPutWord32, to ensure buffer isn't deallocated before non-blocking operation completes
+};
+
+//! returns a reference to a BufferedTransformation object that discards all input
+BufferedTransformation & TheBitBucket();
+
+//! interface for crypto material, such as public and private keys, and crypto parameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoMaterial : public NameValuePairs
+{
+public:
+ //! exception thrown when invalid crypto material is detected
+ class CRYPTOPP_DLL InvalidMaterial : public InvalidDataFormat
+ {
+ public:
+ explicit InvalidMaterial(const std::string &s) : InvalidDataFormat(s) {}
+ };
+
+ //! assign values from source to this object
+ /*! \note This function can be used to create a public key from a private key. */
+ virtual void AssignFrom(const NameValuePairs &source) =0;
+
+ //! check this object for errors
+ /*! \param level denotes the level of thoroughness:
+ 0 - using this object won't cause a crash or exception (rng is ignored)
+ 1 - this object will probably function (encrypt, sign, etc.) correctly (but may not check for weak keys and such)
+ 2 - make sure this object will function correctly, and do reasonable security checks
+ 3 - do checks that may take a long time
+ \return true if the tests pass */
+ virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0;
+
+ //! throws InvalidMaterial if this object fails Validate() test
+ virtual void ThrowIfInvalid(RandomNumberGenerator &rng, unsigned int level) const
+ {if (!Validate(rng, level)) throw InvalidMaterial("CryptoMaterial: this object contains invalid values");}
+
+// virtual std::vector<std::string> GetSupportedFormats(bool includeSaveOnly=false, bool includeLoadOnly=false);
+
+ //! save key into a BufferedTransformation
+ virtual void Save(BufferedTransformation &bt) const
+ {throw NotImplemented("CryptoMaterial: this object does not support saving");}
+
+ //! load key from a BufferedTransformation
+ /*! \throws KeyingErr if decode fails
+ \note Generally does not check that the key is valid.
+ Call ValidateKey() or ThrowIfInvalidKey() to check that. */
+ virtual void Load(BufferedTransformation &bt)
+ {throw NotImplemented("CryptoMaterial: this object does not support loading");}
+
+ //! \return whether this object supports precomputation
+ virtual bool SupportsPrecomputation() const {return false;}
+ //! do precomputation
+ /*! The exact semantics of Precompute() is varies, but
+ typically it means calculate a table of n objects
+ that can be used later to speed up computation. */
+ virtual void Precompute(unsigned int n)
+ {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+ //! retrieve previously saved precomputation
+ virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
+ {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+ //! save precomputation for later use
+ virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
+ {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+
+ // for internal library use
+ void DoQuickSanityCheck() const {ThrowIfInvalid(NullRNG(), 0);}
+
+#if (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+ // Sun Studio 11/CC 5.8 workaround: it generates incorrect code when casting to an empty virtual base class
+ char m_sunCCworkaround;
+#endif
+};
+
+//! interface for generatable crypto material, such as private keys and crypto parameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GeneratableCryptoMaterial : virtual public CryptoMaterial
+{
+public:
+ //! generate a random key or crypto parameters
+ /*! \throws KeyingErr if algorithm parameters are invalid, or if a key can't be generated
+ (e.g., if this is a public key object) */
+ virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs)
+ {throw NotImplemented("GeneratableCryptoMaterial: this object does not support key/parameter generation");}
+
+ //! calls the above function with a NameValuePairs object that just specifies "KeySize"
+ void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize);
+};
+
+//! interface for public keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKey : virtual public CryptoMaterial
+{
+};
+
+//! interface for private keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKey : public GeneratableCryptoMaterial
+{
+};
+
+//! interface for crypto prameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoParameters : public GeneratableCryptoMaterial
+{
+};
+
+//! interface for asymmetric algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AsymmetricAlgorithm : public Algorithm
+{
+public:
+ //! returns a reference to the crypto material used by this object
+ virtual CryptoMaterial & AccessMaterial() =0;
+ //! returns a const reference to the crypto material used by this object
+ virtual const CryptoMaterial & GetMaterial() const =0;
+
+ //! for backwards compatibility, calls AccessMaterial().Load(bt)
+ void BERDecode(BufferedTransformation &bt)
+ {AccessMaterial().Load(bt);}
+ //! for backwards compatibility, calls GetMaterial().Save(bt)
+ void DEREncode(BufferedTransformation &bt) const
+ {GetMaterial().Save(bt);}
+};
+
+//! interface for asymmetric algorithms using public keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKeyAlgorithm : public AsymmetricAlgorithm
+{
+public:
+ // VC60 workaround: no co-variant return type
+ CryptoMaterial & AccessMaterial() {return AccessPublicKey();}
+ const CryptoMaterial & GetMaterial() const {return GetPublicKey();}
+
+ virtual PublicKey & AccessPublicKey() =0;
+ virtual const PublicKey & GetPublicKey() const {return const_cast<PublicKeyAlgorithm *>(this)->AccessPublicKey();}
+};
+
+//! interface for asymmetric algorithms using private keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKeyAlgorithm : public AsymmetricAlgorithm
+{
+public:
+ CryptoMaterial & AccessMaterial() {return AccessPrivateKey();}
+ const CryptoMaterial & GetMaterial() const {return GetPrivateKey();}
+
+ virtual PrivateKey & AccessPrivateKey() =0;
+ virtual const PrivateKey & GetPrivateKey() const {return const_cast<PrivateKeyAlgorithm *>(this)->AccessPrivateKey();}
+};
+
+//! interface for key agreement algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE KeyAgreementAlgorithm : public AsymmetricAlgorithm
+{
+public:
+ CryptoMaterial & AccessMaterial() {return AccessCryptoParameters();}
+ const CryptoMaterial & GetMaterial() const {return GetCryptoParameters();}
+
+ virtual CryptoParameters & AccessCryptoParameters() =0;
+ virtual const CryptoParameters & GetCryptoParameters() const {return const_cast<KeyAgreementAlgorithm *>(this)->AccessCryptoParameters();}
+};
+
+//! interface for public-key encryptors and decryptors
+
+/*! This class provides an interface common to encryptors and decryptors
+ for querying their plaintext and ciphertext lengths.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_CryptoSystem
+{
+public:
+ virtual ~PK_CryptoSystem() {}
+
+ //! maximum length of plaintext for a given ciphertext length
+ /*! \note This function returns 0 if ciphertextLength is not valid (too long or too short). */
+ virtual size_t MaxPlaintextLength(size_t ciphertextLength) const =0;
+
+ //! calculate length of ciphertext given length of plaintext
+ /*! \note This function returns 0 if plaintextLength is not valid (too long). */
+ virtual size_t CiphertextLength(size_t plaintextLength) const =0;
+
+ //! this object supports the use of the parameter with the given name
+ /*! some possible parameter names: EncodingParameters, KeyDerivationParameters */
+ virtual bool ParameterSupported(const char *name) const =0;
+
+ //! return fixed ciphertext length, if one exists, otherwise return 0
+ /*! \note "Fixed" here means length of ciphertext does not depend on length of plaintext.
+ It usually does depend on the key length. */
+ virtual size_t FixedCiphertextLength() const {return 0;}
+
+ //! return maximum plaintext length given the fixed ciphertext length, if one exists, otherwise return 0
+ virtual size_t FixedMaxPlaintextLength() const {return 0;}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ size_t MaxPlainTextLength(size_t cipherTextLength) const {return MaxPlaintextLength(cipherTextLength);}
+ size_t CipherTextLength(size_t plainTextLength) const {return CiphertextLength(plainTextLength);}
+#endif
+};
+
+//! interface for public-key encryptors
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Encryptor : public PK_CryptoSystem, public PublicKeyAlgorithm
+{
+public:
+ //! exception thrown when trying to encrypt plaintext of invalid length
+ class CRYPTOPP_DLL InvalidPlaintextLength : public Exception
+ {
+ public:
+ InvalidPlaintextLength() : Exception(OTHER_ERROR, "PK_Encryptor: invalid plaintext length") {}
+ };
+
+ //! encrypt a byte string
+ /*! \pre CiphertextLength(plaintextLength) != 0 (i.e., plaintext isn't too long)
+ \pre size of ciphertext == CiphertextLength(plaintextLength)
+ */
+ virtual void Encrypt(RandomNumberGenerator &rng,
+ const byte *plaintext, size_t plaintextLength,
+ byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const =0;
+
+ //! create a new encryption filter
+ /*! \note The caller is responsible for deleting the returned pointer.
+ \note Encoding parameters should be passed in the "EP" channel.
+ */
+ virtual BufferedTransformation * CreateEncryptionFilter(RandomNumberGenerator &rng,
+ BufferedTransformation *attachment=NULL, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+};
+
+//! interface for public-key decryptors
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Decryptor : public PK_CryptoSystem, public PrivateKeyAlgorithm
+{
+public:
+ //! decrypt a byte string, and return the length of plaintext
+ /*! \pre size of plaintext == MaxPlaintextLength(ciphertextLength) bytes.
+ \return the actual length of the plaintext, indication that decryption failed.
+ */
+ virtual DecodingResult Decrypt(RandomNumberGenerator &rng,
+ const byte *ciphertext, size_t ciphertextLength,
+ byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const =0;
+
+ //! create a new decryption filter
+ /*! \note caller is responsible for deleting the returned pointer
+ */
+ virtual BufferedTransformation * CreateDecryptionFilter(RandomNumberGenerator &rng,
+ BufferedTransformation *attachment=NULL, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+
+ //! decrypt a fixed size ciphertext
+ DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *ciphertext, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const
+ {return Decrypt(rng, ciphertext, FixedCiphertextLength(), plaintext, parameters);}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef PK_CryptoSystem PK_FixedLengthCryptoSystem;
+typedef PK_Encryptor PK_FixedLengthEncryptor;
+typedef PK_Decryptor PK_FixedLengthDecryptor;
+#endif
+
+//! interface for public-key signers and verifiers
+
+/*! This class provides an interface common to signers and verifiers
+ for querying scheme properties.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_SignatureScheme
+{
+public:
+ //! invalid key exception, may be thrown by any function in this class if the private or public key has a length that can't be used
+ class CRYPTOPP_DLL InvalidKeyLength : public Exception
+ {
+ public:
+ InvalidKeyLength(const std::string &message) : Exception(OTHER_ERROR, message) {}
+ };
+
+ //! key too short exception, may be thrown by any function in this class if the private or public key is too short to sign or verify anything
+ class CRYPTOPP_DLL KeyTooShort : public InvalidKeyLength
+ {
+ public:
+ KeyTooShort() : InvalidKeyLength("PK_Signer: key too short for this signature scheme") {}
+ };
+
+ virtual ~PK_SignatureScheme() {}
+
+ //! signature length if it only depends on the key, otherwise 0
+ virtual size_t SignatureLength() const =0;
+
+ //! maximum signature length produced for a given length of recoverable message part
+ virtual size_t MaxSignatureLength(size_t recoverablePartLength = 0) const {return SignatureLength();}
+
+ //! length of longest message that can be recovered, or 0 if this signature scheme does not support message recovery
+ virtual size_t MaxRecoverableLength() const =0;
+
+ //! length of longest message that can be recovered from a signature of given length, or 0 if this signature scheme does not support message recovery
+ virtual size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const =0;
+
+ //! requires a random number generator to sign
+ /*! if this returns false, NullRNG() can be passed to functions that take RandomNumberGenerator & */
+ virtual bool IsProbabilistic() const =0;
+
+ //! whether or not a non-recoverable message part can be signed
+ virtual bool AllowNonrecoverablePart() const =0;
+
+ //! if this function returns true, during verification you must input the signature before the message, otherwise you can input it at anytime */
+ virtual bool SignatureUpfront() const {return false;}
+
+ //! whether you must input the recoverable part before the non-recoverable part during signing
+ virtual bool RecoverablePartFirst() const =0;
+};
+
+//! interface for accumulating messages to be signed or verified
+/*! Only Update() should be called
+ on this class. No other functions inherited from HashTransformation should be called.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulator : public HashTransformation
+{
+public:
+ //! should not be called on PK_MessageAccumulator
+ unsigned int DigestSize() const
+ {throw NotImplemented("PK_MessageAccumulator: DigestSize() should not be called");}
+ //! should not be called on PK_MessageAccumulator
+ void TruncatedFinal(byte *digest, size_t digestSize)
+ {throw NotImplemented("PK_MessageAccumulator: TruncatedFinal() should not be called");}
+};
+
+//! interface for public-key signers
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Signer : public PK_SignatureScheme, public PrivateKeyAlgorithm
+{
+public:
+ //! create a new HashTransformation to accumulate the message to be signed
+ virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0;
+
+ virtual void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const =0;
+
+ //! sign and delete messageAccumulator (even in case of exception thrown)
+ /*! \pre size of signature == MaxSignatureLength()
+ \return actual signature length
+ */
+ virtual size_t Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const;
+
+ //! sign and restart messageAccumulator
+ /*! \pre size of signature == MaxSignatureLength()
+ \return actual signature length
+ */
+ virtual size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const =0;
+
+ //! sign a message
+ /*! \pre size of signature == MaxSignatureLength()
+ \return actual signature length
+ */
+ virtual size_t SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const;
+
+ //! sign a recoverable message
+ /*! \pre size of signature == MaxSignatureLength(recoverableMessageLength)
+ \return actual signature length
+ */
+ virtual size_t SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength,
+ const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const;
+};
+
+//! interface for public-key signature verifiers
+/*! The Recover* functions throw NotImplemented if the signature scheme does not support
+ message recovery.
+ The Verify* functions throw InvalidDataFormat if the scheme does support message
+ recovery and the signature contains a non-empty recoverable message part. The
+ Recovery* functions should be used in that case.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Verifier : public PK_SignatureScheme, public PublicKeyAlgorithm
+{
+public:
+ //! create a new HashTransformation to accumulate the message to be verified
+ virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0;
+
+ //! input signature into a message accumulator
+ virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const =0;
+
+ //! check whether messageAccumulator contains a valid signature and message, and delete messageAccumulator (even in case of exception thrown)
+ virtual bool Verify(PK_MessageAccumulator *messageAccumulator) const;
+
+ //! check whether messageAccumulator contains a valid signature and message, and restart messageAccumulator
+ virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0;
+
+ //! check whether input signature is a valid signature for input message
+ virtual bool VerifyMessage(const byte *message, size_t messageLen,
+ const byte *signature, size_t signatureLength) const;
+
+ //! recover a message from its signature
+ /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+ */
+ virtual DecodingResult Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const;
+
+ //! recover a message from its signature
+ /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+ */
+ virtual DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const =0;
+
+ //! recover a message from its signature
+ /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+ */
+ virtual DecodingResult RecoverMessage(byte *recoveredMessage,
+ const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength,
+ const byte *signature, size_t signatureLength) const;
+};
+
+//! interface for domains of simple key agreement protocols
+
+/*! A key agreement domain is a set of parameters that must be shared
+ by two parties in a key agreement protocol, along with the algorithms
+ for generating key pairs and deriving agreed values.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+ //! return length of agreed value produced
+ virtual unsigned int AgreedValueLength() const =0;
+ //! return length of private keys in this domain
+ virtual unsigned int PrivateKeyLength() const =0;
+ //! return length of public keys in this domain
+ virtual unsigned int PublicKeyLength() const =0;
+ //! generate private key
+ /*! \pre size of privateKey == PrivateKeyLength() */
+ virtual void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+ //! generate public key
+ /*! \pre size of publicKey == PublicKeyLength() */
+ virtual void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+ //! generate private/public key pair
+ /*! \note equivalent to calling GeneratePrivateKey() and then GeneratePublicKey() */
+ virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+ //! derive agreed value from your private key and couterparty's public key, return false in case of failure
+ /*! \note If you have previously validated the public key, use validateOtherPublicKey=false to save time.
+ \pre size of agreedValue == AgreedValueLength()
+ \pre length of privateKey == PrivateKeyLength()
+ \pre length of otherPublicKey == PublicKeyLength()
+ */
+ virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+ {return GetCryptoParameters().Validate(rng, 2);}
+#endif
+};
+
+//! interface for domains of authenticated key agreement protocols
+
+/*! In an authenticated key agreement protocol, each party has two
+ key pairs. The long-lived key pair is called the static key pair,
+ and the short-lived key pair is called the ephemeral key pair.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+ //! return length of agreed value produced
+ virtual unsigned int AgreedValueLength() const =0;
+
+ //! return length of static private keys in this domain
+ virtual unsigned int StaticPrivateKeyLength() const =0;
+ //! return length of static public keys in this domain
+ virtual unsigned int StaticPublicKeyLength() const =0;
+ //! generate static private key
+ /*! \pre size of privateKey == PrivateStaticKeyLength() */
+ virtual void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+ //! generate static public key
+ /*! \pre size of publicKey == PublicStaticKeyLength() */
+ virtual void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+ //! generate private/public key pair
+ /*! \note equivalent to calling GenerateStaticPrivateKey() and then GenerateStaticPublicKey() */
+ virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+
+ //! return length of ephemeral private keys in this domain
+ virtual unsigned int EphemeralPrivateKeyLength() const =0;
+ //! return length of ephemeral public keys in this domain
+ virtual unsigned int EphemeralPublicKeyLength() const =0;
+ //! generate ephemeral private key
+ /*! \pre size of privateKey == PrivateEphemeralKeyLength() */
+ virtual void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+ //! generate ephemeral public key
+ /*! \pre size of publicKey == PublicEphemeralKeyLength() */
+ virtual void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+ //! generate private/public key pair
+ /*! \note equivalent to calling GenerateEphemeralPrivateKey() and then GenerateEphemeralPublicKey() */
+ virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+
+ //! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
+ /*! \note The ephemeral public key will always be validated.
+ If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
+ \pre size of agreedValue == AgreedValueLength()
+ \pre length of staticPrivateKey == StaticPrivateKeyLength()
+ \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
+ \pre length of staticOtherPublicKey == StaticPublicKeyLength()
+ \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
+ */
+ virtual bool Agree(byte *agreedValue,
+ const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
+ const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
+ bool validateStaticOtherPublicKey=true) const =0;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+ {return GetCryptoParameters().Validate(rng, 2);}
+#endif
+};
+
+// interface for password authenticated key agreement protocols, not implemented yet
+#if 0
+//! interface for protocol sessions
+/*! The methods should be called in the following order:
+
+ InitializeSession(rng, parameters); // or call initialize method in derived class
+ while (true)
+ {
+ if (OutgoingMessageAvailable())
+ {
+ length = GetOutgoingMessageLength();
+ GetOutgoingMessage(message);
+ ; // send outgoing message
+ }
+
+ if (LastMessageProcessed())
+ break;
+
+ ; // receive incoming message
+ ProcessIncomingMessage(message);
+ }
+ ; // call methods in derived class to obtain result of protocol session
+*/
+class ProtocolSession
+{
+public:
+ //! exception thrown when an invalid protocol message is processed
+ class ProtocolError : public Exception
+ {
+ public:
+ ProtocolError(ErrorType errorType, const std::string &s) : Exception(errorType, s) {}
+ };
+
+ //! exception thrown when a function is called unexpectedly
+ /*! for example calling ProcessIncomingMessage() when ProcessedLastMessage() == true */
+ class UnexpectedMethodCall : public Exception
+ {
+ public:
+ UnexpectedMethodCall(const std::string &s) : Exception(OTHER_ERROR, s) {}
+ };
+
+ ProtocolSession() : m_rng(NULL), m_throwOnProtocolError(true), m_validState(false) {}
+ virtual ~ProtocolSession() {}
+
+ virtual void InitializeSession(RandomNumberGenerator &rng, const NameValuePairs &parameters) =0;
+
+ bool GetThrowOnProtocolError() const {return m_throwOnProtocolError;}
+ void SetThrowOnProtocolError(bool throwOnProtocolError) {m_throwOnProtocolError = throwOnProtocolError;}
+
+ bool HasValidState() const {return m_validState;}
+
+ virtual bool OutgoingMessageAvailable() const =0;
+ virtual unsigned int GetOutgoingMessageLength() const =0;
+ virtual void GetOutgoingMessage(byte *message) =0;
+
+ virtual bool LastMessageProcessed() const =0;
+ virtual void ProcessIncomingMessage(const byte *message, unsigned int messageLength) =0;
+
+protected:
+ void HandleProtocolError(Exception::ErrorType errorType, const std::string &s) const;
+ void CheckAndHandleInvalidState() const;
+ void SetValidState(bool valid) {m_validState = valid;}
+
+ RandomNumberGenerator *m_rng;
+
+private:
+ bool m_throwOnProtocolError, m_validState;
+};
+
+class KeyAgreementSession : public ProtocolSession
+{
+public:
+ virtual unsigned int GetAgreedValueLength() const =0;
+ virtual void GetAgreedValue(byte *agreedValue) const =0;
+};
+
+class PasswordAuthenticatedKeyAgreementSession : public KeyAgreementSession
+{
+public:
+ void InitializePasswordAuthenticatedKeyAgreementSession(RandomNumberGenerator &rng,
+ const byte *myId, unsigned int myIdLength,
+ const byte *counterPartyId, unsigned int counterPartyIdLength,
+ const byte *passwordOrVerifier, unsigned int passwordOrVerifierLength);
+};
+
+class PasswordAuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+ //! return whether the domain parameters stored in this object are valid
+ virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+ {return GetCryptoParameters().Validate(rng, 2);}
+
+ virtual unsigned int GetPasswordVerifierLength(const byte *password, unsigned int passwordLength) const =0;
+ virtual void GeneratePasswordVerifier(RandomNumberGenerator &rng, const byte *userId, unsigned int userIdLength, const byte *password, unsigned int passwordLength, byte *verifier) const =0;
+
+ enum RoleFlags {CLIENT=1, SERVER=2, INITIATOR=4, RESPONDER=8};
+
+ virtual bool IsValidRole(unsigned int role) =0;
+ virtual PasswordAuthenticatedKeyAgreementSession * CreateProtocolSession(unsigned int role) const =0;
+};
+#endif
+
+//! BER Decode Exception Class, may be thrown during an ASN1 BER decode operation
+class CRYPTOPP_DLL BERDecodeErr : public InvalidArgument
+{
+public:
+ BERDecodeErr() : InvalidArgument("BER decode error") {}
+ BERDecodeErr(const std::string &s) : InvalidArgument(s) {}
+};
+
+//! interface for encoding and decoding ASN1 objects
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object
+{
+public:
+ virtual ~ASN1Object() {}
+ //! decode this object from a BufferedTransformation, using BER (Basic Encoding Rules)
+ virtual void BERDecode(BufferedTransformation &bt) =0;
+ //! encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules)
+ virtual void DEREncode(BufferedTransformation &bt) const =0;
+ //! encode this object into a BufferedTransformation, using BER
+ /*! this may be useful if DEREncode() would be too inefficient */
+ virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef PK_SignatureScheme PK_SignatureSystem;
+typedef SimpleKeyAgreementDomain PK_SimpleKeyAgreementDomain;
+typedef AuthenticatedKeyAgreementDomain PK_AuthenticatedKeyAgreementDomain;
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/default.cpp b/lib/cryptopp/default.cpp
new file mode 100644
index 000000000..72940784d
--- /dev/null
+++ b/lib/cryptopp/default.cpp
@@ -0,0 +1,258 @@
+// default.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "default.h"
+#include "queue.h"
+#include <time.h>
+#include <memory>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const unsigned int MASH_ITERATIONS = 200;
+static const unsigned int SALTLENGTH = 8;
+static const unsigned int BLOCKSIZE = Default_BlockCipher::Encryption::BLOCKSIZE;
+static const unsigned int KEYLENGTH = Default_BlockCipher::Encryption::DEFAULT_KEYLENGTH;
+
+// The purpose of this function Mash() is to take an arbitrary length input
+// string and *deterministicly* produce an arbitrary length output string such
+// that (1) it looks random, (2) no information about the input is
+// deducible from it, and (3) it contains as much entropy as it can hold, or
+// the amount of entropy in the input string, whichever is smaller.
+
+static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations)
+{
+ if (BytePrecision(outLen) > 2)
+ throw InvalidArgument("Mash: output legnth too large");
+
+ size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
+ byte b[2];
+ SecByteBlock buf(bufSize);
+ SecByteBlock outBuf(bufSize);
+ DefaultHashModule hash;
+
+ unsigned int i;
+ for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
+ {
+ b[0] = (byte) (i >> 8);
+ b[1] = (byte) i;
+ hash.Update(b, 2);
+ hash.Update(in, inLen);
+ hash.Final(outBuf+i);
+ }
+
+ while (iterations-- > 1)
+ {
+ memcpy(buf, outBuf, bufSize);
+ for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
+ {
+ b[0] = (byte) (i >> 8);
+ b[1] = (byte) i;
+ hash.Update(b, 2);
+ hash.Update(buf, bufSize);
+ hash.Final(outBuf+i);
+ }
+ }
+
+ memcpy(out, outBuf, outLen);
+}
+
+static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, byte *key, byte *IV)
+{
+ SecByteBlock temp(passphraseLength+saltLength);
+ memcpy(temp, passphrase, passphraseLength);
+ memcpy(temp+passphraseLength, salt, saltLength);
+ SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
+ Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
+ memcpy(key, keyIV, KEYLENGTH);
+ memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
+}
+
+// ********************************************************
+
+DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment)
+ : ProxyFilter(NULL, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase))
+{
+}
+
+DefaultEncryptor::DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
+ : ProxyFilter(NULL, 0, 0, attachment), m_passphrase(passphrase, passphraseLength)
+{
+}
+
+
+void DefaultEncryptor::FirstPut(const byte *)
+{
+ // VC60 workaround: __LINE__ expansion bug
+ CRYPTOPP_COMPILE_ASSERT_INSTANCE(SALTLENGTH <= DefaultHashModule::DIGESTSIZE, 1);
+ CRYPTOPP_COMPILE_ASSERT_INSTANCE(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE, 2);
+
+ SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
+ DefaultHashModule hash;
+
+ // use hash(passphrase | time | clock) as salt
+ hash.Update(m_passphrase, m_passphrase.size());
+ time_t t=time(0);
+ hash.Update((byte *)&t, sizeof(t));
+ clock_t c=clock();
+ hash.Update((byte *)&c, sizeof(c));
+ hash.Final(salt);
+
+ // use hash(passphrase | salt) as key check
+ hash.Update(m_passphrase, m_passphrase.size());
+ hash.Update(salt, SALTLENGTH);
+ hash.Final(keyCheck);
+
+ AttachedTransformation()->Put(salt, SALTLENGTH);
+
+ // mash passphrase and salt together into key and IV
+ SecByteBlock key(KEYLENGTH);
+ SecByteBlock IV(BLOCKSIZE);
+ GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
+
+ m_cipher.SetKeyWithIV(key, key.size(), IV);
+ SetFilter(new StreamTransformationFilter(m_cipher));
+
+ m_filter->Put(keyCheck, BLOCKSIZE);
+}
+
+void DefaultEncryptor::LastPut(const byte *inString, size_t length)
+{
+ m_filter->MessageEnd();
+}
+
+// ********************************************************
+
+DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *attachment, bool throwException)
+ : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
+ , m_state(WAITING_FOR_KEYCHECK)
+ , m_passphrase((const byte *)p, strlen(p))
+ , m_throwException(throwException)
+{
+}
+
+DefaultDecryptor::DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
+ : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
+ , m_state(WAITING_FOR_KEYCHECK)
+ , m_passphrase(passphrase, passphraseLength)
+ , m_throwException(throwException)
+{
+}
+
+void DefaultDecryptor::FirstPut(const byte *inString)
+{
+ CheckKey(inString, inString+SALTLENGTH);
+}
+
+void DefaultDecryptor::LastPut(const byte *inString, size_t length)
+{
+ if (m_filter.get() == NULL)
+ {
+ m_state = KEY_BAD;
+ if (m_throwException)
+ throw KeyBadErr();
+ }
+ else
+ {
+ m_filter->MessageEnd();
+ m_state = WAITING_FOR_KEYCHECK;
+ }
+}
+
+void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
+{
+ SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
+
+ DefaultHashModule hash;
+ hash.Update(m_passphrase, m_passphrase.size());
+ hash.Update(salt, SALTLENGTH);
+ hash.Final(check);
+
+ SecByteBlock key(KEYLENGTH);
+ SecByteBlock IV(BLOCKSIZE);
+ GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
+
+ m_cipher.SetKeyWithIV(key, key.size(), IV);
+ std::auto_ptr<StreamTransformationFilter> decryptor(new StreamTransformationFilter(m_cipher));
+
+ decryptor->Put(keyCheck, BLOCKSIZE);
+ decryptor->ForceNextPut();
+ decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
+
+ SetFilter(decryptor.release());
+
+ if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
+ {
+ m_state = KEY_BAD;
+ if (m_throwException)
+ throw KeyBadErr();
+ }
+ else
+ m_state = KEY_GOOD;
+}
+
+// ********************************************************
+
+static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, size_t passphraseLength)
+{
+ size_t macKeyLength = DefaultMAC::StaticGetValidKeyLength(16);
+ SecByteBlock macKey(macKeyLength);
+ // since the MAC is encrypted there is no reason to mash the passphrase for many iterations
+ Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
+ return new DefaultMAC(macKey, macKeyLength);
+}
+
+DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment)
+ : ProxyFilter(NULL, 0, 0, attachment)
+ , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
+{
+ SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
+}
+
+DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
+ : ProxyFilter(NULL, 0, 0, attachment)
+ , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
+{
+ SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
+}
+
+void DefaultEncryptorWithMAC::LastPut(const byte *inString, size_t length)
+{
+ m_filter->MessageEnd();
+}
+
+// ********************************************************
+
+DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException)
+ : ProxyFilter(NULL, 0, 0, attachment)
+ , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
+ , m_throwException(throwException)
+{
+ SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
+}
+
+DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
+ : ProxyFilter(NULL, 0, 0, attachment)
+ , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
+ , m_throwException(throwException)
+{
+ SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
+}
+
+DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
+{
+ return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
+}
+
+bool DefaultDecryptorWithMAC::CheckLastMAC() const
+{
+ return m_hashVerifier->GetLastResult();
+}
+
+void DefaultDecryptorWithMAC::LastPut(const byte *inString, size_t length)
+{
+ m_filter->MessageEnd();
+ if (m_throwException && !CheckLastMAC())
+ throw MACBadErr();
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/default.h b/lib/cryptopp/default.h
new file mode 100644
index 000000000..fb5364152
--- /dev/null
+++ b/lib/cryptopp/default.h
@@ -0,0 +1,104 @@
+#ifndef CRYPTOPP_DEFAULT_H
+#define CRYPTOPP_DEFAULT_H
+
+#include "sha.h"
+#include "hmac.h"
+#include "des.h"
+#include "filters.h"
+#include "modes.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+typedef DES_EDE2 Default_BlockCipher;
+typedef SHA DefaultHashModule;
+typedef HMAC<DefaultHashModule> DefaultMAC;
+
+//! Password-Based Encryptor using DES-EDE2
+class DefaultEncryptor : public ProxyFilter
+{
+public:
+ DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment = NULL);
+ DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
+
+protected:
+ void FirstPut(const byte *);
+ void LastPut(const byte *inString, size_t length);
+
+private:
+ SecByteBlock m_passphrase;
+ CBC_Mode<Default_BlockCipher>::Encryption m_cipher;
+};
+
+//! Password-Based Decryptor using DES-EDE2
+class DefaultDecryptor : public ProxyFilter
+{
+public:
+ DefaultDecryptor(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
+ DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
+
+ class Err : public Exception
+ {
+ public:
+ Err(const std::string &s)
+ : Exception(DATA_INTEGRITY_CHECK_FAILED, s) {}
+ };
+ class KeyBadErr : public Err {public: KeyBadErr() : Err("DefaultDecryptor: cannot decrypt message with this passphrase") {}};
+
+ enum State {WAITING_FOR_KEYCHECK, KEY_GOOD, KEY_BAD};
+ State CurrentState() const {return m_state;}
+
+protected:
+ void FirstPut(const byte *inString);
+ void LastPut(const byte *inString, size_t length);
+
+ State m_state;
+
+private:
+ void CheckKey(const byte *salt, const byte *keyCheck);
+
+ SecByteBlock m_passphrase;
+ CBC_Mode<Default_BlockCipher>::Decryption m_cipher;
+ member_ptr<FilterWithBufferedInput> m_decryptor;
+ bool m_throwException;
+};
+
+//! Password-Based Encryptor using DES-EDE2 and HMAC/SHA-1
+class DefaultEncryptorWithMAC : public ProxyFilter
+{
+public:
+ DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL);
+ DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
+
+protected:
+ void FirstPut(const byte *inString) {}
+ void LastPut(const byte *inString, size_t length);
+
+private:
+ member_ptr<DefaultMAC> m_mac;
+};
+
+//! Password-Based Decryptor using DES-EDE2 and HMAC/SHA-1
+class DefaultDecryptorWithMAC : public ProxyFilter
+{
+public:
+ class MACBadErr : public DefaultDecryptor::Err {public: MACBadErr() : DefaultDecryptor::Err("DefaultDecryptorWithMAC: MAC check failed") {}};
+
+ DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
+ DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
+
+ DefaultDecryptor::State CurrentState() const;
+ bool CheckLastMAC() const;
+
+protected:
+ void FirstPut(const byte *inString) {}
+ void LastPut(const byte *inString, size_t length);
+
+private:
+ member_ptr<DefaultMAC> m_mac;
+ HashVerifier *m_hashVerifier;
+ bool m_throwException;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/des.cpp b/lib/cryptopp/des.cpp
new file mode 100644
index 000000000..a6e0c514d
--- /dev/null
+++ b/lib/cryptopp/des.cpp
@@ -0,0 +1,449 @@
+// des.cpp - modified by Wei Dai from Phil Karn's des.c
+// The original code and all modifications are in the public domain.
+
+/*
+ * This is a major rewrite of my old public domain DES code written
+ * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977
+ * public domain code. I pretty much kept my key scheduling code, but
+ * the actual encrypt/decrypt routines are taken from from Richard
+ * Outerbridge's DES code as printed in Schneier's "Applied Cryptography."
+ *
+ * This code is in the public domain. I would appreciate bug reports and
+ * enhancements.
+ *
+ * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994.
+ */
+
+#include "pch.h"
+#include "misc.h"
+#include "des.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+typedef BlockGetAndPut<word32, BigEndian> Block;
+
+// Richard Outerbridge's initial permutation algorithm
+/*
+inline void IPERM(word32 &left, word32 &right)
+{
+ word32 work;
+
+ work = ((left >> 4) ^ right) & 0x0f0f0f0f;
+ right ^= work;
+ left ^= work << 4;
+ work = ((left >> 16) ^ right) & 0xffff;
+ right ^= work;
+ left ^= work << 16;
+ work = ((right >> 2) ^ left) & 0x33333333;
+ left ^= work;
+ right ^= (work << 2);
+ work = ((right >> 8) ^ left) & 0xff00ff;
+ left ^= work;
+ right ^= (work << 8);
+ right = rotl(right, 1);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = rotl(left, 1);
+}
+inline void FPERM(word32 &left, word32 &right)
+{
+ word32 work;
+
+ right = rotr(right, 1);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = rotr(left, 1);
+ work = ((left >> 8) ^ right) & 0xff00ff;
+ right ^= work;
+ left ^= work << 8;
+ work = ((left >> 2) ^ right) & 0x33333333;
+ right ^= work;
+ left ^= work << 2;
+ work = ((right >> 16) ^ left) & 0xffff;
+ left ^= work;
+ right ^= work << 16;
+ work = ((right >> 4) ^ left) & 0x0f0f0f0f;
+ left ^= work;
+ right ^= work << 4;
+}
+*/
+
+// Wei Dai's modification to Richard Outerbridge's initial permutation
+// algorithm, this one is faster if you have access to rotate instructions
+// (like in MSVC)
+static inline void IPERM(word32 &left, word32 &right)
+{
+ word32 work;
+
+ right = rotlFixed(right, 4U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ left ^= work;
+ right = rotrFixed(right^work, 20U);
+ work = (left ^ right) & 0xffff0000;
+ left ^= work;
+ right = rotrFixed(right^work, 18U);
+ work = (left ^ right) & 0x33333333;
+ left ^= work;
+ right = rotrFixed(right^work, 6U);
+ work = (left ^ right) & 0x00ff00ff;
+ left ^= work;
+ right = rotlFixed(right^work, 9U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left = rotlFixed(left^work, 1U);
+ right ^= work;
+}
+
+static inline void FPERM(word32 &left, word32 &right)
+{
+ word32 work;
+
+ right = rotrFixed(right, 1U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ right ^= work;
+ left = rotrFixed(left^work, 9U);
+ work = (left ^ right) & 0x00ff00ff;
+ right ^= work;
+ left = rotlFixed(left^work, 6U);
+ work = (left ^ right) & 0x33333333;
+ right ^= work;
+ left = rotlFixed(left^work, 18U);
+ work = (left ^ right) & 0xffff0000;
+ right ^= work;
+ left = rotlFixed(left^work, 20U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ right ^= work;
+ left = rotrFixed(left^work, 4U);
+}
+
+void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
+{
+ AssertValidKeyLength(length);
+
+ RawSetKey(GetCipherDirection(), userKey);
+}
+
+#ifndef CRYPTOPP_IMPORTS
+
+/* Tables defined in the Data Encryption Standard documents
+ * Three of these tables, the initial permutation, the final
+ * permutation and the expansion operator, are regular enough that
+ * for speed, we hard-code them. They're here for reference only.
+ * Also, the S and P boxes are used by a separate program, gensp.c,
+ * to build the combined SP box, Spbox[]. They're also here just
+ * for reference.
+ */
+#ifdef notdef
+/* initial permutation IP */
+static byte ip[] = {
+ 58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7
+};
+
+/* final permutation IP^-1 */
+static byte fp[] = {
+ 40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25
+};
+/* expansion operation matrix */
+static byte ei[] = {
+ 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1
+};
+/* The (in)famous S-boxes */
+static byte sbox[8][64] = {
+ /* S1 */
+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
+
+ /* S2 */
+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
+
+ /* S3 */
+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
+
+ /* S4 */
+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
+
+ /* S5 */
+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
+
+ /* S6 */
+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
+
+ /* S7 */
+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
+
+ /* S8 */
+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
+};
+
+/* 32-bit permutation function P used on the output of the S-boxes */
+static byte p32i[] = {
+ 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25
+};
+#endif
+
+/* permuted choice table (key) */
+static const byte pc1[] = {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+};
+
+/* number left rotations of pc1 */
+static const byte totrot[] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
+};
+
+/* permuted choice key (table) */
+static const byte pc2[] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+/* End of DES-defined tables */
+
+/* bit 0 is left-most in byte */
+static const int bytebit[] = {
+ 0200,0100,040,020,010,04,02,01
+};
+
+/* Set key (initialize key schedule array) */
+void RawDES::RawSetKey(CipherDir dir, const byte *key)
+{
+ SecByteBlock buffer(56+56+8);
+ byte *const pc1m=buffer; /* place to modify pc1 into */
+ byte *const pcr=pc1m+56; /* place to rotate pc1 into */
+ byte *const ks=pcr+56;
+ register int i,j,l;
+ int m;
+
+ for (j=0; j<56; j++) { /* convert pc1 to bits of key */
+ l=pc1[j]-1; /* integer bit location */
+ m = l & 07; /* find bit */
+ pc1m[j]=(key[l>>3] & /* find which key byte l is in */
+ bytebit[m]) /* and which bit of that byte */
+ ? 1 : 0; /* and store 1-bit result */
+ }
+ for (i=0; i<16; i++) { /* key chunk for each iteration */
+ memset(ks,0,8); /* Clear key schedule */
+ for (j=0; j<56; j++) /* rotate pc1 the right amount */
+ pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
+ /* rotate left and right halves independently */
+ for (j=0; j<48; j++){ /* select bits individually */
+ /* check bit that goes to ks[j] */
+ if (pcr[pc2[j]-1]){
+ /* mask it in if it's there */
+ l= j % 6;
+ ks[j/6] |= bytebit[l] >> 2;
+ }
+ }
+ /* Now convert to odd/even interleaved form for use in F */
+ k[2*i] = ((word32)ks[0] << 24)
+ | ((word32)ks[2] << 16)
+ | ((word32)ks[4] << 8)
+ | ((word32)ks[6]);
+ k[2*i+1] = ((word32)ks[1] << 24)
+ | ((word32)ks[3] << 16)
+ | ((word32)ks[5] << 8)
+ | ((word32)ks[7]);
+ }
+
+ if (dir==DECRYPTION) // reverse key schedule order
+ for (i=0; i<16; i+=2)
+ {
+ std::swap(k[i], k[32-2-i]);
+ std::swap(k[i+1], k[32-1-i]);
+ }
+}
+
+void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const
+{
+ word32 l = l_, r = r_;
+ const word32 *kptr=k;
+
+ for (unsigned i=0; i<8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ l_ = l; r_ = r;
+}
+
+void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
+{
+ AssertValidKeyLength(length);
+
+ m_des1.RawSetKey(GetCipherDirection(), userKey);
+ m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8);
+}
+
+void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 l,r;
+ Block::Get(inBlock)(l)(r);
+ IPERM(l,r);
+ m_des1.RawProcessBlock(l, r);
+ m_des2.RawProcessBlock(r, l);
+ m_des1.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xorBlock, outBlock)(r)(l);
+}
+
+void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
+{
+ AssertValidKeyLength(length);
+
+ m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16));
+ m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8);
+ m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0));
+}
+
+void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 l,r;
+ Block::Get(inBlock)(l)(r);
+ IPERM(l,r);
+ m_des1.RawProcessBlock(l, r);
+ m_des2.RawProcessBlock(r, l);
+ m_des3.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xorBlock, outBlock)(r)(l);
+}
+
+#endif // #ifndef CRYPTOPP_IMPORTS
+
+static inline bool CheckParity(byte b)
+{
+ unsigned int a = b ^ (b >> 4);
+ return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1;
+}
+
+bool DES::CheckKeyParityBits(const byte *key)
+{
+ for (unsigned int i=0; i<8; i++)
+ if (!CheckParity(key[i]))
+ return false;
+ return true;
+}
+
+void DES::CorrectKeyParityBits(byte *key)
+{
+ for (unsigned int i=0; i<8; i++)
+ if (!CheckParity(key[i]))
+ key[i] ^= 1;
+}
+
+// Encrypt or decrypt a block of data in ECB mode
+void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 l,r;
+ Block::Get(inBlock)(l)(r);
+ IPERM(l,r);
+ RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xorBlock, outBlock)(r)(l);
+}
+
+void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &)
+{
+ AssertValidKeyLength(length);
+
+ if (!m_des.get())
+ m_des.reset(new DES::Encryption);
+
+ memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE);
+ m_des->RawSetKey(GetCipherDirection(), key + 8);
+ memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE);
+}
+
+void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE);
+ m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock);
+ xorbuf(outBlock, m_x3, BLOCKSIZE);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/des.h b/lib/cryptopp/des.h
new file mode 100644
index 000000000..62f628824
--- /dev/null
+++ b/lib/cryptopp/des.h
@@ -0,0 +1,144 @@
+#ifndef CRYPTOPP_DES_H
+#define CRYPTOPP_DES_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+class CRYPTOPP_DLL RawDES
+{
+public:
+ void RawSetKey(CipherDir direction, const byte *userKey);
+ void RawProcessBlock(word32 &l, word32 &r) const;
+
+protected:
+ static const word32 Spbox[8][64];
+
+ FixedSizeSecBlock<word32, 32> k;
+};
+
+//! _
+struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8>
+{
+ // disable DES in DLL version by not exporting this function
+ static const char * StaticAlgorithmName() {return "DES";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#DES">DES</a>
+/*! The DES implementation in Crypto++ ignores the parity bits
+ (the least significant bits of each byte) in the key. However
+ you can use CheckKeyParityBits() and CorrectKeyParityBits() to
+ check or correct the parity bits if you wish. */
+class DES : public DES_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_Info>, public RawDES
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+public:
+ //! check DES key parity bits
+ static bool CheckKeyParityBits(const byte *key);
+ //! correct DES key parity bits
+ static void CorrectKeyParityBits(byte *key);
+
+ typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
+};
+
+//! _
+struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16>
+{
+ CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE2</a>
+class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_EDE2_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+ protected:
+ RawDES m_des1, m_des2;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
+};
+
+//! _
+struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
+{
+ CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE3";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE3</a>
+class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_EDE3_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+ protected:
+ RawDES m_des1, m_des2, m_des3;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
+};
+
+//! _
+struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
+{
+ static const char *StaticAlgorithmName() {return "DES-XEX3";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESX">DES-XEX3</a>, AKA DESX
+class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_XEX3_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+ protected:
+ FixedSizeSecBlock<byte, BLOCKSIZE> m_x1, m_x3;
+ // VS2005 workaround: calling modules compiled with /clr gets unresolved external symbol DES::Base::ProcessAndXorBlock
+ // if we use DES::Encryption here directly without value_ptr.
+ value_ptr<DES::Encryption> m_des;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
+};
+
+typedef DES::Encryption DESEncryption;
+typedef DES::Decryption DESDecryption;
+
+typedef DES_EDE2::Encryption DES_EDE2_Encryption;
+typedef DES_EDE2::Decryption DES_EDE2_Decryption;
+
+typedef DES_EDE3::Encryption DES_EDE3_Encryption;
+typedef DES_EDE3::Decryption DES_EDE3_Decryption;
+
+typedef DES_XEX3::Encryption DES_XEX3_Encryption;
+typedef DES_XEX3::Decryption DES_XEX3_Decryption;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dessp.cpp b/lib/cryptopp/dessp.cpp
new file mode 100644
index 000000000..49ed1d26d
--- /dev/null
+++ b/lib/cryptopp/dessp.cpp
@@ -0,0 +1,95 @@
+// This file is mostly generated by Phil Karn's gensp.c
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "des.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// VC60 workaround: gives a C4786 warning without this function
+// when runtime lib is set to multithread debug DLL
+// even though warning 4786 is disabled!
+void DES_VC60Workaround()
+{
+}
+
+const word32 RawDES::Spbox[8][64] = {
+{
+0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000,
+0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004,
+0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404,
+0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000,
+0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400,
+0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404,
+0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400,
+0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004},
+{
+0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020,
+0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020,
+0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000,
+0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020,
+0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000,
+0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000,
+0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020,
+0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000},
+{
+0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200,
+0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208,
+0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208,
+0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000,
+0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000,
+0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008,
+0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008,
+0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200},
+{
+0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001,
+0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001,
+0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080,
+0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081,
+0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000,
+0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081,
+0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080},
+{
+0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000,
+0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000,
+0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100,
+0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100,
+0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100,
+0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000,
+0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000,
+0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100},
+{
+0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000,
+0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010,
+0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010,
+0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000,
+0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010,
+0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000,
+0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010,
+0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010},
+{
+0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800,
+0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802,
+0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002,
+0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800,
+0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002,
+0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800,
+0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802,
+0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002},
+{
+0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000,
+0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040,
+0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000,
+0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000,
+0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040,
+0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040,
+0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000,
+0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000}
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dh.cpp b/lib/cryptopp/dh.cpp
new file mode 100644
index 000000000..22097a051
--- /dev/null
+++ b/lib/cryptopp/dh.cpp
@@ -0,0 +1,19 @@
+// dh.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "dh.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void DH_TestInstantiations()
+{
+ DH dh1;
+ DH dh2(NullRNG(), 10);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dh.h b/lib/cryptopp/dh.h
new file mode 100644
index 000000000..10e8d142e
--- /dev/null
+++ b/lib/cryptopp/dh.h
@@ -0,0 +1,99 @@
+#ifndef CRYPTOPP_DH_H
+#define CRYPTOPP_DH_H
+
+/** \file
+*/
+
+#include "gfpcrypt.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! ,
+template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption>
+class DH_Domain : public DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element>
+{
+ typedef DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element> Base;
+
+public:
+ typedef GROUP_PARAMETERS GroupParameters;
+ typedef typename GroupParameters::Element Element;
+ typedef DL_KeyAgreementAlgorithm_DH<Element, COFACTOR_OPTION> DH_Algorithm;
+ typedef DH_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
+
+ DH_Domain() {}
+
+ DH_Domain(const GroupParameters &params)
+ : m_groupParameters(params) {}
+
+ DH_Domain(BufferedTransformation &bt)
+ {m_groupParameters.BERDecode(bt);}
+
+ template <class T2>
+ DH_Domain(RandomNumberGenerator &v1, const T2 &v2)
+ {m_groupParameters.Initialize(v1, v2);}
+
+ template <class T2, class T3>
+ DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3)
+ {m_groupParameters.Initialize(v1, v2, v3);}
+
+ template <class T2, class T3, class T4>
+ DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4)
+ {m_groupParameters.Initialize(v1, v2, v3, v4);}
+
+ template <class T1, class T2>
+ DH_Domain(const T1 &v1, const T2 &v2)
+ {m_groupParameters.Initialize(v1, v2);}
+
+ template <class T1, class T2, class T3>
+ DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3)
+ {m_groupParameters.Initialize(v1, v2, v3);}
+
+ template <class T1, class T2, class T3, class T4>
+ DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
+ {m_groupParameters.Initialize(v1, v2, v3, v4);}
+
+ const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
+ GroupParameters & AccessGroupParameters() {return m_groupParameters;}
+
+ void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
+ {
+ Base::GeneratePublicKey(rng, privateKey, publicKey);
+
+ if (FIPS_140_2_ComplianceEnabled())
+ {
+ SecByteBlock privateKey2(this->PrivateKeyLength());
+ this->GeneratePrivateKey(rng, privateKey2);
+
+ SecByteBlock publicKey2(this->PublicKeyLength());
+ Base::GeneratePublicKey(rng, privateKey2, publicKey2);
+
+ SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength());
+ bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2);
+ bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey);
+
+ if (!agreed1 || !agreed2 || agreedValue != agreedValue2)
+ throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed");
+ }
+ }
+
+ static std::string CRYPTOPP_API StaticAlgorithmName()
+ {return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();}
+ std::string AlgorithmName() const {return StaticAlgorithmName();}
+
+private:
+ const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
+ {return Singleton<DH_Algorithm>().Ref();}
+ DL_GroupParameters<Element> & AccessAbstractGroupParameters()
+ {return m_groupParameters;}
+
+ GroupParameters m_groupParameters;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime>;
+
+//! <a href="http://www.weidai.com/scan-mirror/ka.html#DH">Diffie-Hellman</a> in GF(p) with key validation
+typedef DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime> DH;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dh2.cpp b/lib/cryptopp/dh2.cpp
new file mode 100644
index 000000000..98175ee28
--- /dev/null
+++ b/lib/cryptopp/dh2.cpp
@@ -0,0 +1,22 @@
+// dh2.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "dh2.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void DH2_TestInstantiations()
+{
+ DH2 dh(*(SimpleKeyAgreementDomain*)NULL);
+}
+
+bool DH2::Agree(byte *agreedValue,
+ const byte *staticSecretKey, const byte *ephemeralSecretKey,
+ const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
+ bool validateStaticOtherPublicKey) const
+{
+ return d1.Agree(agreedValue, staticSecretKey, staticOtherPublicKey, validateStaticOtherPublicKey)
+ && d2.Agree(agreedValue+d1.AgreedValueLength(), ephemeralSecretKey, ephemeralOtherPublicKey, true);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/dh2.h b/lib/cryptopp/dh2.h
new file mode 100644
index 000000000..af9d342d6
--- /dev/null
+++ b/lib/cryptopp/dh2.h
@@ -0,0 +1,58 @@
+#ifndef CRYPTOPP_DH2_H
+#define CRYPTOPP_DH2_H
+
+/** \file
+*/
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// <a href="http://www.weidai.com/scan-mirror/ka.html#DH2">Unified Diffie-Hellman</a>
+class DH2 : public AuthenticatedKeyAgreementDomain
+{
+public:
+ DH2(SimpleKeyAgreementDomain &domain)
+ : d1(domain), d2(domain) {}
+ DH2(SimpleKeyAgreementDomain &staticDomain, SimpleKeyAgreementDomain &ephemeralDomain)
+ : d1(staticDomain), d2(ephemeralDomain) {}
+
+ CryptoParameters & AccessCryptoParameters() {return d1.AccessCryptoParameters();}
+
+ unsigned int AgreedValueLength() const
+ {return d1.AgreedValueLength() + d2.AgreedValueLength();}
+
+ unsigned int StaticPrivateKeyLength() const
+ {return d1.PrivateKeyLength();}
+ unsigned int StaticPublicKeyLength() const
+ {return d1.PublicKeyLength();}
+ void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
+ {d1.GeneratePrivateKey(rng, privateKey);}
+ void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
+ {d1.GeneratePublicKey(rng, privateKey, publicKey);}
+ void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
+ {d1.GenerateKeyPair(rng, privateKey, publicKey);}
+
+ unsigned int EphemeralPrivateKeyLength() const
+ {return d2.PrivateKeyLength();}
+ unsigned int EphemeralPublicKeyLength() const
+ {return d2.PublicKeyLength();}
+ void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
+ {d2.GeneratePrivateKey(rng, privateKey);}
+ void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
+ {d2.GeneratePublicKey(rng, privateKey, publicKey);}
+ void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
+ {d2.GenerateKeyPair(rng, privateKey, publicKey);}
+
+ bool Agree(byte *agreedValue,
+ const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
+ const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
+ bool validateStaticOtherPublicKey=true) const;
+
+protected:
+ SimpleKeyAgreementDomain &d1, &d2;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dll.cpp b/lib/cryptopp/dll.cpp
new file mode 100644
index 000000000..2b4ef7ade
--- /dev/null
+++ b/lib/cryptopp/dll.cpp
@@ -0,0 +1,146 @@
+// dll.cpp - written and placed in the public domain by Wei Dai
+
+#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
+#define CRYPTOPP_DEFAULT_NO_DLL
+
+#include "dll.h"
+#pragma warning(default: 4660)
+
+#if defined(CRYPTOPP_EXPORTS) && defined(CRYPTOPP_WIN32_AVAILABLE)
+#include <windows.h>
+#endif
+
+#ifndef CRYPTOPP_IMPORTS
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template<> const byte PKCS_DigestDecoration<SHA1>::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
+template<> const unsigned int PKCS_DigestDecoration<SHA1>::length = sizeof(PKCS_DigestDecoration<SHA1>::decoration);
+
+template<> const byte PKCS_DigestDecoration<SHA224>::decoration[] = {0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c};
+template<> const unsigned int PKCS_DigestDecoration<SHA224>::length = sizeof(PKCS_DigestDecoration<SHA224>::decoration);
+
+template<> const byte PKCS_DigestDecoration<SHA256>::decoration[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+template<> const unsigned int PKCS_DigestDecoration<SHA256>::length = sizeof(PKCS_DigestDecoration<SHA256>::decoration);
+
+template<> const byte PKCS_DigestDecoration<SHA384>::decoration[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
+template<> const unsigned int PKCS_DigestDecoration<SHA384>::length = sizeof(PKCS_DigestDecoration<SHA384>::decoration);
+
+template<> const byte PKCS_DigestDecoration<SHA512>::decoration[] = {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
+template<> const unsigned int PKCS_DigestDecoration<SHA512>::length = sizeof(PKCS_DigestDecoration<SHA512>::decoration);
+
+template<> const byte EMSA2HashId<SHA>::id = 0x33;
+template<> const byte EMSA2HashId<SHA224>::id = 0x38;
+template<> const byte EMSA2HashId<SHA256>::id = 0x34;
+template<> const byte EMSA2HashId<SHA384>::id = 0x36;
+template<> const byte EMSA2HashId<SHA512>::id = 0x35;
+
+NAMESPACE_END
+
+#endif
+
+#ifdef CRYPTOPP_EXPORTS
+
+USING_NAMESPACE(CryptoPP)
+
+#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
+using std::set_new_handler;
+#endif
+
+static PNew s_pNew = NULL;
+static PDelete s_pDelete = NULL;
+
+static void * New (size_t size)
+{
+ void *p;
+ while (!(p = malloc(size)))
+ CallNewHandler();
+
+ return p;
+}
+
+static void SetNewAndDeleteFunctionPointers()
+{
+ void *p = NULL;
+ HMODULE hModule = NULL;
+ MEMORY_BASIC_INFORMATION mbi;
+
+ while (true)
+ {
+ VirtualQuery(p, &mbi, sizeof(mbi));
+
+ if (p >= (char *)mbi.BaseAddress + mbi.RegionSize)
+ break;
+
+ p = (char *)mbi.BaseAddress + mbi.RegionSize;
+
+ if (!mbi.AllocationBase || mbi.AllocationBase == hModule)
+ continue;
+
+ hModule = HMODULE(mbi.AllocationBase);
+
+ PGetNewAndDelete pGetNewAndDelete = (PGetNewAndDelete)GetProcAddress(hModule, "GetNewAndDeleteForCryptoPP");
+ if (pGetNewAndDelete)
+ {
+ pGetNewAndDelete(s_pNew, s_pDelete);
+ return;
+ }
+
+ PSetNewAndDelete pSetNewAndDelete = (PSetNewAndDelete)GetProcAddress(hModule, "SetNewAndDeleteFromCryptoPP");
+ if (pSetNewAndDelete)
+ {
+ s_pNew = &New;
+ s_pDelete = &free;
+ pSetNewAndDelete(s_pNew, s_pDelete, &set_new_handler);
+ return;
+ }
+ }
+
+ // try getting these directly using mangled names of new and delete operators
+
+ hModule = GetModuleHandle("msvcrtd");
+ if (!hModule)
+ hModule = GetModuleHandle("msvcrt");
+ if (hModule)
+ {
+ // 32-bit versions
+ s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPAXI@Z");
+ s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPAX@Z");
+ if (s_pNew && s_pDelete)
+ return;
+
+ // 64-bit versions
+ s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPEAX_K@Z");
+ s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPEAX@Z");
+ if (s_pNew && s_pDelete)
+ return;
+ }
+
+ OutputDebugString("Crypto++ was not able to obtain new and delete function pointers.\n");
+ throw 0;
+}
+
+void * operator new (size_t size)
+{
+ if (!s_pNew)
+ SetNewAndDeleteFunctionPointers();
+
+ return s_pNew(size);
+}
+
+void operator delete (void * p)
+{
+ s_pDelete(p);
+}
+
+void * operator new [] (size_t size)
+{
+ return operator new (size);
+}
+
+void operator delete [] (void * p)
+{
+ operator delete (p);
+}
+
+#endif // #ifdef CRYPTOPP_EXPORTS
diff --git a/lib/cryptopp/dll.h b/lib/cryptopp/dll.h
new file mode 100644
index 000000000..50775e98b
--- /dev/null
+++ b/lib/cryptopp/dll.h
@@ -0,0 +1,70 @@
+#ifndef CRYPTOPP_DLL_H
+#define CRYPTOPP_DLL_H
+
+#if !defined(CRYPTOPP_IMPORTS) && !defined(CRYPTOPP_EXPORTS) && !defined(CRYPTOPP_DEFAULT_NO_DLL)
+#ifdef CRYPTOPP_CONFIG_H
+#error To use the DLL version of Crypto++, this file must be included before any other Crypto++ header files.
+#endif
+#define CRYPTOPP_IMPORTS
+#endif
+
+#include "aes.h"
+#include "cbcmac.h"
+#include "ccm.h"
+#include "cmac.h"
+#include "channels.h"
+#include "des.h"
+#include "dh.h"
+#include "dsa.h"
+#include "ec2n.h"
+#include "eccrypto.h"
+#include "ecp.h"
+#include "files.h"
+#include "fips140.h"
+#include "gcm.h"
+#include "hex.h"
+#include "hmac.h"
+#include "modes.h"
+#include "mqueue.h"
+#include "nbtheory.h"
+#include "osrng.h"
+#include "pkcspad.h"
+#include "pssr.h"
+#include "randpool.h"
+#include "rsa.h"
+#include "rw.h"
+#include "sha.h"
+#include "trdlocal.h"
+
+#ifdef CRYPTOPP_IMPORTS
+
+#ifdef _DLL
+// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain()
+#ifdef NDEBUG
+#pragma comment(lib, "msvcrt")
+#else
+#pragma comment(lib, "msvcrtd")
+#endif
+#endif
+
+#pragma comment(lib, "cryptopp")
+
+#endif // #ifdef CRYPTOPP_IMPORTS
+
+#include <new> // for new_handler
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
+using std::new_handler;
+#endif
+
+typedef void * (CRYPTOPP_API * PNew)(size_t);
+typedef void (CRYPTOPP_API * PDelete)(void *);
+typedef void (CRYPTOPP_API * PGetNewAndDelete)(PNew &, PDelete &);
+typedef new_handler (CRYPTOPP_API * PSetNewHandler)(new_handler);
+typedef void (CRYPTOPP_API * PSetNewAndDelete)(PNew, PDelete, PSetNewHandler);
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dmac.h b/lib/cryptopp/dmac.h
new file mode 100644
index 000000000..80b54ac2f
--- /dev/null
+++ b/lib/cryptopp/dmac.h
@@ -0,0 +1,93 @@
+#ifndef CRYPTOPP_DMAC_H
+#define CRYPTOPP_DMAC_H
+
+#include "cbcmac.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE DMAC_Base : public SameKeyLengthAs<T>, public MessageAuthenticationCode
+{
+public:
+ static std::string StaticAlgorithmName() {return std::string("DMAC(") + T::StaticAlgorithmName() + ")";}
+
+ CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE)
+
+ DMAC_Base() {}
+
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *mac, size_t size);
+ unsigned int DigestSize() const {return DIGESTSIZE;}
+
+private:
+ byte *GenerateSubKeys(const byte *key, size_t keylength);
+
+ size_t m_subkeylength;
+ SecByteBlock m_subkeys;
+ CBC_MAC<T> m_mac1;
+ typename T::Encryption m_f2;
+ unsigned int m_counter;
+};
+
+//! DMAC
+/*! Based on "CBC MAC for Real-Time Data Sources" by Erez Petrank
+ and Charles Rackoff. T should be a class derived from BlockCipherDocumentation.
+*/
+template <class T>
+class DMAC : public MessageAuthenticationCodeFinal<DMAC_Base<T> >
+{
+public:
+ DMAC() {}
+ DMAC(const byte *key, size_t length=DMAC_Base<T>::DEFAULT_KEYLENGTH)
+ {this->SetKey(key, length);}
+};
+
+template <class T>
+void DMAC_Base<T>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+{
+ m_subkeylength = T::StaticGetValidKeyLength(T::BLOCKSIZE);
+ m_subkeys.resize(2*UnsignedMin((unsigned int)T::BLOCKSIZE, m_subkeylength));
+ m_mac1.SetKey(GenerateSubKeys(key, length), m_subkeylength, params);
+ m_f2.SetKey(m_subkeys+m_subkeys.size()/2, m_subkeylength, params);
+ m_counter = 0;
+ m_subkeys.resize(0);
+}
+
+template <class T>
+void DMAC_Base<T>::Update(const byte *input, size_t length)
+{
+ m_mac1.Update(input, length);
+ m_counter = (unsigned int)((m_counter + length) % T::BLOCKSIZE);
+}
+
+template <class T>
+void DMAC_Base<T>::TruncatedFinal(byte *mac, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ byte pad[T::BLOCKSIZE];
+ byte padByte = byte(T::BLOCKSIZE-m_counter);
+ memset(pad, padByte, padByte);
+ m_mac1.Update(pad, padByte);
+ m_mac1.TruncatedFinal(mac, size);
+ m_f2.ProcessBlock(mac);
+
+ m_counter = 0; // reset for next message
+}
+
+template <class T>
+byte *DMAC_Base<T>::GenerateSubKeys(const byte *key, size_t keylength)
+{
+ typename T::Encryption cipher(key, keylength);
+ memset(m_subkeys, 0, m_subkeys.size());
+ cipher.ProcessBlock(m_subkeys);
+ m_subkeys[m_subkeys.size()/2 + T::BLOCKSIZE - 1] = 1;
+ cipher.ProcessBlock(m_subkeys+m_subkeys.size()/2);
+ return m_subkeys;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dsa.cpp b/lib/cryptopp/dsa.cpp
new file mode 100644
index 000000000..5aace4857
--- /dev/null
+++ b/lib/cryptopp/dsa.cpp
@@ -0,0 +1,63 @@
+// dsa.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "dsa.h"
+#include "nbtheory.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat)
+{
+ Integer r, s;
+ StringStore store(signature, signatureLen);
+ ArraySink sink(buffer, bufferSize);
+
+ switch (fromFormat)
+ {
+ case DSA_P1363:
+ r.Decode(store, signatureLen/2);
+ s.Decode(store, signatureLen/2);
+ break;
+ case DSA_DER:
+ {
+ BERSequenceDecoder seq(store);
+ r.BERDecode(seq);
+ s.BERDecode(seq);
+ seq.MessageEnd();
+ break;
+ }
+ case DSA_OPENPGP:
+ r.OpenPGPDecode(store);
+ s.OpenPGPDecode(store);
+ break;
+ }
+
+ switch (toFormat)
+ {
+ case DSA_P1363:
+ r.Encode(sink, bufferSize/2);
+ s.Encode(sink, bufferSize/2);
+ break;
+ case DSA_DER:
+ {
+ DERSequenceEncoder seq(sink);
+ r.DEREncode(seq);
+ s.DEREncode(seq);
+ seq.MessageEnd();
+ break;
+ }
+ case DSA_OPENPGP:
+ r.OpenPGPEncode(sink);
+ s.OpenPGPEncode(sink);
+ break;
+ }
+
+ return (size_t)sink.TotalPutLength();
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/dsa.h b/lib/cryptopp/dsa.h
new file mode 100644
index 000000000..6ae03877c
--- /dev/null
+++ b/lib/cryptopp/dsa.h
@@ -0,0 +1,35 @@
+#ifndef CRYPTOPP_DSA_H
+#define CRYPTOPP_DSA_H
+
+/** \file
+*/
+
+#include "gfpcrypt.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/*! The DSA signature format used by Crypto++ is as defined by IEEE P1363.
+ Java uses the DER format, and OpenPGP uses the OpenPGP format. */
+enum DSASignatureFormat {DSA_P1363, DSA_DER, DSA_OPENPGP};
+/** This function converts between these formats, and returns length of signature in the target format.
+ If toFormat == DSA_P1363, bufferSize must equal publicKey.SignatureLength() */
+size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat,
+ const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat);
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+
+typedef DSA::Signer DSAPrivateKey;
+typedef DSA::Verifier DSAPublicKey;
+
+const int MIN_DSA_PRIME_LENGTH = DSA::MIN_PRIME_LENGTH;
+const int MAX_DSA_PRIME_LENGTH = DSA::MAX_PRIME_LENGTH;
+const int DSA_PRIME_LENGTH_MULTIPLE = DSA::PRIME_LENGTH_MULTIPLE;
+
+inline bool GenerateDSAPrimes(const byte *seed, size_t seedLength, int &counter, Integer &p, unsigned int primeLength, Integer &q)
+ {return DSA::GeneratePrimes(seed, seedLength, counter, p, primeLength, q);}
+
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/eax.cpp b/lib/cryptopp/eax.cpp
new file mode 100644
index 000000000..2728c9bcd
--- /dev/null
+++ b/lib/cryptopp/eax.cpp
@@ -0,0 +1,59 @@
+// eax.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "eax.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void EAX_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
+{
+ AccessMAC().SetKey(userKey, keylength, params);
+ m_buffer.New(2*AccessMAC().TagSize());
+}
+
+void EAX_Base::Resync(const byte *iv, size_t len)
+{
+ MessageAuthenticationCode &mac = AccessMAC();
+ unsigned int blockSize = mac.TagSize();
+
+ memset(m_buffer, 0, blockSize);
+ mac.Update(m_buffer, blockSize);
+ mac.CalculateDigest(m_buffer+blockSize, iv, len);
+
+ m_buffer[blockSize-1] = 1;
+ mac.Update(m_buffer, blockSize);
+
+ m_ctr.SetCipherWithIV(AccessMAC().AccessCipher(), m_buffer+blockSize, blockSize);
+}
+
+size_t EAX_Base::AuthenticateBlocks(const byte *data, size_t len)
+{
+ AccessMAC().Update(data, len);
+ return 0;
+}
+
+void EAX_Base::AuthenticateLastHeaderBlock()
+{
+ assert(m_bufferedDataLength == 0);
+ MessageAuthenticationCode &mac = AccessMAC();
+ unsigned int blockSize = mac.TagSize();
+
+ mac.Final(m_buffer);
+ xorbuf(m_buffer+blockSize, m_buffer, blockSize);
+
+ memset(m_buffer, 0, blockSize);
+ m_buffer[blockSize-1] = 2;
+ mac.Update(m_buffer, blockSize);
+}
+
+void EAX_Base::AuthenticateLastFooterBlock(byte *tag, size_t macSize)
+{
+ assert(m_bufferedDataLength == 0);
+ MessageAuthenticationCode &mac = AccessMAC();
+ unsigned int blockSize = mac.TagSize();
+
+ mac.TruncatedFinal(m_buffer, macSize);
+ xorbuf(tag, m_buffer, m_buffer+blockSize, macSize);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/eax.h b/lib/cryptopp/eax.h
new file mode 100644
index 000000000..e48ee92b5
--- /dev/null
+++ b/lib/cryptopp/eax.h
@@ -0,0 +1,91 @@
+#ifndef CRYPTOPP_EAX_H
+#define CRYPTOPP_EAX_H
+
+#include "authenc.h"
+#include "modes.h"
+#include "cmac.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! .
+class CRYPTOPP_NO_VTABLE EAX_Base : public AuthenticatedSymmetricCipherBase
+{
+public:
+ // AuthenticatedSymmetricCipher
+ std::string AlgorithmName() const
+ {return GetMAC().GetCipher().AlgorithmName() + std::string("/EAX");}
+ size_t MinKeyLength() const
+ {return GetMAC().MinKeyLength();}
+ size_t MaxKeyLength() const
+ {return GetMAC().MaxKeyLength();}
+ size_t DefaultKeyLength() const
+ {return GetMAC().DefaultKeyLength();}
+ size_t GetValidKeyLength(size_t n) const
+ {return GetMAC().GetValidKeyLength(n);}
+ bool IsValidKeyLength(size_t n) const
+ {return GetMAC().IsValidKeyLength(n);}
+ unsigned int OptimalDataAlignment() const
+ {return GetMAC().OptimalDataAlignment();}
+ IV_Requirement IVRequirement() const
+ {return UNIQUE_IV;}
+ unsigned int IVSize() const
+ {return GetMAC().TagSize();}
+ unsigned int MinIVLength() const
+ {return 0;}
+ unsigned int MaxIVLength() const
+ {return UINT_MAX;}
+ unsigned int DigestSize() const
+ {return GetMAC().TagSize();}
+ lword MaxHeaderLength() const
+ {return LWORD_MAX;}
+ lword MaxMessageLength() const
+ {return LWORD_MAX;}
+
+protected:
+ // AuthenticatedSymmetricCipherBase
+ bool AuthenticationIsOnPlaintext() const
+ {return false;}
+ unsigned int AuthenticationBlockSize() const
+ {return 1;}
+ void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
+ void Resync(const byte *iv, size_t len);
+ size_t AuthenticateBlocks(const byte *data, size_t len);
+ void AuthenticateLastHeaderBlock();
+ void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
+ SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
+ const CMAC_Base & GetMAC() const {return const_cast<EAX_Base *>(this)->AccessMAC();}
+ virtual CMAC_Base & AccessMAC() =0;
+
+ CTR_Mode_ExternalCipher::Encryption m_ctr;
+};
+
+//! .
+template <class T_BlockCipher, bool T_IsEncryption>
+class EAX_Final : public EAX_Base
+{
+public:
+ static std::string StaticAlgorithmName()
+ {return T_BlockCipher::StaticAlgorithmName() + std::string("/EAX");}
+ bool IsForwardTransformation() const
+ {return T_IsEncryption;}
+
+private:
+ CMAC_Base & AccessMAC() {return m_cmac;}
+ CMAC<T_BlockCipher> m_cmac;
+};
+
+#ifdef EAX // EAX is defined to 11 on GCC 3.4.3, OpenSolaris 8.11
+#undef EAX
+#endif
+
+/// <a href="http://www.cryptolounge.org/wiki/EAX">EAX</a>
+template <class T_BlockCipher>
+struct EAX : public AuthenticatedSymmetricCipherDocumentation
+{
+ typedef EAX_Final<T_BlockCipher, true> Encryption;
+ typedef EAX_Final<T_BlockCipher, false> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/ec2n.cpp b/lib/cryptopp/ec2n.cpp
new file mode 100644
index 000000000..b513b2cb8
--- /dev/null
+++ b/lib/cryptopp/ec2n.cpp
@@ -0,0 +1,292 @@
+// ec2n.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "ec2n.h"
+#include "asn.h"
+
+#include "algebra.cpp"
+#include "eprecomp.cpp"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+EC2N::EC2N(BufferedTransformation &bt)
+ : m_field(BERDecodeGF2NP(bt))
+{
+ BERSequenceDecoder seq(bt);
+ m_field->BERDecodeElement(seq, m_a);
+ m_field->BERDecodeElement(seq, m_b);
+ // skip optional seed
+ if (!seq.EndReached())
+ {
+ SecByteBlock seed;
+ unsigned int unused;
+ BERDecodeBitString(seq, seed, unused);
+ }
+ seq.MessageEnd();
+}
+
+void EC2N::DEREncode(BufferedTransformation &bt) const
+{
+ m_field->DEREncode(bt);
+ DERSequenceEncoder seq(bt);
+ m_field->DEREncodeElement(seq, m_a);
+ m_field->DEREncodeElement(seq, m_b);
+ seq.MessageEnd();
+}
+
+bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, size_t encodedPointLen) const
+{
+ StringStore store(encodedPoint, encodedPointLen);
+ return DecodePoint(P, store, encodedPointLen);
+}
+
+bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const
+{
+ byte type;
+ if (encodedPointLen < 1 || !bt.Get(type))
+ return false;
+
+ switch (type)
+ {
+ case 0:
+ P.identity = true;
+ return true;
+ case 2:
+ case 3:
+ {
+ if (encodedPointLen != EncodedPointSize(true))
+ return false;
+
+ P.identity = false;
+ P.x.Decode(bt, m_field->MaxElementByteLength());
+
+ if (P.x.IsZero())
+ {
+ P.y = m_field->SquareRoot(m_b);
+ return true;
+ }
+
+ FieldElement z = m_field->Square(P.x);
+ assert(P.x == m_field->SquareRoot(z));
+ P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z);
+ assert(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a));
+ z = m_field->SolveQuadraticEquation(P.y);
+ assert(m_field->Add(m_field->Square(z), z) == P.y);
+ z.SetCoefficient(0, type & 1);
+
+ P.y = m_field->Multiply(z, P.x);
+ return true;
+ }
+ case 4:
+ {
+ if (encodedPointLen != EncodedPointSize(false))
+ return false;
+
+ unsigned int len = m_field->MaxElementByteLength();
+ P.identity = false;
+ P.x.Decode(bt, len);
+ P.y.Decode(bt, len);
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
+void EC2N::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
+{
+ if (P.identity)
+ NullStore().TransferTo(bt, EncodedPointSize(compressed));
+ else if (compressed)
+ {
+ bt.Put(2 + (!P.x ? 0 : m_field->Divide(P.y, P.x).GetBit(0)));
+ P.x.Encode(bt, m_field->MaxElementByteLength());
+ }
+ else
+ {
+ unsigned int len = m_field->MaxElementByteLength();
+ bt.Put(4); // uncompressed
+ P.x.Encode(bt, len);
+ P.y.Encode(bt, len);
+ }
+}
+
+void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const
+{
+ ArraySink sink(encodedPoint, EncodedPointSize(compressed));
+ EncodePoint(sink, P, compressed);
+ assert(sink.TotalPutLength() == EncodedPointSize(compressed));
+}
+
+EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const
+{
+ SecByteBlock str;
+ BERDecodeOctetString(bt, str);
+ Point P;
+ if (!DecodePoint(P, str, str.size()))
+ BERDecodeError();
+ return P;
+}
+
+void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
+{
+ SecByteBlock str(EncodedPointSize(compressed));
+ EncodePoint(str, P, compressed);
+ DEREncodeOctetString(bt, str);
+}
+
+bool EC2N::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = !!m_b;
+ pass = pass && m_a.CoefficientCount() <= m_field->MaxElementBitLength();
+ pass = pass && m_b.CoefficientCount() <= m_field->MaxElementBitLength();
+
+ if (level >= 1)
+ pass = pass && m_field->GetModulus().IsIrreducible();
+
+ return pass;
+}
+
+bool EC2N::VerifyPoint(const Point &P) const
+{
+ const FieldElement &x = P.x, &y = P.y;
+ return P.identity ||
+ (x.CoefficientCount() <= m_field->MaxElementBitLength()
+ && y.CoefficientCount() <= m_field->MaxElementBitLength()
+ && !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus()));
+}
+
+bool EC2N::Equal(const Point &P, const Point &Q) const
+{
+ if (P.identity && Q.identity)
+ return true;
+
+ if (P.identity && !Q.identity)
+ return false;
+
+ if (!P.identity && Q.identity)
+ return false;
+
+ return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y));
+}
+
+const EC2N::Point& EC2N::Identity() const
+{
+ return Singleton<Point>().Ref();
+}
+
+const EC2N::Point& EC2N::Inverse(const Point &P) const
+{
+ if (P.identity)
+ return P;
+ else
+ {
+ m_R.identity = false;
+ m_R.y = m_field->Add(P.x, P.y);
+ m_R.x = P.x;
+ return m_R;
+ }
+}
+
+const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const
+{
+ if (P.identity) return Q;
+ if (Q.identity) return P;
+ if (Equal(P, Q)) return Double(P);
+ if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Identity();
+
+ FieldElement t = m_field->Add(P.y, Q.y);
+ t = m_field->Divide(t, m_field->Add(P.x, Q.x));
+ FieldElement x = m_field->Square(t);
+ m_field->Accumulate(x, t);
+ m_field->Accumulate(x, Q.x);
+ m_field->Accumulate(x, m_a);
+ m_R.y = m_field->Add(P.y, m_field->Multiply(t, x));
+ m_field->Accumulate(x, P.x);
+ m_field->Accumulate(m_R.y, x);
+
+ m_R.x.swap(x);
+ m_R.identity = false;
+ return m_R;
+}
+
+const EC2N::Point& EC2N::Double(const Point &P) const
+{
+ if (P.identity) return P;
+ if (!m_field->IsUnit(P.x)) return Identity();
+
+ FieldElement t = m_field->Divide(P.y, P.x);
+ m_field->Accumulate(t, P.x);
+ m_R.y = m_field->Square(P.x);
+ m_R.x = m_field->Square(t);
+ m_field->Accumulate(m_R.x, t);
+ m_field->Accumulate(m_R.x, m_a);
+ m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x));
+ m_field->Accumulate(m_R.y, m_R.x);
+
+ m_R.identity = false;
+ return m_R;
+}
+
+// ********************************************************
+
+/*
+EcPrecomputation<EC2N>& EcPrecomputation<EC2N>::operator=(const EcPrecomputation<EC2N> &rhs)
+{
+ m_ec = rhs.m_ec;
+ m_ep = rhs.m_ep;
+ m_ep.m_group = m_ec.get();
+ return *this;
+}
+
+void EcPrecomputation<EC2N>::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base)
+{
+ m_ec.reset(new EC2N(ec));
+ m_ep.SetGroupAndBase(*m_ec, base);
+}
+
+void EcPrecomputation<EC2N>::Precompute(unsigned int maxExpBits, unsigned int storage)
+{
+ m_ep.Precompute(maxExpBits, storage);
+}
+
+void EcPrecomputation<EC2N>::Load(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ word32 version;
+ BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
+ m_ep.m_exponentBase.BERDecode(seq);
+ m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1;
+ m_ep.m_bases.clear();
+ while (!seq.EndReached())
+ m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq));
+ seq.MessageEnd();
+}
+
+void EcPrecomputation<EC2N>::Save(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ DEREncodeUnsigned<word32>(seq, 1); // version
+ m_ep.m_exponentBase.DEREncode(seq);
+ for (unsigned i=0; i<m_ep.m_bases.size(); i++)
+ m_ec->DEREncodePoint(seq, m_ep.m_bases[i]);
+ seq.MessageEnd();
+}
+
+EC2N::Point EcPrecomputation<EC2N>::Exponentiate(const Integer &exponent) const
+{
+ return m_ep.Exponentiate(exponent);
+}
+
+EC2N::Point EcPrecomputation<EC2N>::CascadeExponentiate(const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const
+{
+ return m_ep.CascadeExponentiate(exponent, static_cast<const EcPrecomputation<EC2N> &>(pc2).m_ep, exponent2);
+}
+*/
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/ec2n.h b/lib/cryptopp/ec2n.h
new file mode 100644
index 000000000..ae4007cd6
--- /dev/null
+++ b/lib/cryptopp/ec2n.h
@@ -0,0 +1,113 @@
+#ifndef CRYPTOPP_EC2N_H
+#define CRYPTOPP_EC2N_H
+
+#include "gf2n.h"
+#include "eprecomp.h"
+#include "smartptr.h"
+#include "pubkey.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Elliptic Curve Point
+struct CRYPTOPP_DLL EC2NPoint
+{
+ EC2NPoint() : identity(true) {}
+ EC2NPoint(const PolynomialMod2 &x, const PolynomialMod2 &y)
+ : identity(false), x(x), y(y) {}
+
+ bool operator==(const EC2NPoint &t) const
+ {return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
+ bool operator< (const EC2NPoint &t) const
+ {return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
+
+ bool identity;
+ PolynomialMod2 x, y;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<EC2NPoint>;
+
+//! Elliptic Curve over GF(2^n)
+class CRYPTOPP_DLL EC2N : public AbstractGroup<EC2NPoint>
+{
+public:
+ typedef GF2NP Field;
+ typedef Field::Element FieldElement;
+ typedef EC2NPoint Point;
+
+ EC2N() {}
+ EC2N(const Field &field, const Field::Element &a, const Field::Element &b)
+ : m_field(field), m_a(a), m_b(b) {}
+ // construct from BER encoded parameters
+ // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
+ EC2N(BufferedTransformation &bt);
+
+ // encode the fields fieldID and curve of the sequence ECParameters
+ void DEREncode(BufferedTransformation &bt) const;
+
+ bool Equal(const Point &P, const Point &Q) const;
+ const Point& Identity() const;
+ const Point& Inverse(const Point &P) const;
+ bool InversionIsFast() const {return true;}
+ const Point& Add(const Point &P, const Point &Q) const;
+ const Point& Double(const Point &P) const;
+
+ Point Multiply(const Integer &k, const Point &P) const
+ {return ScalarMultiply(P, k);}
+ Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const
+ {return CascadeScalarMultiply(P, k1, Q, k2);}
+
+ bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const;
+ bool VerifyPoint(const Point &P) const;
+
+ unsigned int EncodedPointSize(bool compressed = false) const
+ {return 1 + (compressed?1:2)*m_field->MaxElementByteLength();}
+ // returns false if point is compressed and not valid (doesn't check if uncompressed)
+ bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const;
+ bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const;
+ void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const;
+ void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
+
+ Point BERDecodePoint(BufferedTransformation &bt) const;
+ void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
+
+ Integer FieldSize() const {return Integer::Power2(m_field->MaxElementBitLength());}
+ const Field & GetField() const {return *m_field;}
+ const FieldElement & GetA() const {return m_a;}
+ const FieldElement & GetB() const {return m_b;}
+
+ bool operator==(const EC2N &rhs) const
+ {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;}
+
+private:
+ clonable_ptr<Field> m_field;
+ FieldElement m_a, m_b;
+ mutable Point m_R;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<EC2N::Point>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation<EC2N::Point>;
+
+template <class T> class EcPrecomputation;
+
+//! EC2N precomputation
+template<> class EcPrecomputation<EC2N> : public DL_GroupPrecomputation<EC2N::Point>
+{
+public:
+ typedef EC2N EllipticCurve;
+
+ // DL_GroupPrecomputation
+ const AbstractGroup<Element> & GetGroup() const {return m_ec;}
+ Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec.BERDecodePoint(bt);}
+ void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec.DEREncodePoint(bt, v, false);}
+
+ // non-inherited
+ void SetCurve(const EC2N &ec) {m_ec = ec;}
+ const EC2N & GetCurve() const {return m_ec;}
+
+private:
+ EC2N m_ec;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/eccrypto.cpp b/lib/cryptopp/eccrypto.cpp
new file mode 100644
index 000000000..922104c4d
--- /dev/null
+++ b/lib/cryptopp/eccrypto.cpp
@@ -0,0 +1,694 @@
+// eccrypto.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "eccrypto.h"
+#include "nbtheory.h"
+#include "oids.h"
+#include "hex.h"
+#include "argnames.h"
+#include "ec2n.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if 0
+static void ECDSA_TestInstantiations()
+{
+ ECDSA<EC2N>::Signer t1;
+ ECDSA<EC2N>::Verifier t2(t1);
+ ECNR<ECP>::Signer t3;
+ ECNR<ECP>::Verifier t4(t3);
+ ECIES<ECP>::Encryptor t5;
+ ECIES<EC2N>::Decryptor t6;
+ ECDH<ECP>::Domain t7;
+ ECMQV<ECP>::Domain t8;
+}
+#endif
+
+// VC60 workaround: complains when these functions are put into an anonymous namespace
+static Integer ConvertToInteger(const PolynomialMod2 &x)
+{
+ unsigned int l = x.ByteCount();
+ SecByteBlock temp(l);
+ x.Encode(temp, l);
+ return Integer(temp, l);
+}
+
+static inline Integer ConvertToInteger(const Integer &x)
+{
+ return x;
+}
+
+static bool CheckMOVCondition(const Integer &q, const Integer &r)
+{
+ // see "Updated standards for validating elliptic curves", http://eprint.iacr.org/2007/343
+ Integer t = 1;
+ unsigned int n = q.IsEven() ? 1 : q.BitCount(), m = r.BitCount();
+
+ for (unsigned int i=n; DiscreteLogWorkFactor(i)<m/2; i+=n)
+ {
+ if (q.IsEven())
+ t = (t+t)%r;
+ else
+ t = (t*q)%r;
+ if (t == 1)
+ return false;
+ }
+ return true;
+}
+
+// ******************************************************************
+
+template <class T> struct EcRecommendedParameters;
+
+template<> struct EcRecommendedParameters<EC2N>
+{
+ EcRecommendedParameters(const OID &oid, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h)
+ : oid(oid), t0(0), t1(0), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {}
+ EcRecommendedParameters(const OID &oid, unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h)
+ : oid(oid), t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {}
+ EC2N *NewEC() const
+ {
+ StringSource ssA(a, true, new HexDecoder);
+ StringSource ssB(b, true, new HexDecoder);
+ if (t0 == 0)
+ return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
+ else
+ return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
+ };
+
+ OID oid;
+ unsigned int t0, t1, t2, t3, t4;
+ const char *a, *b, *g, *n;
+ unsigned int h;
+};
+
+template<> struct EcRecommendedParameters<ECP>
+{
+ EcRecommendedParameters(const OID &oid, const char *p, const char *a, const char *b, const char *g, const char *n, unsigned int h)
+ : oid(oid), p(p), a(a), b(b), g(g), n(n), h(h) {}
+ ECP *NewEC() const
+ {
+ StringSource ssP(p, true, new HexDecoder);
+ StringSource ssA(a, true, new HexDecoder);
+ StringSource ssB(b, true, new HexDecoder);
+ return new ECP(Integer(ssP, (size_t)ssP.MaxRetrievable()), ECP::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), ECP::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
+ };
+
+ OID oid;
+ const char *p;
+ const char *a, *b, *g, *n;
+ unsigned int h;
+};
+
+struct OIDLessThan
+{
+ template <typename T>
+ inline bool operator()(const EcRecommendedParameters<T>& a, const OID& b) {return a.oid < b;}
+ template <typename T>
+ inline bool operator()(const OID& a, const EcRecommendedParameters<T>& b) {return a < b.oid;}
+ template <typename T>
+ inline bool operator()(const EcRecommendedParameters<T>& a, const EcRecommendedParameters<T>& b) {return a.oid < b.oid;}
+};
+
+static void GetRecommendedParameters(const EcRecommendedParameters<EC2N> *&begin, const EcRecommendedParameters<EC2N> *&end)
+{
+ // this array must be sorted by OID
+ static const EcRecommendedParameters<EC2N> rec[] = {
+ EcRecommendedParameters<EC2N>(ASN1::sect163k1(),
+ 163, 7, 6, 3, 0,
+ "000000000000000000000000000000000000000001",
+ "000000000000000000000000000000000000000001",
+ "0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9",
+ "04000000000000000000020108A2E0CC0D99F8A5EF",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect163r1(),
+ 163, 7, 6, 3, 0,
+ "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2",
+ "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9",
+ "040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883",
+ "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect239k1(),
+ 239, 158, 0,
+ "000000000000000000000000000000000000000000000000000000000000",
+ "000000000000000000000000000000000000000000000000000000000001",
+ "0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA",
+ "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5",
+ 4),
+ EcRecommendedParameters<EC2N>(ASN1::sect113r1(),
+ 113, 9, 0,
+ "003088250CA6E7C7FE649CE85820F7",
+ "00E8BEE4D3E2260744188BE0E9C723",
+ "04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886",
+ "0100000000000000D9CCEC8A39E56F",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect113r2(),
+ 113, 9, 0,
+ "00689918DBEC7E5A0DD6DFC0AA55C7",
+ "0095E9A9EC9B297BD4BF36E059184F",
+ "0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D",
+ "010000000000000108789B2496AF93",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect163r2(),
+ 163, 7, 6, 3, 0,
+ "000000000000000000000000000000000000000001",
+ "020A601907B8C953CA1481EB10512F78744A3205FD",
+ "0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
+ "040000000000000000000292FE77E70C12A4234C33",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect283k1(),
+ 283, 12, 7, 5, 0,
+ "000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000000000000000000000000000000000000000000000000000000000000000000001",
+ "040503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC245849283601CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
+ 4),
+ EcRecommendedParameters<EC2N>(ASN1::sect283r1(),
+ 283, 12, 7, 5, 0,
+ "000000000000000000000000000000000000000000000000000000000000000000000001",
+ "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
+ "0405F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B1205303676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
+ "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect131r1(),
+ 131, 8, 3, 2, 0,
+ "07A11B09A76B562144418FF3FF8C2570B8",
+ "0217C05610884B63B9C6C7291678F9D341",
+ "040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150",
+ "0400000000000000023123953A9464B54D",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect131r2(),
+ 131, 8, 3, 2, 0,
+ "03E5A88919D7CAFCBF415F07C2176573B2",
+ "04B8266A46C55657AC734CE38F018F2192",
+ "040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F",
+ "0400000000000000016954A233049BA98F",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect193r1(),
+ 193, 15, 0,
+ "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01",
+ "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814",
+ "0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05",
+ "01000000000000000000000000C7F34A778F443ACC920EBA49",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect193r2(),
+ 193, 15, 0,
+ "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B",
+ "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE",
+ "0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C",
+ "010000000000000000000000015AAB561B005413CCD4EE99D5",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect233k1(),
+ 233, 74, 0,
+ "000000000000000000000000000000000000000000000000000000000000",
+ "000000000000000000000000000000000000000000000000000000000001",
+ "04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
+ "8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
+ 4),
+ EcRecommendedParameters<EC2N>(ASN1::sect233r1(),
+ 233, 74, 0,
+ "000000000000000000000000000000000000000000000000000000000001",
+ "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
+ "0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
+ "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect409k1(),
+ 409, 87, 0,
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "040060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE902374601E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
+ "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
+ 4),
+ EcRecommendedParameters<EC2N>(ASN1::sect409r1(),
+ 409, 87, 0,
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
+ "04015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A70061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
+ "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
+ 2),
+ EcRecommendedParameters<EC2N>(ASN1::sect571k1(),
+ 571, 10, 5, 2, 0,
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "04026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C89720349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
+ "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
+ 4),
+ EcRecommendedParameters<EC2N>(ASN1::sect571r1(),
+ 571, 10, 5, 2, 0,
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
+ "040303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
+ "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
+ 2),
+ };
+ begin = rec;
+ end = rec + sizeof(rec)/sizeof(rec[0]);
+}
+
+static void GetRecommendedParameters(const EcRecommendedParameters<ECP> *&begin, const EcRecommendedParameters<ECP> *&end)
+{
+ // this array must be sorted by OID
+ static const EcRecommendedParameters<ECP> rec[] = {
+ EcRecommendedParameters<ECP>(ASN1::secp192r1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
+ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
+ "04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp256r1(),
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::brainpoolP160r1(),
+ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
+ "1E589A8595423412134FAA2DBDEC95C8D8675E58",
+ "04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321",
+ "E95E4A5F737059DC60DF5991D45029409E60FC09",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::brainpoolP192r1(),
+ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
+ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
+ "04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
+ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::brainpoolP224r1(),
+ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
+ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
+ "040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
+ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::brainpoolP256r1(),
+ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
+ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
+ "048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
+ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::brainpoolP320r1(),
+ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
+ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
+ "0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
+ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::brainpoolP384r1(),
+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
+ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
+ "041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::brainpoolP512r1(),
+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
+ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
+ "0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp112r1(),
+ "DB7C2ABF62E35E668076BEAD208B",
+ "DB7C2ABF62E35E668076BEAD2088",
+ "659EF8BA043916EEDE8911702B22",
+ "0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500",
+ "DB7C2ABF62E35E7628DFAC6561C5",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp112r2(),
+ "DB7C2ABF62E35E668076BEAD208B",
+ "6127C24C05F38A0AAAF65C0EF02C",
+ "51DEF1815DB5ED74FCC34C85D709",
+ "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97",
+ "36DF0AAFD8B8D7597CA10520D04B",
+ 4),
+ EcRecommendedParameters<ECP>(ASN1::secp160r1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
+ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
+ "044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32",
+ "0100000000000000000001F4C8F927AED3CA752257",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp160k1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
+ "0000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000007",
+ "043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE",
+ "0100000000000000000001B8FA16DFAB9ACA16B6B3",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp256k1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000007",
+ "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp128r1(),
+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
+ "E87579C11079F43DD824993C2CEE5ED3",
+ "04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83",
+ "FFFFFFFE0000000075A30D1B9038A115",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp128r2(),
+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
+ "D6031998D1B3BBFEBF59CC9BBFF9AEE1",
+ "5EEEFCA380D02919DC2C6558BB6D8A5D",
+ "047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44",
+ "3FFFFFFF7FFFFFFFBE0024720613B5A3",
+ 4),
+ EcRecommendedParameters<ECP>(ASN1::secp160r2(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
+ "B4E134D3FB59EB8BAB57274904664D5AF50388BA",
+ "0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
+ "0100000000000000000000351EE786A818F3A1A16B",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp192k1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
+ "000000000000000000000000000000000000000000000000",
+ "000000000000000000000000000000000000000000000003",
+ "04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
+ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp224k1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
+ "00000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000000000000000000000000005",
+ "04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
+ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp224r1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
+ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
+ "04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp384r1(),
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ "04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ 1),
+ EcRecommendedParameters<ECP>(ASN1::secp521r1(),
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ 1),
+ };
+ begin = rec;
+ end = rec + sizeof(rec)/sizeof(rec[0]);
+}
+
+template <class EC> OID DL_GroupParameters_EC<EC>::GetNextRecommendedParametersOID(const OID &oid)
+{
+ const EcRecommendedParameters<EllipticCurve> *begin, *end;
+ GetRecommendedParameters(begin, end);
+ const EcRecommendedParameters<EllipticCurve> *it = std::upper_bound(begin, end, oid, OIDLessThan());
+ return (it == end ? OID() : it->oid);
+}
+
+template <class EC> void DL_GroupParameters_EC<EC>::Initialize(const OID &oid)
+{
+ const EcRecommendedParameters<EllipticCurve> *begin, *end;
+ GetRecommendedParameters(begin, end);
+ const EcRecommendedParameters<EllipticCurve> *it = std::lower_bound(begin, end, oid, OIDLessThan());
+ if (it == end || it->oid != oid)
+ throw UnknownOID();
+
+ const EcRecommendedParameters<EllipticCurve> &param = *it;
+ m_oid = oid;
+ std::auto_ptr<EllipticCurve> ec(param.NewEC());
+ this->m_groupPrecomputation.SetCurve(*ec);
+
+ StringSource ssG(param.g, true, new HexDecoder);
+ Element G;
+ bool result = GetCurve().DecodePoint(G, ssG, (size_t)ssG.MaxRetrievable());
+ this->SetSubgroupGenerator(G);
+ assert(result);
+
+ StringSource ssN(param.n, true, new HexDecoder);
+ m_n.Decode(ssN, (size_t)ssN.MaxRetrievable());
+ m_k = param.h;
+}
+
+template <class EC>
+bool DL_GroupParameters_EC<EC>::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ if (strcmp(name, Name::GroupOID()) == 0)
+ {
+ if (m_oid.m_values.empty())
+ return false;
+
+ this->ThrowIfTypeMismatch(name, typeid(OID), valueType);
+ *reinterpret_cast<OID *>(pValue) = m_oid;
+ return true;
+ }
+ else
+ return GetValueHelper<DL_GroupParameters<Element> >(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Curve);
+}
+
+template <class EC>
+void DL_GroupParameters_EC<EC>::AssignFrom(const NameValuePairs &source)
+{
+ OID oid;
+ if (source.GetValue(Name::GroupOID(), oid))
+ Initialize(oid);
+ else
+ {
+ EllipticCurve ec;
+ Point G;
+ Integer n;
+
+ source.GetRequiredParameter("DL_GroupParameters_EC<EC>", Name::Curve(), ec);
+ source.GetRequiredParameter("DL_GroupParameters_EC<EC>", Name::SubgroupGenerator(), G);
+ source.GetRequiredParameter("DL_GroupParameters_EC<EC>", Name::SubgroupOrder(), n);
+ Integer k = source.GetValueWithDefault(Name::Cofactor(), Integer::Zero());
+
+ Initialize(ec, G, n, k);
+ }
+}
+
+template <class EC>
+void DL_GroupParameters_EC<EC>::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ try
+ {
+ AssignFrom(alg);
+ }
+ catch (InvalidArgument &)
+ {
+ throw NotImplemented("DL_GroupParameters_EC<EC>: curve generation is not implemented yet");
+ }
+}
+
+template <class EC>
+void DL_GroupParameters_EC<EC>::BERDecode(BufferedTransformation &bt)
+{
+ byte b;
+ if (!bt.Peek(b))
+ BERDecodeError();
+ if (b == OBJECT_IDENTIFIER)
+ Initialize(OID(bt));
+ else
+ {
+ BERSequenceDecoder seq(bt);
+ word32 version;
+ BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1); // check version
+ EllipticCurve ec(seq);
+ Point G = ec.BERDecodePoint(seq);
+ Integer n(seq);
+ Integer k;
+ bool cofactorPresent = !seq.EndReached();
+ if (cofactorPresent)
+ k.BERDecode(seq);
+ else
+ k = Integer::Zero();
+ seq.MessageEnd();
+
+ Initialize(ec, G, n, k);
+ }
+}
+
+template <class EC>
+void DL_GroupParameters_EC<EC>::DEREncode(BufferedTransformation &bt) const
+{
+ if (m_encodeAsOID && !m_oid.m_values.empty())
+ m_oid.DEREncode(bt);
+ else
+ {
+ DERSequenceEncoder seq(bt);
+ DEREncodeUnsigned<word32>(seq, 1); // version
+ GetCurve().DEREncode(seq);
+ GetCurve().DEREncodePoint(seq, this->GetSubgroupGenerator(), m_compress);
+ m_n.DEREncode(seq);
+ if (m_k.NotZero())
+ m_k.DEREncode(seq);
+ seq.MessageEnd();
+ }
+}
+
+template <class EC>
+Integer DL_GroupParameters_EC<EC>::GetCofactor() const
+{
+ if (!m_k)
+ {
+ Integer q = GetCurve().FieldSize();
+ Integer qSqrt = q.SquareRoot();
+ m_k = (q+2*qSqrt+1)/m_n;
+ }
+
+ return m_k;
+}
+
+template <class EC>
+Integer DL_GroupParameters_EC<EC>::ConvertElementToInteger(const Element &element) const
+{
+ return ConvertToInteger(element.x);
+};
+
+template <class EC>
+bool DL_GroupParameters_EC<EC>::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = GetCurve().ValidateParameters(rng, level);
+
+ Integer q = GetCurve().FieldSize();
+ pass = pass && m_n!=q;
+
+ if (level >= 2)
+ {
+ Integer qSqrt = q.SquareRoot();
+ pass = pass && m_n>4*qSqrt;
+ pass = pass && VerifyPrime(rng, m_n, level-2);
+ pass = pass && (m_k.IsZero() || m_k == (q+2*qSqrt+1)/m_n);
+ pass = pass && CheckMOVCondition(q, m_n);
+ }
+
+ return pass;
+}
+
+template <class EC>
+bool DL_GroupParameters_EC<EC>::ValidateElement(unsigned int level, const Element &g, const DL_FixedBasePrecomputation<Element> *gpc) const
+{
+ bool pass = !IsIdentity(g) && GetCurve().VerifyPoint(g);
+ if (level >= 1)
+ {
+ if (gpc)
+ pass = pass && gpc->Exponentiate(this->GetGroupPrecomputation(), Integer::One()) == g;
+ }
+ if (level >= 2 && pass)
+ {
+ const Integer &q = GetSubgroupOrder();
+ Element gq = gpc ? gpc->Exponentiate(this->GetGroupPrecomputation(), q) : this->ExponentiateElement(g, q);
+ pass = pass && IsIdentity(gq);
+ }
+ return pass;
+}
+
+template <class EC>
+void DL_GroupParameters_EC<EC>::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
+{
+ GetCurve().SimultaneousMultiply(results, base, exponents, exponentsCount);
+}
+
+template <class EC>
+CPP_TYPENAME DL_GroupParameters_EC<EC>::Element DL_GroupParameters_EC<EC>::MultiplyElements(const Element &a, const Element &b) const
+{
+ return GetCurve().Add(a, b);
+}
+
+template <class EC>
+CPP_TYPENAME DL_GroupParameters_EC<EC>::Element DL_GroupParameters_EC<EC>::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
+{
+ return GetCurve().CascadeMultiply(exponent1, element1, exponent2, element2);
+}
+
+template <class EC>
+OID DL_GroupParameters_EC<EC>::GetAlgorithmID() const
+{
+ return ASN1::id_ecPublicKey();
+}
+
+// ******************************************************************
+
+template <class EC>
+void DL_PublicKey_EC<EC>::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
+{
+ typename EC::Point P;
+ if (!this->GetGroupParameters().GetCurve().DecodePoint(P, bt, size))
+ BERDecodeError();
+ this->SetPublicElement(P);
+}
+
+template <class EC>
+void DL_PublicKey_EC<EC>::DEREncodePublicKey(BufferedTransformation &bt) const
+{
+ this->GetGroupParameters().GetCurve().EncodePoint(bt, this->GetPublicElement(), this->GetGroupParameters().GetPointCompression());
+}
+
+// ******************************************************************
+
+template <class EC>
+void DL_PrivateKey_EC<EC>::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
+{
+ BERSequenceDecoder seq(bt);
+ word32 version;
+ BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1); // check version
+
+ BERGeneralDecoder dec(seq, OCTET_STRING);
+ if (!dec.IsDefiniteLength())
+ BERDecodeError();
+ Integer x;
+ x.Decode(dec, (size_t)dec.RemainingLength());
+ dec.MessageEnd();
+ if (!parametersPresent && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0))
+ BERDecodeError();
+ if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0))
+ {
+ BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0);
+ this->AccessGroupParameters().BERDecode(parameters);
+ parameters.MessageEnd();
+ }
+ if (!seq.EndReached())
+ {
+ // skip over the public element
+ SecByteBlock subjectPublicKey;
+ unsigned int unusedBits;
+ BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
+ BERDecodeBitString(publicKey, subjectPublicKey, unusedBits);
+ publicKey.MessageEnd();
+ Element Q;
+ if (!(unusedBits == 0 && this->GetGroupParameters().GetCurve().DecodePoint(Q, subjectPublicKey, subjectPublicKey.size())))
+ BERDecodeError();
+ }
+ seq.MessageEnd();
+
+ this->SetPrivateExponent(x);
+}
+
+template <class EC>
+void DL_PrivateKey_EC<EC>::DEREncodePrivateKey(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder privateKey(bt);
+ DEREncodeUnsigned<word32>(privateKey, 1); // version
+ // SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve
+ // this will be changed to order of base point in a future version
+ this->GetPrivateExponent().DEREncodeAsOctetString(privateKey, this->GetGroupParameters().GetSubgroupOrder().ByteCount());
+ privateKey.MessageEnd();
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/eccrypto.h b/lib/cryptopp/eccrypto.h
new file mode 100644
index 000000000..3530455a3
--- /dev/null
+++ b/lib/cryptopp/eccrypto.h
@@ -0,0 +1,280 @@
+#ifndef CRYPTOPP_ECCRYPTO_H
+#define CRYPTOPP_ECCRYPTO_H
+
+/*! \file
+*/
+
+#include "pubkey.h"
+#include "integer.h"
+#include "asn.h"
+#include "hmac.h"
+#include "sha.h"
+#include "gfpcrypt.h"
+#include "dh.h"
+#include "mqv.h"
+#include "ecp.h"
+#include "ec2n.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Elliptic Curve Parameters
+/*! This class corresponds to the ASN.1 sequence of the same name
+ in ANSI X9.62 (also SEC 1).
+*/
+template <class EC>
+class DL_GroupParameters_EC : public DL_GroupParametersImpl<EcPrecomputation<EC> >
+{
+ typedef DL_GroupParameters_EC<EC> ThisClass;
+
+public:
+ typedef EC EllipticCurve;
+ typedef typename EllipticCurve::Point Point;
+ typedef Point Element;
+ typedef IncompatibleCofactorMultiplication DefaultCofactorOption;
+
+ DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {}
+ DL_GroupParameters_EC(const OID &oid)
+ : m_compress(false), m_encodeAsOID(false) {Initialize(oid);}
+ DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
+ : m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);}
+ DL_GroupParameters_EC(BufferedTransformation &bt)
+ : m_compress(false), m_encodeAsOID(false) {BERDecode(bt);}
+
+ void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
+ {
+ this->m_groupPrecomputation.SetCurve(ec);
+ this->SetSubgroupGenerator(G);
+ m_n = n;
+ m_k = k;
+ }
+ void Initialize(const OID &oid);
+
+ // NameValuePairs
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ // GeneratibleCryptoMaterial interface
+ //! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values
+ /*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+
+ // DL_GroupParameters
+ const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
+ DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
+ const Integer & GetSubgroupOrder() const {return m_n;}
+ Integer GetCofactor() const;
+ bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
+ bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const;
+ bool FastSubgroupCheckAvailable() const {return false;}
+ void EncodeElement(bool reversible, const Element &element, byte *encoded) const
+ {
+ if (reversible)
+ GetCurve().EncodePoint(encoded, element, m_compress);
+ else
+ element.x.Encode(encoded, GetEncodedElementSize(false));
+ }
+ unsigned int GetEncodedElementSize(bool reversible) const
+ {
+ if (reversible)
+ return GetCurve().EncodedPointSize(m_compress);
+ else
+ return GetCurve().GetField().MaxElementByteLength();
+ }
+ Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const
+ {
+ Point result;
+ if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true)))
+ throw DL_BadElement();
+ if (checkForGroupMembership && !ValidateElement(1, result, NULL))
+ throw DL_BadElement();
+ return result;
+ }
+ Integer ConvertElementToInteger(const Element &element) const;
+ Integer GetMaxExponent() const {return GetSubgroupOrder()-1;}
+ bool IsIdentity(const Element &element) const {return element.identity;}
+ void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
+ static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";}
+
+ // ASN1Key
+ OID GetAlgorithmID() const;
+
+ // used by MQV
+ Element MultiplyElements(const Element &a, const Element &b) const;
+ Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
+
+ // non-inherited
+
+ // enumerate OIDs for recommended parameters, use OID() to get first one
+ static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid);
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ void SetPointCompression(bool compress) {m_compress = compress;}
+ bool GetPointCompression() const {return m_compress;}
+
+ void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;}
+ bool GetEncodeAsOID() const {return m_encodeAsOID;}
+
+ const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();}
+
+ bool operator==(const ThisClass &rhs) const
+ {return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+ const Point& GetBasePoint() const {return GetSubgroupGenerator();}
+ const Integer& GetBasePointOrder() const {return GetSubgroupOrder();}
+ void LoadRecommendedParameters(const OID &oid) {Initialize(oid);}
+#endif
+
+protected:
+ unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();}
+ unsigned int ExponentLength() const {return m_n.ByteCount();}
+
+ OID m_oid; // set if parameters loaded from a recommended curve
+ Integer m_n; // order of base point
+ bool m_compress, m_encodeAsOID;
+ mutable Integer m_k; // cofactor
+};
+
+//! EC public key
+template <class EC>
+class DL_PublicKey_EC : public DL_PublicKeyImpl<DL_GroupParameters_EC<EC> >
+{
+public:
+ typedef typename EC::Point Element;
+
+ void Initialize(const DL_GroupParameters_EC<EC> &params, const Element &Q)
+ {this->AccessGroupParameters() = params; this->SetPublicElement(Q);}
+ void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q)
+ {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);}
+
+ // X509PublicKey
+ void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
+ void DEREncodePublicKey(BufferedTransformation &bt) const;
+};
+
+//! EC private key
+template <class EC>
+class DL_PrivateKey_EC : public DL_PrivateKeyImpl<DL_GroupParameters_EC<EC> >
+{
+public:
+ typedef typename EC::Point Element;
+
+ void Initialize(const DL_GroupParameters_EC<EC> &params, const Integer &x)
+ {this->AccessGroupParameters() = params; this->SetPrivateExponent(x);}
+ void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x)
+ {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);}
+ void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> &params)
+ {this->GenerateRandom(rng, params);}
+ void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
+ {this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));}
+
+ // PKCS8PrivateKey
+ void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
+ void DEREncodePrivateKey(BufferedTransformation &bt) const;
+};
+
+//! Elliptic Curve Diffie-Hellman, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECDH">ECDH</a>
+template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
+struct ECDH
+{
+ typedef DH_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
+};
+
+/// Elliptic Curve Menezes-Qu-Vanstone, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECMQV">ECMQV</a>
+template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
+struct ECMQV
+{
+ typedef MQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
+};
+
+//! EC keys
+template <class EC>
+struct DL_Keys_EC
+{
+ typedef DL_PublicKey_EC<EC> PublicKey;
+ typedef DL_PrivateKey_EC<EC> PrivateKey;
+};
+
+template <class EC, class H>
+struct ECDSA;
+
+//! ECDSA keys
+template <class EC>
+struct DL_Keys_ECDSA
+{
+ typedef DL_PublicKey_EC<EC> PublicKey;
+ typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC>, ECDSA<EC, SHA256> > PrivateKey;
+};
+
+//! ECDSA algorithm
+template <class EC>
+class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA<typename EC::Point>
+{
+public:
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";}
+};
+
+//! ECNR algorithm
+template <class EC>
+class DL_Algorithm_ECNR : public DL_Algorithm_NR<typename EC::Point>
+{
+public:
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";}
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a>
+template <class EC, class H>
+struct ECDSA : public DL_SS<DL_Keys_ECDSA<EC>, DL_Algorithm_ECDSA<EC>, DL_SignatureMessageEncodingMethod_DSA, H>
+{
+};
+
+//! ECNR
+template <class EC, class H = SHA>
+struct ECNR : public DL_SS<DL_Keys_EC<EC>, DL_Algorithm_ECNR<EC>, DL_SignatureMessageEncodingMethod_NR, H>
+{
+};
+
+//! Elliptic Curve Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">ECIES</a>
+/*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2.
+ The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best
+ efficiency and security. */
+template <class EC, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = false>
+struct ECIES
+ : public DL_ES<
+ DL_Keys_EC<EC>,
+ DL_KeyAgreementAlgorithm_DH<typename EC::Point, COFACTOR_OPTION>,
+ DL_KeyDerivationAlgorithm_P1363<typename EC::Point, DHAES_MODE, P1363_KDF2<SHA1> >,
+ DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
+ ECIES<EC> >
+{
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";} // TODO: fix this after name is standardized
+};
+
+NAMESPACE_END
+
+#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
+#include "eccrypto.cpp"
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<ECP>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<EC2N>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<ECP> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<EC2N> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<ECP>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<EC2N>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<ECP> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<EC2N> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<ECP>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<EC2N>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<ECP::Point>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<EC2N::Point>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<ECP>, ECDSA<ECP, SHA256> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC2N>, ECDSA<EC2N, SHA256> >;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/ecp.cpp b/lib/cryptopp/ecp.cpp
new file mode 100644
index 000000000..55a7cc15b
--- /dev/null
+++ b/lib/cryptopp/ecp.cpp
@@ -0,0 +1,473 @@
+// ecp.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "ecp.h"
+#include "asn.h"
+#include "nbtheory.h"
+
+#include "algebra.cpp"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+ANONYMOUS_NAMESPACE_BEGIN
+static inline ECP::Point ToMontgomery(const ModularArithmetic &mr, const ECP::Point &P)
+{
+ return P.identity ? P : ECP::Point(mr.ConvertIn(P.x), mr.ConvertIn(P.y));
+}
+
+static inline ECP::Point FromMontgomery(const ModularArithmetic &mr, const ECP::Point &P)
+{
+ return P.identity ? P : ECP::Point(mr.ConvertOut(P.x), mr.ConvertOut(P.y));
+}
+NAMESPACE_END
+
+ECP::ECP(const ECP &ecp, bool convertToMontgomeryRepresentation)
+{
+ if (convertToMontgomeryRepresentation && !ecp.GetField().IsMontgomeryRepresentation())
+ {
+ m_fieldPtr.reset(new MontgomeryRepresentation(ecp.GetField().GetModulus()));
+ m_a = GetField().ConvertIn(ecp.m_a);
+ m_b = GetField().ConvertIn(ecp.m_b);
+ }
+ else
+ operator=(ecp);
+}
+
+ECP::ECP(BufferedTransformation &bt)
+ : m_fieldPtr(new Field(bt))
+{
+ BERSequenceDecoder seq(bt);
+ GetField().BERDecodeElement(seq, m_a);
+ GetField().BERDecodeElement(seq, m_b);
+ // skip optional seed
+ if (!seq.EndReached())
+ {
+ SecByteBlock seed;
+ unsigned int unused;
+ BERDecodeBitString(seq, seed, unused);
+ }
+ seq.MessageEnd();
+}
+
+void ECP::DEREncode(BufferedTransformation &bt) const
+{
+ GetField().DEREncode(bt);
+ DERSequenceEncoder seq(bt);
+ GetField().DEREncodeElement(seq, m_a);
+ GetField().DEREncodeElement(seq, m_b);
+ seq.MessageEnd();
+}
+
+bool ECP::DecodePoint(ECP::Point &P, const byte *encodedPoint, size_t encodedPointLen) const
+{
+ StringStore store(encodedPoint, encodedPointLen);
+ return DecodePoint(P, store, encodedPointLen);
+}
+
+bool ECP::DecodePoint(ECP::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const
+{
+ byte type;
+ if (encodedPointLen < 1 || !bt.Get(type))
+ return false;
+
+ switch (type)
+ {
+ case 0:
+ P.identity = true;
+ return true;
+ case 2:
+ case 3:
+ {
+ if (encodedPointLen != EncodedPointSize(true))
+ return false;
+
+ Integer p = FieldSize();
+
+ P.identity = false;
+ P.x.Decode(bt, GetField().MaxElementByteLength());
+ P.y = ((P.x*P.x+m_a)*P.x+m_b) % p;
+
+ if (Jacobi(P.y, p) !=1)
+ return false;
+
+ P.y = ModularSquareRoot(P.y, p);
+
+ if ((type & 1) != P.y.GetBit(0))
+ P.y = p-P.y;
+
+ return true;
+ }
+ case 4:
+ {
+ if (encodedPointLen != EncodedPointSize(false))
+ return false;
+
+ unsigned int len = GetField().MaxElementByteLength();
+ P.identity = false;
+ P.x.Decode(bt, len);
+ P.y.Decode(bt, len);
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
+void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
+{
+ if (P.identity)
+ NullStore().TransferTo(bt, EncodedPointSize(compressed));
+ else if (compressed)
+ {
+ bt.Put(2 + P.y.GetBit(0));
+ P.x.Encode(bt, GetField().MaxElementByteLength());
+ }
+ else
+ {
+ unsigned int len = GetField().MaxElementByteLength();
+ bt.Put(4); // uncompressed
+ P.x.Encode(bt, len);
+ P.y.Encode(bt, len);
+ }
+}
+
+void ECP::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const
+{
+ ArraySink sink(encodedPoint, EncodedPointSize(compressed));
+ EncodePoint(sink, P, compressed);
+ assert(sink.TotalPutLength() == EncodedPointSize(compressed));
+}
+
+ECP::Point ECP::BERDecodePoint(BufferedTransformation &bt) const
+{
+ SecByteBlock str;
+ BERDecodeOctetString(bt, str);
+ Point P;
+ if (!DecodePoint(P, str, str.size()))
+ BERDecodeError();
+ return P;
+}
+
+void ECP::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
+{
+ SecByteBlock str(EncodedPointSize(compressed));
+ EncodePoint(str, P, compressed);
+ DEREncodeOctetString(bt, str);
+}
+
+bool ECP::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const
+{
+ Integer p = FieldSize();
+
+ bool pass = p.IsOdd();
+ pass = pass && !m_a.IsNegative() && m_a<p && !m_b.IsNegative() && m_b<p;
+
+ if (level >= 1)
+ pass = pass && ((4*m_a*m_a*m_a+27*m_b*m_b)%p).IsPositive();
+
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, p);
+
+ return pass;
+}
+
+bool ECP::VerifyPoint(const Point &P) const
+{
+ const FieldElement &x = P.x, &y = P.y;
+ Integer p = FieldSize();
+ return P.identity ||
+ (!x.IsNegative() && x<p && !y.IsNegative() && y<p
+ && !(((x*x+m_a)*x+m_b-y*y)%p));
+}
+
+bool ECP::Equal(const Point &P, const Point &Q) const
+{
+ if (P.identity && Q.identity)
+ return true;
+
+ if (P.identity && !Q.identity)
+ return false;
+
+ if (!P.identity && Q.identity)
+ return false;
+
+ return (GetField().Equal(P.x,Q.x) && GetField().Equal(P.y,Q.y));
+}
+
+const ECP::Point& ECP::Identity() const
+{
+ return Singleton<Point>().Ref();
+}
+
+const ECP::Point& ECP::Inverse(const Point &P) const
+{
+ if (P.identity)
+ return P;
+ else
+ {
+ m_R.identity = false;
+ m_R.x = P.x;
+ m_R.y = GetField().Inverse(P.y);
+ return m_R;
+ }
+}
+
+const ECP::Point& ECP::Add(const Point &P, const Point &Q) const
+{
+ if (P.identity) return Q;
+ if (Q.identity) return P;
+ if (GetField().Equal(P.x, Q.x))
+ return GetField().Equal(P.y, Q.y) ? Double(P) : Identity();
+
+ FieldElement t = GetField().Subtract(Q.y, P.y);
+ t = GetField().Divide(t, GetField().Subtract(Q.x, P.x));
+ FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), Q.x);
+ m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y);
+
+ m_R.x.swap(x);
+ m_R.identity = false;
+ return m_R;
+}
+
+const ECP::Point& ECP::Double(const Point &P) const
+{
+ if (P.identity || P.y==GetField().Identity()) return Identity();
+
+ FieldElement t = GetField().Square(P.x);
+ t = GetField().Add(GetField().Add(GetField().Double(t), t), m_a);
+ t = GetField().Divide(t, GetField().Double(P.y));
+ FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), P.x);
+ m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y);
+
+ m_R.x.swap(x);
+ m_R.identity = false;
+ return m_R;
+}
+
+template <class T, class Iterator> void ParallelInvert(const AbstractRing<T> &ring, Iterator begin, Iterator end)
+{
+ size_t n = end-begin;
+ if (n == 1)
+ *begin = ring.MultiplicativeInverse(*begin);
+ else if (n > 1)
+ {
+ std::vector<T> vec((n+1)/2);
+ unsigned int i;
+ Iterator it;
+
+ for (i=0, it=begin; i<n/2; i++, it+=2)
+ vec[i] = ring.Multiply(*it, *(it+1));
+ if (n%2 == 1)
+ vec[n/2] = *it;
+
+ ParallelInvert(ring, vec.begin(), vec.end());
+
+ for (i=0, it=begin; i<n/2; i++, it+=2)
+ {
+ if (!vec[i])
+ {
+ *it = ring.MultiplicativeInverse(*it);
+ *(it+1) = ring.MultiplicativeInverse(*(it+1));
+ }
+ else
+ {
+ std::swap(*it, *(it+1));
+ *it = ring.Multiply(*it, vec[i]);
+ *(it+1) = ring.Multiply(*(it+1), vec[i]);
+ }
+ }
+ if (n%2 == 1)
+ *it = vec[n/2];
+ }
+}
+
+struct ProjectivePoint
+{
+ ProjectivePoint() {}
+ ProjectivePoint(const Integer &x, const Integer &y, const Integer &z)
+ : x(x), y(y), z(z) {}
+
+ Integer x,y,z;
+};
+
+class ProjectiveDoubling
+{
+public:
+ ProjectiveDoubling(const ModularArithmetic &mr, const Integer &m_a, const Integer &m_b, const ECPPoint &Q)
+ : mr(mr), firstDoubling(true), negated(false)
+ {
+ if (Q.identity)
+ {
+ sixteenY4 = P.x = P.y = mr.MultiplicativeIdentity();
+ aZ4 = P.z = mr.Identity();
+ }
+ else
+ {
+ P.x = Q.x;
+ P.y = Q.y;
+ sixteenY4 = P.z = mr.MultiplicativeIdentity();
+ aZ4 = m_a;
+ }
+ }
+
+ void Double()
+ {
+ twoY = mr.Double(P.y);
+ P.z = mr.Multiply(P.z, twoY);
+ fourY2 = mr.Square(twoY);
+ S = mr.Multiply(fourY2, P.x);
+ aZ4 = mr.Multiply(aZ4, sixteenY4);
+ M = mr.Square(P.x);
+ M = mr.Add(mr.Add(mr.Double(M), M), aZ4);
+ P.x = mr.Square(M);
+ mr.Reduce(P.x, S);
+ mr.Reduce(P.x, S);
+ mr.Reduce(S, P.x);
+ P.y = mr.Multiply(M, S);
+ sixteenY4 = mr.Square(fourY2);
+ mr.Reduce(P.y, mr.Half(sixteenY4));
+ }
+
+ const ModularArithmetic &mr;
+ ProjectivePoint P;
+ bool firstDoubling, negated;
+ Integer sixteenY4, aZ4, twoY, fourY2, S, M;
+};
+
+struct ZIterator
+{
+ ZIterator() {}
+ ZIterator(std::vector<ProjectivePoint>::iterator it) : it(it) {}
+ Integer& operator*() {return it->z;}
+ int operator-(ZIterator it2) {return int(it-it2.it);}
+ ZIterator operator+(int i) {return ZIterator(it+i);}
+ ZIterator& operator+=(int i) {it+=i; return *this;}
+ std::vector<ProjectivePoint>::iterator it;
+};
+
+ECP::Point ECP::ScalarMultiply(const Point &P, const Integer &k) const
+{
+ Element result;
+ if (k.BitCount() <= 5)
+ AbstractGroup<ECPPoint>::SimultaneousMultiply(&result, P, &k, 1);
+ else
+ ECP::SimultaneousMultiply(&result, P, &k, 1);
+ return result;
+}
+
+void ECP::SimultaneousMultiply(ECP::Point *results, const ECP::Point &P, const Integer *expBegin, unsigned int expCount) const
+{
+ if (!GetField().IsMontgomeryRepresentation())
+ {
+ ECP ecpmr(*this, true);
+ const ModularArithmetic &mr = ecpmr.GetField();
+ ecpmr.SimultaneousMultiply(results, ToMontgomery(mr, P), expBegin, expCount);
+ for (unsigned int i=0; i<expCount; i++)
+ results[i] = FromMontgomery(mr, results[i]);
+ return;
+ }
+
+ ProjectiveDoubling rd(GetField(), m_a, m_b, P);
+ std::vector<ProjectivePoint> bases;
+ std::vector<WindowSlider> exponents;
+ exponents.reserve(expCount);
+ std::vector<std::vector<word32> > baseIndices(expCount);
+ std::vector<std::vector<bool> > negateBase(expCount);
+ std::vector<std::vector<word32> > exponentWindows(expCount);
+ unsigned int i;
+
+ for (i=0; i<expCount; i++)
+ {
+ assert(expBegin->NotNegative());
+ exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 5));
+ exponents[i].FindNextWindow();
+ }
+
+ unsigned int expBitPosition = 0;
+ bool notDone = true;
+
+ while (notDone)
+ {
+ notDone = false;
+ bool baseAdded = false;
+ for (i=0; i<expCount; i++)
+ {
+ if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
+ {
+ if (!baseAdded)
+ {
+ bases.push_back(rd.P);
+ baseAdded =true;
+ }
+
+ exponentWindows[i].push_back(exponents[i].expWindow);
+ baseIndices[i].push_back((word32)bases.size()-1);
+ negateBase[i].push_back(exponents[i].negateNext);
+
+ exponents[i].FindNextWindow();
+ }
+ notDone = notDone || !exponents[i].finished;
+ }
+
+ if (notDone)
+ {
+ rd.Double();
+ expBitPosition++;
+ }
+ }
+
+ // convert from projective to affine coordinates
+ ParallelInvert(GetField(), ZIterator(bases.begin()), ZIterator(bases.end()));
+ for (i=0; i<bases.size(); i++)
+ {
+ if (bases[i].z.NotZero())
+ {
+ bases[i].y = GetField().Multiply(bases[i].y, bases[i].z);
+ bases[i].z = GetField().Square(bases[i].z);
+ bases[i].x = GetField().Multiply(bases[i].x, bases[i].z);
+ bases[i].y = GetField().Multiply(bases[i].y, bases[i].z);
+ }
+ }
+
+ std::vector<BaseAndExponent<Point, Integer> > finalCascade;
+ for (i=0; i<expCount; i++)
+ {
+ finalCascade.resize(baseIndices[i].size());
+ for (unsigned int j=0; j<baseIndices[i].size(); j++)
+ {
+ ProjectivePoint &base = bases[baseIndices[i][j]];
+ if (base.z.IsZero())
+ finalCascade[j].base.identity = true;
+ else
+ {
+ finalCascade[j].base.identity = false;
+ finalCascade[j].base.x = base.x;
+ if (negateBase[i][j])
+ finalCascade[j].base.y = GetField().Inverse(base.y);
+ else
+ finalCascade[j].base.y = base.y;
+ }
+ finalCascade[j].exponent = Integer(Integer::POSITIVE, 0, exponentWindows[i][j]);
+ }
+ results[i] = GeneralCascadeMultiplication(*this, finalCascade.begin(), finalCascade.end());
+ }
+}
+
+ECP::Point ECP::CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const
+{
+ if (!GetField().IsMontgomeryRepresentation())
+ {
+ ECP ecpmr(*this, true);
+ const ModularArithmetic &mr = ecpmr.GetField();
+ return FromMontgomery(mr, ecpmr.CascadeScalarMultiply(ToMontgomery(mr, P), k1, ToMontgomery(mr, Q), k2));
+ }
+ else
+ return AbstractGroup<Point>::CascadeScalarMultiply(P, k1, Q, k2);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/ecp.h b/lib/cryptopp/ecp.h
new file mode 100644
index 000000000..d946be63a
--- /dev/null
+++ b/lib/cryptopp/ecp.h
@@ -0,0 +1,126 @@
+#ifndef CRYPTOPP_ECP_H
+#define CRYPTOPP_ECP_H
+
+#include "modarith.h"
+#include "eprecomp.h"
+#include "smartptr.h"
+#include "pubkey.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Elliptical Curve Point
+struct CRYPTOPP_DLL ECPPoint
+{
+ ECPPoint() : identity(true) {}
+ ECPPoint(const Integer &x, const Integer &y)
+ : identity(false), x(x), y(y) {}
+
+ bool operator==(const ECPPoint &t) const
+ {return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
+ bool operator< (const ECPPoint &t) const
+ {return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
+
+ bool identity;
+ Integer x, y;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<ECPPoint>;
+
+//! Elliptic Curve over GF(p), where p is prime
+class CRYPTOPP_DLL ECP : public AbstractGroup<ECPPoint>
+{
+public:
+ typedef ModularArithmetic Field;
+ typedef Integer FieldElement;
+ typedef ECPPoint Point;
+
+ ECP() {}
+ ECP(const ECP &ecp, bool convertToMontgomeryRepresentation = false);
+ ECP(const Integer &modulus, const FieldElement &a, const FieldElement &b)
+ : m_fieldPtr(new Field(modulus)), m_a(a.IsNegative() ? modulus+a : a), m_b(b) {}
+ // construct from BER encoded parameters
+ // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
+ ECP(BufferedTransformation &bt);
+
+ // encode the fields fieldID and curve of the sequence ECParameters
+ void DEREncode(BufferedTransformation &bt) const;
+
+ bool Equal(const Point &P, const Point &Q) const;
+ const Point& Identity() const;
+ const Point& Inverse(const Point &P) const;
+ bool InversionIsFast() const {return true;}
+ const Point& Add(const Point &P, const Point &Q) const;
+ const Point& Double(const Point &P) const;
+ Point ScalarMultiply(const Point &P, const Integer &k) const;
+ Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const;
+ void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const;
+
+ Point Multiply(const Integer &k, const Point &P) const
+ {return ScalarMultiply(P, k);}
+ Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const
+ {return CascadeScalarMultiply(P, k1, Q, k2);}
+
+ bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const;
+ bool VerifyPoint(const Point &P) const;
+
+ unsigned int EncodedPointSize(bool compressed = false) const
+ {return 1 + (compressed?1:2)*GetField().MaxElementByteLength();}
+ // returns false if point is compressed and not valid (doesn't check if uncompressed)
+ bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const;
+ bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const;
+ void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const;
+ void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
+
+ Point BERDecodePoint(BufferedTransformation &bt) const;
+ void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
+
+ Integer FieldSize() const {return GetField().GetModulus();}
+ const Field & GetField() const {return *m_fieldPtr;}
+ const FieldElement & GetA() const {return m_a;}
+ const FieldElement & GetB() const {return m_b;}
+
+ bool operator==(const ECP &rhs) const
+ {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;}
+
+private:
+ clonable_ptr<Field> m_fieldPtr;
+ FieldElement m_a, m_b;
+ mutable Point m_R;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<ECP::Point>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation<ECP::Point>;
+
+template <class T> class EcPrecomputation;
+
+//! ECP precomputation
+template<> class EcPrecomputation<ECP> : public DL_GroupPrecomputation<ECP::Point>
+{
+public:
+ typedef ECP EllipticCurve;
+
+ // DL_GroupPrecomputation
+ bool NeedConversions() const {return true;}
+ Element ConvertIn(const Element &P) const
+ {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y));};
+ Element ConvertOut(const Element &P) const
+ {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y));}
+ const AbstractGroup<Element> & GetGroup() const {return *m_ec;}
+ Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec->BERDecodePoint(bt);}
+ void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec->DEREncodePoint(bt, v, false);}
+
+ // non-inherited
+ void SetCurve(const ECP &ec)
+ {
+ m_ec.reset(new ECP(ec, true));
+ m_ecOriginal = ec;
+ }
+ const ECP & GetCurve() const {return *m_ecOriginal;}
+
+private:
+ value_ptr<ECP> m_ec, m_ecOriginal;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/elgamal.cpp b/lib/cryptopp/elgamal.cpp
new file mode 100644
index 000000000..b58fe7c06
--- /dev/null
+++ b/lib/cryptopp/elgamal.cpp
@@ -0,0 +1,17 @@
+// elgamal.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "elgamal.h"
+#include "asn.h"
+#include "nbtheory.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void ElGamal_TestInstantiations()
+{
+ ElGamalEncryptor test1(1, 1, 1);
+ ElGamalDecryptor test2(NullRNG(), 123);
+ ElGamalEncryptor test3(test2);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/elgamal.h b/lib/cryptopp/elgamal.h
new file mode 100644
index 000000000..9afc30eee
--- /dev/null
+++ b/lib/cryptopp/elgamal.h
@@ -0,0 +1,121 @@
+#ifndef CRYPTOPP_ELGAMAL_H
+#define CRYPTOPP_ELGAMAL_H
+
+#include "modexppc.h"
+#include "dsa.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+class CRYPTOPP_NO_VTABLE ElGamalBase : public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>,
+ public DL_KeyDerivationAlgorithm<Integer>,
+ public DL_SymmetricEncryptionAlgorithm
+{
+public:
+ void Derive(const DL_GroupParameters<Integer> &groupParams, byte *derivedKey, size_t derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey, const NameValuePairs &derivationParams) const
+ {
+ agreedElement.Encode(derivedKey, derivedLength);
+ }
+
+ size_t GetSymmetricKeyLength(size_t plainTextLength) const
+ {
+ return GetGroupParameters().GetModulus().ByteCount();
+ }
+
+ size_t GetSymmetricCiphertextLength(size_t plainTextLength) const
+ {
+ unsigned int len = GetGroupParameters().GetModulus().ByteCount();
+ if (plainTextLength <= GetMaxSymmetricPlaintextLength(len))
+ return len;
+ else
+ return 0;
+ }
+
+ size_t GetMaxSymmetricPlaintextLength(size_t cipherTextLength) const
+ {
+ unsigned int len = GetGroupParameters().GetModulus().ByteCount();
+ if (cipherTextLength == len)
+ return STDMIN(255U, len-3);
+ else
+ return 0;
+ }
+
+ void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, size_t plainTextLength, byte *cipherText, const NameValuePairs &parameters) const
+ {
+ const Integer &p = GetGroupParameters().GetModulus();
+ unsigned int modulusLen = p.ByteCount();
+
+ SecByteBlock block(modulusLen-1);
+ rng.GenerateBlock(block, modulusLen-2-plainTextLength);
+ memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength);
+ block[modulusLen-2] = (byte)plainTextLength;
+
+ a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen);
+ }
+
+ DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, size_t cipherTextLength, byte *plainText, const NameValuePairs &parameters) const
+ {
+ const Integer &p = GetGroupParameters().GetModulus();
+ unsigned int modulusLen = p.ByteCount();
+
+ if (cipherTextLength != modulusLen)
+ return DecodingResult();
+
+ Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p);
+
+ m.Encode(plainText, 1);
+ unsigned int plainTextLength = plainText[0];
+ if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen))
+ return DecodingResult();
+ m >>= 8;
+ m.Encode(plainText, plainTextLength);
+ return DecodingResult(plainTextLength);
+ }
+
+ virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0;
+};
+
+template <class BASE, class SCHEME_OPTIONS, class KEY>
+class ElGamalObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>, public ElGamalBase
+{
+public:
+ size_t FixedMaxPlaintextLength() const {return this->MaxPlaintextLength(FixedCiphertextLength());}
+ size_t FixedCiphertextLength() const {return this->CiphertextLength(0);}
+
+ const DL_GroupParameters_GFP & GetGroupParameters() const {return this->GetKey().GetGroupParameters();}
+
+ DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const
+ {return Decrypt(rng, cipherText, FixedCiphertextLength(), plainText);}
+
+protected:
+ const DL_KeyAgreementAlgorithm<Integer> & GetKeyAgreementAlgorithm() const {return *this;}
+ const DL_KeyDerivationAlgorithm<Integer> & GetKeyDerivationAlgorithm() const {return *this;}
+ const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;}
+};
+
+struct ElGamalKeys
+{
+ typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters;
+ typedef DL_PrivateKey_GFP_OldFormat<DL_CryptoKeys_GFP::PrivateKey> PrivateKey;
+ typedef DL_PublicKey_GFP_OldFormat<DL_CryptoKeys_GFP::PublicKey> PublicKey;
+};
+
+//! ElGamal encryption scheme with non-standard padding
+struct ElGamal
+{
+ typedef DL_CryptoSchemeOptions<ElGamal, ElGamalKeys, int, int, int> SchemeOptions;
+
+ static const char * StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";}
+
+ typedef SchemeOptions::GroupParameters GroupParameters;
+ //! implements PK_Encryptor interface
+ typedef PK_FinalTemplate<ElGamalObjectImpl<DL_EncryptorBase<Integer>, SchemeOptions, SchemeOptions::PublicKey> > Encryptor;
+ //! implements PK_Decryptor interface
+ typedef PK_FinalTemplate<ElGamalObjectImpl<DL_DecryptorBase<Integer>, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor;
+};
+
+typedef ElGamal::Encryptor ElGamalEncryptor;
+typedef ElGamal::Decryptor ElGamalDecryptor;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/emsa2.cpp b/lib/cryptopp/emsa2.cpp
new file mode 100644
index 000000000..3dbb7e8c0
--- /dev/null
+++ b/lib/cryptopp/emsa2.cpp
@@ -0,0 +1,34 @@
+// emsa2.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "emsa2.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void EMSA2Pad::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
+
+ if (representativeBitLength % 8 != 7)
+ throw PK_SignatureScheme::InvalidKeyLength("EMSA2: EMSA2 requires a key length that is a multiple of 8");
+
+ size_t digestSize = hash.DigestSize();
+ size_t representativeByteLength = BitsToBytes(representativeBitLength);
+
+ representative[0] = messageEmpty ? 0x4b : 0x6b;
+ memset(representative+1, 0xbb, representativeByteLength-digestSize-4); // pad with 0xbb
+ byte *afterP2 = representative+representativeByteLength-digestSize-3;
+ afterP2[0] = 0xba;
+ hash.Final(afterP2+1);
+ representative[representativeByteLength-2] = *hashIdentifier.first;
+ representative[representativeByteLength-1] = 0xcc;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/emsa2.h b/lib/cryptopp/emsa2.h
new file mode 100644
index 000000000..49109e6db
--- /dev/null
+++ b/lib/cryptopp/emsa2.h
@@ -0,0 +1,86 @@
+#ifndef CRYPTOPP_EMSA2_H
+#define CRYPTOPP_EMSA2_H
+
+/** \file
+ This file contains various padding schemes for public key algorithms.
+*/
+
+#include "cryptlib.h"
+#include "pubkey.h"
+
+#ifdef CRYPTOPP_IS_DLL
+#include "sha.h"
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class H> class EMSA2HashId
+{
+public:
+ static const byte id;
+};
+
+template <class BASE>
+class EMSA2HashIdLookup : public BASE
+{
+public:
+ struct HashIdentifierLookup
+ {
+ template <class H> struct HashIdentifierLookup2
+ {
+ static HashIdentifier Lookup()
+ {
+ return HashIdentifier(&EMSA2HashId<H>::id, 1);
+ }
+ };
+ };
+};
+
+// EMSA2HashId can be instantiated with the following classes.
+class SHA1;
+class RIPEMD160;
+class RIPEMD128;
+class SHA256;
+class SHA384;
+class SHA512;
+class Whirlpool;
+class SHA224;
+// end of list
+
+#ifdef CRYPTOPP_IS_DLL
+CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA1>;
+CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA224>;
+CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA256>;
+CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA384>;
+CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA512>;
+#endif
+
+//! _
+class CRYPTOPP_DLL EMSA2Pad : public EMSA2HashIdLookup<PK_DeterministicSignatureMessageEncodingMethod>
+{
+public:
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA2";}
+
+ size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
+ {return 8*digestLength + 31;}
+
+ void ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const;
+};
+
+//! EMSA2, for use with RWSS and RSA_ISO
+/*! Only the following hash functions are supported by this signature standard:
+ \dontinclude emsa2.h
+ \skip EMSA2HashId can be instantiated
+ \until end of list
+*/
+struct P1363_EMSA2 : public SignatureStandard
+{
+ typedef EMSA2Pad SignatureMessageEncodingMethod;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/eprecomp.cpp b/lib/cryptopp/eprecomp.cpp
new file mode 100644
index 000000000..a061cf6cd
--- /dev/null
+++ b/lib/cryptopp/eprecomp.cpp
@@ -0,0 +1,112 @@
+// eprecomp.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "eprecomp.h"
+#include "asn.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T> void DL_FixedBasePrecomputationImpl<T>::SetBase(const DL_GroupPrecomputation<Element> &group, const Element &i_base)
+{
+ m_base = group.NeedConversions() ? group.ConvertIn(i_base) : i_base;
+
+ if (m_bases.empty() || !(m_base == m_bases[0]))
+ {
+ m_bases.resize(1);
+ m_bases[0] = m_base;
+ }
+
+ if (group.NeedConversions())
+ m_base = i_base;
+}
+
+template <class T> void DL_FixedBasePrecomputationImpl<T>::Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage)
+{
+ assert(m_bases.size() > 0);
+ assert(storage <= maxExpBits);
+
+ if (storage > 1)
+ {
+ m_windowSize = (maxExpBits+storage-1)/storage;
+ m_exponentBase = Integer::Power2(m_windowSize);
+ }
+
+ m_bases.resize(storage);
+ for (unsigned i=1; i<storage; i++)
+ m_bases[i] = group.GetGroup().ScalarMultiply(m_bases[i-1], m_exponentBase);
+}
+
+template <class T> void DL_FixedBasePrecomputationImpl<T>::Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ word32 version;
+ BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
+ m_exponentBase.BERDecode(seq);
+ m_windowSize = m_exponentBase.BitCount() - 1;
+ m_bases.clear();
+ while (!seq.EndReached())
+ m_bases.push_back(group.BERDecodeElement(seq));
+ if (!m_bases.empty() && group.NeedConversions())
+ m_base = group.ConvertOut(m_bases[0]);
+ seq.MessageEnd();
+}
+
+template <class T> void DL_FixedBasePrecomputationImpl<T>::Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ DEREncodeUnsigned<word32>(seq, 1); // version
+ m_exponentBase.DEREncode(seq);
+ for (unsigned i=0; i<m_bases.size(); i++)
+ group.DEREncodeElement(seq, m_bases[i]);
+ seq.MessageEnd();
+}
+
+template <class T> void DL_FixedBasePrecomputationImpl<T>::PrepareCascade(const DL_GroupPrecomputation<Element> &i_group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const
+{
+ const AbstractGroup<T> &group = i_group.GetGroup();
+
+ Integer r, q, e = exponent;
+ bool fastNegate = group.InversionIsFast() && m_windowSize > 1;
+ unsigned int i;
+
+ for (i=0; i+1<m_bases.size(); i++)
+ {
+ Integer::DivideByPowerOf2(r, q, e, m_windowSize);
+ std::swap(q, e);
+ if (fastNegate && r.GetBit(m_windowSize-1))
+ {
+ ++e;
+ eb.push_back(BaseAndExponent<Element>(group.Inverse(m_bases[i]), m_exponentBase - r));
+ }
+ else
+ eb.push_back(BaseAndExponent<Element>(m_bases[i], r));
+ }
+ eb.push_back(BaseAndExponent<Element>(m_bases[i], e));
+}
+
+template <class T> T DL_FixedBasePrecomputationImpl<T>::Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const
+{
+ std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
+ eb.reserve(m_bases.size());
+ PrepareCascade(group, eb, exponent);
+ return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
+}
+
+template <class T> T
+ DL_FixedBasePrecomputationImpl<T>::CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent,
+ const DL_FixedBasePrecomputation<T> &i_pc2, const Integer &exponent2) const
+{
+ std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
+ const DL_FixedBasePrecomputationImpl<T> &pc2 = static_cast<const DL_FixedBasePrecomputationImpl<T> &>(i_pc2);
+ eb.reserve(m_bases.size() + pc2.m_bases.size());
+ PrepareCascade(group, eb, exponent);
+ pc2.PrepareCascade(group, eb, exponent2);
+ return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/eprecomp.h b/lib/cryptopp/eprecomp.h
new file mode 100644
index 000000000..1f3256766
--- /dev/null
+++ b/lib/cryptopp/eprecomp.h
@@ -0,0 +1,75 @@
+#ifndef CRYPTOPP_EPRECOMP_H
+#define CRYPTOPP_EPRECOMP_H
+
+#include "integer.h"
+#include "algebra.h"
+#include <vector>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T>
+class DL_GroupPrecomputation
+{
+public:
+ typedef T Element;
+
+ virtual bool NeedConversions() const {return false;}
+ virtual Element ConvertIn(const Element &v) const {return v;}
+ virtual Element ConvertOut(const Element &v) const {return v;}
+ virtual const AbstractGroup<Element> & GetGroup() const =0;
+ virtual Element BERDecodeElement(BufferedTransformation &bt) const =0;
+ virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0;
+};
+
+template <class T>
+class DL_FixedBasePrecomputation
+{
+public:
+ typedef T Element;
+
+ virtual bool IsInitialized() const =0;
+ virtual void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base) =0;
+ virtual const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const =0;
+ virtual void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage) =0;
+ virtual void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) =0;
+ virtual void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const =0;
+ virtual Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const =0;
+ virtual Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const =0;
+};
+
+template <class T>
+class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation<T>
+{
+public:
+ typedef T Element;
+
+ DL_FixedBasePrecomputationImpl() : m_windowSize(0) {}
+
+ // DL_FixedBasePrecomputation
+ bool IsInitialized() const
+ {return !m_bases.empty();}
+ void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base);
+ const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const
+ {return group.NeedConversions() ? m_base : m_bases[0];}
+ void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage);
+ void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation);
+ void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const;
+ Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const;
+ Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const;
+
+private:
+ void PrepareCascade(const DL_GroupPrecomputation<Element> &group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const;
+
+ Element m_base;
+ unsigned int m_windowSize;
+ Integer m_exponentBase; // what base to represent the exponent in
+ std::vector<Element> m_bases; // precalculated bases
+};
+
+NAMESPACE_END
+
+#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
+#include "eprecomp.cpp"
+#endif
+
+#endif
diff --git a/lib/cryptopp/esign.cpp b/lib/cryptopp/esign.cpp
new file mode 100644
index 000000000..8b42c1fa4
--- /dev/null
+++ b/lib/cryptopp/esign.cpp
@@ -0,0 +1,210 @@
+// esign.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "esign.h"
+#include "asn.h"
+#include "modarith.h"
+#include "nbtheory.h"
+#include "sha.h"
+#include "algparam.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void ESIGN_TestInstantiations()
+{
+ ESIGN<SHA>::Verifier x1(1, 1);
+ ESIGN<SHA>::Signer x2(NullRNG(), 1);
+ ESIGN<SHA>::Verifier x3(x2);
+ ESIGN<SHA>::Verifier x4(x2.GetKey());
+ ESIGN<SHA>::Verifier x5(x3);
+ ESIGN<SHA>::Signer x6 = x2;
+
+ x6 = x2;
+ x3 = ESIGN<SHA>::Verifier(x2);
+ x4 = x2.GetKey();
+}
+
+void ESIGNFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ m_n.BERDecode(seq);
+ m_e.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void ESIGNFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ m_n.DEREncode(seq);
+ m_e.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer ESIGNFunction::ApplyFunction(const Integer &x) const
+{
+ DoQuickSanityCheck();
+ return STDMIN(a_exp_b_mod_c(x, m_e, m_n) >> (2*GetK()+2), MaxImage());
+}
+
+bool ESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = true;
+ pass = pass && m_n > Integer::One() && m_n.IsOdd();
+ pass = pass && m_e >= 8 && m_e < m_n;
+ return pass;
+}
+
+bool ESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
+ ;
+}
+
+void ESIGNFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
+ ;
+}
+
+// *****************************************************************************
+
+void InvertibleESIGNFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &param)
+{
+ int modulusSize = 1023*2;
+ param.GetIntValue("ModulusSize", modulusSize) || param.GetIntValue("KeySize", modulusSize);
+
+ if (modulusSize < 24)
+ throw InvalidArgument("InvertibleESIGNFunction: specified modulus size is too small");
+
+ if (modulusSize % 3 != 0)
+ throw InvalidArgument("InvertibleESIGNFunction: modulus size must be divisible by 3");
+
+ m_e = param.GetValueWithDefault("PublicExponent", Integer(32));
+
+ if (m_e < 8)
+ throw InvalidArgument("InvertibleESIGNFunction: public exponents less than 8 may not be secure");
+
+ // VC70 workaround: putting these after primeParam causes overlapped stack allocation
+ ConstByteArrayParameter seedParam;
+ SecByteBlock seed;
+
+ const Integer minP = Integer(204) << (modulusSize/3-8);
+ const Integer maxP = Integer::Power2(modulusSize/3)-1;
+ AlgorithmParameters primeParam = MakeParameters("Min", minP)("Max", maxP)("RandomNumberType", Integer::PRIME);
+
+ if (param.GetValue("Seed", seedParam))
+ {
+ seed.resize(seedParam.size() + 4);
+ memcpy(seed + 4, seedParam.begin(), seedParam.size());
+
+ PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)0);
+ m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
+ PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)1);
+ m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
+ }
+ else
+ {
+ m_p.GenerateRandom(rng, primeParam);
+ m_q.GenerateRandom(rng, primeParam);
+ }
+
+ m_n = m_p * m_p * m_q;
+
+ assert(m_n.BitCount() == modulusSize);
+}
+
+void InvertibleESIGNFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder privateKey(bt);
+ m_n.BERDecode(privateKey);
+ m_e.BERDecode(privateKey);
+ m_p.BERDecode(privateKey);
+ m_q.BERDecode(privateKey);
+ privateKey.MessageEnd();
+}
+
+void InvertibleESIGNFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder privateKey(bt);
+ m_n.DEREncode(privateKey);
+ m_e.DEREncode(privateKey);
+ m_p.DEREncode(privateKey);
+ m_q.DEREncode(privateKey);
+ privateKey.MessageEnd();
+}
+
+Integer InvertibleESIGNFunction::CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
+{
+ DoQuickSanityCheck();
+
+ Integer pq = m_p * m_q;
+ Integer p2 = m_p * m_p;
+ Integer r, z, re, a, w0, w1;
+
+ do
+ {
+ r.Randomize(rng, Integer::Zero(), pq);
+ z = x << (2*GetK()+2);
+ re = a_exp_b_mod_c(r, m_e, m_n);
+ a = (z - re) % m_n;
+ Integer::Divide(w1, w0, a, pq);
+ if (w1.NotZero())
+ {
+ ++w0;
+ w1 = pq - w1;
+ }
+ }
+ while ((w1 >> 2*GetK()+1).IsPositive());
+
+ ModularArithmetic modp(m_p);
+ Integer t = modp.Divide(w0 * r % m_p, m_e * re % m_p);
+ Integer s = r + t*pq;
+ assert(s < m_n);
+/*
+ using namespace std;
+ cout << "f = " << x << endl;
+ cout << "r = " << r << endl;
+ cout << "z = " << z << endl;
+ cout << "a = " << a << endl;
+ cout << "w0 = " << w0 << endl;
+ cout << "w1 = " << w1 << endl;
+ cout << "t = " << t << endl;
+ cout << "s = " << s << endl;
+*/
+ return s;
+}
+
+bool InvertibleESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = ESIGNFunction::Validate(rng, level);
+ pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
+ pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
+ pass = pass && m_p.BitCount() == m_q.BitCount();
+ if (level >= 1)
+ pass = pass && m_p * m_p * m_q == m_n;
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
+ return pass;
+}
+
+bool InvertibleESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper<ESIGNFunction>(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
+ ;
+}
+
+void InvertibleESIGNFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper<ESIGNFunction>(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
+ ;
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/esign.h b/lib/cryptopp/esign.h
new file mode 100644
index 000000000..8eecbc5a1
--- /dev/null
+++ b/lib/cryptopp/esign.h
@@ -0,0 +1,128 @@
+#ifndef CRYPTOPP_ESIGN_H
+#define CRYPTOPP_ESIGN_H
+
+/** \file
+ This file contains classes that implement the
+ ESIGN signature schemes as defined in IEEE P1363a.
+*/
+
+#include "pubkey.h"
+#include "integer.h"
+#include "asn.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class ESIGNFunction : public TrapdoorFunction, public ASN1CryptoMaterial<PublicKey>
+{
+ typedef ESIGNFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n, const Integer &e)
+ {m_n = n; m_e = e;}
+
+ // PublicKey
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ // CryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ // TrapdoorFunction
+ Integer ApplyFunction(const Integer &x) const;
+ Integer PreimageBound() const {return m_n;}
+ Integer ImageBound() const {return Integer::Power2(GetK());}
+
+ // non-derived
+ const Integer & GetModulus() const {return m_n;}
+ const Integer & GetPublicExponent() const {return m_e;}
+
+ void SetModulus(const Integer &n) {m_n = n;}
+ void SetPublicExponent(const Integer &e) {m_e = e;}
+
+protected:
+ unsigned int GetK() const {return m_n.BitCount()/3-1;}
+
+ Integer m_n, m_e;
+};
+
+//! _
+class InvertibleESIGNFunction : public ESIGNFunction, public RandomizedTrapdoorFunctionInverse, public PrivateKey
+{
+ typedef InvertibleESIGNFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n, const Integer &e, const Integer &p, const Integer &q)
+ {m_n = n; m_e = e; m_p = p; m_q = q;}
+ // generate a random private key
+ void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
+ {GenerateRandomWithKeySize(rng, modulusBits);}
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const;
+
+ // GeneratibleCryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+ /*! parameters: (ModulusSize) */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+
+ const Integer& GetPrime1() const {return m_p;}
+ const Integer& GetPrime2() const {return m_q;}
+
+ void SetPrime1(const Integer &p) {m_p = p;}
+ void SetPrime2(const Integer &q) {m_q = q;}
+
+protected:
+ Integer m_p, m_q;
+};
+
+//! _
+template <class T>
+class EMSA5Pad : public PK_DeterministicSignatureMessageEncodingMethod
+{
+public:
+ static const char *StaticAlgorithmName() {return "EMSA5";}
+
+ void ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+ {
+ SecByteBlock digest(hash.DigestSize());
+ hash.Final(digest);
+ size_t representativeByteLength = BitsToBytes(representativeBitLength);
+ T mgf;
+ mgf.GenerateAndMask(hash, representative, representativeByteLength, digest, digest.size(), false);
+ if (representativeBitLength % 8 != 0)
+ representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
+ }
+};
+
+//! EMSA5, for use with ESIGN
+struct P1363_EMSA5 : public SignatureStandard
+{
+ typedef EMSA5Pad<P1363_MGF1> SignatureMessageEncodingMethod;
+};
+
+struct ESIGN_Keys
+{
+ static std::string StaticAlgorithmName() {return "ESIGN";}
+ typedef ESIGNFunction PublicKey;
+ typedef InvertibleESIGNFunction PrivateKey;
+};
+
+//! ESIGN, as defined in IEEE P1363a
+template <class H, class STANDARD = P1363_EMSA5>
+struct ESIGN : public TF_SS<STANDARD, H, ESIGN_Keys>
+{
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/factory.h b/lib/cryptopp/factory.h
new file mode 100644
index 000000000..5b65db3da
--- /dev/null
+++ b/lib/cryptopp/factory.h
@@ -0,0 +1,136 @@
+#ifndef CRYPTOPP_OBJFACT_H
+#define CRYPTOPP_OBJFACT_H
+
+#include "cryptlib.h"
+#include <map>
+#include <vector>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+template <class AbstractClass>
+class ObjectFactory
+{
+public:
+ virtual ~ObjectFactory () {}
+ virtual AbstractClass * CreateObject() const =0;
+};
+
+//! _
+template <class AbstractClass, class ConcreteClass>
+class DefaultObjectFactory : public ObjectFactory<AbstractClass>
+{
+public:
+ AbstractClass * CreateObject() const
+ {
+ return new ConcreteClass;
+ }
+
+};
+
+//! _
+template <class AbstractClass, int instance=0>
+class ObjectFactoryRegistry
+{
+public:
+ class FactoryNotFound : public Exception
+ {
+ public:
+ FactoryNotFound(const char *name) : Exception(OTHER_ERROR, std::string("ObjectFactoryRegistry: could not find factory for algorithm ") + name) {}
+ };
+
+ ~ObjectFactoryRegistry()
+ {
+ for (CPP_TYPENAME Map::iterator i = m_map.begin(); i != m_map.end(); ++i)
+ {
+ delete (ObjectFactory<AbstractClass> *)i->second;
+ i->second = NULL;
+ }
+ }
+
+ void RegisterFactory(const std::string &name, ObjectFactory<AbstractClass> *factory)
+ {
+ m_map[name] = factory;
+ }
+
+ const ObjectFactory<AbstractClass> * GetFactory(const char *name) const
+ {
+ CPP_TYPENAME Map::const_iterator i = m_map.find(name);
+ return i == m_map.end() ? NULL : (ObjectFactory<AbstractClass> *)i->second;
+ }
+
+ AbstractClass *CreateObject(const char *name) const
+ {
+ const ObjectFactory<AbstractClass> *factory = GetFactory(name);
+ if (!factory)
+ throw FactoryNotFound(name);
+ return factory->CreateObject();
+ }
+
+ // Return a vector containing the factory names. This is easier than returning an iterator.
+ // from Andrew Pitonyak
+ std::vector<std::string> GetFactoryNames() const
+ {
+ std::vector<std::string> names;
+ CPP_TYPENAME Map::const_iterator iter;
+ for (iter = m_map.begin(); iter != m_map.end(); ++iter)
+ names.push_back(iter->first);
+ return names;
+ }
+
+ CRYPTOPP_NOINLINE static ObjectFactoryRegistry<AbstractClass, instance> & Registry(CRYPTOPP_NOINLINE_DOTDOTDOT);
+
+private:
+ // use void * instead of ObjectFactory<AbstractClass> * to save code size
+ typedef std::map<std::string, void *> Map;
+ Map m_map;
+};
+
+template <class AbstractClass, int instance>
+ObjectFactoryRegistry<AbstractClass, instance> & ObjectFactoryRegistry<AbstractClass, instance>::Registry(CRYPTOPP_NOINLINE_DOTDOTDOT)
+{
+ static ObjectFactoryRegistry<AbstractClass, instance> s_registry;
+ return s_registry;
+}
+
+template <class AbstractClass, class ConcreteClass, int instance = 0>
+struct RegisterDefaultFactoryFor {
+RegisterDefaultFactoryFor(const char *name=NULL)
+{
+ // BCB2006 workaround
+ std::string n = name ? std::string(name) : std::string(ConcreteClass::StaticAlgorithmName());
+ ObjectFactoryRegistry<AbstractClass, instance>::Registry().
+ RegisterFactory(n, new DefaultObjectFactory<AbstractClass, ConcreteClass>);
+}};
+
+template <class SchemeClass>
+void RegisterAsymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
+{
+ RegisterDefaultFactoryFor<PK_Encryptor, CPP_TYPENAME SchemeClass::Encryptor>((const char *)name);
+ RegisterDefaultFactoryFor<PK_Decryptor, CPP_TYPENAME SchemeClass::Decryptor>((const char *)name);
+}
+
+template <class SchemeClass>
+void RegisterSignatureSchemeDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
+{
+ RegisterDefaultFactoryFor<PK_Signer, CPP_TYPENAME SchemeClass::Signer>((const char *)name);
+ RegisterDefaultFactoryFor<PK_Verifier, CPP_TYPENAME SchemeClass::Verifier>((const char *)name);
+}
+
+template <class SchemeClass>
+void RegisterSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
+{
+ RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
+ RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
+}
+
+template <class SchemeClass>
+void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
+{
+ RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
+ RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/files.cpp b/lib/cryptopp/files.cpp
new file mode 100644
index 000000000..453b56248
--- /dev/null
+++ b/lib/cryptopp/files.cpp
@@ -0,0 +1,259 @@
+// files.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "files.h"
+
+#include <limits>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+using namespace std;
+
+#ifndef NDEBUG
+void Files_TestInstantiations()
+{
+ FileStore f0;
+ FileSource f1;
+ FileSink f2;
+}
+#endif
+
+void FileStore::StoreInitialize(const NameValuePairs &parameters)
+{
+ m_waiting = false;
+ m_stream = NULL;
+ m_file.release();
+
+ const char *fileName = NULL;
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
+ const wchar_t *fileNameWide = NULL;
+ if (!parameters.GetValue(Name::InputFileNameWide(), fileNameWide))
+#endif
+ if (!parameters.GetValue(Name::InputFileName(), fileName))
+ {
+ parameters.GetValue(Name::InputStreamPointer(), m_stream);
+ return;
+ }
+
+ ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? ios::binary : ios::openmode(0);
+ m_file.reset(new std::ifstream);
+#ifdef CRYPTOPP_UNIX_AVAILABLE
+ std::string narrowed;
+ if (fileNameWide)
+ fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
+#endif
+#if _MSC_VER >= 1400
+ if (fileNameWide)
+ {
+ m_file->open(fileNameWide, ios::in | binary);
+ if (!*m_file)
+ throw OpenErr(StringNarrow(fileNameWide, false));
+ }
+#endif
+ if (fileName)
+ {
+ m_file->open(fileName, ios::in | binary);
+ if (!*m_file)
+ throw OpenErr(fileName);
+ }
+ m_stream = m_file.get();
+}
+
+lword FileStore::MaxRetrievable() const
+{
+ if (!m_stream)
+ return 0;
+
+ streampos current = m_stream->tellg();
+ streampos end = m_stream->seekg(0, ios::end).tellg();
+ m_stream->seekg(current);
+ return end-current;
+}
+
+size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ if (!m_stream)
+ {
+ transferBytes = 0;
+ return 0;
+ }
+
+ lword size=transferBytes;
+ transferBytes = 0;
+
+ if (m_waiting)
+ goto output;
+
+ while (size && m_stream->good())
+ {
+ {
+ size_t spaceSize = 1024;
+ m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(0)-1, size), spaceSize);
+
+ m_stream->read((char *)m_space, (unsigned int)STDMIN(size, (lword)spaceSize));
+ }
+ m_len = (size_t)m_stream->gcount();
+ size_t blockedBytes;
+output:
+ blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
+ m_waiting = blockedBytes > 0;
+ if (m_waiting)
+ return blockedBytes;
+ size -= m_len;
+ transferBytes += m_len;
+ }
+
+ if (!m_stream->good() && !m_stream->eof())
+ throw ReadErr();
+
+ return 0;
+}
+
+size_t FileStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ if (!m_stream)
+ return 0;
+
+ if (begin == 0 && end == 1)
+ {
+ int result = m_stream->peek();
+ if (result == char_traits<char>::eof())
+ return 0;
+ else
+ {
+ size_t blockedBytes = target.ChannelPut(channel, byte(result), blocking);
+ begin += 1-blockedBytes;
+ return blockedBytes;
+ }
+ }
+
+ // TODO: figure out what happens on cin
+ streampos current = m_stream->tellg();
+ streampos endPosition = m_stream->seekg(0, ios::end).tellg();
+ streampos newPosition = current + (streamoff)begin;
+
+ if (newPosition >= endPosition)
+ {
+ m_stream->seekg(current);
+ return 0; // don't try to seek beyond the end of file
+ }
+ m_stream->seekg(newPosition);
+ try
+ {
+ assert(!m_waiting);
+ lword copyMax = end-begin;
+ size_t blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking);
+ begin += copyMax;
+ if (blockedBytes)
+ {
+ const_cast<FileStore *>(this)->m_waiting = false;
+ return blockedBytes;
+ }
+ }
+ catch(...)
+ {
+ m_stream->clear();
+ m_stream->seekg(current);
+ throw;
+ }
+ m_stream->clear();
+ m_stream->seekg(current);
+
+ return 0;
+}
+
+lword FileStore::Skip(lword skipMax)
+{
+ if (!m_stream)
+ return 0;
+
+ lword oldPos = m_stream->tellg();
+ std::istream::off_type offset;
+ if (!SafeConvert(skipMax, offset))
+ throw InvalidArgument("FileStore: maximum seek offset exceeded");
+ m_stream->seekg(offset, ios::cur);
+ return (lword)m_stream->tellg() - oldPos;
+}
+
+void FileSink::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_stream = NULL;
+ m_file.release();
+
+ const char *fileName = NULL;
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
+ const wchar_t *fileNameWide = NULL;
+ if (!parameters.GetValue(Name::OutputFileNameWide(), fileNameWide))
+#endif
+ if (!parameters.GetValue(Name::OutputFileName(), fileName))
+ {
+ parameters.GetValue(Name::OutputStreamPointer(), m_stream);
+ return;
+ }
+
+ ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? ios::binary : ios::openmode(0);
+ m_file.reset(new std::ofstream);
+#ifdef CRYPTOPP_UNIX_AVAILABLE
+ std::string narrowed;
+ if (fileNameWide)
+ fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
+#endif
+#if _MSC_VER >= 1400
+ if (fileNameWide)
+ {
+ m_file->open(fileNameWide, ios::out | ios::trunc | binary);
+ if (!*m_file)
+ throw OpenErr(StringNarrow(fileNameWide, false));
+ }
+#endif
+ if (fileName)
+ {
+ m_file->open(fileName, ios::out | ios::trunc | binary);
+ if (!*m_file)
+ throw OpenErr(fileName);
+ }
+ m_stream = m_file.get();
+}
+
+bool FileSink::IsolatedFlush(bool hardFlush, bool blocking)
+{
+ if (!m_stream)
+ throw Err("FileSink: output stream not opened");
+
+ m_stream->flush();
+ if (!m_stream->good())
+ throw WriteErr();
+
+ return false;
+}
+
+size_t FileSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ if (!m_stream)
+ throw Err("FileSink: output stream not opened");
+
+ while (length > 0)
+ {
+ std::streamsize size;
+ if (!SafeConvert(length, size))
+ size = numeric_limits<std::streamsize>::max();
+ m_stream->write((const char *)inString, size);
+ inString += size;
+ length -= (size_t)size;
+ }
+
+ if (messageEnd)
+ m_stream->flush();
+
+ if (!m_stream->good())
+ throw WriteErr();
+
+ return 0;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/files.h b/lib/cryptopp/files.h
new file mode 100644
index 000000000..a47e856bf
--- /dev/null
+++ b/lib/cryptopp/files.h
@@ -0,0 +1,112 @@
+#ifndef CRYPTOPP_FILES_H
+#define CRYPTOPP_FILES_H
+
+#include "cryptlib.h"
+#include "filters.h"
+#include "argnames.h"
+
+#include <iostream>
+#include <fstream>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! file-based implementation of Store interface
+class CRYPTOPP_DLL FileStore : public Store, private FilterPutSpaceHelper, public NotCopyable
+{
+public:
+ class Err : public Exception
+ {
+ public:
+ Err(const std::string &s) : Exception(IO_ERROR, s) {}
+ };
+ class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}};
+ class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}};
+
+ FileStore() : m_stream(NULL) {}
+ FileStore(std::istream &in)
+ {StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));}
+ FileStore(const char *filename)
+ {StoreInitialize(MakeParameters(Name::InputFileName(), filename));}
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
+ //! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
+ FileStore(const wchar_t *filename)
+ {StoreInitialize(MakeParameters(Name::InputFileNameWide(), filename));}
+#endif
+
+ std::istream* GetStream() {return m_stream;}
+
+ lword MaxRetrievable() const;
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+ lword Skip(lword skipMax=ULONG_MAX);
+
+private:
+ void StoreInitialize(const NameValuePairs &parameters);
+
+ member_ptr<std::ifstream> m_file;
+ std::istream *m_stream;
+ byte *m_space;
+ size_t m_len;
+ bool m_waiting;
+};
+
+//! file-based implementation of Source interface
+class CRYPTOPP_DLL FileSource : public SourceTemplate<FileStore>
+{
+public:
+ typedef FileStore::Err Err;
+ typedef FileStore::OpenErr OpenErr;
+ typedef FileStore::ReadErr ReadErr;
+
+ FileSource(BufferedTransformation *attachment = NULL)
+ : SourceTemplate<FileStore>(attachment) {}
+ FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL)
+ : SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));}
+ FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
+ : SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));}
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
+ //! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
+ FileSource(const wchar_t *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
+ : SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileNameWide(), filename)(Name::InputBinaryMode(), binary));}
+#endif
+
+ std::istream* GetStream() {return m_store.GetStream();}
+};
+
+//! file-based implementation of Sink interface
+class CRYPTOPP_DLL FileSink : public Sink, public NotCopyable
+{
+public:
+ class Err : public Exception
+ {
+ public:
+ Err(const std::string &s) : Exception(IO_ERROR, s) {}
+ };
+ class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}};
+ class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}};
+
+ FileSink() : m_stream(NULL) {}
+ FileSink(std::ostream &out)
+ {IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));}
+ FileSink(const char *filename, bool binary=true)
+ {IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)(Name::OutputBinaryMode(), binary));}
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
+ //! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
+ FileSink(const wchar_t *filename, bool binary=true)
+ {IsolatedInitialize(MakeParameters(Name::OutputFileNameWide(), filename)(Name::OutputBinaryMode(), binary));}
+#endif
+
+ std::ostream* GetStream() {return m_stream;}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
+ bool IsolatedFlush(bool hardFlush, bool blocking);
+
+private:
+ member_ptr<std::ofstream> m_file;
+ std::ostream *m_stream;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/filters.cpp b/lib/cryptopp/filters.cpp
new file mode 100644
index 000000000..083dfd361
--- /dev/null
+++ b/lib/cryptopp/filters.cpp
@@ -0,0 +1,1120 @@
+// filters.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "filters.h"
+#include "mqueue.h"
+#include "fltrimpl.h"
+#include "argnames.h"
+#include <memory>
+#include <functional>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+Filter::Filter(BufferedTransformation *attachment)
+ : m_attachment(attachment), m_continueAt(0)
+{
+}
+
+BufferedTransformation * Filter::NewDefaultAttachment() const
+{
+ return new MessageQueue;
+}
+
+BufferedTransformation * Filter::AttachedTransformation()
+{
+ if (m_attachment.get() == NULL)
+ m_attachment.reset(NewDefaultAttachment());
+ return m_attachment.get();
+}
+
+const BufferedTransformation *Filter::AttachedTransformation() const
+{
+ if (m_attachment.get() == NULL)
+ const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
+ return m_attachment.get();
+}
+
+void Filter::Detach(BufferedTransformation *newOut)
+{
+ m_attachment.reset(newOut);
+}
+
+void Filter::Insert(Filter *filter)
+{
+ filter->m_attachment.reset(m_attachment.release());
+ m_attachment.reset(filter);
+}
+
+size_t Filter::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
+}
+
+size_t Filter::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
+}
+
+void Filter::Initialize(const NameValuePairs &parameters, int propagation)
+{
+ m_continueAt = 0;
+ IsolatedInitialize(parameters);
+ PropagateInitialize(parameters, propagation);
+}
+
+bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
+{
+ switch (m_continueAt)
+ {
+ case 0:
+ if (IsolatedFlush(hardFlush, blocking))
+ return true;
+ case 1:
+ if (OutputFlush(1, hardFlush, propagation, blocking))
+ return true;
+ }
+ return false;
+}
+
+bool Filter::MessageSeriesEnd(int propagation, bool blocking)
+{
+ switch (m_continueAt)
+ {
+ case 0:
+ if (IsolatedMessageSeriesEnd(blocking))
+ return true;
+ case 1:
+ if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
+ return true;
+ }
+ return false;
+}
+
+void Filter::PropagateInitialize(const NameValuePairs &parameters, int propagation)
+{
+ if (propagation)
+ AttachedTransformation()->Initialize(parameters, propagation-1);
+}
+
+size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
+{
+ if (messageEnd)
+ messageEnd--;
+ size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking);
+ m_continueAt = result ? outputSite : 0;
+ return result;
+}
+
+size_t Filter::Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
+{
+ if (messageEnd)
+ messageEnd--;
+ size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking);
+ m_continueAt = result ? outputSite : 0;
+ return result;
+}
+
+bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
+{
+ if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
+ {
+ m_continueAt = outputSite;
+ return true;
+ }
+ m_continueAt = 0;
+ return false;
+}
+
+bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
+{
+ if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
+ {
+ m_continueAt = outputSite;
+ return true;
+ }
+ m_continueAt = 0;
+ return false;
+}
+
+// *************************************************************
+
+void MeterFilter::ResetMeter()
+{
+ m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0;
+ m_rangesToSkip.clear();
+}
+
+void MeterFilter::AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow)
+{
+ MessageRange r = {message, position, size};
+ m_rangesToSkip.push_back(r);
+ if (sortNow)
+ std::sort(m_rangesToSkip.begin(), m_rangesToSkip.end());
+}
+
+size_t MeterFilter::PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable)
+{
+ if (!m_transparent)
+ return 0;
+
+ size_t t;
+ FILTER_BEGIN;
+
+ m_begin = begin;
+ m_length = length;
+
+ while (m_length > 0 || messageEnd)
+ {
+ if (m_length > 0 && !m_rangesToSkip.empty() && m_rangesToSkip.front().message == m_totalMessages && m_currentMessageBytes + m_length > m_rangesToSkip.front().position)
+ {
+ FILTER_OUTPUT_MAYBE_MODIFIABLE(1, m_begin, t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position, m_currentMessageBytes), false, modifiable);
+
+ assert(t < m_length);
+ m_begin += t;
+ m_length -= t;
+ m_currentMessageBytes += t;
+ m_totalBytes += t;
+
+ if (m_currentMessageBytes + m_length < m_rangesToSkip.front().position + m_rangesToSkip.front().size)
+ t = m_length;
+ else
+ {
+ t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position + m_rangesToSkip.front().size, m_currentMessageBytes);
+ assert(t <= m_length);
+ m_rangesToSkip.pop_front();
+ }
+
+ m_begin += t;
+ m_length -= t;
+ m_currentMessageBytes += t;
+ m_totalBytes += t;
+ }
+ else
+ {
+ FILTER_OUTPUT_MAYBE_MODIFIABLE(2, m_begin, m_length, messageEnd, modifiable);
+
+ m_currentMessageBytes += m_length;
+ m_totalBytes += m_length;
+ m_length = 0;
+
+ if (messageEnd)
+ {
+ m_currentMessageBytes = 0;
+ m_currentSeriesMessages++;
+ m_totalMessages++;
+ messageEnd = false;
+ }
+ }
+ }
+
+ FILTER_END_NO_MESSAGE_END;
+}
+
+size_t MeterFilter::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ return PutMaybeModifiable(const_cast<byte *>(begin), length, messageEnd, blocking, false);
+}
+
+size_t MeterFilter::PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ return PutMaybeModifiable(begin, length, messageEnd, blocking, true);
+}
+
+bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
+{
+ m_currentMessageBytes = 0;
+ m_currentSeriesMessages = 0;
+ m_totalMessageSeries++;
+ return false;
+}
+
+// *************************************************************
+
+void FilterWithBufferedInput::BlockQueue::ResetQueue(size_t blockSize, size_t maxBlocks)
+{
+ m_buffer.New(blockSize * maxBlocks);
+ m_blockSize = blockSize;
+ m_maxBlocks = maxBlocks;
+ m_size = 0;
+ m_begin = m_buffer;
+}
+
+byte *FilterWithBufferedInput::BlockQueue::GetBlock()
+{
+ if (m_size >= m_blockSize)
+ {
+ byte *ptr = m_begin;
+ if ((m_begin+=m_blockSize) == m_buffer.end())
+ m_begin = m_buffer;
+ m_size -= m_blockSize;
+ return ptr;
+ }
+ else
+ return NULL;
+}
+
+byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes)
+{
+ numberOfBytes = STDMIN(numberOfBytes, STDMIN(size_t(m_buffer.end()-m_begin), m_size));
+ byte *ptr = m_begin;
+ m_begin += numberOfBytes;
+ m_size -= numberOfBytes;
+ if (m_size == 0 || m_begin == m_buffer.end())
+ m_begin = m_buffer;
+ return ptr;
+}
+
+size_t FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
+{
+ size_t size = m_size;
+ size_t numberOfBytes = m_maxBlocks*m_blockSize;
+ const byte *ptr = GetContigousBlocks(numberOfBytes);
+ memcpy(outString, ptr, numberOfBytes);
+ memcpy(outString+numberOfBytes, m_begin, m_size);
+ m_size = 0;
+ return size;
+}
+
+void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, size_t length)
+{
+ assert(m_size + length <= m_buffer.size());
+ byte *end = (m_size < size_t(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
+ size_t len = STDMIN(length, size_t(m_buffer.end()-end));
+ memcpy(end, inString, len);
+ if (len < length)
+ memcpy(m_buffer, inString+len, length-len);
+ m_size += length;
+}
+
+FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
+ : Filter(attachment)
+{
+}
+
+FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment)
+ : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize)
+ , m_firstInputDone(false)
+{
+ if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
+ throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
+
+ m_queue.ResetQueue(1, m_firstSize);
+}
+
+void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
+ if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
+ throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
+ m_queue.ResetQueue(1, m_firstSize);
+ m_firstInputDone = false;
+}
+
+bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
+{
+ if (!blocking)
+ throw BlockingInputOnly("FilterWithBufferedInput");
+
+ if (hardFlush)
+ ForceNextPut();
+ FlushDerived();
+
+ return false;
+}
+
+size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable)
+{
+ if (!blocking)
+ throw BlockingInputOnly("FilterWithBufferedInput");
+
+ if (length != 0)
+ {
+ size_t newLength = m_queue.CurrentSize() + length;
+
+ if (!m_firstInputDone && newLength >= m_firstSize)
+ {
+ size_t len = m_firstSize - m_queue.CurrentSize();
+ m_queue.Put(inString, len);
+ FirstPut(m_queue.GetContigousBlocks(m_firstSize));
+ assert(m_queue.CurrentSize() == 0);
+ m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
+
+ inString += len;
+ newLength -= m_firstSize;
+ m_firstInputDone = true;
+ }
+
+ if (m_firstInputDone)
+ {
+ if (m_blockSize == 1)
+ {
+ while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
+ {
+ size_t len = newLength - m_lastSize;
+ byte *ptr = m_queue.GetContigousBlocks(len);
+ NextPutModifiable(ptr, len);
+ newLength -= len;
+ }
+
+ if (newLength > m_lastSize)
+ {
+ size_t len = newLength - m_lastSize;
+ NextPutMaybeModifiable(inString, len, modifiable);
+ inString += len;
+ newLength -= len;
+ }
+ }
+ else
+ {
+ while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
+ {
+ NextPutModifiable(m_queue.GetBlock(), m_blockSize);
+ newLength -= m_blockSize;
+ }
+
+ if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
+ {
+ assert(m_queue.CurrentSize() < m_blockSize);
+ size_t len = m_blockSize - m_queue.CurrentSize();
+ m_queue.Put(inString, len);
+ inString += len;
+ NextPutModifiable(m_queue.GetBlock(), m_blockSize);
+ newLength -= m_blockSize;
+ }
+
+ if (newLength >= m_blockSize + m_lastSize)
+ {
+ size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
+ NextPutMaybeModifiable(inString, len, modifiable);
+ inString += len;
+ newLength -= len;
+ }
+ }
+ }
+
+ m_queue.Put(inString, newLength - m_queue.CurrentSize());
+ }
+
+ if (messageEnd)
+ {
+ if (!m_firstInputDone && m_firstSize==0)
+ FirstPut(NULL);
+
+ SecByteBlock temp(m_queue.CurrentSize());
+ m_queue.GetAll(temp);
+ LastPut(temp, temp.size());
+
+ m_firstInputDone = false;
+ m_queue.ResetQueue(1, m_firstSize);
+
+ Output(1, NULL, 0, messageEnd, blocking);
+ }
+ return 0;
+}
+
+void FilterWithBufferedInput::ForceNextPut()
+{
+ if (!m_firstInputDone)
+ return;
+
+ if (m_blockSize > 1)
+ {
+ while (m_queue.CurrentSize() >= m_blockSize)
+ NextPutModifiable(m_queue.GetBlock(), m_blockSize);
+ }
+ else
+ {
+ size_t len;
+ while ((len = m_queue.CurrentSize()) > 0)
+ NextPutModifiable(m_queue.GetContigousBlocks(len), len);
+ }
+}
+
+void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length)
+{
+ assert(m_blockSize > 1); // m_blockSize = 1 should always override this function
+ while (length > 0)
+ {
+ assert(length >= m_blockSize);
+ NextPutSingle(inString);
+ inString += m_blockSize;
+ length -= m_blockSize;
+ }
+}
+
+// *************************************************************
+
+void Redirector::Initialize(const NameValuePairs &parameters, int propagation)
+{
+ m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
+ m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING);
+
+ if (m_target && GetPassSignals())
+ m_target->Initialize(parameters, propagation);
+}
+
+// *************************************************************
+
+ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment)
+ : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter)
+{
+ if (m_filter.get())
+ m_filter->Attach(new OutputProxy(*this, false));
+}
+
+bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking)
+{
+ return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false;
+}
+
+void ProxyFilter::SetFilter(Filter *filter)
+{
+ m_filter.reset(filter);
+ if (filter)
+ {
+ OutputProxy *proxy;
+ std::auto_ptr<OutputProxy> temp(proxy = new OutputProxy(*this, false));
+ m_filter->TransferAllTo(*proxy);
+ m_filter->Attach(temp.release());
+ }
+}
+
+void ProxyFilter::NextPutMultiple(const byte *s, size_t len)
+{
+ if (m_filter.get())
+ m_filter->Put(s, len);
+}
+
+void ProxyFilter::NextPutModifiable(byte *s, size_t len)
+{
+ if (m_filter.get())
+ m_filter->PutModifiable(s, len);
+}
+
+// *************************************************************
+
+void RandomNumberSink::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng);
+}
+
+size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ m_rng->IncorporateEntropy(begin, length);
+ return 0;
+}
+
+size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (m_buf+m_total != begin)
+ memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
+ m_total += length;
+ return 0;
+}
+
+byte * ArraySink::CreatePutSpace(size_t &size)
+{
+ size = SaturatingSubtract(m_size, m_total);
+ return m_buf + m_total;
+}
+
+void ArraySink::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ ByteArrayParameter array;
+ if (!parameters.GetValue(Name::OutputBuffer(), array))
+ throw InvalidArgument("ArraySink: missing OutputBuffer argument");
+ m_buf = array.begin();
+ m_size = array.size();
+ m_total = 0;
+}
+
+size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
+ m_total += length;
+ return 0;
+}
+
+// *************************************************************
+
+StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool allowAuthenticatedSymmetricCipher)
+ : FilterWithBufferedInput(attachment)
+ , m_cipher(c)
+{
+ assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
+
+ if (!allowAuthenticatedSymmetricCipher && dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != 0)
+ throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
+
+ IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
+}
+
+size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding)
+{
+ if (c.MinLastBlockSize() > 0)
+ return c.MinLastBlockSize();
+ else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
+ return c.MandatoryBlockSize();
+ else
+ return 0;
+}
+
+void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
+{
+ BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING);
+ bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0);
+
+ if (padding == DEFAULT_PADDING)
+ m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
+ else
+ m_padding = padding;
+
+ if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING))
+ throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName());
+
+ firstSize = 0;
+ blockSize = m_cipher.MandatoryBlockSize();
+ lastSize = LastBlockSize(m_cipher, m_padding);
+}
+
+void StreamTransformationFilter::FirstPut(const byte *inString)
+{
+ m_optimalBufferSize = m_cipher.OptimalBlockSize();
+ m_optimalBufferSize = (unsigned int)STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
+}
+
+void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length)
+{
+ if (!length)
+ return;
+
+ size_t s = m_cipher.MandatoryBlockSize();
+
+ do
+ {
+ size_t len = m_optimalBufferSize;
+ byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len);
+ if (len < length)
+ {
+ if (len == m_optimalBufferSize)
+ len -= m_cipher.GetOptimalBlockSizeUsed();
+ len = RoundDownToMultipleOf(len, s);
+ }
+ else
+ len = length;
+ m_cipher.ProcessString(space, inString, len);
+ AttachedTransformation()->PutModifiable(space, len);
+ inString += len;
+ length -= len;
+ }
+ while (length > 0);
+}
+
+void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length)
+{
+ m_cipher.ProcessString(inString, length);
+ AttachedTransformation()->PutModifiable(inString, length);
+}
+
+void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
+{
+ byte *space = NULL;
+
+ switch (m_padding)
+ {
+ case NO_PADDING:
+ case ZEROS_PADDING:
+ if (length > 0)
+ {
+ size_t minLastBlockSize = m_cipher.MinLastBlockSize();
+ bool isForwardTransformation = m_cipher.IsForwardTransformation();
+
+ if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
+ {
+ // do padding
+ size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize());
+ space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize);
+ memcpy(space, inString, length);
+ memset(space + length, 0, blockSize - length);
+ m_cipher.ProcessLastBlock(space, space, blockSize);
+ AttachedTransformation()->Put(space, blockSize);
+ }
+ else
+ {
+ if (minLastBlockSize == 0)
+ {
+ if (isForwardTransformation)
+ throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified");
+ else
+ throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
+ }
+
+ space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize);
+ m_cipher.ProcessLastBlock(space, inString, length);
+ AttachedTransformation()->Put(space, length);
+ }
+ }
+ break;
+
+ case PKCS_PADDING:
+ case ONE_AND_ZEROS_PADDING:
+ unsigned int s;
+ s = m_cipher.MandatoryBlockSize();
+ assert(s > 1);
+ space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize);
+ if (m_cipher.IsForwardTransformation())
+ {
+ assert(length < s);
+ memcpy(space, inString, length);
+ if (m_padding == PKCS_PADDING)
+ {
+ assert(s < 256);
+ byte pad = byte(s-length);
+ memset(space+length, pad, s-length);
+ }
+ else
+ {
+ space[length] = 0x80;
+ memset(space+length+1, 0, s-length-1);
+ }
+ m_cipher.ProcessData(space, space, s);
+ AttachedTransformation()->Put(space, s);
+ }
+ else
+ {
+ if (length != s)
+ throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
+ m_cipher.ProcessData(space, inString, s);
+ if (m_padding == PKCS_PADDING)
+ {
+ byte pad = space[s-1];
+ if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to<byte>(), pad)) != space+s)
+ throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found");
+ length = s-pad;
+ }
+ else
+ {
+ while (length > 1 && space[length-1] == 0)
+ --length;
+ if (space[--length] != 0x80)
+ throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found");
+ }
+ AttachedTransformation()->Put(space, length);
+ }
+ break;
+
+ default:
+ assert(false);
+ }
+}
+
+// *************************************************************
+
+HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel)
+ : m_hashModule(hm), m_putMessage(putMessage), m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel)
+{
+ m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize;
+ Detach(attachment);
+}
+
+void HashFilter::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
+ int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
+ m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
+}
+
+size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ FILTER_BEGIN;
+ if (m_putMessage)
+ FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel);
+ m_hashModule.Update(inString, length);
+ if (messageEnd)
+ {
+ {
+ size_t size;
+ m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize);
+ m_hashModule.TruncatedFinal(m_space, m_digestSize);
+ }
+ FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel);
+ }
+ FILTER_END_NO_MESSAGE_END;
+}
+
+// *************************************************************
+
+HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize)
+ : FilterWithBufferedInput(attachment)
+ , m_hashModule(hm)
+{
+ IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
+}
+
+void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
+{
+ m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
+ int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
+ m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
+ m_verified = false;
+ firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0;
+ blockSize = 1;
+ lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize;
+}
+
+void HashVerificationFilter::FirstPut(const byte *inString)
+{
+ if (m_flags & HASH_AT_BEGIN)
+ {
+ m_expectedHash.New(m_digestSize);
+ memcpy(m_expectedHash, inString, m_expectedHash.size());
+ if (m_flags & PUT_HASH)
+ AttachedTransformation()->Put(inString, m_expectedHash.size());
+ }
+}
+
+void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
+{
+ m_hashModule.Update(inString, length);
+ if (m_flags & PUT_MESSAGE)
+ AttachedTransformation()->Put(inString, length);
+}
+
+void HashVerificationFilter::LastPut(const byte *inString, size_t length)
+{
+ if (m_flags & HASH_AT_BEGIN)
+ {
+ assert(length == 0);
+ m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize);
+ }
+ else
+ {
+ m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length));
+ if (m_flags & PUT_HASH)
+ AttachedTransformation()->Put(inString, length);
+ }
+
+ if (m_flags & PUT_RESULT)
+ AttachedTransformation()->Put(m_verified);
+
+ if ((m_flags & THROW_EXCEPTION) && !m_verified)
+ throw HashVerificationFailed();
+}
+
+// *************************************************************
+
+AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment,
+ bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding)
+ : StreamTransformationFilter(c, attachment, padding, true)
+ , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel)
+{
+ assert(c.IsForwardTransformation());
+}
+
+void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_hf.IsolatedInitialize(parameters);
+ StreamTransformationFilter::IsolatedInitialize(parameters);
+}
+
+byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
+{
+ if (channel.empty())
+ return StreamTransformationFilter::CreatePutSpace(size);
+
+ if (channel == AAD_CHANNEL)
+ return m_hf.CreatePutSpace(size);
+
+ throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
+}
+
+size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (channel.empty())
+ return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking);
+
+ if (channel == AAD_CHANNEL)
+ return m_hf.Put2(begin, length, 0, blocking);
+
+ throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
+}
+
+void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length)
+{
+ StreamTransformationFilter::LastPut(inString, length);
+ m_hf.MessageEnd();
+}
+
+// *************************************************************
+
+AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize, BlockPaddingScheme padding)
+ : FilterWithBufferedInput(attachment)
+ , m_hashVerifier(c, new OutputProxy(*this, false))
+ , m_streamFilter(c, new OutputProxy(*this, false), padding, true)
+{
+ assert(!c.IsForwardTransformation() || c.IsSelfInverting());
+ IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)(Name::AuthenticatedDecryptionFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
+}
+
+void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
+{
+ word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS);
+
+ m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags)));
+ m_streamFilter.Initialize(parameters);
+
+ firstSize = m_hashVerifier.m_firstSize;
+ blockSize = 1;
+ lastSize = m_hashVerifier.m_lastSize;
+}
+
+byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
+{
+ if (channel.empty())
+ return m_streamFilter.CreatePutSpace(size);
+
+ if (channel == AAD_CHANNEL)
+ return m_hashVerifier.CreatePutSpace(size);
+
+ throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
+}
+
+size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (channel.empty())
+ {
+ if (m_lastSize > 0)
+ m_hashVerifier.ForceNextPut();
+ return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking);
+ }
+
+ if (channel == AAD_CHANNEL)
+ return m_hashVerifier.Put2(begin, length, 0, blocking);
+
+ throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
+}
+
+void AuthenticatedDecryptionFilter::FirstPut(const byte *inString)
+{
+ m_hashVerifier.Put(inString, m_firstSize);
+}
+
+void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length)
+{
+ m_streamFilter.Put(inString, length);
+}
+
+void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length)
+{
+ m_streamFilter.MessageEnd();
+ m_hashVerifier.PutMessageEnd(inString, length);
+}
+
+// *************************************************************
+
+void SignerFilter::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
+ m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
+}
+
+size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ FILTER_BEGIN;
+ m_messageAccumulator->Update(inString, length);
+ if (m_putMessage)
+ FILTER_OUTPUT(1, inString, length, 0);
+ if (messageEnd)
+ {
+ m_buf.New(m_signer.SignatureLength());
+ m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
+ FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
+ m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
+ }
+ FILTER_END_NO_MESSAGE_END;
+}
+
+SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags)
+ : FilterWithBufferedInput(attachment)
+ , m_verifier(verifier)
+{
+ IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags));
+}
+
+void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
+{
+ m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
+ m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
+ size_t size = m_verifier.SignatureLength();
+ assert(size != 0); // TODO: handle recoverable signature scheme
+ m_verified = false;
+ firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
+ blockSize = 1;
+ lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
+}
+
+void SignatureVerificationFilter::FirstPut(const byte *inString)
+{
+ if (m_flags & SIGNATURE_AT_BEGIN)
+ {
+ if (m_verifier.SignatureUpfront())
+ m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
+ else
+ {
+ m_signature.New(m_verifier.SignatureLength());
+ memcpy(m_signature, inString, m_signature.size());
+ }
+
+ if (m_flags & PUT_SIGNATURE)
+ AttachedTransformation()->Put(inString, m_signature.size());
+ }
+ else
+ {
+ assert(!m_verifier.SignatureUpfront());
+ }
+}
+
+void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
+{
+ m_messageAccumulator->Update(inString, length);
+ if (m_flags & PUT_MESSAGE)
+ AttachedTransformation()->Put(inString, length);
+}
+
+void SignatureVerificationFilter::LastPut(const byte *inString, size_t length)
+{
+ if (m_flags & SIGNATURE_AT_BEGIN)
+ {
+ assert(length == 0);
+ m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
+ m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
+ }
+ else
+ {
+ m_verifier.InputSignature(*m_messageAccumulator, inString, length);
+ m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
+ if (m_flags & PUT_SIGNATURE)
+ AttachedTransformation()->Put(inString, length);
+ }
+
+ if (m_flags & PUT_RESULT)
+ AttachedTransformation()->Put(m_verified);
+
+ if ((m_flags & THROW_EXCEPTION) && !m_verified)
+ throw SignatureVerificationFailed();
+}
+
+// *************************************************************
+
+size_t Source::PumpAll2(bool blocking)
+{
+ unsigned int messageCount = UINT_MAX;
+ do {
+ RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking));
+ } while(messageCount == UINT_MAX);
+
+ return 0;
+}
+
+bool Store::GetNextMessage()
+{
+ if (!m_messageEnd && !AnyRetrievable())
+ {
+ m_messageEnd=true;
+ return true;
+ }
+ else
+ return false;
+}
+
+unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
+{
+ if (m_messageEnd || count == 0)
+ return 0;
+ else
+ {
+ CopyTo(target, ULONG_MAX, channel);
+ if (GetAutoSignalPropagation())
+ target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
+ return 1;
+ }
+}
+
+void StringStore::StoreInitialize(const NameValuePairs &parameters)
+{
+ ConstByteArrayParameter array;
+ if (!parameters.GetValue(Name::InputBuffer(), array))
+ throw InvalidArgument("StringStore: missing InputBuffer argument");
+ m_store = array.begin();
+ m_length = array.size();
+ m_count = 0;
+}
+
+size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ lword position = 0;
+ size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
+ m_count += (size_t)position;
+ transferBytes = position;
+ return blockedBytes;
+}
+
+size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ size_t i = UnsignedMin(m_length, m_count+begin);
+ size_t len = UnsignedMin(m_length-i, end-begin);
+ size_t blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
+ if (!blockedBytes)
+ begin += len;
+ return blockedBytes;
+}
+
+void RandomNumberStore::StoreInitialize(const NameValuePairs &parameters)
+{
+ parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng);
+ int length;
+ parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length);
+ m_length = length;
+}
+
+size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ if (!blocking)
+ throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");
+
+ transferBytes = UnsignedMin(transferBytes, m_length - m_count);
+ m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes);
+ m_count += transferBytes;
+
+ return 0;
+}
+
+size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ static const byte nullBytes[128] = {0};
+ while (begin < end)
+ {
+ size_t len = (size_t)STDMIN(end-begin, lword(128));
+ size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking);
+ if (blockedBytes)
+ return blockedBytes;
+ begin += len;
+ }
+ return 0;
+}
+
+size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ lword begin = 0;
+ size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking);
+ transferBytes = begin;
+ m_size -= begin;
+ return blockedBytes;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/filters.h b/lib/cryptopp/filters.h
new file mode 100644
index 000000000..c72a4ece3
--- /dev/null
+++ b/lib/cryptopp/filters.h
@@ -0,0 +1,810 @@
+#ifndef CRYPTOPP_FILTERS_H
+#define CRYPTOPP_FILTERS_H
+
+//! \file
+
+#include "simple.h"
+#include "secblock.h"
+#include "misc.h"
+#include "smartptr.h"
+#include "queue.h"
+#include "algparam.h"
+#include <deque>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// provides an implementation of BufferedTransformation's attachment interface
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable
+{
+public:
+ Filter(BufferedTransformation *attachment = NULL);
+
+ bool Attachable() {return true;}
+ BufferedTransformation *AttachedTransformation();
+ const BufferedTransformation *AttachedTransformation() const;
+ void Detach(BufferedTransformation *newAttachment = NULL);
+
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+
+ void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1);
+ bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
+ bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
+
+protected:
+ virtual BufferedTransformation * NewDefaultAttachment() const;
+ void Insert(Filter *nextFilter); // insert filter after this one
+
+ virtual bool ShouldPropagateMessageEnd() const {return true;}
+ virtual bool ShouldPropagateMessageSeriesEnd() const {return true;}
+
+ void PropagateInitialize(const NameValuePairs &parameters, int propagation);
+
+ size_t Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
+ size_t OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
+ bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
+ bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
+ bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
+
+private:
+ member_ptr<BufferedTransformation> m_attachment;
+
+protected:
+ size_t m_inputPosition;
+ int m_continueAt;
+};
+
+struct CRYPTOPP_DLL FilterPutSpaceHelper
+{
+ // desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace
+ byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize)
+ {
+ assert(desiredSize >= minSize && bufferSize >= minSize);
+ if (m_tempSpace.size() < minSize)
+ {
+ byte *result = target.ChannelCreatePutSpace(channel, desiredSize);
+ if (desiredSize >= minSize)
+ {
+ bufferSize = desiredSize;
+ return result;
+ }
+ m_tempSpace.New(bufferSize);
+ }
+
+ bufferSize = m_tempSpace.size();
+ return m_tempSpace.begin();
+ }
+ byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize)
+ {return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);}
+ byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t bufferSize)
+ {return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);}
+ SecByteBlock m_tempSpace;
+};
+
+//! measure how many byte and messages pass through, also serves as valve
+class CRYPTOPP_DLL MeterFilter : public Bufferless<Filter>
+{
+public:
+ MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true)
+ : m_transparent(transparent) {Detach(attachment); ResetMeter();}
+
+ void SetTransparent(bool transparent) {m_transparent = transparent;}
+ void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow = true);
+ void ResetMeter();
+ void IsolatedInitialize(const NameValuePairs &parameters) {ResetMeter();}
+
+ lword GetCurrentMessageBytes() const {return m_currentMessageBytes;}
+ lword GetTotalBytes() {return m_totalBytes;}
+ unsigned int GetCurrentSeriesMessages() {return m_currentSeriesMessages;}
+ unsigned int GetTotalMessages() {return m_totalMessages;}
+ unsigned int GetTotalMessageSeries() {return m_totalMessageSeries;}
+
+ byte * CreatePutSpace(size_t &size)
+ {return AttachedTransformation()->CreatePutSpace(size);}
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+ size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking);
+ bool IsolatedMessageSeriesEnd(bool blocking);
+
+private:
+ size_t PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable);
+ bool ShouldPropagateMessageEnd() const {return m_transparent;}
+ bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;}
+
+ struct MessageRange
+ {
+ inline bool operator<(const MessageRange &b) const // BCB2006 workaround: this has to be a member function
+ {return message < b.message || (message == b.message && position < b.position);}
+ unsigned int message; lword position; lword size;
+ };
+
+ bool m_transparent;
+ lword m_currentMessageBytes, m_totalBytes;
+ unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries;
+ std::deque<MessageRange> m_rangesToSkip;
+ byte *m_begin;
+ size_t m_length;
+};
+
+//! _
+class CRYPTOPP_DLL TransparentFilter : public MeterFilter
+{
+public:
+ TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {}
+};
+
+//! _
+class CRYPTOPP_DLL OpaqueFilter : public MeterFilter
+{
+public:
+ OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {}
+};
+
+/*! FilterWithBufferedInput divides up the input stream into
+ a first block, a number of middle blocks, and a last block.
+ First and last blocks are optional, and middle blocks may
+ be a stream instead (i.e. blockSize == 1).
+*/
+class CRYPTOPP_DLL FilterWithBufferedInput : public Filter
+{
+public:
+ FilterWithBufferedInput(BufferedTransformation *attachment);
+ //! firstSize and lastSize may be 0, blockSize must be at least 1
+ FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment);
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+ {
+ return PutMaybeModifiable(const_cast<byte *>(inString), length, messageEnd, blocking, false);
+ }
+ size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
+ {
+ return PutMaybeModifiable(inString, length, messageEnd, blocking, true);
+ }
+ /*! calls ForceNextPut() if hardFlush is true */
+ bool IsolatedFlush(bool hardFlush, bool blocking);
+
+ /*! The input buffer may contain more than blockSize bytes if lastSize != 0.
+ ForceNextPut() forces a call to NextPut() if this is the case.
+ */
+ void ForceNextPut();
+
+protected:
+ bool DidFirstPut() {return m_firstInputDone;}
+
+ virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
+ {InitializeDerived(parameters);}
+ virtual void InitializeDerived(const NameValuePairs &parameters) {}
+ // FirstPut() is called if (firstSize != 0 and totalLength >= firstSize)
+ // or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received))
+ virtual void FirstPut(const byte *inString) =0;
+ // NextPut() is called if totalLength >= firstSize+blockSize+lastSize
+ virtual void NextPutSingle(const byte *inString) {assert(false);}
+ // Same as NextPut() except length can be a multiple of blockSize
+ // Either NextPut() or NextPutMultiple() must be overriden
+ virtual void NextPutMultiple(const byte *inString, size_t length);
+ // Same as NextPutMultiple(), but inString can be modified
+ virtual void NextPutModifiable(byte *inString, size_t length)
+ {NextPutMultiple(inString, length);}
+ // LastPut() is always called
+ // if totalLength < firstSize then length == totalLength
+ // else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
+ // else lastSize <= length < lastSize+blockSize
+ virtual void LastPut(const byte *inString, size_t length) =0;
+ virtual void FlushDerived() {}
+
+protected:
+ size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable);
+ void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable)
+ {
+ if (modifiable) NextPutModifiable(inString, length);
+ else NextPutMultiple(inString, length);
+ }
+
+ // This function should no longer be used, put this here to cause a compiler error
+ // if someone tries to override NextPut().
+ virtual int NextPut(const byte *inString, size_t length) {assert(false); return 0;}
+
+ class BlockQueue
+ {
+ public:
+ void ResetQueue(size_t blockSize, size_t maxBlocks);
+ byte *GetBlock();
+ byte *GetContigousBlocks(size_t &numberOfBytes);
+ size_t GetAll(byte *outString);
+ void Put(const byte *inString, size_t length);
+ size_t CurrentSize() const {return m_size;}
+ size_t MaxSize() const {return m_buffer.size();}
+
+ private:
+ SecByteBlock m_buffer;
+ size_t m_blockSize, m_maxBlocks, m_size;
+ byte *m_begin;
+ };
+
+ size_t m_firstSize, m_blockSize, m_lastSize;
+ bool m_firstInputDone;
+ BlockQueue m_queue;
+};
+
+//! _
+class CRYPTOPP_DLL FilterWithInputQueue : public Filter
+{
+public:
+ FilterWithInputQueue(BufferedTransformation *attachment=NULL) : Filter(attachment) {}
+
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+ {
+ if (!blocking)
+ throw BlockingInputOnly("FilterWithInputQueue");
+
+ m_inQueue.Put(inString, length);
+ if (messageEnd)
+ {
+ IsolatedMessageEnd(blocking);
+ Output(0, NULL, 0, messageEnd, blocking);
+ }
+ return 0;
+ }
+
+protected:
+ virtual bool IsolatedMessageEnd(bool blocking) =0;
+ void IsolatedInitialize(const NameValuePairs &parameters) {m_inQueue.Clear();}
+
+ ByteQueue m_inQueue;
+};
+
+struct BlockPaddingSchemeDef
+{
+ enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
+};
+
+//! Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed
+class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper
+{
+public:
+ /*! DEFAULT_PADDING means PKCS_PADDING if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode),
+ otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes).
+ See http://www.weidai.com/scan-mirror/csp.html for details of the padding schemes. */
+ StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, bool allowAuthenticatedSymmetricCipher = false);
+
+ std::string AlgorithmName() const {return m_cipher.AlgorithmName();}
+
+protected:
+ void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
+ void FirstPut(const byte *inString);
+ void NextPutMultiple(const byte *inString, size_t length);
+ void NextPutModifiable(byte *inString, size_t length);
+ void LastPut(const byte *inString, size_t length);
+
+ static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding);
+
+ StreamTransformation &m_cipher;
+ BlockPaddingScheme m_padding;
+ unsigned int m_optimalBufferSize;
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef StreamTransformationFilter StreamCipherFilter;
+#endif
+
+//! Filter Wrapper for HashTransformation
+class CRYPTOPP_DLL HashFilter : public Bufferless<Filter>, private FilterPutSpaceHelper
+{
+public:
+ HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL);
+
+ std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+ byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);}
+
+private:
+ HashTransformation &m_hashModule;
+ bool m_putMessage;
+ unsigned int m_digestSize;
+ byte *m_space;
+ std::string m_messagePutChannel, m_hashPutChannel;
+};
+
+//! Filter Wrapper for HashTransformation
+class CRYPTOPP_DLL HashVerificationFilter : public FilterWithBufferedInput
+{
+public:
+ class HashVerificationFailed : public Exception
+ {
+ public:
+ HashVerificationFailed()
+ : Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {}
+ };
+
+ enum Flags {HASH_AT_END=0, HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT};
+ HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1);
+
+ std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
+ bool GetLastResult() const {return m_verified;}
+
+protected:
+ void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
+ void FirstPut(const byte *inString);
+ void NextPutMultiple(const byte *inString, size_t length);
+ void LastPut(const byte *inString, size_t length);
+
+private:
+ friend class AuthenticatedDecryptionFilter;
+
+ HashTransformation &m_hashModule;
+ word32 m_flags;
+ unsigned int m_digestSize;
+ bool m_verified;
+ SecByteBlock m_expectedHash;
+};
+
+typedef HashVerificationFilter HashVerifier; // for backwards compatibility
+
+//! Filter wrapper for encrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
+/*! Additional authenticated data should be given in channel "AAD". If putAAD is true, AAD will be Put() to the attached BufferedTransformation in channel "AAD". */
+class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter
+{
+public:
+ /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */
+ AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding = DEFAULT_PADDING);
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+ void LastPut(const byte *inString, size_t length);
+
+protected:
+ HashFilter m_hf;
+};
+
+//! Filter wrapper for decrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
+/*! Additional authenticated data should be given in channel "AAD". */
+class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef
+{
+public:
+ enum Flags {MAC_AT_END=0, MAC_AT_BEGIN=1, THROW_EXCEPTION=16, DEFAULT_FLAGS = THROW_EXCEPTION};
+
+ /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */
+ AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding = DEFAULT_PADDING);
+
+ std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();}
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+ bool GetLastResult() const {return m_hashVerifier.GetLastResult();}
+
+protected:
+ void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
+ void FirstPut(const byte *inString);
+ void NextPutMultiple(const byte *inString, size_t length);
+ void LastPut(const byte *inString, size_t length);
+
+ HashVerificationFilter m_hashVerifier;
+ StreamTransformationFilter m_streamFilter;
+};
+
+//! Filter Wrapper for PK_Signer
+class CRYPTOPP_DLL SignerFilter : public Unflushable<Filter>
+{
+public:
+ SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false)
+ : m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator(rng)), m_putMessage(putMessage) {Detach(attachment);}
+
+ std::string AlgorithmName() const {return m_signer.AlgorithmName();}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+
+private:
+ RandomNumberGenerator &m_rng;
+ const PK_Signer &m_signer;
+ member_ptr<PK_MessageAccumulator> m_messageAccumulator;
+ bool m_putMessage;
+ SecByteBlock m_buf;
+};
+
+//! Filter Wrapper for PK_Verifier
+class CRYPTOPP_DLL SignatureVerificationFilter : public FilterWithBufferedInput
+{
+public:
+ class SignatureVerificationFailed : public Exception
+ {
+ public:
+ SignatureVerificationFailed()
+ : Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {}
+ };
+
+ enum Flags {SIGNATURE_AT_END=0, SIGNATURE_AT_BEGIN=1, PUT_MESSAGE=2, PUT_SIGNATURE=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT};
+ SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
+
+ std::string AlgorithmName() const {return m_verifier.AlgorithmName();}
+
+ bool GetLastResult() const {return m_verified;}
+
+protected:
+ void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
+ void FirstPut(const byte *inString);
+ void NextPutMultiple(const byte *inString, size_t length);
+ void LastPut(const byte *inString, size_t length);
+
+private:
+ const PK_Verifier &m_verifier;
+ member_ptr<PK_MessageAccumulator> m_messageAccumulator;
+ word32 m_flags;
+ SecByteBlock m_signature;
+ bool m_verified;
+};
+
+typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibility
+
+//! Redirect input to another BufferedTransformation without owning it
+class CRYPTOPP_DLL Redirector : public CustomSignalPropagation<Sink>
+{
+public:
+ enum Behavior
+ {
+ DATA_ONLY = 0x00,
+ PASS_SIGNALS = 0x01,
+ PASS_WAIT_OBJECTS = 0x02,
+ PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS
+ };
+
+ Redirector() : m_target(NULL), m_behavior(PASS_EVERYTHING) {}
+ Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING)
+ : m_target(&target), m_behavior(behavior) {}
+
+ void Redirect(BufferedTransformation &target) {m_target = &target;}
+ void StopRedirection() {m_target = NULL;}
+
+ Behavior GetBehavior() {return (Behavior) m_behavior;}
+ void SetBehavior(Behavior behavior) {m_behavior=behavior;}
+ bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;}
+ void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; }
+ bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;}
+ void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; }
+
+ bool CanModifyInput() const
+ {return m_target ? m_target->CanModifyInput() : false;}
+
+ void Initialize(const NameValuePairs &parameters, int propagation);
+ byte * CreatePutSpace(size_t &size)
+ {return m_target ? m_target->CreatePutSpace(size) : (byte *)(size=0, NULL);}
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+ {return m_target ? m_target->Put2(begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
+ bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
+ {return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;}
+ bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
+ {return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;}
+
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
+ {return m_target ? m_target->ChannelCreatePutSpace(channel, size) : (byte *)(size=0, NULL);}
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+ {return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
+ size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
+ {return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
+ bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
+ {return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
+ bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
+ {return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
+
+ unsigned int GetMaxWaitObjectCount() const
+ { return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; }
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+ { if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container, callStack); }
+
+private:
+ BufferedTransformation *m_target;
+ word32 m_behavior;
+};
+
+// Used By ProxyFilter
+class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation<Sink>
+{
+public:
+ OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {}
+
+ bool GetPassSignal() const {return m_passSignal;}
+ void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
+
+ byte * CreatePutSpace(size_t &size)
+ {return m_owner.AttachedTransformation()->CreatePutSpace(size);}
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+ {return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
+ size_t PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
+ {return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
+ void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1)
+ {if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);}
+ bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
+ {return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;}
+ bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
+ {return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;}
+
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
+ {return m_owner.AttachedTransformation()->ChannelCreatePutSpace(channel, size);}
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+ {return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
+ size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
+ {return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
+ bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
+ {return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
+ bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
+ {return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
+
+private:
+ BufferedTransformation &m_owner;
+ bool m_passSignal;
+};
+
+//! Base class for Filter classes that are proxies for a chain of other filters.
+class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput
+{
+public:
+ ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment);
+
+ bool IsolatedFlush(bool hardFlush, bool blocking);
+
+ void SetFilter(Filter *filter);
+ void NextPutMultiple(const byte *s, size_t len);
+ void NextPutModifiable(byte *inString, size_t length);
+
+protected:
+ member_ptr<BufferedTransformation> m_filter;
+};
+
+//! simple proxy filter that doesn't modify the underlying filter's input or output
+class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter
+{
+public:
+ SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment)
+ : ProxyFilter(filter, 0, 0, attachment) {}
+
+ void FirstPut(const byte *) {}
+ void LastPut(const byte *, size_t) {m_filter->MessageEnd();}
+};
+
+//! proxy for the filter created by PK_Encryptor::CreateEncryptionFilter
+/*! This class is here just to provide symmetry with VerifierFilter. */
+class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter
+{
+public:
+ PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULL)
+ : SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {}
+};
+
+//! proxy for the filter created by PK_Decryptor::CreateDecryptionFilter
+/*! This class is here just to provide symmetry with SignerFilter. */
+class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter
+{
+public:
+ PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULL)
+ : SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {}
+};
+
+//! Append input to a string object
+template <class T>
+class StringSinkTemplate : public Bufferless<Sink>
+{
+public:
+ // VC60 workaround: no T::char_type
+ typedef typename T::traits_type::char_type char_type;
+
+ StringSinkTemplate(T &output)
+ : m_output(&output) {assert(sizeof(output[0])==1);}
+
+ void IsolatedInitialize(const NameValuePairs &parameters)
+ {if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");}
+
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+ {
+ if (length > 0)
+ {
+ typename T::size_type size = m_output->size();
+ if (length < size && size + length > m_output->capacity())
+ m_output->reserve(2*size);
+ m_output->append((const char_type *)begin, (const char_type *)begin+length);
+ }
+ return 0;
+ }
+
+private:
+ T *m_output;
+};
+
+//! Append input to an std::string
+CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate<std::string>;
+typedef StringSinkTemplate<std::string> StringSink;
+
+//! incorporates input into RNG as additional entropy
+class RandomNumberSink : public Bufferless<Sink>
+{
+public:
+ RandomNumberSink()
+ : m_rng(NULL) {}
+
+ RandomNumberSink(RandomNumberGenerator &rng)
+ : m_rng(&rng) {}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+
+private:
+ RandomNumberGenerator *m_rng;
+};
+
+//! Copy input to a memory buffer
+class CRYPTOPP_DLL ArraySink : public Bufferless<Sink>
+{
+public:
+ ArraySink(const NameValuePairs &parameters = g_nullNameValuePairs) {IsolatedInitialize(parameters);}
+ ArraySink(byte *buf, size_t size) : m_buf(buf), m_size(size), m_total(0) {}
+
+ size_t AvailableSize() {return SaturatingSubtract(m_size, m_total);}
+ lword TotalPutLength() {return m_total;}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ byte * CreatePutSpace(size_t &size);
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+
+protected:
+ byte *m_buf;
+ size_t m_size;
+ lword m_total;
+};
+
+//! Xor input to a memory buffer
+class CRYPTOPP_DLL ArrayXorSink : public ArraySink
+{
+public:
+ ArrayXorSink(byte *buf, size_t size)
+ : ArraySink(buf, size) {}
+
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
+ byte * CreatePutSpace(size_t &size) {return BufferedTransformation::CreatePutSpace(size);}
+};
+
+//! string-based implementation of Store interface
+class StringStore : public Store
+{
+public:
+ StringStore(const char *string = NULL)
+ {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
+ StringStore(const byte *string, size_t length)
+ {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
+ template <class T> StringStore(const T &string)
+ {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
+
+ CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+
+private:
+ CRYPTOPP_DLL void StoreInitialize(const NameValuePairs &parameters);
+
+ const byte *m_store;
+ size_t m_length, m_count;
+};
+
+//! RNG-based implementation of Source interface
+class CRYPTOPP_DLL RandomNumberStore : public Store
+{
+public:
+ RandomNumberStore()
+ : m_rng(NULL), m_length(0), m_count(0) {}
+
+ RandomNumberStore(RandomNumberGenerator &rng, lword length)
+ : m_rng(&rng), m_length(length), m_count(0) {}
+
+ bool AnyRetrievable() const {return MaxRetrievable() != 0;}
+ lword MaxRetrievable() const {return m_length-m_count;}
+
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
+ {
+ throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store");
+ }
+
+private:
+ void StoreInitialize(const NameValuePairs &parameters);
+
+ RandomNumberGenerator *m_rng;
+ lword m_length, m_count;
+};
+
+//! empty store
+class CRYPTOPP_DLL NullStore : public Store
+{
+public:
+ NullStore(lword size = ULONG_MAX) : m_size(size) {}
+ void StoreInitialize(const NameValuePairs &parameters) {}
+ lword MaxRetrievable() const {return m_size;}
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+
+private:
+ lword m_size;
+};
+
+//! A Filter that pumps data into its attachment as input
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting<Filter>
+{
+public:
+ Source(BufferedTransformation *attachment = NULL)
+ {Source::Detach(attachment);}
+
+ lword Pump(lword pumpMax=size_t(0)-1)
+ {Pump2(pumpMax); return pumpMax;}
+ unsigned int PumpMessages(unsigned int count=UINT_MAX)
+ {PumpMessages2(count); return count;}
+ void PumpAll()
+ {PumpAll2();}
+ virtual size_t Pump2(lword &byteCount, bool blocking=true) =0;
+ virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) =0;
+ virtual size_t PumpAll2(bool blocking=true);
+ virtual bool SourceExhausted() const =0;
+
+protected:
+ void SourceInitialize(bool pumpAll, const NameValuePairs &parameters)
+ {
+ IsolatedInitialize(parameters);
+ if (pumpAll)
+ PumpAll();
+ }
+};
+
+//! Turn a Store into a Source
+template <class T>
+class SourceTemplate : public Source
+{
+public:
+ SourceTemplate<T>(BufferedTransformation *attachment)
+ : Source(attachment) {}
+ void IsolatedInitialize(const NameValuePairs &parameters)
+ {m_store.IsolatedInitialize(parameters);}
+ size_t Pump2(lword &byteCount, bool blocking=true)
+ {return m_store.TransferTo2(*AttachedTransformation(), byteCount, DEFAULT_CHANNEL, blocking);}
+ size_t PumpMessages2(unsigned int &messageCount, bool blocking=true)
+ {return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, DEFAULT_CHANNEL, blocking);}
+ size_t PumpAll2(bool blocking=true)
+ {return m_store.TransferAllTo2(*AttachedTransformation(), DEFAULT_CHANNEL, blocking);}
+ bool SourceExhausted() const
+ {return !m_store.AnyRetrievable() && !m_store.AnyMessages();}
+ void SetAutoSignalPropagation(int propagation)
+ {m_store.SetAutoSignalPropagation(propagation);}
+ int GetAutoSignalPropagation() const
+ {return m_store.GetAutoSignalPropagation();}
+
+protected:
+ T m_store;
+};
+
+//! string-based implementation of Source interface
+class CRYPTOPP_DLL StringSource : public SourceTemplate<StringStore>
+{
+public:
+ StringSource(BufferedTransformation *attachment = NULL)
+ : SourceTemplate<StringStore>(attachment) {}
+ //! zero terminated string as source
+ StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL)
+ : SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
+ //! binary byte array as source
+ StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL)
+ : SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
+ //! std::string as source
+ StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL)
+ : SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
+};
+
+//! use the third constructor for an array source
+typedef StringSource ArraySource;
+
+//! RNG-based implementation of Source interface
+class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate<RandomNumberStore>
+{
+public:
+ RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULL)
+ : SourceTemplate<RandomNumberStore>(attachment)
+ {SourceInitialize(pumpAll, MakeParameters("RandomNumberGeneratorPointer", &rng)("RandomNumberStoreSize", length));}
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/fips140.cpp b/lib/cryptopp/fips140.cpp
new file mode 100644
index 000000000..1fcf59014
--- /dev/null
+++ b/lib/cryptopp/fips140.cpp
@@ -0,0 +1,84 @@
+// fips140.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "fips140.h"
+#include "trdlocal.h" // needs to be included last for cygwin
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// Define this to 1 to turn on FIPS 140-2 compliance features, including additional tests during
+// startup, random number generation, and key generation. These tests may affect performance.
+#ifndef CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
+#define CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 0
+#endif
+
+#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(THREADS_AVAILABLE))
+#error FIPS 140-2 compliance requires the availability of thread local storage.
+#endif
+
+#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(OS_RNG_AVAILABLE))
+#error FIPS 140-2 compliance requires the availability of OS provided RNG.
+#endif
+
+PowerUpSelfTestStatus g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE;
+
+bool FIPS_140_2_ComplianceEnabled()
+{
+ return CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2;
+}
+
+void SimulatePowerUpSelfTestFailure()
+{
+ g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED;
+}
+
+PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus()
+{
+ return g_powerUpSelfTestStatus;
+}
+
+#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
+ThreadLocalStorage & AccessPowerUpSelfTestInProgress()
+{
+ static ThreadLocalStorage selfTestInProgress;
+ return selfTestInProgress;
+}
+#endif
+
+bool PowerUpSelfTestInProgressOnThisThread()
+{
+#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
+ return AccessPowerUpSelfTestInProgress().GetValue() != NULL;
+#else
+ assert(false); // should not be called
+ return false;
+#endif
+}
+
+void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress)
+{
+#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
+ AccessPowerUpSelfTestInProgress().SetValue((void *)inProgress);
+#endif
+}
+
+void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor)
+{
+#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
+ EncryptionPairwiseConsistencyTest(encryptor, decryptor);
+#endif
+}
+
+void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier)
+{
+#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
+ SignaturePairwiseConsistencyTest(signer, verifier);
+#endif
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/fips140.h b/lib/cryptopp/fips140.h
new file mode 100644
index 000000000..a3e538613
--- /dev/null
+++ b/lib/cryptopp/fips140.h
@@ -0,0 +1,59 @@
+#ifndef CRYPTOPP_FIPS140_H
+#define CRYPTOPP_FIPS140_H
+
+/*! \file
+ FIPS 140 related functions and classes.
+*/
+
+#include "cryptlib.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! exception thrown when a crypto algorithm is used after a self test fails
+class CRYPTOPP_DLL SelfTestFailure : public Exception
+{
+public:
+ explicit SelfTestFailure(const std::string &s) : Exception(OTHER_ERROR, s) {}
+};
+
+//! returns whether FIPS 140-2 compliance features were enabled at compile time
+CRYPTOPP_DLL bool CRYPTOPP_API FIPS_140_2_ComplianceEnabled();
+
+//! enum values representing status of the power-up self test
+enum PowerUpSelfTestStatus {POWER_UP_SELF_TEST_NOT_DONE, POWER_UP_SELF_TEST_FAILED, POWER_UP_SELF_TEST_PASSED};
+
+//! perform the power-up self test, and set the self test status
+CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac);
+
+//! perform the power-up self test using the filename of this DLL and the embedded module MAC
+CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest();
+
+//! set the power-up self test status to POWER_UP_SELF_TEST_FAILED
+CRYPTOPP_DLL void CRYPTOPP_API SimulatePowerUpSelfTestFailure();
+
+//! return the current power-up self test status
+CRYPTOPP_DLL PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus();
+
+typedef PowerUpSelfTestStatus (CRYPTOPP_API * PGetPowerUpSelfTestStatus)();
+
+CRYPTOPP_DLL MessageAuthenticationCode * CRYPTOPP_API NewIntegrityCheckingMAC();
+
+CRYPTOPP_DLL bool CRYPTOPP_API IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac = NULL, unsigned long *pMacFileLocation = NULL);
+
+// this is used by Algorithm constructor to allow Algorithm objects to be constructed for the self test
+bool PowerUpSelfTestInProgressOnThisThread();
+
+void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress);
+
+void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier);
+void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
+
+void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier);
+void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
+
+#define CRYPTOPP_DUMMY_DLL_MAC "MAC_51f34b8db820ae8"
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/fltrimpl.h b/lib/cryptopp/fltrimpl.h
new file mode 100644
index 000000000..4087d7d9f
--- /dev/null
+++ b/lib/cryptopp/fltrimpl.h
@@ -0,0 +1,67 @@
+#ifndef CRYPTOPP_FLTRIMPL_H
+#define CRYPTOPP_FLTRIMPL_H
+
+#define FILTER_BEGIN \
+ switch (m_continueAt) \
+ { \
+ case 0: \
+ m_inputPosition = 0;
+
+#define FILTER_END_NO_MESSAGE_END_NO_RETURN \
+ break; \
+ default: \
+ assert(false); \
+ }
+
+#define FILTER_END_NO_MESSAGE_END \
+ FILTER_END_NO_MESSAGE_END_NO_RETURN \
+ return 0;
+
+/*
+#define FILTER_END \
+ case -1: \
+ if (messageEnd && Output(-1, NULL, 0, messageEnd, blocking)) \
+ return 1; \
+ FILTER_END_NO_MESSAGE_END
+*/
+
+#define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel) \
+ {\
+ case site: \
+ statement; \
+ if (Output(site, output, length, messageEnd, blocking, channel)) \
+ return STDMAX(size_t(1), length-m_inputPosition);\
+ }
+
+#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \
+ FILTER_OUTPUT3(site, statement, output, length, messageEnd, DEFAULT_CHANNEL)
+
+#define FILTER_OUTPUT(site, output, length, messageEnd) \
+ FILTER_OUTPUT2(site, 0, output, length, messageEnd)
+
+#define FILTER_OUTPUT_BYTE(site, output) \
+ FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0)
+
+#define FILTER_OUTPUT2_MODIFIABLE(site, statement, output, length, messageEnd) \
+ {\
+ case site: \
+ statement; \
+ if (OutputModifiable(site, output, length, messageEnd, blocking)) \
+ return STDMAX(size_t(1), length-m_inputPosition);\
+ }
+
+#define FILTER_OUTPUT_MODIFIABLE(site, output, length, messageEnd) \
+ FILTER_OUTPUT2_MODIFIABLE(site, 0, output, length, messageEnd)
+
+#define FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, statement, output, length, messageEnd, modifiable) \
+ {\
+ case site: \
+ statement; \
+ if (modifiable ? OutputModifiable(site, output, length, messageEnd, blocking) : Output(site, output, length, messageEnd, blocking)) \
+ return STDMAX(size_t(1), length-m_inputPosition);\
+ }
+
+#define FILTER_OUTPUT_MAYBE_MODIFIABLE(site, output, length, messageEnd, modifiable) \
+ FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, 0, output, length, messageEnd, modifiable)
+
+#endif
diff --git a/lib/cryptopp/gcm.cpp b/lib/cryptopp/gcm.cpp
new file mode 100644
index 000000000..2304f96d8
--- /dev/null
+++ b/lib/cryptopp/gcm.cpp
@@ -0,0 +1,828 @@
+// gcm.cpp - written and placed in the public domain by Wei Dai
+
+// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM gcm.cpp" to generate MASM code
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#include "gcm.h"
+#include "cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+word16 GCM_Base::s_reductionTable[256];
+volatile bool GCM_Base::s_reductionTableInitialized = false;
+
+void GCM_Base::GCTR::IncrementCounterBy256()
+{
+ IncrementCounterByOne(m_counterArray+BlockSize()-4, 3);
+}
+
+#if 0
+// preserved for testing
+void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c)
+{
+ word64 Z0=0, Z1=0, V0, V1;
+
+ typedef BlockGetAndPut<word64, BigEndian> Block;
+ Block::Get(a)(V0)(V1);
+
+ for (int i=0; i<16; i++)
+ {
+ for (int j=0x80; j!=0; j>>=1)
+ {
+ int x = b[i] & j;
+ Z0 ^= x ? V0 : 0;
+ Z1 ^= x ? V1 : 0;
+ x = (int)V1 & 1;
+ V1 = (V1>>1) | (V0<<63);
+ V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
+ }
+ }
+ Block::Put(NULL, c)(Z0)(Z1);
+}
+
+__m128i _mm_clmulepi64_si128(const __m128i &a, const __m128i &b, int i)
+{
+ word64 A[1] = {ByteReverse(((word64*)&a)[i&1])};
+ word64 B[1] = {ByteReverse(((word64*)&b)[i>>4])};
+
+ PolynomialMod2 pa((byte *)A, 8);
+ PolynomialMod2 pb((byte *)B, 8);
+ PolynomialMod2 c = pa*pb;
+
+ __m128i output;
+ for (int i=0; i<16; i++)
+ ((byte *)&output)[i] = c.GetByte(i);
+ return output;
+}
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+inline static void SSE2_Xor16(byte *a, const byte *b, const byte *c)
+{
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+ *(__m128i *)a = _mm_xor_si128(*(__m128i *)b, *(__m128i *)c);
+#else
+ asm ("movdqa %1, %%xmm0; pxor %2, %%xmm0; movdqa %%xmm0, %0;" : "=m" (a[0]) : "m"(b[0]), "m"(c[0]));
+#endif
+}
+#endif
+
+inline static void Xor16(byte *a, const byte *b, const byte *c)
+{
+ ((word64 *)a)[0] = ((word64 *)b)[0] ^ ((word64 *)c)[0];
+ ((word64 *)a)[1] = ((word64 *)b)[1] ^ ((word64 *)c)[1];
+}
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+static CRYPTOPP_ALIGN_DATA(16) const word64 s_clmulConstants64[] = {
+ W64LIT(0xe100000000000000), W64LIT(0xc200000000000000),
+ W64LIT(0x08090a0b0c0d0e0f), W64LIT(0x0001020304050607),
+ W64LIT(0x0001020304050607), W64LIT(0x08090a0b0c0d0e0f)};
+static const __m128i *s_clmulConstants = (const __m128i *)s_clmulConstants64;
+static const unsigned int s_clmulTableSizeInBlocks = 8;
+
+inline __m128i CLMUL_Reduce(__m128i c0, __m128i c1, __m128i c2, const __m128i &r)
+{
+ /*
+ The polynomial to be reduced is c0 * x^128 + c1 * x^64 + c2. c0t below refers to the most
+ significant half of c0 as a polynomial, which, due to GCM's bit reflection, are in the
+ rightmost bit positions, and the lowest byte addresses.
+
+ c1 ^= c0t * 0xc200000000000000
+ c2t ^= c0t
+ t = shift (c1t ^ c0b) left 1 bit
+ c2 ^= t * 0xe100000000000000
+ c2t ^= c1b
+ shift c2 left 1 bit and xor in lowest bit of c1t
+ */
+#if 0 // MSVC 2010 workaround: see http://connect.microsoft.com/VisualStudio/feedback/details/575301
+ c2 = _mm_xor_si128(c2, _mm_move_epi64(c0));
+#else
+ c1 = _mm_xor_si128(c1, _mm_slli_si128(c0, 8));
+#endif
+ c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(c0, r, 0x10));
+ c0 = _mm_srli_si128(c0, 8);
+ c0 = _mm_xor_si128(c0, c1);
+ c0 = _mm_slli_epi64(c0, 1);
+ c0 = _mm_clmulepi64_si128(c0, r, 0);
+ c2 = _mm_xor_si128(c2, c0);
+ c2 = _mm_xor_si128(c2, _mm_srli_si128(c1, 8));
+ c1 = _mm_unpacklo_epi64(c1, c2);
+ c1 = _mm_srli_epi64(c1, 63);
+ c2 = _mm_slli_epi64(c2, 1);
+ return _mm_xor_si128(c2, c1);
+}
+
+inline __m128i CLMUL_GF_Mul(const __m128i &x, const __m128i &h, const __m128i &r)
+{
+ __m128i c0 = _mm_clmulepi64_si128(x,h,0);
+ __m128i c1 = _mm_xor_si128(_mm_clmulepi64_si128(x,h,1), _mm_clmulepi64_si128(x,h,0x10));
+ __m128i c2 = _mm_clmulepi64_si128(x,h,0x11);
+
+ return CLMUL_Reduce(c0, c1, c2, r);
+}
+#endif
+
+void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
+{
+ BlockCipher &blockCipher = AccessBlockCipher();
+ blockCipher.SetKey(userKey, keylength, params);
+
+ if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
+ throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
+
+ int tableSize, i, j, k;
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ if (HasCLMUL())
+ {
+ params.GetIntValue(Name::TableSize(), tableSize); // avoid "parameter not used" error
+ tableSize = s_clmulTableSizeInBlocks * REQUIRED_BLOCKSIZE;
+ }
+ else
+#endif
+ {
+ if (params.GetIntValue(Name::TableSize(), tableSize))
+ tableSize = (tableSize >= 64*1024) ? 64*1024 : 2*1024;
+ else
+ tableSize = (GetTablesOption() == GCM_64K_Tables) ? 64*1024 : 2*1024;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1300 && _MSC_VER < 1400)
+ // VC 2003 workaround: compiler generates bad code for 64K tables
+ tableSize = 2*1024;
+#endif
+ }
+
+ m_buffer.resize(3*REQUIRED_BLOCKSIZE + tableSize);
+ byte *table = MulTable();
+ byte *hashKey = HashKey();
+ memset(hashKey, 0, REQUIRED_BLOCKSIZE);
+ blockCipher.ProcessBlock(hashKey);
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ if (HasCLMUL())
+ {
+ const __m128i r = s_clmulConstants[0];
+ __m128i h0 = _mm_shuffle_epi8(_mm_load_si128((__m128i *)hashKey), s_clmulConstants[1]);
+ __m128i h = h0;
+
+ for (i=0; i<tableSize; i+=32)
+ {
+ __m128i h1 = CLMUL_GF_Mul(h, h0, r);
+ _mm_storel_epi64((__m128i *)(table+i), h);
+ _mm_storeu_si128((__m128i *)(table+i+16), h1);
+ _mm_storeu_si128((__m128i *)(table+i+8), h);
+ _mm_storel_epi64((__m128i *)(table+i+8), h1);
+ h = CLMUL_GF_Mul(h1, h0, r);
+ }
+
+ return;
+ }
+#endif
+
+ word64 V0, V1;
+ typedef BlockGetAndPut<word64, BigEndian> Block;
+ Block::Get(hashKey)(V0)(V1);
+
+ if (tableSize == 64*1024)
+ {
+ for (i=0; i<128; i++)
+ {
+ k = i%8;
+ Block::Put(NULL, table+(i/8)*256*16+(size_t(1)<<(11-k)))(V0)(V1);
+
+ int x = (int)V1 & 1;
+ V1 = (V1>>1) | (V0<<63);
+ V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
+ }
+
+ for (i=0; i<16; i++)
+ {
+ memset(table+i*256*16, 0, 16);
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ if (HasSSE2())
+ for (j=2; j<=0x80; j*=2)
+ for (k=1; k<j; k++)
+ SSE2_Xor16(table+i*256*16+(j+k)*16, table+i*256*16+j*16, table+i*256*16+k*16);
+ else
+#endif
+ for (j=2; j<=0x80; j*=2)
+ for (k=1; k<j; k++)
+ Xor16(table+i*256*16+(j+k)*16, table+i*256*16+j*16, table+i*256*16+k*16);
+ }
+ }
+ else
+ {
+ if (!s_reductionTableInitialized)
+ {
+ s_reductionTable[0] = 0;
+ word16 x = 0x01c2;
+ s_reductionTable[1] = ByteReverse(x);
+ for (int i=2; i<=0x80; i*=2)
+ {
+ x <<= 1;
+ s_reductionTable[i] = ByteReverse(x);
+ for (int j=1; j<i; j++)
+ s_reductionTable[i+j] = s_reductionTable[i] ^ s_reductionTable[j];
+ }
+ s_reductionTableInitialized = true;
+ }
+
+ for (i=0; i<128-24; i++)
+ {
+ k = i%32;
+ if (k < 4)
+ Block::Put(NULL, table+1024+(i/32)*256+(size_t(1)<<(7-k)))(V0)(V1);
+ else if (k < 8)
+ Block::Put(NULL, table+(i/32)*256+(size_t(1)<<(11-k)))(V0)(V1);
+
+ int x = (int)V1 & 1;
+ V1 = (V1>>1) | (V0<<63);
+ V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
+ }
+
+ for (i=0; i<4; i++)
+ {
+ memset(table+i*256, 0, 16);
+ memset(table+1024+i*256, 0, 16);
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ if (HasSSE2())
+ for (j=2; j<=8; j*=2)
+ for (k=1; k<j; k++)
+ {
+ SSE2_Xor16(table+i*256+(j+k)*16, table+i*256+j*16, table+i*256+k*16);
+ SSE2_Xor16(table+1024+i*256+(j+k)*16, table+1024+i*256+j*16, table+1024+i*256+k*16);
+ }
+ else
+#endif
+ for (j=2; j<=8; j*=2)
+ for (k=1; k<j; k++)
+ {
+ Xor16(table+i*256+(j+k)*16, table+i*256+j*16, table+i*256+k*16);
+ Xor16(table+1024+i*256+(j+k)*16, table+1024+i*256+j*16, table+1024+i*256+k*16);
+ }
+ }
+ }
+}
+
+inline void GCM_Base::ReverseHashBufferIfNeeded()
+{
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ if (HasCLMUL())
+ {
+ __m128i &x = *(__m128i *)HashBuffer();
+ x = _mm_shuffle_epi8(x, s_clmulConstants[1]);
+ }
+#endif
+}
+
+void GCM_Base::Resync(const byte *iv, size_t len)
+{
+ BlockCipher &cipher = AccessBlockCipher();
+ byte *hashBuffer = HashBuffer();
+
+ if (len == 12)
+ {
+ memcpy(hashBuffer, iv, len);
+ memset(hashBuffer+len, 0, 3);
+ hashBuffer[len+3] = 1;
+ }
+ else
+ {
+ size_t origLen = len;
+ memset(hashBuffer, 0, HASH_BLOCKSIZE);
+
+ if (len >= HASH_BLOCKSIZE)
+ {
+ len = GCM_Base::AuthenticateBlocks(iv, len);
+ iv += (origLen - len);
+ }
+
+ if (len > 0)
+ {
+ memcpy(m_buffer, iv, len);
+ memset(m_buffer+len, 0, HASH_BLOCKSIZE-len);
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+ }
+
+ PutBlock<word64, BigEndian, true>(NULL, m_buffer)(0)(origLen*8);
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+
+ ReverseHashBufferIfNeeded();
+ }
+
+ if (m_state >= State_IVSet)
+ m_ctr.Resynchronize(hashBuffer, REQUIRED_BLOCKSIZE);
+ else
+ m_ctr.SetCipherWithIV(cipher, hashBuffer);
+
+ m_ctr.Seek(HASH_BLOCKSIZE);
+
+ memset(hashBuffer, 0, HASH_BLOCKSIZE);
+}
+
+unsigned int GCM_Base::OptimalDataAlignment() const
+{
+ return
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ HasSSE2() ? 16 :
+#endif
+ GetBlockCipher().OptimalDataAlignment();
+}
+
+#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+void GCM_AuthenticateBlocks_2K(const byte *data, size_t blocks, word64 *hashBuffer, const word16 *reductionTable);
+void GCM_AuthenticateBlocks_64K(const byte *data, size_t blocks, word64 *hashBuffer);
+}
+#endif
+
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+size_t GCM_Base::AuthenticateBlocks(const byte *data, size_t len)
+{
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ if (HasCLMUL())
+ {
+ const __m128i *table = (const __m128i *)MulTable();
+ __m128i x = _mm_load_si128((__m128i *)HashBuffer());
+ const __m128i r = s_clmulConstants[0], bswapMask = s_clmulConstants[1], bswapMask2 = s_clmulConstants[2];
+
+ while (len >= 16)
+ {
+ size_t s = UnsignedMin(len/16, s_clmulTableSizeInBlocks), i=0;
+ __m128i d, d2 = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)(data+(s-1)*16)), bswapMask2);;
+ __m128i c0 = _mm_setzero_si128();
+ __m128i c1 = _mm_setzero_si128();
+ __m128i c2 = _mm_setzero_si128();
+
+ while (true)
+ {
+ __m128i h0 = _mm_load_si128(table+i);
+ __m128i h1 = _mm_load_si128(table+i+1);
+ __m128i h01 = _mm_xor_si128(h0, h1);
+
+ if (++i == s)
+ {
+ d = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)data), bswapMask);
+ d = _mm_xor_si128(d, x);
+ c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d, h0, 0));
+ c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d, h1, 1));
+ d = _mm_xor_si128(d, _mm_shuffle_epi32(d, _MM_SHUFFLE(1, 0, 3, 2)));
+ c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d, h01, 0));
+ break;
+ }
+
+ d = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)(data+(s-i)*16-8)), bswapMask2);
+ c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d2, h0, 1));
+ c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d, h1, 1));
+ d2 = _mm_xor_si128(d2, d);
+ c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d2, h01, 1));
+
+ if (++i == s)
+ {
+ d = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)data), bswapMask);
+ d = _mm_xor_si128(d, x);
+ c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d, h0, 0x10));
+ c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d, h1, 0x11));
+ d = _mm_xor_si128(d, _mm_shuffle_epi32(d, _MM_SHUFFLE(1, 0, 3, 2)));
+ c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d, h01, 0x10));
+ break;
+ }
+
+ d2 = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)(data+(s-i)*16-8)), bswapMask);
+ c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d, h0, 0x10));
+ c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d2, h1, 0x10));
+ d = _mm_xor_si128(d, d2);
+ c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d, h01, 0x10));
+ }
+ data += s*16;
+ len -= s*16;
+
+ c1 = _mm_xor_si128(_mm_xor_si128(c1, c0), c2);
+ x = CLMUL_Reduce(c0, c1, c2, r);
+ }
+
+ _mm_store_si128((__m128i *)HashBuffer(), x);
+ return len;
+ }
+#endif
+
+ typedef BlockGetAndPut<word64, NativeByteOrder> Block;
+ word64 *hashBuffer = (word64 *)HashBuffer();
+
+ switch (2*(m_buffer.size()>=64*1024)
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ + HasSSE2()
+#endif
+ )
+ {
+ case 0: // non-SSE2 and 2K tables
+ {
+ byte *table = MulTable();
+ word64 x0 = hashBuffer[0], x1 = hashBuffer[1];
+
+ do
+ {
+ word64 y0, y1, a0, a1, b0, b1, c0, c1, d0, d1;
+ Block::Get(data)(y0)(y1);
+ x0 ^= y0;
+ x1 ^= y1;
+
+ data += HASH_BLOCKSIZE;
+ len -= HASH_BLOCKSIZE;
+
+ #define READ_TABLE_WORD64_COMMON(a, b, c, d) *(word64 *)(table+(a*1024)+(b*256)+c+d*8)
+
+ #ifdef IS_LITTLE_ENDIAN
+ #if CRYPTOPP_BOOL_SLOW_WORD64
+ word32 z0 = (word32)x0;
+ word32 z1 = (word32)(x0>>32);
+ word32 z2 = (word32)x1;
+ word32 z3 = (word32)(x1>>32);
+ #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, (d?(z##c>>((d?d-1:0)*4))&0xf0:(z##c&0xf)<<4), e)
+ #else
+ #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, ((d+8*b)?(x##a>>(((d+8*b)?(d+8*b)-1:1)*4))&0xf0:(x##a&0xf)<<4), e)
+ #endif
+ #define GF_MOST_SIG_8BITS(a) (a##1 >> 7*8)
+ #define GF_SHIFT_8(a) a##1 = (a##1 << 8) ^ (a##0 >> 7*8); a##0 <<= 8;
+ #else
+ #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((1-d%2), c, ((15-d-8*b)?(x##a>>(((15-d-8*b)?(15-d-8*b)-1:0)*4))&0xf0:(x##a&0xf)<<4), e)
+ #define GF_MOST_SIG_8BITS(a) (a##1 & 0xff)
+ #define GF_SHIFT_8(a) a##1 = (a##1 >> 8) ^ (a##0 << 7*8); a##0 >>= 8;
+ #endif
+
+ #define GF_MUL_32BY128(op, a, b, c) \
+ a0 op READ_TABLE_WORD64(a, b, c, 0, 0) ^ READ_TABLE_WORD64(a, b, c, 1, 0);\
+ a1 op READ_TABLE_WORD64(a, b, c, 0, 1) ^ READ_TABLE_WORD64(a, b, c, 1, 1);\
+ b0 op READ_TABLE_WORD64(a, b, c, 2, 0) ^ READ_TABLE_WORD64(a, b, c, 3, 0);\
+ b1 op READ_TABLE_WORD64(a, b, c, 2, 1) ^ READ_TABLE_WORD64(a, b, c, 3, 1);\
+ c0 op READ_TABLE_WORD64(a, b, c, 4, 0) ^ READ_TABLE_WORD64(a, b, c, 5, 0);\
+ c1 op READ_TABLE_WORD64(a, b, c, 4, 1) ^ READ_TABLE_WORD64(a, b, c, 5, 1);\
+ d0 op READ_TABLE_WORD64(a, b, c, 6, 0) ^ READ_TABLE_WORD64(a, b, c, 7, 0);\
+ d1 op READ_TABLE_WORD64(a, b, c, 6, 1) ^ READ_TABLE_WORD64(a, b, c, 7, 1);\
+
+ GF_MUL_32BY128(=, 0, 0, 0)
+ GF_MUL_32BY128(^=, 0, 1, 1)
+ GF_MUL_32BY128(^=, 1, 0, 2)
+ GF_MUL_32BY128(^=, 1, 1, 3)
+
+ word32 r = (word32)s_reductionTable[GF_MOST_SIG_8BITS(d)] << 16;
+ GF_SHIFT_8(d)
+ c0 ^= d0; c1 ^= d1;
+ r ^= (word32)s_reductionTable[GF_MOST_SIG_8BITS(c)] << 8;
+ GF_SHIFT_8(c)
+ b0 ^= c0; b1 ^= c1;
+ r ^= s_reductionTable[GF_MOST_SIG_8BITS(b)];
+ GF_SHIFT_8(b)
+ a0 ^= b0; a1 ^= b1;
+ a0 ^= ConditionalByteReverse<word64>(LITTLE_ENDIAN_ORDER, r);
+ x0 = a0; x1 = a1;
+ }
+ while (len >= HASH_BLOCKSIZE);
+
+ hashBuffer[0] = x0; hashBuffer[1] = x1;
+ return len;
+ }
+
+ case 2: // non-SSE2 and 64K tables
+ {
+ byte *table = MulTable();
+ word64 x0 = hashBuffer[0], x1 = hashBuffer[1];
+
+ do
+ {
+ word64 y0, y1, a0, a1;
+ Block::Get(data)(y0)(y1);
+ x0 ^= y0;
+ x1 ^= y1;
+
+ data += HASH_BLOCKSIZE;
+ len -= HASH_BLOCKSIZE;
+
+ #undef READ_TABLE_WORD64_COMMON
+ #undef READ_TABLE_WORD64
+
+ #define READ_TABLE_WORD64_COMMON(a, c, d) *(word64 *)(table+(a)*256*16+(c)+(d)*8)
+
+ #ifdef IS_LITTLE_ENDIAN
+ #if CRYPTOPP_BOOL_SLOW_WORD64
+ word32 z0 = (word32)x0;
+ word32 z1 = (word32)(x0>>32);
+ word32 z2 = (word32)x1;
+ word32 z3 = (word32)(x1>>32);
+ #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, (d?(z##c>>((d?d:1)*8-4))&0xff0:(z##c&0xff)<<4), e)
+ #else
+ #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((d+4*(c%2))?(x##b>>(((d+4*(c%2))?(d+4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e)
+ #endif
+ #else
+ #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((7-d-4*(c%2))?(x##b>>(((7-d-4*(c%2))?(7-d-4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e)
+ #endif
+
+ #define GF_MUL_8BY128(op, b, c, d) \
+ a0 op READ_TABLE_WORD64(b, c, d, 0);\
+ a1 op READ_TABLE_WORD64(b, c, d, 1);\
+
+ GF_MUL_8BY128(=, 0, 0, 0)
+ GF_MUL_8BY128(^=, 0, 0, 1)
+ GF_MUL_8BY128(^=, 0, 0, 2)
+ GF_MUL_8BY128(^=, 0, 0, 3)
+ GF_MUL_8BY128(^=, 0, 1, 0)
+ GF_MUL_8BY128(^=, 0, 1, 1)
+ GF_MUL_8BY128(^=, 0, 1, 2)
+ GF_MUL_8BY128(^=, 0, 1, 3)
+ GF_MUL_8BY128(^=, 1, 2, 0)
+ GF_MUL_8BY128(^=, 1, 2, 1)
+ GF_MUL_8BY128(^=, 1, 2, 2)
+ GF_MUL_8BY128(^=, 1, 2, 3)
+ GF_MUL_8BY128(^=, 1, 3, 0)
+ GF_MUL_8BY128(^=, 1, 3, 1)
+ GF_MUL_8BY128(^=, 1, 3, 2)
+ GF_MUL_8BY128(^=, 1, 3, 3)
+
+ x0 = a0; x1 = a1;
+ }
+ while (len >= HASH_BLOCKSIZE);
+
+ hashBuffer[0] = x0; hashBuffer[1] = x1;
+ return len;
+ }
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+ case 1: // SSE2 and 2K tables
+ GCM_AuthenticateBlocks_2K(data, len/16, hashBuffer, s_reductionTable);
+ return len % 16;
+ case 3: // SSE2 and 64K tables
+ GCM_AuthenticateBlocks_64K(data, len/16, hashBuffer);
+ return len % 16;
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ case 1: // SSE2 and 2K tables
+ {
+ #ifdef __GNUC__
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ ALIGN 8
+ GCM_AuthenticateBlocks_2K PROC FRAME
+ rex_push_reg rsi
+ push_reg rdi
+ push_reg rbx
+ .endprolog
+ mov rsi, r8
+ mov r11, r9
+ #else
+ AS2( mov WORD_REG(cx), data )
+ AS2( mov WORD_REG(dx), len )
+ AS2( mov WORD_REG(si), hashBuffer )
+ AS2( shr WORD_REG(dx), 4 )
+ #endif
+
+ AS_PUSH_IF86( bx)
+ AS_PUSH_IF86( bp)
+
+ #ifdef __GNUC__
+ AS2( mov AS_REG_7, WORD_REG(di))
+ #elif CRYPTOPP_BOOL_X86
+ AS2( lea AS_REG_7, s_reductionTable)
+ #endif
+
+ AS2( movdqa xmm0, [WORD_REG(si)] )
+
+ #define MUL_TABLE_0 WORD_REG(si) + 32
+ #define MUL_TABLE_1 WORD_REG(si) + 32 + 1024
+ #define RED_TABLE AS_REG_7
+
+ ASL(0)
+ AS2( movdqu xmm4, [WORD_REG(cx)] )
+ AS2( pxor xmm0, xmm4 )
+
+ AS2( movd ebx, xmm0 )
+ AS2( mov eax, AS_HEX(f0f0f0f0) )
+ AS2( and eax, ebx )
+ AS2( shl ebx, 4 )
+ AS2( and ebx, AS_HEX(f0f0f0f0) )
+ AS2( movzx edi, ah )
+ AS2( movdqa xmm5, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+ AS2( movzx edi, al )
+ AS2( movdqa xmm4, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+ AS2( shr eax, 16 )
+ AS2( movzx edi, ah )
+ AS2( movdqa xmm3, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+ AS2( movzx edi, al )
+ AS2( movdqa xmm2, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+
+ #define SSE2_MUL_32BITS(i) \
+ AS2( psrldq xmm0, 4 )\
+ AS2( movd eax, xmm0 )\
+ AS2( and eax, AS_HEX(f0f0f0f0) )\
+ AS2( movzx edi, bh )\
+ AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( movzx edi, bl )\
+ AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( shr ebx, 16 )\
+ AS2( movzx edi, bh )\
+ AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( movzx edi, bl )\
+ AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( movd ebx, xmm0 )\
+ AS2( shl ebx, 4 )\
+ AS2( and ebx, AS_HEX(f0f0f0f0) )\
+ AS2( movzx edi, ah )\
+ AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+ AS2( movzx edi, al )\
+ AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+ AS2( shr eax, 16 )\
+ AS2( movzx edi, ah )\
+ AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+ AS2( movzx edi, al )\
+ AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+
+ SSE2_MUL_32BITS(1)
+ SSE2_MUL_32BITS(2)
+ SSE2_MUL_32BITS(3)
+
+ AS2( movzx edi, bh )
+ AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+ AS2( movzx edi, bl )
+ AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+ AS2( shr ebx, 16 )
+ AS2( movzx edi, bh )
+ AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+ AS2( movzx edi, bl )
+ AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+
+ AS2( movdqa xmm0, xmm3 )
+ AS2( pslldq xmm3, 1 )
+ AS2( pxor xmm2, xmm3 )
+ AS2( movdqa xmm1, xmm2 )
+ AS2( pslldq xmm2, 1 )
+ AS2( pxor xmm5, xmm2 )
+
+ AS2( psrldq xmm0, 15 )
+ AS2( movd WORD_REG(di), xmm0 )
+ AS2( movzx eax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
+ AS2( shl eax, 8 )
+
+ AS2( movdqa xmm0, xmm5 )
+ AS2( pslldq xmm5, 1 )
+ AS2( pxor xmm4, xmm5 )
+
+ AS2( psrldq xmm1, 15 )
+ AS2( movd WORD_REG(di), xmm1 )
+ AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
+ AS2( shl eax, 8 )
+
+ AS2( psrldq xmm0, 15 )
+ AS2( movd WORD_REG(di), xmm0 )
+ AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
+
+ AS2( movd xmm0, eax )
+ AS2( pxor xmm0, xmm4 )
+
+ AS2( add WORD_REG(cx), 16 )
+ AS2( sub WORD_REG(dx), 1 )
+ ASJ( jnz, 0, b )
+ AS2( movdqa [WORD_REG(si)], xmm0 )
+
+ AS_POP_IF86( bp)
+ AS_POP_IF86( bx)
+
+ #ifdef __GNUC__
+ ".att_syntax prefix;"
+ :
+ : "c" (data), "d" (len/16), "S" (hashBuffer), "D" (s_reductionTable)
+ : "memory", "cc", "%eax"
+ #if CRYPTOPP_BOOL_X64
+ , "%ebx", "%r11"
+ #endif
+ );
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ pop rbx
+ pop rdi
+ pop rsi
+ ret
+ GCM_AuthenticateBlocks_2K ENDP
+ #endif
+
+ return len%16;
+ }
+ case 3: // SSE2 and 64K tables
+ {
+ #ifdef __GNUC__
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ ALIGN 8
+ GCM_AuthenticateBlocks_64K PROC FRAME
+ rex_push_reg rsi
+ push_reg rdi
+ .endprolog
+ mov rsi, r8
+ #else
+ AS2( mov WORD_REG(cx), data )
+ AS2( mov WORD_REG(dx), len )
+ AS2( mov WORD_REG(si), hashBuffer )
+ AS2( shr WORD_REG(dx), 4 )
+ #endif
+
+ AS2( movdqa xmm0, [WORD_REG(si)] )
+
+ #undef MUL_TABLE
+ #define MUL_TABLE(i,j) WORD_REG(si) + 32 + (i*4+j)*256*16
+
+ ASL(1)
+ AS2( movdqu xmm1, [WORD_REG(cx)] )
+ AS2( pxor xmm1, xmm0 )
+ AS2( pxor xmm0, xmm0 )
+
+ #undef SSE2_MUL_32BITS
+ #define SSE2_MUL_32BITS(i) \
+ AS2( movd eax, xmm1 )\
+ AS2( psrldq xmm1, 4 )\
+ AS2( movzx edi, al )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,0) + WORD_REG(di)*8] )\
+ AS2( movzx edi, ah )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,1) + WORD_REG(di)*8] )\
+ AS2( shr eax, 16 )\
+ AS2( movzx edi, al )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,2) + WORD_REG(di)*8] )\
+ AS2( movzx edi, ah )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,3) + WORD_REG(di)*8] )\
+
+ SSE2_MUL_32BITS(0)
+ SSE2_MUL_32BITS(1)
+ SSE2_MUL_32BITS(2)
+ SSE2_MUL_32BITS(3)
+
+ AS2( add WORD_REG(cx), 16 )
+ AS2( sub WORD_REG(dx), 1 )
+ ASJ( jnz, 1, b )
+ AS2( movdqa [WORD_REG(si)], xmm0 )
+
+ #ifdef __GNUC__
+ ".att_syntax prefix;"
+ :
+ : "c" (data), "d" (len/16), "S" (hashBuffer)
+ : "memory", "cc", "%edi", "%eax"
+ );
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ pop rdi
+ pop rsi
+ ret
+ GCM_AuthenticateBlocks_64K ENDP
+ #endif
+
+ return len%16;
+ }
+#endif
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+ }
+
+ return len%16;
+}
+
+void GCM_Base::AuthenticateLastHeaderBlock()
+{
+ if (m_bufferedDataLength > 0)
+ {
+ memset(m_buffer+m_bufferedDataLength, 0, HASH_BLOCKSIZE-m_bufferedDataLength);
+ m_bufferedDataLength = 0;
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+ }
+}
+
+void GCM_Base::AuthenticateLastConfidentialBlock()
+{
+ GCM_Base::AuthenticateLastHeaderBlock();
+ PutBlock<word64, BigEndian, true>(NULL, m_buffer)(m_totalHeaderLength*8)(m_totalMessageLength*8);
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+}
+
+void GCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
+{
+ m_ctr.Seek(0);
+ ReverseHashBufferIfNeeded();
+ m_ctr.ProcessData(mac, HashBuffer(), macSize);
+}
+
+NAMESPACE_END
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+#endif
diff --git a/lib/cryptopp/gcm.h b/lib/cryptopp/gcm.h
new file mode 100644
index 000000000..272a51c9c
--- /dev/null
+++ b/lib/cryptopp/gcm.h
@@ -0,0 +1,106 @@
+#ifndef CRYPTOPP_GCM_H
+#define CRYPTOPP_GCM_H
+
+#include "authenc.h"
+#include "modes.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! .
+enum GCM_TablesOption {GCM_2K_Tables, GCM_64K_Tables};
+
+//! .
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GCM_Base : public AuthenticatedSymmetricCipherBase
+{
+public:
+ // AuthenticatedSymmetricCipher
+ std::string AlgorithmName() const
+ {return GetBlockCipher().AlgorithmName() + std::string("/GCM");}
+ size_t MinKeyLength() const
+ {return GetBlockCipher().MinKeyLength();}
+ size_t MaxKeyLength() const
+ {return GetBlockCipher().MaxKeyLength();}
+ size_t DefaultKeyLength() const
+ {return GetBlockCipher().DefaultKeyLength();}
+ size_t GetValidKeyLength(size_t n) const
+ {return GetBlockCipher().GetValidKeyLength(n);}
+ bool IsValidKeyLength(size_t n) const
+ {return GetBlockCipher().IsValidKeyLength(n);}
+ unsigned int OptimalDataAlignment() const;
+ IV_Requirement IVRequirement() const
+ {return UNIQUE_IV;}
+ unsigned int IVSize() const
+ {return 12;}
+ unsigned int MinIVLength() const
+ {return 1;}
+ unsigned int MaxIVLength() const
+ {return UINT_MAX;} // (W64LIT(1)<<61)-1 in the standard
+ unsigned int DigestSize() const
+ {return 16;}
+ lword MaxHeaderLength() const
+ {return (W64LIT(1)<<61)-1;}
+ lword MaxMessageLength() const
+ {return ((W64LIT(1)<<39)-256)/8;}
+
+protected:
+ // AuthenticatedSymmetricCipherBase
+ bool AuthenticationIsOnPlaintext() const
+ {return false;}
+ unsigned int AuthenticationBlockSize() const
+ {return HASH_BLOCKSIZE;}
+ void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
+ void Resync(const byte *iv, size_t len);
+ size_t AuthenticateBlocks(const byte *data, size_t len);
+ void AuthenticateLastHeaderBlock();
+ void AuthenticateLastConfidentialBlock();
+ void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
+ SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
+
+ virtual BlockCipher & AccessBlockCipher() =0;
+ virtual GCM_TablesOption GetTablesOption() const =0;
+
+ const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();};
+ byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
+ byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;}
+ byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;}
+ inline void ReverseHashBufferIfNeeded();
+
+ class CRYPTOPP_DLL GCTR : public CTR_Mode_ExternalCipher::Encryption
+ {
+ protected:
+ void IncrementCounterBy256();
+ };
+
+ GCTR m_ctr;
+ static word16 s_reductionTable[256];
+ static volatile bool s_reductionTableInitialized;
+ enum {REQUIRED_BLOCKSIZE = 16, HASH_BLOCKSIZE = 16};
+};
+
+//! .
+template <class T_BlockCipher, GCM_TablesOption T_TablesOption, bool T_IsEncryption>
+class GCM_Final : public GCM_Base
+{
+public:
+ static std::string StaticAlgorithmName()
+ {return T_BlockCipher::StaticAlgorithmName() + std::string("/GCM");}
+ bool IsForwardTransformation() const
+ {return T_IsEncryption;}
+
+private:
+ GCM_TablesOption GetTablesOption() const {return T_TablesOption;}
+ BlockCipher & AccessBlockCipher() {return m_cipher;}
+ typename T_BlockCipher::Encryption m_cipher;
+};
+
+//! <a href="http://www.cryptolounge.org/wiki/GCM">GCM</a>
+template <class T_BlockCipher, GCM_TablesOption T_TablesOption=GCM_2K_Tables>
+struct GCM : public AuthenticatedSymmetricCipherDocumentation
+{
+ typedef GCM_Final<T_BlockCipher, T_TablesOption, true> Encryption;
+ typedef GCM_Final<T_BlockCipher, T_TablesOption, false> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/gf256.cpp b/lib/cryptopp/gf256.cpp
new file mode 100644
index 000000000..72026d1e1
--- /dev/null
+++ b/lib/cryptopp/gf256.cpp
@@ -0,0 +1,34 @@
+// gf256.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "gf256.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+GF256::Element GF256::Multiply(Element a, Element b) const
+{
+ word result = 0, t = b;
+
+ for (unsigned int i=0; i<8; i++)
+ {
+ result <<= 1;
+ if (result & 0x100)
+ result ^= m_modulus;
+
+ t <<= 1;
+ if (t & 0x100)
+ result ^= a;
+ }
+
+ return (GF256::Element) result;
+}
+
+GF256::Element GF256::MultiplicativeInverse(Element a) const
+{
+ Element result = a;
+ for (int i=1; i<7; i++)
+ result = Multiply(Square(result), a);
+ return Square(result);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/gf256.h b/lib/cryptopp/gf256.h
new file mode 100644
index 000000000..e0ea74826
--- /dev/null
+++ b/lib/cryptopp/gf256.h
@@ -0,0 +1,66 @@
+#ifndef CRYPTOPP_GF256_H
+#define CRYPTOPP_GF256_H
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! GF(256) with polynomial basis
+class GF256
+{
+public:
+ typedef byte Element;
+ typedef int RandomizationParameter;
+
+ GF256(byte modulus) : m_modulus(modulus) {}
+
+ Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const
+ {return rng.GenerateByte();}
+
+ bool Equal(Element a, Element b) const
+ {return a==b;}
+
+ Element Zero() const
+ {return 0;}
+
+ Element Add(Element a, Element b) const
+ {return a^b;}
+
+ Element& Accumulate(Element &a, Element b) const
+ {return a^=b;}
+
+ Element Inverse(Element a) const
+ {return a;}
+
+ Element Subtract(Element a, Element b) const
+ {return a^b;}
+
+ Element& Reduce(Element &a, Element b) const
+ {return a^=b;}
+
+ Element Double(Element a) const
+ {return 0;}
+
+ Element One() const
+ {return 1;}
+
+ Element Multiply(Element a, Element b) const;
+
+ Element Square(Element a) const
+ {return Multiply(a, a);}
+
+ bool IsUnit(Element a) const
+ {return a != 0;}
+
+ Element MultiplicativeInverse(Element a) const;
+
+ Element Divide(Element a, Element b) const
+ {return Multiply(a, MultiplicativeInverse(b));}
+
+private:
+ word m_modulus;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/gf2_32.cpp b/lib/cryptopp/gf2_32.cpp
new file mode 100644
index 000000000..ae4874a40
--- /dev/null
+++ b/lib/cryptopp/gf2_32.cpp
@@ -0,0 +1,99 @@
+// gf2_32.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "misc.h"
+#include "gf2_32.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+GF2_32::Element GF2_32::Multiply(Element a, Element b) const
+{
+ word32 table[4];
+ table[0] = 0;
+ table[1] = m_modulus;
+ if (a & 0x80000000)
+ {
+ table[2] = m_modulus ^ (a<<1);
+ table[3] = a<<1;
+ }
+ else
+ {
+ table[2] = a<<1;
+ table[3] = m_modulus ^ (a<<1);
+ }
+
+#if CRYPTOPP_FAST_ROTATE(32)
+ b = rotrFixed(b, 30U);
+ word32 result = table[b&2];
+
+ for (int i=29; i>=0; --i)
+ {
+ b = rotlFixed(b, 1U);
+ result = (result<<1) ^ table[(b&2) + (result>>31)];
+ }
+
+ return (b&1) ? result ^ a : result;
+#else
+ word32 result = table[(b>>30) & 2];
+
+ for (int i=29; i>=0; --i)
+ result = (result<<1) ^ table[((b>>i)&2) + (result>>31)];
+
+ return (b&1) ? result ^ a : result;
+#endif
+}
+
+GF2_32::Element GF2_32::MultiplicativeInverse(Element a) const
+{
+ if (a <= 1) // 1 is a special case
+ return a;
+
+ // warning - don't try to adapt this algorithm for another situation
+ word32 g0=m_modulus, g1=a, g2=a;
+ word32 v0=0, v1=1, v2=1;
+
+ assert(g1);
+
+ while (!(g2 & 0x80000000))
+ {
+ g2 <<= 1;
+ v2 <<= 1;
+ }
+
+ g2 <<= 1;
+ v2 <<= 1;
+
+ g0 ^= g2;
+ v0 ^= v2;
+
+ while (g0 != 1)
+ {
+ if (g1 < g0 || ((g0^g1) < g0 && (g0^g1) < g1))
+ {
+ assert(BitPrecision(g1) <= BitPrecision(g0));
+ g2 = g1;
+ v2 = v1;
+ }
+ else
+ {
+ assert(BitPrecision(g1) > BitPrecision(g0));
+ g2 = g0; g0 = g1; g1 = g2;
+ v2 = v0; v0 = v1; v1 = v2;
+ }
+
+ while ((g0^g2) >= g2)
+ {
+ assert(BitPrecision(g0) > BitPrecision(g2));
+ g2 <<= 1;
+ v2 <<= 1;
+ }
+
+ assert(BitPrecision(g0) == BitPrecision(g2));
+ g0 ^= g2;
+ v0 ^= v2;
+ }
+
+ return v0;
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/gf2_32.h b/lib/cryptopp/gf2_32.h
new file mode 100644
index 000000000..31713f4c0
--- /dev/null
+++ b/lib/cryptopp/gf2_32.h
@@ -0,0 +1,66 @@
+#ifndef CRYPTOPP_GF2_32_H
+#define CRYPTOPP_GF2_32_H
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! GF(2^32) with polynomial basis
+class GF2_32
+{
+public:
+ typedef word32 Element;
+ typedef int RandomizationParameter;
+
+ GF2_32(word32 modulus=0x0000008D) : m_modulus(modulus) {}
+
+ Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const
+ {return rng.GenerateWord32();}
+
+ bool Equal(Element a, Element b) const
+ {return a==b;}
+
+ Element Identity() const
+ {return 0;}
+
+ Element Add(Element a, Element b) const
+ {return a^b;}
+
+ Element& Accumulate(Element &a, Element b) const
+ {return a^=b;}
+
+ Element Inverse(Element a) const
+ {return a;}
+
+ Element Subtract(Element a, Element b) const
+ {return a^b;}
+
+ Element& Reduce(Element &a, Element b) const
+ {return a^=b;}
+
+ Element Double(Element a) const
+ {return 0;}
+
+ Element MultiplicativeIdentity() const
+ {return 1;}
+
+ Element Multiply(Element a, Element b) const;
+
+ Element Square(Element a) const
+ {return Multiply(a, a);}
+
+ bool IsUnit(Element a) const
+ {return a != 0;}
+
+ Element MultiplicativeInverse(Element a) const;
+
+ Element Divide(Element a, Element b) const
+ {return Multiply(a, MultiplicativeInverse(b));}
+
+private:
+ word32 m_modulus;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/gf2n.cpp b/lib/cryptopp/gf2n.cpp
new file mode 100644
index 000000000..bcc56071a
--- /dev/null
+++ b/lib/cryptopp/gf2n.cpp
@@ -0,0 +1,882 @@
+// gf2n.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "gf2n.h"
+#include "algebra.h"
+#include "words.h"
+#include "randpool.h"
+#include "asn.h"
+#include "oids.h"
+
+#include <iostream>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+PolynomialMod2::PolynomialMod2()
+{
+}
+
+PolynomialMod2::PolynomialMod2(word value, size_t bitLength)
+ : reg(BitsToWords(bitLength))
+{
+ assert(value==0 || reg.size()>0);
+
+ if (reg.size() > 0)
+ {
+ reg[0] = value;
+ SetWords(reg+1, 0, reg.size()-1);
+ }
+}
+
+PolynomialMod2::PolynomialMod2(const PolynomialMod2& t)
+ : reg(t.reg.size())
+{
+ CopyWords(reg, t.reg, reg.size());
+}
+
+void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits)
+{
+ const size_t nbytes = nbits/8 + 1;
+ SecByteBlock buf(nbytes);
+ rng.GenerateBlock(buf, nbytes);
+ buf[0] = (byte)Crop(buf[0], nbits % 8);
+ Decode(buf, nbytes);
+}
+
+PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength)
+{
+ PolynomialMod2 result((word)0, bitLength);
+ SetWords(result.reg, ~(word)0, result.reg.size());
+ if (bitLength%WORD_BITS)
+ result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS);
+ return result;
+}
+
+void PolynomialMod2::SetBit(size_t n, int value)
+{
+ if (value)
+ {
+ reg.CleanGrow(n/WORD_BITS + 1);
+ reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
+ }
+ else
+ {
+ if (n/WORD_BITS < reg.size())
+ reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
+ }
+}
+
+byte PolynomialMod2::GetByte(size_t n) const
+{
+ if (n/WORD_SIZE >= reg.size())
+ return 0;
+ else
+ return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
+}
+
+void PolynomialMod2::SetByte(size_t n, byte value)
+{
+ reg.CleanGrow(BytesToWords(n+1));
+ reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
+ reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
+}
+
+PolynomialMod2 PolynomialMod2::Monomial(size_t i)
+{
+ PolynomialMod2 r((word)0, i+1);
+ r.SetBit(i);
+ return r;
+}
+
+PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2)
+{
+ PolynomialMod2 r((word)0, t0+1);
+ r.SetBit(t0);
+ r.SetBit(t1);
+ r.SetBit(t2);
+ return r;
+}
+
+PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4)
+{
+ PolynomialMod2 r((word)0, t0+1);
+ r.SetBit(t0);
+ r.SetBit(t1);
+ r.SetBit(t2);
+ r.SetBit(t3);
+ r.SetBit(t4);
+ return r;
+}
+
+template <word i>
+struct NewPolynomialMod2
+{
+ PolynomialMod2 * operator()() const
+ {
+ return new PolynomialMod2(i);
+ }
+};
+
+const PolynomialMod2 &PolynomialMod2::Zero()
+{
+ return Singleton<PolynomialMod2>().Ref();
+}
+
+const PolynomialMod2 &PolynomialMod2::One()
+{
+ return Singleton<PolynomialMod2, NewPolynomialMod2<1> >().Ref();
+}
+
+void PolynomialMod2::Decode(const byte *input, size_t inputLen)
+{
+ StringStore store(input, inputLen);
+ Decode(store, inputLen);
+}
+
+void PolynomialMod2::Encode(byte *output, size_t outputLen) const
+{
+ ArraySink sink(output, outputLen);
+ Encode(sink, outputLen);
+}
+
+void PolynomialMod2::Decode(BufferedTransformation &bt, size_t inputLen)
+{
+ reg.CleanNew(BytesToWords(inputLen));
+
+ for (size_t i=inputLen; i > 0; i--)
+ {
+ byte b;
+ bt.Get(b);
+ reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8;
+ }
+}
+
+void PolynomialMod2::Encode(BufferedTransformation &bt, size_t outputLen) const
+{
+ for (size_t i=outputLen; i > 0; i--)
+ bt.Put(GetByte(i-1));
+}
+
+void PolynomialMod2::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const
+{
+ DERGeneralEncoder enc(bt, OCTET_STRING);
+ Encode(enc, length);
+ enc.MessageEnd();
+}
+
+void PolynomialMod2::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length)
+{
+ BERGeneralDecoder dec(bt, OCTET_STRING);
+ if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
+ BERDecodeError();
+ Decode(dec, length);
+ dec.MessageEnd();
+}
+
+unsigned int PolynomialMod2::WordCount() const
+{
+ return (unsigned int)CountWords(reg, reg.size());
+}
+
+unsigned int PolynomialMod2::ByteCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]);
+ else
+ return 0;
+}
+
+unsigned int PolynomialMod2::BitCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]);
+ else
+ return 0;
+}
+
+unsigned int PolynomialMod2::Parity() const
+{
+ unsigned i;
+ word temp=0;
+ for (i=0; i<reg.size(); i++)
+ temp ^= reg[i];
+ return CryptoPP::Parity(temp);
+}
+
+PolynomialMod2& PolynomialMod2::operator=(const PolynomialMod2& t)
+{
+ reg.Assign(t.reg);
+ return *this;
+}
+
+PolynomialMod2& PolynomialMod2::operator^=(const PolynomialMod2& t)
+{
+ reg.CleanGrow(t.reg.size());
+ XorWords(reg, t.reg, t.reg.size());
+ return *this;
+}
+
+PolynomialMod2 PolynomialMod2::Xor(const PolynomialMod2 &b) const
+{
+ if (b.reg.size() >= reg.size())
+ {
+ PolynomialMod2 result((word)0, b.reg.size()*WORD_BITS);
+ XorWords(result.reg, reg, b.reg, reg.size());
+ CopyWords(result.reg+reg.size(), b.reg+reg.size(), b.reg.size()-reg.size());
+ return result;
+ }
+ else
+ {
+ PolynomialMod2 result((word)0, reg.size()*WORD_BITS);
+ XorWords(result.reg, reg, b.reg, b.reg.size());
+ CopyWords(result.reg+b.reg.size(), reg+b.reg.size(), reg.size()-b.reg.size());
+ return result;
+ }
+}
+
+PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const
+{
+ PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size(), b.reg.size()));
+ AndWords(result.reg, reg, b.reg, result.reg.size());
+ return result;
+}
+
+PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const
+{
+ PolynomialMod2 result((word)0, BitCount() + b.BitCount());
+
+ for (int i=b.Degree(); i>=0; i--)
+ {
+ result <<= 1;
+ if (b[i])
+ XorWords(result.reg, reg, reg.size());
+ }
+ return result;
+}
+
+PolynomialMod2 PolynomialMod2::Squared() const
+{
+ static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85};
+
+ PolynomialMod2 result((word)0, 2*reg.size()*WORD_BITS);
+
+ for (unsigned i=0; i<reg.size(); i++)
+ {
+ unsigned j;
+
+ for (j=0; j<WORD_BITS; j+=8)
+ result.reg[2*i] |= map[(reg[i] >> (j/2)) % 16] << j;
+
+ for (j=0; j<WORD_BITS; j+=8)
+ result.reg[2*i+1] |= map[(reg[i] >> (j/2 + WORD_BITS/2)) % 16] << j;
+ }
+
+ return result;
+}
+
+void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 &quotient,
+ const PolynomialMod2 &dividend, const PolynomialMod2 &divisor)
+{
+ if (!divisor)
+ throw PolynomialMod2::DivideByZero();
+
+ int degree = divisor.Degree();
+ remainder.reg.CleanNew(BitsToWords(degree+1));
+ if (dividend.BitCount() >= divisor.BitCount())
+ quotient.reg.CleanNew(BitsToWords(dividend.BitCount() - divisor.BitCount() + 1));
+ else
+ quotient.reg.CleanNew(0);
+
+ for (int i=dividend.Degree(); i>=0; i--)
+ {
+ remainder <<= 1;
+ remainder.reg[0] |= dividend[i];
+ if (remainder[degree])
+ {
+ remainder -= divisor;
+ quotient.SetBit(i);
+ }
+ }
+}
+
+PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const
+{
+ PolynomialMod2 remainder, quotient;
+ PolynomialMod2::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const
+{
+ PolynomialMod2 remainder, quotient;
+ PolynomialMod2::Divide(remainder, quotient, *this, b);
+ return remainder;
+}
+
+PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n)
+{
+ if (!reg.size())
+ return *this;
+
+ int i;
+ word u;
+ word carry=0;
+ word *r=reg;
+
+ if (n==1) // special case code for most frequent case
+ {
+ i = (int)reg.size();
+ while (i--)
+ {
+ u = *r;
+ *r = (u << 1) | carry;
+ carry = u >> (WORD_BITS-1);
+ r++;
+ }
+
+ if (carry)
+ {
+ reg.Grow(reg.size()+1);
+ reg[reg.size()-1] = carry;
+ }
+
+ return *this;
+ }
+
+ int shiftWords = n / WORD_BITS;
+ int shiftBits = n % WORD_BITS;
+
+ if (shiftBits)
+ {
+ i = (int)reg.size();
+ while (i--)
+ {
+ u = *r;
+ *r = (u << shiftBits) | carry;
+ carry = u >> (WORD_BITS-shiftBits);
+ r++;
+ }
+ }
+
+ if (carry)
+ {
+ reg.Grow(reg.size()+shiftWords+1);
+ reg[reg.size()-1] = carry;
+ }
+ else
+ reg.Grow(reg.size()+shiftWords);
+
+ if (shiftWords)
+ {
+ for (i = (int)reg.size()-1; i>=shiftWords; i--)
+ reg[i] = reg[i-shiftWords];
+ for (; i>=0; i--)
+ reg[i] = 0;
+ }
+
+ return *this;
+}
+
+PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n)
+{
+ if (!reg.size())
+ return *this;
+
+ int shiftWords = n / WORD_BITS;
+ int shiftBits = n % WORD_BITS;
+
+ size_t i;
+ word u;
+ word carry=0;
+ word *r=reg+reg.size()-1;
+
+ if (shiftBits)
+ {
+ i = reg.size();
+ while (i--)
+ {
+ u = *r;
+ *r = (u >> shiftBits) | carry;
+ carry = u << (WORD_BITS-shiftBits);
+ r--;
+ }
+ }
+
+ if (shiftWords)
+ {
+ for (i=0; i<reg.size()-shiftWords; i++)
+ reg[i] = reg[i+shiftWords];
+ for (; i<reg.size(); i++)
+ reg[i] = 0;
+ }
+
+ return *this;
+}
+
+PolynomialMod2 PolynomialMod2::operator<<(unsigned int n) const
+{
+ PolynomialMod2 result(*this);
+ return result<<=n;
+}
+
+PolynomialMod2 PolynomialMod2::operator>>(unsigned int n) const
+{
+ PolynomialMod2 result(*this);
+ return result>>=n;
+}
+
+bool PolynomialMod2::operator!() const
+{
+ for (unsigned i=0; i<reg.size(); i++)
+ if (reg[i]) return false;
+ return true;
+}
+
+bool PolynomialMod2::Equals(const PolynomialMod2 &rhs) const
+{
+ size_t i, smallerSize = STDMIN(reg.size(), rhs.reg.size());
+
+ for (i=0; i<smallerSize; i++)
+ if (reg[i] != rhs.reg[i]) return false;
+
+ for (i=smallerSize; i<reg.size(); i++)
+ if (reg[i] != 0) return false;
+
+ for (i=smallerSize; i<rhs.reg.size(); i++)
+ if (rhs.reg[i] != 0) return false;
+
+ return true;
+}
+
+std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a)
+{
+ // Get relevant conversion specifications from ostream.
+ long f = out.flags() & std::ios::basefield; // Get base digits.
+ int bits, block;
+ char suffix;
+ switch(f)
+ {
+ case std::ios::oct :
+ bits = 3;
+ block = 4;
+ suffix = 'o';
+ break;
+ case std::ios::hex :
+ bits = 4;
+ block = 2;
+ suffix = 'h';
+ break;
+ default :
+ bits = 1;
+ block = 8;
+ suffix = 'b';
+ }
+
+ if (!a)
+ return out << '0' << suffix;
+
+ SecBlock<char> s(a.BitCount()/bits+1);
+ unsigned i;
+
+ static const char upper[]="0123456789ABCDEF";
+ static const char lower[]="0123456789abcdef";
+ const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower;
+
+ for (i=0; i*bits < a.BitCount(); i++)
+ {
+ int digit=0;
+ for (int j=0; j<bits; j++)
+ digit |= a[i*bits+j] << j;
+ s[i]=vec[digit];
+ }
+
+ while (i--)
+ {
+ out << s[i];
+ if (i && (i%block)==0)
+ out << ',';
+ }
+
+ return out << suffix;
+}
+
+PolynomialMod2 PolynomialMod2::Gcd(const PolynomialMod2 &a, const PolynomialMod2 &b)
+{
+ return EuclideanDomainOf<PolynomialMod2>().Gcd(a, b);
+}
+
+PolynomialMod2 PolynomialMod2::InverseMod(const PolynomialMod2 &modulus) const
+{
+ typedef EuclideanDomainOf<PolynomialMod2> Domain;
+ return QuotientRing<Domain>(Domain(), modulus).MultiplicativeInverse(*this);
+}
+
+bool PolynomialMod2::IsIrreducible() const
+{
+ signed int d = Degree();
+ if (d <= 0)
+ return false;
+
+ PolynomialMod2 t(2), u(t);
+ for (int i=1; i<=d/2; i++)
+ {
+ u = u.Squared()%(*this);
+ if (!Gcd(u+t, *this).IsUnit())
+ return false;
+ }
+ return true;
+}
+
+// ********************************************************
+
+GF2NP::GF2NP(const PolynomialMod2 &modulus)
+ : QuotientRing<EuclideanDomainOf<PolynomialMod2> >(EuclideanDomainOf<PolynomialMod2>(), modulus), m(modulus.Degree())
+{
+}
+
+GF2NP::Element GF2NP::SquareRoot(const Element &a) const
+{
+ Element r = a;
+ for (unsigned int i=1; i<m; i++)
+ r = Square(r);
+ return r;
+}
+
+GF2NP::Element GF2NP::HalfTrace(const Element &a) const
+{
+ assert(m%2 == 1);
+ Element h = a;
+ for (unsigned int i=1; i<=(m-1)/2; i++)
+ h = Add(Square(Square(h)), a);
+ return h;
+}
+
+GF2NP::Element GF2NP::SolveQuadraticEquation(const Element &a) const
+{
+ if (m%2 == 0)
+ {
+ Element z, w;
+ RandomPool rng;
+ do
+ {
+ Element p((RandomNumberGenerator &)rng, m);
+ z = PolynomialMod2::Zero();
+ w = p;
+ for (unsigned int i=1; i<=m-1; i++)
+ {
+ w = Square(w);
+ z = Square(z);
+ Accumulate(z, Multiply(w, a));
+ Accumulate(w, p);
+ }
+ } while (w.IsZero());
+ return z;
+ }
+ else
+ return HalfTrace(a);
+}
+
+// ********************************************************
+
+GF2NT::GF2NT(unsigned int t0, unsigned int t1, unsigned int t2)
+ : GF2NP(PolynomialMod2::Trinomial(t0, t1, t2))
+ , t0(t0), t1(t1)
+ , result((word)0, m)
+{
+ assert(t0 > t1 && t1 > t2 && t2==0);
+}
+
+const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const
+{
+ if (t0-t1 < WORD_BITS)
+ return GF2NP::MultiplicativeInverse(a);
+
+ SecWordBlock T(m_modulus.reg.size() * 4);
+ word *b = T;
+ word *c = T+m_modulus.reg.size();
+ word *f = T+2*m_modulus.reg.size();
+ word *g = T+3*m_modulus.reg.size();
+ size_t bcLen=1, fgLen=m_modulus.reg.size();
+ unsigned int k=0;
+
+ SetWords(T, 0, 3*m_modulus.reg.size());
+ b[0]=1;
+ assert(a.reg.size() <= m_modulus.reg.size());
+ CopyWords(f, a.reg, a.reg.size());
+ CopyWords(g, m_modulus.reg, m_modulus.reg.size());
+
+ while (1)
+ {
+ word t=f[0];
+ while (!t)
+ {
+ ShiftWordsRightByWords(f, fgLen, 1);
+ if (c[bcLen-1])
+ bcLen++;
+ assert(bcLen <= m_modulus.reg.size());
+ ShiftWordsLeftByWords(c, bcLen, 1);
+ k+=WORD_BITS;
+ t=f[0];
+ }
+
+ unsigned int i=0;
+ while (t%2 == 0)
+ {
+ t>>=1;
+ i++;
+ }
+ k+=i;
+
+ if (t==1 && CountWords(f, fgLen)==1)
+ break;
+
+ if (i==1)
+ {
+ ShiftWordsRightByBits(f, fgLen, 1);
+ t=ShiftWordsLeftByBits(c, bcLen, 1);
+ }
+ else
+ {
+ ShiftWordsRightByBits(f, fgLen, i);
+ t=ShiftWordsLeftByBits(c, bcLen, i);
+ }
+ if (t)
+ {
+ c[bcLen] = t;
+ bcLen++;
+ assert(bcLen <= m_modulus.reg.size());
+ }
+
+ if (f[fgLen-1]==0 && g[fgLen-1]==0)
+ fgLen--;
+
+ if (f[fgLen-1] < g[fgLen-1])
+ {
+ std::swap(f, g);
+ std::swap(b, c);
+ }
+
+ XorWords(f, g, fgLen);
+ XorWords(b, c, bcLen);
+ }
+
+ while (k >= WORD_BITS)
+ {
+ word temp = b[0];
+ // right shift b
+ for (unsigned i=0; i+1<BitsToWords(m); i++)
+ b[i] = b[i+1];
+ b[BitsToWords(m)-1] = 0;
+
+ if (t1 < WORD_BITS)
+ for (unsigned int j=0; j<WORD_BITS-t1; j++)
+ temp ^= ((temp >> j) & 1) << (t1 + j);
+ else
+ b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
+
+ if (t1 % WORD_BITS)
+ b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
+
+ if (t0%WORD_BITS)
+ {
+ b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
+ b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
+ }
+ else
+ b[t0/WORD_BITS-1] ^= temp;
+
+ k -= WORD_BITS;
+ }
+
+ if (k)
+ {
+ word temp = b[0] << (WORD_BITS - k);
+ ShiftWordsRightByBits(b, BitsToWords(m), k);
+
+ if (t1 < WORD_BITS)
+ for (unsigned int j=0; j<WORD_BITS-t1; j++)
+ temp ^= ((temp >> j) & 1) << (t1 + j);
+ else
+ b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
+
+ if (t1 % WORD_BITS)
+ b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
+
+ if (t0%WORD_BITS)
+ {
+ b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
+ b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
+ }
+ else
+ b[t0/WORD_BITS-1] ^= temp;
+ }
+
+ CopyWords(result.reg.begin(), b, result.reg.size());
+ return result;
+}
+
+const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const
+{
+ size_t aSize = STDMIN(a.reg.size(), result.reg.size());
+ Element r((word)0, m);
+
+ for (int i=m-1; i>=0; i--)
+ {
+ if (r[m-1])
+ {
+ ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
+ XorWords(r.reg.begin(), m_modulus.reg, r.reg.size());
+ }
+ else
+ ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
+
+ if (b[i])
+ XorWords(r.reg.begin(), a.reg, aSize);
+ }
+
+ if (m%WORD_BITS)
+ r.reg.begin()[r.reg.size()-1] = (word)Crop(r.reg[r.reg.size()-1], m%WORD_BITS);
+
+ CopyWords(result.reg.begin(), r.reg.begin(), result.reg.size());
+ return result;
+}
+
+const GF2NT::Element& GF2NT::Reduced(const Element &a) const
+{
+ if (t0-t1 < WORD_BITS)
+ return m_domain.Mod(a, m_modulus);
+
+ SecWordBlock b(a.reg);
+
+ size_t i;
+ for (i=b.size()-1; i>=BitsToWords(t0); i--)
+ {
+ word temp = b[i];
+
+ if (t0%WORD_BITS)
+ {
+ b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
+ b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS);
+ }
+ else
+ b[i-t0/WORD_BITS] ^= temp;
+
+ if ((t0-t1)%WORD_BITS)
+ {
+ b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
+ b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
+ }
+ else
+ b[i-(t0-t1)/WORD_BITS] ^= temp;
+ }
+
+ if (i==BitsToWords(t0)-1 && t0%WORD_BITS)
+ {
+ word mask = ((word)1<<(t0%WORD_BITS))-1;
+ word temp = b[i] & ~mask;
+ b[i] &= mask;
+
+ b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
+
+ if ((t0-t1)%WORD_BITS)
+ {
+ b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
+ if ((t0-t1)%WORD_BITS > t0%WORD_BITS)
+ b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
+ else
+ assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0);
+ }
+ else
+ b[i-(t0-t1)/WORD_BITS] ^= temp;
+ }
+
+ SetWords(result.reg.begin(), 0, result.reg.size());
+ CopyWords(result.reg.begin(), b, STDMIN(b.size(), result.reg.size()));
+ return result;
+}
+
+void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const
+{
+ a.DEREncodeAsOctetString(out, MaxElementByteLength());
+}
+
+void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const
+{
+ a.BERDecodeAsOctetString(in, MaxElementByteLength());
+}
+
+void GF2NT::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ ASN1::characteristic_two_field().DEREncode(seq);
+ DERSequenceEncoder parameters(seq);
+ DEREncodeUnsigned(parameters, m);
+ ASN1::tpBasis().DEREncode(parameters);
+ DEREncodeUnsigned(parameters, t1);
+ parameters.MessageEnd();
+ seq.MessageEnd();
+}
+
+void GF2NPP::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ ASN1::characteristic_two_field().DEREncode(seq);
+ DERSequenceEncoder parameters(seq);
+ DEREncodeUnsigned(parameters, m);
+ ASN1::ppBasis().DEREncode(parameters);
+ DERSequenceEncoder pentanomial(parameters);
+ DEREncodeUnsigned(pentanomial, t3);
+ DEREncodeUnsigned(pentanomial, t2);
+ DEREncodeUnsigned(pentanomial, t1);
+ pentanomial.MessageEnd();
+ parameters.MessageEnd();
+ seq.MessageEnd();
+}
+
+GF2NP * BERDecodeGF2NP(BufferedTransformation &bt)
+{
+ // VC60 workaround: auto_ptr lacks reset()
+ member_ptr<GF2NP> result;
+
+ BERSequenceDecoder seq(bt);
+ if (OID(seq) != ASN1::characteristic_two_field())
+ BERDecodeError();
+ BERSequenceDecoder parameters(seq);
+ unsigned int m;
+ BERDecodeUnsigned(parameters, m);
+ OID oid(parameters);
+ if (oid == ASN1::tpBasis())
+ {
+ unsigned int t1;
+ BERDecodeUnsigned(parameters, t1);
+ result.reset(new GF2NT(m, t1, 0));
+ }
+ else if (oid == ASN1::ppBasis())
+ {
+ unsigned int t1, t2, t3;
+ BERSequenceDecoder pentanomial(parameters);
+ BERDecodeUnsigned(pentanomial, t3);
+ BERDecodeUnsigned(pentanomial, t2);
+ BERDecodeUnsigned(pentanomial, t1);
+ pentanomial.MessageEnd();
+ result.reset(new GF2NPP(m, t3, t2, t1, 0));
+ }
+ else
+ {
+ BERDecodeError();
+ return NULL;
+ }
+ parameters.MessageEnd();
+ seq.MessageEnd();
+
+ return result.release();
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/gf2n.h b/lib/cryptopp/gf2n.h
new file mode 100644
index 000000000..67ade641e
--- /dev/null
+++ b/lib/cryptopp/gf2n.h
@@ -0,0 +1,369 @@
+#ifndef CRYPTOPP_GF2N_H
+#define CRYPTOPP_GF2N_H
+
+/*! \file */
+
+#include "cryptlib.h"
+#include "secblock.h"
+#include "misc.h"
+#include "algebra.h"
+
+#include <iosfwd>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Polynomial with Coefficients in GF(2)
+/*! \nosubgrouping */
+class CRYPTOPP_DLL PolynomialMod2
+{
+public:
+ //! \name ENUMS, EXCEPTIONS, and TYPEDEFS
+ //@{
+ //! divide by zero exception
+ class DivideByZero : public Exception
+ {
+ public:
+ DivideByZero() : Exception(OTHER_ERROR, "PolynomialMod2: division by zero") {}
+ };
+
+ typedef unsigned int RandomizationParameter;
+ //@}
+
+ //! \name CREATORS
+ //@{
+ //! creates the zero polynomial
+ PolynomialMod2();
+ //! copy constructor
+ PolynomialMod2(const PolynomialMod2& t);
+
+ //! convert from word
+ /*! value should be encoded with the least significant bit as coefficient to x^0
+ and most significant bit as coefficient to x^(WORD_BITS-1)
+ bitLength denotes how much memory to allocate initially
+ */
+ PolynomialMod2(word value, size_t bitLength=WORD_BITS);
+
+ //! convert from big-endian byte array
+ PolynomialMod2(const byte *encodedPoly, size_t byteCount)
+ {Decode(encodedPoly, byteCount);}
+
+ //! convert from big-endian form stored in a BufferedTransformation
+ PolynomialMod2(BufferedTransformation &encodedPoly, size_t byteCount)
+ {Decode(encodedPoly, byteCount);}
+
+ //! create a random polynomial uniformly distributed over all polynomials with degree less than bitcount
+ PolynomialMod2(RandomNumberGenerator &rng, size_t bitcount)
+ {Randomize(rng, bitcount);}
+
+ //! return x^i
+ static PolynomialMod2 CRYPTOPP_API Monomial(size_t i);
+ //! return x^t0 + x^t1 + x^t2
+ static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2);
+ //! return x^t0 + x^t1 + x^t2 + x^t3 + x^t4
+ static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4);
+ //! return x^(n-1) + ... + x + 1
+ static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n);
+
+ //!
+ static const PolynomialMod2 & CRYPTOPP_API Zero();
+ //!
+ static const PolynomialMod2 & CRYPTOPP_API One();
+ //@}
+
+ //! \name ENCODE/DECODE
+ //@{
+ //! minimum number of bytes to encode this polynomial
+ /*! MinEncodedSize of 0 is 1 */
+ unsigned int MinEncodedSize() const {return STDMAX(1U, ByteCount());}
+
+ //! encode in big-endian format
+ /*! if outputLen < MinEncodedSize, the most significant bytes will be dropped
+ if outputLen > MinEncodedSize, the most significant bytes will be padded
+ */
+ void Encode(byte *output, size_t outputLen) const;
+ //!
+ void Encode(BufferedTransformation &bt, size_t outputLen) const;
+
+ //!
+ void Decode(const byte *input, size_t inputLen);
+ //!
+ //* Precondition: bt.MaxRetrievable() >= inputLen
+ void Decode(BufferedTransformation &bt, size_t inputLen);
+
+ //! encode value as big-endian octet string
+ void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const;
+ //! decode value as big-endian octet string
+ void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length);
+ //@}
+
+ //! \name ACCESSORS
+ //@{
+ //! number of significant bits = Degree() + 1
+ unsigned int BitCount() const;
+ //! number of significant bytes = ceiling(BitCount()/8)
+ unsigned int ByteCount() const;
+ //! number of significant words = ceiling(ByteCount()/sizeof(word))
+ unsigned int WordCount() const;
+
+ //! return the n-th bit, n=0 being the least significant bit
+ bool GetBit(size_t n) const {return GetCoefficient(n)!=0;}
+ //! return the n-th byte
+ byte GetByte(size_t n) const;
+
+ //! the zero polynomial will return a degree of -1
+ signed int Degree() const {return BitCount()-1;}
+ //! degree + 1
+ unsigned int CoefficientCount() const {return BitCount();}
+ //! return coefficient for x^i
+ int GetCoefficient(size_t i) const
+ {return (i/WORD_BITS < reg.size()) ? int(reg[i/WORD_BITS] >> (i % WORD_BITS)) & 1 : 0;}
+ //! return coefficient for x^i
+ int operator[](unsigned int i) const {return GetCoefficient(i);}
+
+ //!
+ bool IsZero() const {return !*this;}
+ //!
+ bool Equals(const PolynomialMod2 &rhs) const;
+ //@}
+
+ //! \name MANIPULATORS
+ //@{
+ //!
+ PolynomialMod2& operator=(const PolynomialMod2& t);
+ //!
+ PolynomialMod2& operator&=(const PolynomialMod2& t);
+ //!
+ PolynomialMod2& operator^=(const PolynomialMod2& t);
+ //!
+ PolynomialMod2& operator+=(const PolynomialMod2& t) {return *this ^= t;}
+ //!
+ PolynomialMod2& operator-=(const PolynomialMod2& t) {return *this ^= t;}
+ //!
+ PolynomialMod2& operator*=(const PolynomialMod2& t);
+ //!
+ PolynomialMod2& operator/=(const PolynomialMod2& t);
+ //!
+ PolynomialMod2& operator%=(const PolynomialMod2& t);
+ //!
+ PolynomialMod2& operator<<=(unsigned int);
+ //!
+ PolynomialMod2& operator>>=(unsigned int);
+
+ //!
+ void Randomize(RandomNumberGenerator &rng, size_t bitcount);
+
+ //!
+ void SetBit(size_t i, int value = 1);
+ //! set the n-th byte to value
+ void SetByte(size_t n, byte value);
+
+ //!
+ void SetCoefficient(size_t i, int value) {SetBit(i, value);}
+
+ //!
+ void swap(PolynomialMod2 &a) {reg.swap(a.reg);}
+ //@}
+
+ //! \name UNARY OPERATORS
+ //@{
+ //!
+ bool operator!() const;
+ //!
+ PolynomialMod2 operator+() const {return *this;}
+ //!
+ PolynomialMod2 operator-() const {return *this;}
+ //@}
+
+ //! \name BINARY OPERATORS
+ //@{
+ //!
+ PolynomialMod2 And(const PolynomialMod2 &b) const;
+ //!
+ PolynomialMod2 Xor(const PolynomialMod2 &b) const;
+ //!
+ PolynomialMod2 Plus(const PolynomialMod2 &b) const {return Xor(b);}
+ //!
+ PolynomialMod2 Minus(const PolynomialMod2 &b) const {return Xor(b);}
+ //!
+ PolynomialMod2 Times(const PolynomialMod2 &b) const;
+ //!
+ PolynomialMod2 DividedBy(const PolynomialMod2 &b) const;
+ //!
+ PolynomialMod2 Modulo(const PolynomialMod2 &b) const;
+
+ //!
+ PolynomialMod2 operator>>(unsigned int n) const;
+ //!
+ PolynomialMod2 operator<<(unsigned int n) const;
+ //@}
+
+ //! \name OTHER ARITHMETIC FUNCTIONS
+ //@{
+ //! sum modulo 2 of all coefficients
+ unsigned int Parity() const;
+
+ //! check for irreducibility
+ bool IsIrreducible() const;
+
+ //! is always zero since we're working modulo 2
+ PolynomialMod2 Doubled() const {return Zero();}
+ //!
+ PolynomialMod2 Squared() const;
+
+ //! only 1 is a unit
+ bool IsUnit() const {return Equals(One());}
+ //! return inverse if *this is a unit, otherwise return 0
+ PolynomialMod2 MultiplicativeInverse() const {return IsUnit() ? One() : Zero();}
+
+ //! greatest common divisor
+ static PolynomialMod2 CRYPTOPP_API Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n);
+ //! calculate multiplicative inverse of *this mod n
+ PolynomialMod2 InverseMod(const PolynomialMod2 &) const;
+
+ //! calculate r and q such that (a == d*q + r) && (deg(r) < deg(d))
+ static void CRYPTOPP_API Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d);
+ //@}
+
+ //! \name INPUT/OUTPUT
+ //@{
+ //!
+ friend std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a);
+ //@}
+
+private:
+ friend class GF2NT;
+
+ SecWordBlock reg;
+};
+
+//!
+inline bool operator==(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Equals(b);}
+//!
+inline bool operator!=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return !(a==b);}
+//! compares degree
+inline bool operator> (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() > b.Degree();}
+//! compares degree
+inline bool operator>=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() >= b.Degree();}
+//! compares degree
+inline bool operator< (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() < b.Degree();}
+//! compares degree
+inline bool operator<=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
+{return a.Degree() <= b.Degree();}
+//!
+inline CryptoPP::PolynomialMod2 operator&(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.And(b);}
+//!
+inline CryptoPP::PolynomialMod2 operator^(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Xor(b);}
+//!
+inline CryptoPP::PolynomialMod2 operator+(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Plus(b);}
+//!
+inline CryptoPP::PolynomialMod2 operator-(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Minus(b);}
+//!
+inline CryptoPP::PolynomialMod2 operator*(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Times(b);}
+//!
+inline CryptoPP::PolynomialMod2 operator/(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.DividedBy(b);}
+//!
+inline CryptoPP::PolynomialMod2 operator%(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Modulo(b);}
+
+// CodeWarrior 8 workaround: put these template instantiations after overloaded operator declarations,
+// but before the use of QuotientRing<EuclideanDomainOf<PolynomialMod2> > for VC .NET 2003
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<PolynomialMod2>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<PolynomialMod2>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<PolynomialMod2>;
+CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf<PolynomialMod2>;
+CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing<EuclideanDomainOf<PolynomialMod2> >;
+
+//! GF(2^n) with Polynomial Basis
+class CRYPTOPP_DLL GF2NP : public QuotientRing<EuclideanDomainOf<PolynomialMod2> >
+{
+public:
+ GF2NP(const PolynomialMod2 &modulus);
+
+ virtual GF2NP * Clone() const {return new GF2NP(*this);}
+ virtual void DEREncode(BufferedTransformation &bt) const
+ {assert(false);} // no ASN.1 syntax yet for general polynomial basis
+
+ void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
+ void BERDecodeElement(BufferedTransformation &in, Element &a) const;
+
+ bool Equal(const Element &a, const Element &b) const
+ {assert(a.Degree() < m_modulus.Degree() && b.Degree() < m_modulus.Degree()); return a.Equals(b);}
+
+ bool IsUnit(const Element &a) const
+ {assert(a.Degree() < m_modulus.Degree()); return !!a;}
+
+ unsigned int MaxElementBitLength() const
+ {return m;}
+
+ unsigned int MaxElementByteLength() const
+ {return (unsigned int)BitsToBytes(MaxElementBitLength());}
+
+ Element SquareRoot(const Element &a) const;
+
+ Element HalfTrace(const Element &a) const;
+
+ // returns z such that z^2 + z == a
+ Element SolveQuadraticEquation(const Element &a) const;
+
+protected:
+ unsigned int m;
+};
+
+//! GF(2^n) with Trinomial Basis
+class CRYPTOPP_DLL GF2NT : public GF2NP
+{
+public:
+ // polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
+ GF2NT(unsigned int t0, unsigned int t1, unsigned int t2);
+
+ GF2NP * Clone() const {return new GF2NT(*this);}
+ void DEREncode(BufferedTransformation &bt) const;
+
+ const Element& Multiply(const Element &a, const Element &b) const;
+
+ const Element& Square(const Element &a) const
+ {return Reduced(a.Squared());}
+
+ const Element& MultiplicativeInverse(const Element &a) const;
+
+private:
+ const Element& Reduced(const Element &a) const;
+
+ unsigned int t0, t1;
+ mutable PolynomialMod2 result;
+};
+
+//! GF(2^n) with Pentanomial Basis
+class CRYPTOPP_DLL GF2NPP : public GF2NP
+{
+public:
+ // polynomial modulus = x^t0 + x^t1 + x^t2 + x^t3 + x^t4, t0 > t1 > t2 > t3 > t4
+ GF2NPP(unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4)
+ : GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t0(t0), t1(t1), t2(t2), t3(t3) {}
+
+ GF2NP * Clone() const {return new GF2NPP(*this);}
+ void DEREncode(BufferedTransformation &bt) const;
+
+private:
+ unsigned int t0, t1, t2, t3;
+};
+
+// construct new GF2NP from the ASN.1 sequence Characteristic-two
+CRYPTOPP_DLL GF2NP * CRYPTOPP_API BERDecodeGF2NP(BufferedTransformation &bt);
+
+NAMESPACE_END
+
+#ifndef __BORLANDC__
+NAMESPACE_BEGIN(std)
+template<> inline void swap(CryptoPP::PolynomialMod2 &a, CryptoPP::PolynomialMod2 &b)
+{
+ a.swap(b);
+}
+NAMESPACE_END
+#endif
+
+#endif
diff --git a/lib/cryptopp/gfpcrypt.cpp b/lib/cryptopp/gfpcrypt.cpp
new file mode 100644
index 000000000..e293fc598
--- /dev/null
+++ b/lib/cryptopp/gfpcrypt.cpp
@@ -0,0 +1,273 @@
+// dsa.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "gfpcrypt.h"
+#include "asn.h"
+#include "oids.h"
+#include "nbtheory.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void TestInstantiations_gfpcrypt()
+{
+ GDSA<SHA>::Signer test;
+ GDSA<SHA>::Verifier test1;
+ DSA::Signer test5(NullRNG(), 100);
+ DSA::Signer test2(test5);
+ NR<SHA>::Signer test3;
+ NR<SHA>::Verifier test4;
+ DLIES<>::Encryptor test6;
+ DLIES<>::Decryptor test7;
+}
+
+void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ Integer p, q, g;
+
+ if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
+ {
+ q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
+ Initialize(p, q, g);
+ }
+ else
+ {
+ int modulusSize = 1024, defaultSubgroupOrderSize;
+ alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
+
+ switch (modulusSize)
+ {
+ case 1024:
+ defaultSubgroupOrderSize = 160;
+ break;
+ case 2048:
+ defaultSubgroupOrderSize = 224;
+ break;
+ case 3072:
+ defaultSubgroupOrderSize = 256;
+ break;
+ default:
+ throw InvalidArgument("DSA: not a valid prime length");
+ }
+
+ DL_GroupParameters_GFP::GenerateRandom(rng, CombinedNameValuePairs(alg, MakeParameters(Name::SubgroupOrderSize(), defaultSubgroupOrderSize, false)));
+ }
+}
+
+bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level);
+ int pSize = GetModulus().BitCount(), qSize = GetSubgroupOrder().BitCount();
+ pass = pass && ((pSize==1024 && qSize==160) || (pSize==2048 && qSize==224) || (pSize==2048 && qSize==256) || (pSize==3072 && qSize==256));
+ return pass;
+}
+
+void DL_SignatureMessageEncodingMethod_DSA::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ assert(recoverableMessageLength == 0);
+ assert(hashIdentifier.second == 0);
+ const size_t representativeByteLength = BitsToBytes(representativeBitLength);
+ const size_t digestSize = hash.DigestSize();
+ const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
+
+ memset(representative, 0, paddingLength);
+ hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
+
+ if (digestSize*8 > representativeBitLength)
+ {
+ Integer h(representative, representativeByteLength);
+ h >>= representativeByteLength*8 - representativeBitLength;
+ h.Encode(representative, representativeByteLength);
+ }
+}
+
+void DL_SignatureMessageEncodingMethod_NR::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ assert(recoverableMessageLength == 0);
+ assert(hashIdentifier.second == 0);
+ const size_t representativeByteLength = BitsToBytes(representativeBitLength);
+ const size_t digestSize = hash.DigestSize();
+ const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
+
+ memset(representative, 0, paddingLength);
+ hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
+
+ if (digestSize*8 >= representativeBitLength)
+ {
+ Integer h(representative, representativeByteLength);
+ h >>= representativeByteLength*8 - representativeBitLength + 1;
+ h.Encode(representative, representativeByteLength);
+ }
+}
+
+bool DL_GroupParameters_IntegerBased::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
+{
+ const Integer &p = GetModulus(), &q = GetSubgroupOrder();
+
+ bool pass = true;
+ pass = pass && p > Integer::One() && p.IsOdd();
+ pass = pass && q > Integer::One() && q.IsOdd();
+
+ if (level >= 1)
+ pass = pass && GetCofactor() > Integer::One() && GetGroupOrder() % q == Integer::Zero();
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, q, level-2) && VerifyPrime(rng, p, level-2);
+
+ return pass;
+}
+
+bool DL_GroupParameters_IntegerBased::ValidateElement(unsigned int level, const Integer &g, const DL_FixedBasePrecomputation<Integer> *gpc) const
+{
+ const Integer &p = GetModulus(), &q = GetSubgroupOrder();
+
+ bool pass = true;
+ pass = pass && GetFieldType() == 1 ? g.IsPositive() : g.NotNegative();
+ pass = pass && g < p && !IsIdentity(g);
+
+ if (level >= 1)
+ {
+ if (gpc)
+ pass = pass && gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g;
+ }
+ if (level >= 2)
+ {
+ if (GetFieldType() == 2)
+ pass = pass && Jacobi(g*g-4, p)==-1;
+
+ // verifying that Lucas((p+1)/2, w, p)==2 is omitted because it's too costly
+ // and at most 1 bit is leaked if it's false
+ bool fullValidate = (GetFieldType() == 2 && level >= 3) || !FastSubgroupCheckAvailable();
+
+ if (fullValidate && pass)
+ {
+ Integer gp = gpc ? gpc->Exponentiate(GetGroupPrecomputation(), q) : ExponentiateElement(g, q);
+ pass = pass && IsIdentity(gp);
+ }
+ else if (GetFieldType() == 1)
+ pass = pass && Jacobi(g, p) == 1;
+ }
+
+ return pass;
+}
+
+void DL_GroupParameters_IntegerBased::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ Integer p, q, g;
+
+ if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
+ {
+ q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
+ }
+ else
+ {
+ int modulusSize, subgroupOrderSize;
+
+ if (!alg.GetIntValue("ModulusSize", modulusSize))
+ modulusSize = alg.GetIntValueWithDefault("KeySize", 2048);
+
+ if (!alg.GetIntValue("SubgroupOrderSize", subgroupOrderSize))
+ subgroupOrderSize = GetDefaultSubgroupOrderSize(modulusSize);
+
+ PrimeAndGenerator pg;
+ pg.Generate(GetFieldType() == 1 ? 1 : -1, rng, modulusSize, subgroupOrderSize);
+ p = pg.Prime();
+ q = pg.SubPrime();
+ g = pg.Generator();
+ }
+
+ Initialize(p, q, g);
+}
+
+Integer DL_GroupParameters_IntegerBased::DecodeElement(const byte *encoded, bool checkForGroupMembership) const
+{
+ Integer g(encoded, GetModulus().ByteCount());
+ if (!ValidateElement(1, g, NULL))
+ throw DL_BadElement();
+ return g;
+}
+
+void DL_GroupParameters_IntegerBased::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder parameters(bt);
+ Integer p(parameters);
+ Integer q(parameters);
+ Integer g;
+ if (parameters.EndReached())
+ {
+ g = q;
+ q = ComputeGroupOrder(p) / 2;
+ }
+ else
+ g.BERDecode(parameters);
+ parameters.MessageEnd();
+
+ SetModulusAndSubgroupGenerator(p, g);
+ SetSubgroupOrder(q);
+}
+
+void DL_GroupParameters_IntegerBased::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder parameters(bt);
+ GetModulus().DEREncode(parameters);
+ m_q.DEREncode(parameters);
+ GetSubgroupGenerator().DEREncode(parameters);
+ parameters.MessageEnd();
+}
+
+bool DL_GroupParameters_IntegerBased::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper<DL_GroupParameters<Element> >(this, name, valueType, pValue)
+ CRYPTOPP_GET_FUNCTION_ENTRY(Modulus);
+}
+
+void DL_GroupParameters_IntegerBased::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY2(Modulus, SubgroupGenerator)
+ CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder)
+ ;
+}
+
+OID DL_GroupParameters_IntegerBased::GetAlgorithmID() const
+{
+ return ASN1::id_dsa();
+}
+
+void DL_GroupParameters_GFP::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
+{
+ ModularArithmetic ma(GetModulus());
+ ma.SimultaneousExponentiate(results, base, exponents, exponentsCount);
+}
+
+DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::MultiplyElements(const Element &a, const Element &b) const
+{
+ return a_times_b_mod_c(a, b, GetModulus());
+}
+
+DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
+{
+ ModularArithmetic ma(GetModulus());
+ return ma.CascadeExponentiate(element1, exponent1, element2, exponent2);
+}
+
+Integer DL_GroupParameters_IntegerBased::GetMaxExponent() const
+{
+ return STDMIN(GetSubgroupOrder()-1, Integer::Power2(2*DiscreteLogWorkFactor(GetFieldType()*GetModulus().BitCount())));
+}
+
+unsigned int DL_GroupParameters_IntegerBased::GetDefaultSubgroupOrderSize(unsigned int modulusSize) const
+{
+ return 2*DiscreteLogWorkFactor(GetFieldType()*modulusSize);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/gfpcrypt.h b/lib/cryptopp/gfpcrypt.h
new file mode 100644
index 000000000..7af993fb3
--- /dev/null
+++ b/lib/cryptopp/gfpcrypt.h
@@ -0,0 +1,528 @@
+#ifndef CRYPTOPP_GFPCRYPT_H
+#define CRYPTOPP_GFPCRYPT_H
+
+/** \file
+ Implementation of schemes based on DL over GF(p)
+*/
+
+#include "pubkey.h"
+#include "modexppc.h"
+#include "sha.h"
+#include "algparam.h"
+#include "asn.h"
+#include "smartptr.h"
+#include "hmac.h"
+
+#include <limits.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>;
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial<DL_GroupParameters<Integer> >
+{
+ typedef DL_GroupParameters_IntegerBased ThisClass;
+
+public:
+ void Initialize(const DL_GroupParameters_IntegerBased &params)
+ {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
+ void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
+ {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
+ void Initialize(const Integer &p, const Integer &g)
+ {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
+ void Initialize(const Integer &p, const Integer &q, const Integer &g)
+ {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
+
+ // ASN1Object interface
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ // GeneratibleCryptoMaterial interface
+ /*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ // DL_GroupParameters
+ const Integer & GetSubgroupOrder() const {return m_q;}
+ Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
+ bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
+ bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
+ bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
+ void EncodeElement(bool reversible, const Element &element, byte *encoded) const
+ {element.Encode(encoded, GetModulus().ByteCount());}
+ unsigned int GetEncodedElementSize(bool reversible) const {return GetModulus().ByteCount();}
+ Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
+ Integer ConvertElementToInteger(const Element &element) const
+ {return element;}
+ Integer GetMaxExponent() const;
+ static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
+
+ OID GetAlgorithmID() const;
+
+ virtual const Integer & GetModulus() const =0;
+ virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
+
+ void SetSubgroupOrder(const Integer &q)
+ {m_q = q; ParametersChanged();}
+
+protected:
+ Integer ComputeGroupOrder(const Integer &modulus) const
+ {return modulus-(GetFieldType() == 1 ? 1 : -1);}
+
+ // GF(p) = 1, GF(p^2) = 2
+ virtual int GetFieldType() const =0;
+ virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
+
+private:
+ Integer m_q;
+};
+
+//! _
+template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element> >
+class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl<GROUP_PRECOMP, BASE_PRECOMP, DL_GroupParameters_IntegerBased>
+{
+ typedef DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> ThisClass;
+
+public:
+ typedef typename GROUP_PRECOMP::Element Element;
+
+ // GeneratibleCryptoMaterial interface
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();}
+
+ void AssignFrom(const NameValuePairs &source)
+ {AssignFromHelper<DL_GroupParameters_IntegerBased>(this, source);}
+
+ // DL_GroupParameters
+ const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
+ DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
+
+ // IntegerGroupParameters
+ const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();}
+ const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());}
+
+ void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) // these have to be set together
+ {this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();}
+
+ // non-inherited
+ bool operator==(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
+ {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();}
+ bool operator!=(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
+ {return !operator==(rhs);}
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>;
+
+//! GF(p) group parameters
+class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>
+{
+public:
+ // DL_GroupParameters
+ bool IsIdentity(const Integer &element) const {return element == Integer::One();}
+ void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
+
+ // NameValuePairs interface
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
+ }
+
+ // used by MQV
+ Element MultiplyElements(const Element &a, const Element &b) const;
+ Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
+
+protected:
+ int GetFieldType() const {return 1;}
+};
+
+//! GF(p) group parameters that default to same primes
+class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP
+{
+public:
+ typedef NoCofactorMultiplication DefaultCofactorOption;
+
+protected:
+ unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
+};
+
+//! GDSA algorithm
+template <class T>
+class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T>
+{
+public:
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";}
+
+ void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
+ {
+ const Integer &q = params.GetSubgroupOrder();
+ r %= q;
+ Integer kInv = k.InverseMod(q);
+ s = (kInv * (x*r + e)) % q;
+ assert(!!r && !!s);
+ }
+
+ bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
+ {
+ const Integer &q = params.GetSubgroupOrder();
+ if (r>=q || r<1 || s>=q || s<1)
+ return false;
+
+ Integer w = s.InverseMod(q);
+ Integer u1 = (e * w) % q;
+ Integer u2 = (r * w) % q;
+ // verify r == (g^u1 * y^u2 mod p) mod q
+ return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
+ }
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>;
+
+//! NR algorithm
+template <class T>
+class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T>
+{
+public:
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";}
+
+ void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
+ {
+ const Integer &q = params.GetSubgroupOrder();
+ r = (r + e) % q;
+ s = (k - x*r) % q;
+ assert(!!r);
+ }
+
+ bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
+ {
+ const Integer &q = params.GetSubgroupOrder();
+ if (r>=q || r<1 || s>=q)
+ return false;
+
+ // check r == (m_g^s * m_y^r + m) mod m_q
+ return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
+ }
+};
+
+/*! DSA public key format is defined in 7.3.3 of RFC 2459. The
+ private key format is defined in 12.9 of PKCS #11 v2.10. */
+template <class GP>
+class DL_PublicKey_GFP : public DL_PublicKeyImpl<GP>
+{
+public:
+ void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &y)
+ {this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);}
+ void Initialize(const Integer &p, const Integer &g, const Integer &y)
+ {this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);}
+ void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
+ {this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);}
+
+ // X509PublicKey
+ void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
+ {this->SetPublicElement(Integer(bt));}
+ void DEREncodePublicKey(BufferedTransformation &bt) const
+ {this->GetPublicElement().DEREncode(bt);}
+};
+
+//! DL private key (in GF(p) groups)
+template <class GP>
+class DL_PrivateKey_GFP : public DL_PrivateKeyImpl<GP>
+{
+public:
+ void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
+ {this->GenerateRandomWithKeySize(rng, modulusBits);}
+ void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
+ {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
+ void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
+ {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
+ void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &x)
+ {this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);}
+ void Initialize(const Integer &p, const Integer &g, const Integer &x)
+ {this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);}
+ void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
+ {this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);}
+};
+
+//! DL signing/verification keys (in GF(p) groups)
+struct DL_SignatureKeys_GFP
+{
+ typedef DL_GroupParameters_GFP GroupParameters;
+ typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
+ typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
+};
+
+//! DL encryption/decryption keys (in GF(p) groups)
+struct DL_CryptoKeys_GFP
+{
+ typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters;
+ typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
+ typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
+};
+
+//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
+template <class BASE>
+class DL_PublicKey_GFP_OldFormat : public BASE
+{
+public:
+ void BERDecode(BufferedTransformation &bt)
+ {
+ BERSequenceDecoder seq(bt);
+ Integer v1(seq);
+ Integer v2(seq);
+ Integer v3(seq);
+
+ if (seq.EndReached())
+ {
+ this->AccessGroupParameters().Initialize(v1, v1/2, v2);
+ this->SetPublicElement(v3);
+ }
+ else
+ {
+ Integer v4(seq);
+ this->AccessGroupParameters().Initialize(v1, v2, v3);
+ this->SetPublicElement(v4);
+ }
+
+ seq.MessageEnd();
+ }
+
+ void DEREncode(BufferedTransformation &bt) const
+ {
+ DERSequenceEncoder seq(bt);
+ this->GetGroupParameters().GetModulus().DEREncode(seq);
+ if (this->GetGroupParameters().GetCofactor() != 2)
+ this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
+ this->GetGroupParameters().GetGenerator().DEREncode(seq);
+ this->GetPublicElement().DEREncode(seq);
+ seq.MessageEnd();
+ }
+};
+
+//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
+template <class BASE>
+class DL_PrivateKey_GFP_OldFormat : public BASE
+{
+public:
+ void BERDecode(BufferedTransformation &bt)
+ {
+ BERSequenceDecoder seq(bt);
+ Integer v1(seq);
+ Integer v2(seq);
+ Integer v3(seq);
+ Integer v4(seq);
+
+ if (seq.EndReached())
+ {
+ this->AccessGroupParameters().Initialize(v1, v1/2, v2);
+ this->SetPrivateExponent(v4 % (v1/2)); // some old keys may have x >= q
+ }
+ else
+ {
+ Integer v5(seq);
+ this->AccessGroupParameters().Initialize(v1, v2, v3);
+ this->SetPrivateExponent(v5);
+ }
+
+ seq.MessageEnd();
+ }
+
+ void DEREncode(BufferedTransformation &bt) const
+ {
+ DERSequenceEncoder seq(bt);
+ this->GetGroupParameters().GetModulus().DEREncode(seq);
+ if (this->GetGroupParameters().GetCofactor() != 2)
+ this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
+ this->GetGroupParameters().GetGenerator().DEREncode(seq);
+ this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq);
+ this->GetPrivateExponent().DEREncode(seq);
+ seq.MessageEnd();
+ }
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/sig.html#DSA-1363">DSA-1363</a>
+template <class H>
+struct GDSA : public DL_SS<
+ DL_SignatureKeys_GFP,
+ DL_Algorithm_GDSA<Integer>,
+ DL_SignatureMessageEncodingMethod_DSA,
+ H>
+{
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/sig.html#NR">NR</a>
+template <class H>
+struct NR : public DL_SS<
+ DL_SignatureKeys_GFP,
+ DL_Algorithm_NR<Integer>,
+ DL_SignatureMessageEncodingMethod_NR,
+ H>
+{
+};
+
+//! DSA group parameters, these are GF(p) group parameters that are allowed by the DSA standard
+class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP
+{
+public:
+ /*! also checks that the lengths of p and q are allowed by the DSA standard */
+ bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
+ /*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */
+ /*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+
+ static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
+ {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
+
+ enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
+};
+
+template <class H>
+class DSA2;
+
+//! DSA keys
+struct DL_Keys_DSA
+{
+ typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
+ typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> > PrivateKey;
+};
+
+//! <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>, as specified in FIPS 186-3
+// class named DSA2 instead of DSA for backwards compatibility (DSA was a non-template class)
+template <class H>
+class DSA2 : public DL_SS<
+ DL_Keys_DSA,
+ DL_Algorithm_GDSA<Integer>,
+ DL_SignatureMessageEncodingMethod_DSA,
+ H,
+ DSA2<H> >
+{
+public:
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();}
+};
+
+//! DSA with SHA-1, typedef'd for backwards compatibility
+typedef DSA2<SHA> DSA;
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>;
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> >;
+
+//! the XOR encryption method, for use with DL-based cryptosystems
+template <class MAC, bool DHAES_MODE>
+class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm
+{
+public:
+ bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
+ size_t GetSymmetricKeyLength(size_t plaintextLength) const
+ {return plaintextLength + MAC::DEFAULT_KEYLENGTH;}
+ size_t GetSymmetricCiphertextLength(size_t plaintextLength) const
+ {return plaintextLength + MAC::DIGESTSIZE;}
+ size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const
+ {return (unsigned int)SaturatingSubtract(ciphertextLength, (unsigned int)MAC::DIGESTSIZE);}
+ void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
+ {
+ const byte *cipherKey, *macKey;
+ if (DHAES_MODE)
+ {
+ macKey = key;
+ cipherKey = key + MAC::DEFAULT_KEYLENGTH;
+ }
+ else
+ {
+ cipherKey = key;
+ macKey = key + plaintextLength;
+ }
+
+ ConstByteArrayParameter encodingParameters;
+ parameters.GetValue(Name::EncodingParameters(), encodingParameters);
+
+ xorbuf(ciphertext, plaintext, cipherKey, plaintextLength);
+ MAC mac(macKey);
+ mac.Update(ciphertext, plaintextLength);
+ mac.Update(encodingParameters.begin(), encodingParameters.size());
+ if (DHAES_MODE)
+ {
+ byte L[8] = {0,0,0,0};
+ PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
+ mac.Update(L, 8);
+ }
+ mac.Final(ciphertext + plaintextLength);
+ }
+ DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
+ {
+ size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength);
+ const byte *cipherKey, *macKey;
+ if (DHAES_MODE)
+ {
+ macKey = key;
+ cipherKey = key + MAC::DEFAULT_KEYLENGTH;
+ }
+ else
+ {
+ cipherKey = key;
+ macKey = key + plaintextLength;
+ }
+
+ ConstByteArrayParameter encodingParameters;
+ parameters.GetValue(Name::EncodingParameters(), encodingParameters);
+
+ MAC mac(macKey);
+ mac.Update(ciphertext, plaintextLength);
+ mac.Update(encodingParameters.begin(), encodingParameters.size());
+ if (DHAES_MODE)
+ {
+ byte L[8] = {0,0,0,0};
+ PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
+ mac.Update(L, 8);
+ }
+ if (!mac.Verify(ciphertext + plaintextLength))
+ return DecodingResult();
+
+ xorbuf(plaintext, ciphertext, cipherKey, plaintextLength);
+ return DecodingResult(plaintextLength);
+ }
+};
+
+//! _
+template <class T, bool DHAES_MODE, class KDF>
+class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T>
+{
+public:
+ bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;}
+ void Derive(const DL_GroupParameters<T> &params, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &parameters) const
+ {
+ SecByteBlock agreedSecret;
+ if (DHAES_MODE)
+ {
+ agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false));
+ params.EncodeElement(true, ephemeralPublicKey, agreedSecret);
+ params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true));
+ }
+ else
+ {
+ agreedSecret.New(params.GetEncodedElementSize(false));
+ params.EncodeElement(false, agreedElement, agreedSecret);
+ }
+
+ ConstByteArrayParameter derivationParameters;
+ parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters);
+ KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size());
+ }
+};
+
+//! Discrete Log Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#DLIES">DLIES</a>
+template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
+struct DLIES
+ : public DL_ES<
+ DL_CryptoKeys_GFP,
+ DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
+ DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
+ DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
+ DLIES<> >
+{
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/gzip.h b/lib/cryptopp/gzip.h
new file mode 100644
index 000000000..f3148ad71
--- /dev/null
+++ b/lib/cryptopp/gzip.h
@@ -0,0 +1,65 @@
+#ifndef CRYPTOPP_GZIP_H
+#define CRYPTOPP_GZIP_H
+
+#include "zdeflate.h"
+#include "zinflate.h"
+#include "crc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// GZIP Compression (RFC 1952)
+class Gzip : public Deflator
+{
+public:
+ Gzip(BufferedTransformation *attachment=NULL, unsigned int deflateLevel=DEFAULT_DEFLATE_LEVEL, unsigned int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true)
+ : Deflator(attachment, deflateLevel, log2WindowSize, detectUncompressible) {}
+ Gzip(const NameValuePairs &parameters, BufferedTransformation *attachment=NULL)
+ : Deflator(parameters, attachment) {}
+
+protected:
+ enum {MAGIC1=0x1f, MAGIC2=0x8b, // flags for the header
+ DEFLATED=8, FAST=4, SLOW=2};
+
+ void WritePrestreamHeader();
+ void ProcessUncompressedData(const byte *string, size_t length);
+ void WritePoststreamTail();
+
+ word32 m_totalLen;
+ CRC32 m_crc;
+};
+
+/// GZIP Decompression (RFC 1952)
+class Gunzip : public Inflator
+{
+public:
+ typedef Inflator::Err Err;
+ class HeaderErr : public Err {public: HeaderErr() : Err(INVALID_DATA_FORMAT, "Gunzip: header decoding error") {}};
+ class TailErr : public Err {public: TailErr() : Err(INVALID_DATA_FORMAT, "Gunzip: tail too short") {}};
+ class CrcErr : public Err {public: CrcErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: CRC check error") {}};
+ class LengthErr : public Err {public: LengthErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: length check error") {}};
+
+ /*! \param repeat decompress multiple compressed streams in series
+ \param autoSignalPropagation 0 to turn off MessageEnd signal
+ */
+ Gunzip(BufferedTransformation *attachment = NULL, bool repeat = false, int autoSignalPropagation = -1);
+
+protected:
+ enum {MAGIC1=0x1f, MAGIC2=0x8b, // flags for the header
+ DEFLATED=8};
+
+ enum FLAG_MASKS {
+ CONTINUED=2, EXTRA_FIELDS=4, FILENAME=8, COMMENTS=16, ENCRYPTED=32};
+
+ unsigned int MaxPrestreamHeaderSize() const {return 1024;}
+ void ProcessPrestreamHeader();
+ void ProcessDecompressedData(const byte *string, size_t length);
+ unsigned int MaxPoststreamTailSize() const {return 8;}
+ void ProcessPoststreamTail();
+
+ word32 m_length;
+ CRC32 m_crc;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/hex.cpp b/lib/cryptopp/hex.cpp
new file mode 100644
index 000000000..5731df550
--- /dev/null
+++ b/lib/cryptopp/hex.cpp
@@ -0,0 +1,44 @@
+// hex.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "hex.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const byte s_vecUpper[] = "0123456789ABCDEF";
+static const byte s_vecLower[] = "0123456789abcdef";
+
+void HexEncoder::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true);
+ m_filter->Initialize(CombinedNameValuePairs(
+ parameters,
+ MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 4, true)));
+}
+
+void HexDecoder::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs(
+ parameters,
+ MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 4, true)));
+}
+
+const int *HexDecoder::GetDefaultDecodingLookupArray()
+{
+ static volatile bool s_initialized = false;
+ static int s_array[256];
+
+ if (!s_initialized)
+ {
+ InitializeDecodingLookupArray(s_array, s_vecUpper, 16, true);
+ s_initialized = true;
+ }
+ return s_array;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/hex.h b/lib/cryptopp/hex.h
new file mode 100644
index 000000000..006914c5a
--- /dev/null
+++ b/lib/cryptopp/hex.h
@@ -0,0 +1,36 @@
+#ifndef CRYPTOPP_HEX_H
+#define CRYPTOPP_HEX_H
+
+#include "basecode.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Converts given data to base 16
+class CRYPTOPP_DLL HexEncoder : public SimpleProxyFilter
+{
+public:
+ HexEncoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
+ : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
+ {
+ IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator)));
+ }
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+};
+
+//! Decode base 16 data back to bytes
+class CRYPTOPP_DLL HexDecoder : public BaseN_Decoder
+{
+public:
+ HexDecoder(BufferedTransformation *attachment = NULL)
+ : BaseN_Decoder(GetDefaultDecodingLookupArray(), 4, attachment) {}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+
+private:
+ static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/hmac.cpp b/lib/cryptopp/hmac.cpp
new file mode 100644
index 000000000..d4a649c08
--- /dev/null
+++ b/lib/cryptopp/hmac.cpp
@@ -0,0 +1,86 @@
+// hmac.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "hmac.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void HMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &)
+{
+ AssertValidKeyLength(keylength);
+
+ Restart();
+
+ HashTransformation &hash = AccessHash();
+ unsigned int blockSize = hash.BlockSize();
+
+ if (!blockSize)
+ throw InvalidArgument("HMAC: can only be used with a block-based hash function");
+
+ m_buf.resize(2*AccessHash().BlockSize() + AccessHash().DigestSize());
+
+ if (keylength <= blockSize)
+ memcpy(AccessIpad(), userKey, keylength);
+ else
+ {
+ AccessHash().CalculateDigest(AccessIpad(), userKey, keylength);
+ keylength = hash.DigestSize();
+ }
+
+ assert(keylength <= blockSize);
+ memset(AccessIpad()+keylength, 0, blockSize-keylength);
+
+ for (unsigned int i=0; i<blockSize; i++)
+ {
+ AccessOpad()[i] = AccessIpad()[i] ^ 0x5c;
+ AccessIpad()[i] ^= 0x36;
+ }
+}
+
+void HMAC_Base::KeyInnerHash()
+{
+ assert(!m_innerHashKeyed);
+ HashTransformation &hash = AccessHash();
+ hash.Update(AccessIpad(), hash.BlockSize());
+ m_innerHashKeyed = true;
+}
+
+void HMAC_Base::Restart()
+{
+ if (m_innerHashKeyed)
+ {
+ AccessHash().Restart();
+ m_innerHashKeyed = false;
+ }
+}
+
+void HMAC_Base::Update(const byte *input, size_t length)
+{
+ if (!m_innerHashKeyed)
+ KeyInnerHash();
+ AccessHash().Update(input, length);
+}
+
+void HMAC_Base::TruncatedFinal(byte *mac, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ HashTransformation &hash = AccessHash();
+
+ if (!m_innerHashKeyed)
+ KeyInnerHash();
+ hash.Final(AccessInnerHash());
+
+ hash.Update(AccessOpad(), hash.BlockSize());
+ hash.Update(AccessInnerHash(), hash.DigestSize());
+ hash.TruncatedFinal(mac, size);
+
+ m_innerHashKeyed = false;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/hmac.h b/lib/cryptopp/hmac.h
new file mode 100644
index 000000000..62db5ef33
--- /dev/null
+++ b/lib/cryptopp/hmac.h
@@ -0,0 +1,61 @@
+// hmac.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_HMAC_H
+#define CRYPTOPP_HMAC_H
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HMAC_Base : public VariableKeyLength<16, 0, INT_MAX>, public MessageAuthenticationCode
+{
+public:
+ HMAC_Base() : m_innerHashKeyed(false) {}
+ void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &params);
+
+ void Restart();
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *mac, size_t size);
+ unsigned int OptimalBlockSize() const {return const_cast<HMAC_Base*>(this)->AccessHash().OptimalBlockSize();}
+ unsigned int DigestSize() const {return const_cast<HMAC_Base*>(this)->AccessHash().DigestSize();}
+
+protected:
+ virtual HashTransformation & AccessHash() =0;
+ byte * AccessIpad() {return m_buf;}
+ byte * AccessOpad() {return m_buf + AccessHash().BlockSize();}
+ byte * AccessInnerHash() {return m_buf + 2*AccessHash().BlockSize();}
+
+private:
+ void KeyInnerHash();
+
+ SecByteBlock m_buf;
+ bool m_innerHashKeyed;
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/mac.html#HMAC">HMAC</a>
+/*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */
+template <class T>
+class HMAC : public MessageAuthenticationCodeImpl<HMAC_Base, HMAC<T> >
+{
+public:
+ CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE)
+ CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE)
+
+ HMAC() {}
+ HMAC(const byte *key, size_t length=HMAC_Base::DEFAULT_KEYLENGTH)
+ {this->SetKey(key, length);}
+
+ static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";}
+ std::string AlgorithmName() const {return std::string("HMAC(") + m_hash.AlgorithmName() + ")";}
+
+private:
+ HashTransformation & AccessHash() {return m_hash;}
+
+ T m_hash;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/hrtimer.cpp b/lib/cryptopp/hrtimer.cpp
new file mode 100644
index 000000000..6871a15dc
--- /dev/null
+++ b/lib/cryptopp/hrtimer.cpp
@@ -0,0 +1,138 @@
+// hrtimer.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "hrtimer.h"
+#include "misc.h"
+#include <stddef.h> // for NULL
+#include <time.h>
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE)
+#include <windows.h>
+#elif defined(CRYPTOPP_UNIX_AVAILABLE)
+#include <sys/time.h>
+#include <sys/times.h>
+#include <unistd.h>
+#endif
+
+#include <assert.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifndef CRYPTOPP_IMPORTS
+
+double TimerBase::ConvertTo(TimerWord t, Unit unit)
+{
+ static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
+
+ assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0]));
+ return (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond();
+}
+
+void TimerBase::StartTimer()
+{
+ m_last = m_start = GetCurrentTimerValue();
+ m_started = true;
+}
+
+double TimerBase::ElapsedTimeAsDouble()
+{
+ if (m_stuckAtZero)
+ return 0;
+
+ if (m_started)
+ {
+ TimerWord now = GetCurrentTimerValue();
+ if (m_last < now) // protect against OS bugs where time goes backwards
+ m_last = now;
+ return ConvertTo(m_last - m_start, m_timerUnit);
+ }
+
+ StartTimer();
+ return 0;
+}
+
+unsigned long TimerBase::ElapsedTime()
+{
+ double elapsed = ElapsedTimeAsDouble();
+ assert(elapsed <= ULONG_MAX);
+ return (unsigned long)elapsed;
+}
+
+TimerWord Timer::GetCurrentTimerValue()
+{
+#if defined(CRYPTOPP_WIN32_AVAILABLE)
+ LARGE_INTEGER now;
+ if (!QueryPerformanceCounter(&now))
+ throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
+ return now.QuadPart;
+#elif defined(CRYPTOPP_UNIX_AVAILABLE)
+ timeval now;
+ gettimeofday(&now, NULL);
+ return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
+#else
+ return clock();
+#endif
+}
+
+TimerWord Timer::TicksPerSecond()
+{
+#if defined(CRYPTOPP_WIN32_AVAILABLE)
+ static LARGE_INTEGER freq = {0};
+ if (freq.QuadPart == 0)
+ {
+ if (!QueryPerformanceFrequency(&freq))
+ throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
+ }
+ return freq.QuadPart;
+#elif defined(CRYPTOPP_UNIX_AVAILABLE)
+ return 1000000;
+#else
+ return CLOCKS_PER_SEC;
+#endif
+}
+
+#endif // #ifndef CRYPTOPP_IMPORTS
+
+TimerWord ThreadUserTimer::GetCurrentTimerValue()
+{
+#if defined(CRYPTOPP_WIN32_AVAILABLE)
+ static bool getCurrentThreadImplemented = true;
+ if (getCurrentThreadImplemented)
+ {
+ FILETIME now, ignored;
+ if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
+ {
+ DWORD lastError = GetLastError();
+ if (lastError == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ getCurrentThreadImplemented = false;
+ goto GetCurrentThreadNotImplemented;
+ }
+ throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError));
+ }
+ return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32);
+ }
+GetCurrentThreadNotImplemented:
+ return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC);
+#elif defined(CRYPTOPP_UNIX_AVAILABLE)
+ tms now;
+ times(&now);
+ return now.tms_utime;
+#else
+ return clock();
+#endif
+}
+
+TimerWord ThreadUserTimer::TicksPerSecond()
+{
+#if defined(CRYPTOPP_WIN32_AVAILABLE)
+ return 10*1000*1000;
+#elif defined(CRYPTOPP_UNIX_AVAILABLE)
+ static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
+ return ticksPerSecond;
+#else
+ return CLOCKS_PER_SEC;
+#endif
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/hrtimer.h b/lib/cryptopp/hrtimer.h
new file mode 100644
index 000000000..858dbd226
--- /dev/null
+++ b/lib/cryptopp/hrtimer.h
@@ -0,0 +1,61 @@
+#ifndef CRYPTOPP_HRTIMER_H
+#define CRYPTOPP_HRTIMER_H
+
+#include "config.h"
+#ifndef HIGHRES_TIMER_AVAILABLE
+#include <time.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef HIGHRES_TIMER_AVAILABLE
+ typedef word64 TimerWord;
+#else
+ typedef clock_t TimerWord;
+#endif
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TimerBase
+{
+public:
+ enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS};
+ TimerBase(Unit unit, bool stuckAtZero) : m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false) {}
+
+ virtual TimerWord GetCurrentTimerValue() =0; // GetCurrentTime is a macro in MSVC 6.0
+ virtual TimerWord TicksPerSecond() =0; // this is not the resolution, just a conversion factor into seconds
+
+ void StartTimer();
+ double ElapsedTimeAsDouble();
+ unsigned long ElapsedTime();
+
+private:
+ double ConvertTo(TimerWord t, Unit unit);
+
+ Unit m_timerUnit; // HPUX workaround: m_unit is a system macro on HPUX
+ bool m_stuckAtZero, m_started;
+ TimerWord m_start, m_last;
+};
+
+//! measure CPU time spent executing instructions of this thread (if supported by OS)
+/*! /note This only works correctly on Windows NT or later. On Unix it reports process time, and others wall clock time.
+*/
+class ThreadUserTimer : public TimerBase
+{
+public:
+ ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
+ TimerWord GetCurrentTimerValue();
+ TimerWord TicksPerSecond();
+};
+
+//! high resolution timer
+class CRYPTOPP_DLL Timer : public TimerBase
+{
+public:
+ Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
+ TimerWord GetCurrentTimerValue();
+ TimerWord TicksPerSecond();
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/integer.cpp b/lib/cryptopp/integer.cpp
new file mode 100644
index 000000000..f07cce873
--- /dev/null
+++ b/lib/cryptopp/integer.cpp
@@ -0,0 +1,4235 @@
+// integer.cpp - written and placed in the public domain by Wei Dai
+// contains public domain code contributed by Alister Lee and Leonard Janke
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "integer.h"
+#include "modarith.h"
+#include "nbtheory.h"
+#include "asn.h"
+#include "oids.h"
+#include "words.h"
+#include "algparam.h"
+#include "pubkey.h" // for P1363_KDF2
+#include "sha.h"
+#include "cpu.h"
+
+#include <iostream>
+
+#if _MSC_VER >= 1400
+ #include <intrin.h>
+#endif
+
+#ifdef __DECCXX
+ #include <c_asm.h>
+#endif
+
+#ifdef CRYPTOPP_MSVC6_NO_PP
+ #pragma message("You do not seem to have the Visual C++ Processor Pack installed, so use of SSE2 instructions will be disabled.")
+#endif
+
+#define CRYPTOPP_INTEGER_SSE2 (CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86)
+
+NAMESPACE_BEGIN(CryptoPP)
+
+bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt)
+{
+ if (valueType != typeid(Integer))
+ return false;
+ *reinterpret_cast<Integer *>(pInteger) = *reinterpret_cast<const int *>(pInt);
+ return true;
+}
+
+inline static int Compare(const word *A, const word *B, size_t N)
+{
+ while (N--)
+ if (A[N] > B[N])
+ return 1;
+ else if (A[N] < B[N])
+ return -1;
+
+ return 0;
+}
+
+inline static int Increment(word *A, size_t N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t+B;
+ if (A[0] >= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (++A[i])
+ return 0;
+ return 1;
+}
+
+inline static int Decrement(word *A, size_t N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t-B;
+ if (A[0] <= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (A[i]--)
+ return 0;
+ return 1;
+}
+
+static void TwosComplement(word *A, size_t N)
+{
+ Decrement(A, N);
+ for (unsigned i=0; i<N; i++)
+ A[i] = ~A[i];
+}
+
+static word AtomicInverseModPower2(word A)
+{
+ assert(A%2==1);
+
+ word R=A%8;
+
+ for (unsigned i=3; i<WORD_BITS; i*=2)
+ R = R*(2-R*A);
+
+ assert(R*A==1);
+ return R;
+}
+
+// ********************************************************
+
+#if !defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) || (defined(__x86_64__) && defined(CRYPTOPP_WORD128_AVAILABLE))
+ #define Declare2Words(x) word x##0, x##1;
+ #define AssignWord(a, b) a##0 = b; a##1 = 0;
+ #define Add2WordsBy1(a, b, c) a##0 = b##0 + c; a##1 = b##1 + (a##0 < c);
+ #define LowWord(a) a##0
+ #define HighWord(a) a##1
+ #ifdef _MSC_VER
+ #define MultiplyWordsLoHi(p0, p1, a, b) p0 = _umul128(a, b, &p1);
+ #ifndef __INTEL_COMPILER
+ #define Double3Words(c, d) d##1 = __shiftleft128(d##0, d##1, 1); d##0 = __shiftleft128(c, d##0, 1); c *= 2;
+ #endif
+ #elif defined(__DECCXX)
+ #define MultiplyWordsLoHi(p0, p1, a, b) p0 = a*b; p1 = asm("umulh %a0, %a1, %v0", a, b);
+ #elif defined(__x86_64__)
+ #if defined(__SUNPRO_CC) && __SUNPRO_CC < 0x5100
+ // Sun Studio's gcc-style inline assembly is heavily bugged as of version 5.9 Patch 124864-09 2008/12/16, but this one works
+ #define MultiplyWordsLoHi(p0, p1, a, b) asm ("mulq %3" : "=a"(p0), "=d"(p1) : "a"(a), "r"(b) : "cc");
+ #else
+ #define MultiplyWordsLoHi(p0, p1, a, b) asm ("mulq %3" : "=a"(p0), "=d"(p1) : "a"(a), "g"(b) : "cc");
+ #define MulAcc(c, d, a, b) asm ("mulq %6; addq %3, %0; adcq %4, %1; adcq $0, %2;" : "+r"(c), "+r"(d##0), "+r"(d##1), "=a"(p0), "=d"(p1) : "a"(a), "g"(b) : "cc");
+ #define Double3Words(c, d) asm ("addq %0, %0; adcq %1, %1; adcq %2, %2;" : "+r"(c), "+r"(d##0), "+r"(d##1) : : "cc");
+ #define Acc2WordsBy1(a, b) asm ("addq %2, %0; adcq $0, %1;" : "+r"(a##0), "+r"(a##1) : "r"(b) : "cc");
+ #define Acc2WordsBy2(a, b) asm ("addq %2, %0; adcq %3, %1;" : "+r"(a##0), "+r"(a##1) : "r"(b##0), "r"(b##1) : "cc");
+ #define Acc3WordsBy2(c, d, e) asm ("addq %5, %0; adcq %6, %1; adcq $0, %2;" : "+r"(c), "=r"(e##0), "=r"(e##1) : "1"(d##0), "2"(d##1), "r"(e##0), "r"(e##1) : "cc");
+ #endif
+ #endif
+ #define MultiplyWords(p, a, b) MultiplyWordsLoHi(p##0, p##1, a, b)
+ #ifndef Double3Words
+ #define Double3Words(c, d) d##1 = 2*d##1 + (d##0>>(WORD_BITS-1)); d##0 = 2*d##0 + (c>>(WORD_BITS-1)); c *= 2;
+ #endif
+ #ifndef Acc2WordsBy2
+ #define Acc2WordsBy2(a, b) a##0 += b##0; a##1 += a##0 < b##0; a##1 += b##1;
+ #endif
+ #define AddWithCarry(u, a, b) {word t = a+b; u##0 = t + u##1; u##1 = (t<a) + (u##0<t);}
+ #define SubtractWithBorrow(u, a, b) {word t = a-b; u##0 = t - u##1; u##1 = (t>a) + (u##0>t);}
+ #define GetCarry(u) u##1
+ #define GetBorrow(u) u##1
+#else
+ #define Declare2Words(x) dword x;
+ #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER)
+ #define MultiplyWords(p, a, b) p = __emulu(a, b);
+ #else
+ #define MultiplyWords(p, a, b) p = (dword)a*b;
+ #endif
+ #define AssignWord(a, b) a = b;
+ #define Add2WordsBy1(a, b, c) a = b + c;
+ #define Acc2WordsBy2(a, b) a += b;
+ #define LowWord(a) word(a)
+ #define HighWord(a) word(a>>WORD_BITS)
+ #define Double3Words(c, d) d = 2*d + (c>>(WORD_BITS-1)); c *= 2;
+ #define AddWithCarry(u, a, b) u = dword(a) + b + GetCarry(u);
+ #define SubtractWithBorrow(u, a, b) u = dword(a) - b - GetBorrow(u);
+ #define GetCarry(u) HighWord(u)
+ #define GetBorrow(u) word(u>>(WORD_BITS*2-1))
+#endif
+#ifndef MulAcc
+ #define MulAcc(c, d, a, b) MultiplyWords(p, a, b); Acc2WordsBy1(p, c); c = LowWord(p); Acc2WordsBy1(d, HighWord(p));
+#endif
+#ifndef Acc2WordsBy1
+ #define Acc2WordsBy1(a, b) Add2WordsBy1(a, a, b)
+#endif
+#ifndef Acc3WordsBy2
+ #define Acc3WordsBy2(c, d, e) Acc2WordsBy1(e, c); c = LowWord(e); Add2WordsBy1(e, d, HighWord(e));
+#endif
+
+class DWord
+{
+public:
+ DWord() {}
+
+#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ explicit DWord(word low)
+ {
+ m_whole = low;
+ }
+#else
+ explicit DWord(word low)
+ {
+ m_halfs.low = low;
+ m_halfs.high = 0;
+ }
+#endif
+
+ DWord(word low, word high)
+ {
+ m_halfs.low = low;
+ m_halfs.high = high;
+ }
+
+ static DWord Multiply(word a, word b)
+ {
+ DWord r;
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ r.m_whole = (dword)a * b;
+ #elif defined(MultiplyWordsLoHi)
+ MultiplyWordsLoHi(r.m_halfs.low, r.m_halfs.high, a, b);
+ #endif
+ return r;
+ }
+
+ static DWord MultiplyAndAdd(word a, word b, word c)
+ {
+ DWord r = Multiply(a, b);
+ return r += c;
+ }
+
+ DWord & operator+=(word a)
+ {
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ m_whole = m_whole + a;
+ #else
+ m_halfs.low += a;
+ m_halfs.high += (m_halfs.low < a);
+ #endif
+ return *this;
+ }
+
+ DWord operator+(word a)
+ {
+ DWord r;
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ r.m_whole = m_whole + a;
+ #else
+ r.m_halfs.low = m_halfs.low + a;
+ r.m_halfs.high = m_halfs.high + (r.m_halfs.low < a);
+ #endif
+ return r;
+ }
+
+ DWord operator-(DWord a)
+ {
+ DWord r;
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ r.m_whole = m_whole - a.m_whole;
+ #else
+ r.m_halfs.low = m_halfs.low - a.m_halfs.low;
+ r.m_halfs.high = m_halfs.high - a.m_halfs.high - (r.m_halfs.low > m_halfs.low);
+ #endif
+ return r;
+ }
+
+ DWord operator-(word a)
+ {
+ DWord r;
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ r.m_whole = m_whole - a;
+ #else
+ r.m_halfs.low = m_halfs.low - a;
+ r.m_halfs.high = m_halfs.high - (r.m_halfs.low > m_halfs.low);
+ #endif
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ word operator/(word divisor);
+
+ word operator%(word a);
+
+ bool operator!() const
+ {
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ return !m_whole;
+ #else
+ return !m_halfs.high && !m_halfs.low;
+ #endif
+ }
+
+ word GetLowHalf() const {return m_halfs.low;}
+ word GetHighHalf() const {return m_halfs.high;}
+ word GetHighHalfAsBorrow() const {return 0-m_halfs.high;}
+
+private:
+ union
+ {
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ dword m_whole;
+ #endif
+ struct
+ {
+ #ifdef IS_LITTLE_ENDIAN
+ word low;
+ word high;
+ #else
+ word high;
+ word low;
+ #endif
+ } m_halfs;
+ };
+};
+
+class Word
+{
+public:
+ Word() {}
+
+ Word(word value)
+ {
+ m_whole = value;
+ }
+
+ Word(hword low, hword high)
+ {
+ m_whole = low | (word(high) << (WORD_BITS/2));
+ }
+
+ static Word Multiply(hword a, hword b)
+ {
+ Word r;
+ r.m_whole = (word)a * b;
+ return r;
+ }
+
+ Word operator-(Word a)
+ {
+ Word r;
+ r.m_whole = m_whole - a.m_whole;
+ return r;
+ }
+
+ Word operator-(hword a)
+ {
+ Word r;
+ r.m_whole = m_whole - a;
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ hword operator/(hword divisor)
+ {
+ return hword(m_whole / divisor);
+ }
+
+ bool operator!() const
+ {
+ return !m_whole;
+ }
+
+ word GetWhole() const {return m_whole;}
+ hword GetLowHalf() const {return hword(m_whole);}
+ hword GetHighHalf() const {return hword(m_whole>>(WORD_BITS/2));}
+ hword GetHighHalfAsBorrow() const {return 0-hword(m_whole>>(WORD_BITS/2));}
+
+private:
+ word m_whole;
+};
+
+// do a 3 word by 2 word divide, returns quotient and leaves remainder in A
+template <class S, class D>
+S DivideThreeWordsByTwo(S *A, S B0, S B1, D *dummy=NULL)
+{
+ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S
+ assert(A[2] < B1 || (A[2]==B1 && A[1] < B0));
+
+ // estimate the quotient: do a 2 S by 1 S divide
+ S Q;
+ if (S(B1+1) == 0)
+ Q = A[2];
+ else if (B1 > 0)
+ Q = D(A[1], A[2]) / S(B1+1);
+ else
+ Q = D(A[0], A[1]) / B0;
+
+ // now subtract Q*B from A
+ D p = D::Multiply(B0, Q);
+ D u = (D) A[0] - p.GetLowHalf();
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - D::Multiply(B1, Q);
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+
+ // Q <= actual quotient, so fix it
+ while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
+ {
+ u = (D) A[0] - B0;
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - B1 - u.GetHighHalfAsBorrow();
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+ Q++;
+ assert(Q); // shouldn't overflow
+ }
+
+ return Q;
+}
+
+// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1
+template <class S, class D>
+inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B)
+{
+ if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS)
+ return D(Ah.GetLowHalf(), Ah.GetHighHalf());
+ else
+ {
+ S Q[2];
+ T[0] = Al.GetLowHalf();
+ T[1] = Al.GetHighHalf();
+ T[2] = Ah.GetLowHalf();
+ T[3] = Ah.GetHighHalf();
+ Q[1] = DivideThreeWordsByTwo<S, D>(T+1, B.GetLowHalf(), B.GetHighHalf());
+ Q[0] = DivideThreeWordsByTwo<S, D>(T, B.GetLowHalf(), B.GetHighHalf());
+ return D(Q[0], Q[1]);
+ }
+}
+
+// returns quotient, which must fit in a word
+inline word DWord::operator/(word a)
+{
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ return word(m_whole / a);
+ #else
+ hword r[4];
+ return DivideFourWordsByTwo<hword, Word>(r, m_halfs.low, m_halfs.high, a).GetWhole();
+ #endif
+}
+
+inline word DWord::operator%(word a)
+{
+ #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
+ return word(m_whole % a);
+ #else
+ if (a < (word(1) << (WORD_BITS/2)))
+ {
+ hword h = hword(a);
+ word r = m_halfs.high % h;
+ r = ((m_halfs.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h;
+ return hword((hword(m_halfs.low) + (r << (WORD_BITS/2))) % h);
+ }
+ else
+ {
+ hword r[4];
+ DivideFourWordsByTwo<hword, Word>(r, m_halfs.low, m_halfs.high, a);
+ return Word(r[0], r[1]).GetWhole();
+ }
+ #endif
+}
+
+// ********************************************************
+
+// use some tricks to share assembly code between MSVC and GCC
+#if defined(__GNUC__)
+ #define AddPrologue \
+ int result; \
+ __asm__ __volatile__ \
+ ( \
+ ".intel_syntax noprefix;"
+ #define AddEpilogue \
+ ".att_syntax prefix;" \
+ : "=a" (result)\
+ : "d" (C), "a" (A), "D" (B), "c" (N) \
+ : "%esi", "memory", "cc" \
+ );\
+ return result;
+ #define MulPrologue \
+ __asm__ __volatile__ \
+ ( \
+ ".intel_syntax noprefix;" \
+ AS1( push ebx) \
+ AS2( mov ebx, edx)
+ #define MulEpilogue \
+ AS1( pop ebx) \
+ ".att_syntax prefix;" \
+ : \
+ : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B) \
+ : "%esi", "memory", "cc" \
+ );
+ #define SquPrologue MulPrologue
+ #define SquEpilogue \
+ AS1( pop ebx) \
+ ".att_syntax prefix;" \
+ : \
+ : "d" (s_maskLow16), "c" (C), "a" (A) \
+ : "%esi", "%edi", "memory", "cc" \
+ );
+ #define TopPrologue MulPrologue
+ #define TopEpilogue \
+ AS1( pop ebx) \
+ ".att_syntax prefix;" \
+ : \
+ : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B), "S" (L) \
+ : "memory", "cc" \
+ );
+#else
+ #define AddPrologue \
+ __asm push edi \
+ __asm push esi \
+ __asm mov eax, [esp+12] \
+ __asm mov edi, [esp+16]
+ #define AddEpilogue \
+ __asm pop esi \
+ __asm pop edi \
+ __asm ret 8
+#if _MSC_VER < 1300
+ #define SaveEBX __asm push ebx
+ #define RestoreEBX __asm pop ebx
+#else
+ #define SaveEBX
+ #define RestoreEBX
+#endif
+ #define SquPrologue \
+ AS2( mov eax, A) \
+ AS2( mov ecx, C) \
+ SaveEBX \
+ AS2( lea ebx, s_maskLow16)
+ #define MulPrologue \
+ AS2( mov eax, A) \
+ AS2( mov edi, B) \
+ AS2( mov ecx, C) \
+ SaveEBX \
+ AS2( lea ebx, s_maskLow16)
+ #define TopPrologue \
+ AS2( mov eax, A) \
+ AS2( mov edi, B) \
+ AS2( mov ecx, C) \
+ AS2( mov esi, L) \
+ SaveEBX \
+ AS2( lea ebx, s_maskLow16)
+ #define SquEpilogue RestoreEBX
+ #define MulEpilogue RestoreEBX
+ #define TopEpilogue RestoreEBX
+#endif
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+int Baseline_Add(size_t N, word *C, const word *A, const word *B);
+int Baseline_Sub(size_t N, word *C, const word *A, const word *B);
+}
+#elif defined(CRYPTOPP_X64_ASM_AVAILABLE) && defined(__GNUC__) && defined(CRYPTOPP_WORD128_AVAILABLE)
+int Baseline_Add(size_t N, word *C, const word *A, const word *B)
+{
+ word result;
+ __asm__ __volatile__
+ (
+ ".intel_syntax;"
+ AS1( neg %1)
+ ASJ( jz, 1, f)
+ AS2( mov %0,[%3+8*%1])
+ AS2( add %0,[%4+8*%1])
+ AS2( mov [%2+8*%1],%0)
+ ASL(0)
+ AS2( mov %0,[%3+8*%1+8])
+ AS2( adc %0,[%4+8*%1+8])
+ AS2( mov [%2+8*%1+8],%0)
+ AS2( lea %1,[%1+2])
+ ASJ( jrcxz, 1, f)
+ AS2( mov %0,[%3+8*%1])
+ AS2( adc %0,[%4+8*%1])
+ AS2( mov [%2+8*%1],%0)
+ ASJ( jmp, 0, b)
+ ASL(1)
+ AS2( mov %0, 0)
+ AS2( adc %0, %0)
+ ".att_syntax;"
+ : "=&r" (result), "+c" (N)
+ : "r" (C+N), "r" (A+N), "r" (B+N)
+ : "memory", "cc"
+ );
+ return (int)result;
+}
+
+int Baseline_Sub(size_t N, word *C, const word *A, const word *B)
+{
+ word result;
+ __asm__ __volatile__
+ (
+ ".intel_syntax;"
+ AS1( neg %1)
+ ASJ( jz, 1, f)
+ AS2( mov %0,[%3+8*%1])
+ AS2( sub %0,[%4+8*%1])
+ AS2( mov [%2+8*%1],%0)
+ ASL(0)
+ AS2( mov %0,[%3+8*%1+8])
+ AS2( sbb %0,[%4+8*%1+8])
+ AS2( mov [%2+8*%1+8],%0)
+ AS2( lea %1,[%1+2])
+ ASJ( jrcxz, 1, f)
+ AS2( mov %0,[%3+8*%1])
+ AS2( sbb %0,[%4+8*%1])
+ AS2( mov [%2+8*%1],%0)
+ ASJ( jmp, 0, b)
+ ASL(1)
+ AS2( mov %0, 0)
+ AS2( adc %0, %0)
+ ".att_syntax;"
+ : "=&r" (result), "+c" (N)
+ : "r" (C+N), "r" (A+N), "r" (B+N)
+ : "memory", "cc"
+ );
+ return (int)result;
+}
+#elif defined(CRYPTOPP_X86_ASM_AVAILABLE) && CRYPTOPP_BOOL_X86
+CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B)
+{
+ AddPrologue
+
+ // now: eax = A, edi = B, edx = C, ecx = N
+ AS2( lea eax, [eax+4*ecx])
+ AS2( lea edi, [edi+4*ecx])
+ AS2( lea edx, [edx+4*ecx])
+
+ AS1( neg ecx) // ecx is negative index
+ AS2( test ecx, 2) // this clears carry flag
+ ASJ( jz, 0, f)
+ AS2( sub ecx, 2)
+ ASJ( jmp, 1, f)
+
+ ASL(0)
+ ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero
+ AS2( mov esi,[eax+4*ecx])
+ AS2( adc esi,[edi+4*ecx])
+ AS2( mov [edx+4*ecx],esi)
+ AS2( mov esi,[eax+4*ecx+4])
+ AS2( adc esi,[edi+4*ecx+4])
+ AS2( mov [edx+4*ecx+4],esi)
+ ASL(1)
+ AS2( mov esi,[eax+4*ecx+8])
+ AS2( adc esi,[edi+4*ecx+8])
+ AS2( mov [edx+4*ecx+8],esi)
+ AS2( mov esi,[eax+4*ecx+12])
+ AS2( adc esi,[edi+4*ecx+12])
+ AS2( mov [edx+4*ecx+12],esi)
+
+ AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2
+ ASJ( jmp, 0, b)
+
+ ASL(2)
+ AS2( mov eax, 0)
+ AS1( setc al) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Sub(size_t N, word *C, const word *A, const word *B)
+{
+ AddPrologue
+
+ // now: eax = A, edi = B, edx = C, ecx = N
+ AS2( lea eax, [eax+4*ecx])
+ AS2( lea edi, [edi+4*ecx])
+ AS2( lea edx, [edx+4*ecx])
+
+ AS1( neg ecx) // ecx is negative index
+ AS2( test ecx, 2) // this clears carry flag
+ ASJ( jz, 0, f)
+ AS2( sub ecx, 2)
+ ASJ( jmp, 1, f)
+
+ ASL(0)
+ ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero
+ AS2( mov esi,[eax+4*ecx])
+ AS2( sbb esi,[edi+4*ecx])
+ AS2( mov [edx+4*ecx],esi)
+ AS2( mov esi,[eax+4*ecx+4])
+ AS2( sbb esi,[edi+4*ecx+4])
+ AS2( mov [edx+4*ecx+4],esi)
+ ASL(1)
+ AS2( mov esi,[eax+4*ecx+8])
+ AS2( sbb esi,[edi+4*ecx+8])
+ AS2( mov [edx+4*ecx+8],esi)
+ AS2( mov esi,[eax+4*ecx+12])
+ AS2( sbb esi,[edi+4*ecx+12])
+ AS2( mov [edx+4*ecx+12],esi)
+
+ AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2
+ ASJ( jmp, 0, b)
+
+ ASL(2)
+ AS2( mov eax, 0)
+ AS1( setc al) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+#if CRYPTOPP_INTEGER_SSE2
+CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Add(size_t N, word *C, const word *A, const word *B)
+{
+ AddPrologue
+
+ // now: eax = A, edi = B, edx = C, ecx = N
+ AS2( lea eax, [eax+4*ecx])
+ AS2( lea edi, [edi+4*ecx])
+ AS2( lea edx, [edx+4*ecx])
+
+ AS1( neg ecx) // ecx is negative index
+ AS2( pxor mm2, mm2)
+ ASJ( jz, 2, f)
+ AS2( test ecx, 2) // this clears carry flag
+ ASJ( jz, 0, f)
+ AS2( sub ecx, 2)
+ ASJ( jmp, 1, f)
+
+ ASL(0)
+ AS2( movd mm0, DWORD PTR [eax+4*ecx])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx])
+ AS2( paddq mm0, mm1)
+ AS2( paddq mm2, mm0)
+ AS2( movd DWORD PTR [edx+4*ecx], mm2)
+ AS2( psrlq mm2, 32)
+
+ AS2( movd mm0, DWORD PTR [eax+4*ecx+4])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx+4])
+ AS2( paddq mm0, mm1)
+ AS2( paddq mm2, mm0)
+ AS2( movd DWORD PTR [edx+4*ecx+4], mm2)
+ AS2( psrlq mm2, 32)
+
+ ASL(1)
+ AS2( movd mm0, DWORD PTR [eax+4*ecx+8])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx+8])
+ AS2( paddq mm0, mm1)
+ AS2( paddq mm2, mm0)
+ AS2( movd DWORD PTR [edx+4*ecx+8], mm2)
+ AS2( psrlq mm2, 32)
+
+ AS2( movd mm0, DWORD PTR [eax+4*ecx+12])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx+12])
+ AS2( paddq mm0, mm1)
+ AS2( paddq mm2, mm0)
+ AS2( movd DWORD PTR [edx+4*ecx+12], mm2)
+ AS2( psrlq mm2, 32)
+
+ AS2( add ecx, 4)
+ ASJ( jnz, 0, b)
+
+ ASL(2)
+ AS2( movd eax, mm2)
+ AS1( emms)
+
+ AddEpilogue
+}
+CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Sub(size_t N, word *C, const word *A, const word *B)
+{
+ AddPrologue
+
+ // now: eax = A, edi = B, edx = C, ecx = N
+ AS2( lea eax, [eax+4*ecx])
+ AS2( lea edi, [edi+4*ecx])
+ AS2( lea edx, [edx+4*ecx])
+
+ AS1( neg ecx) // ecx is negative index
+ AS2( pxor mm2, mm2)
+ ASJ( jz, 2, f)
+ AS2( test ecx, 2) // this clears carry flag
+ ASJ( jz, 0, f)
+ AS2( sub ecx, 2)
+ ASJ( jmp, 1, f)
+
+ ASL(0)
+ AS2( movd mm0, DWORD PTR [eax+4*ecx])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx])
+ AS2( psubq mm0, mm1)
+ AS2( psubq mm0, mm2)
+ AS2( movd DWORD PTR [edx+4*ecx], mm0)
+ AS2( psrlq mm0, 63)
+
+ AS2( movd mm2, DWORD PTR [eax+4*ecx+4])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx+4])
+ AS2( psubq mm2, mm1)
+ AS2( psubq mm2, mm0)
+ AS2( movd DWORD PTR [edx+4*ecx+4], mm2)
+ AS2( psrlq mm2, 63)
+
+ ASL(1)
+ AS2( movd mm0, DWORD PTR [eax+4*ecx+8])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx+8])
+ AS2( psubq mm0, mm1)
+ AS2( psubq mm0, mm2)
+ AS2( movd DWORD PTR [edx+4*ecx+8], mm0)
+ AS2( psrlq mm0, 63)
+
+ AS2( movd mm2, DWORD PTR [eax+4*ecx+12])
+ AS2( movd mm1, DWORD PTR [edi+4*ecx+12])
+ AS2( psubq mm2, mm1)
+ AS2( psubq mm2, mm0)
+ AS2( movd DWORD PTR [edx+4*ecx+12], mm2)
+ AS2( psrlq mm2, 63)
+
+ AS2( add ecx, 4)
+ ASJ( jnz, 0, b)
+
+ ASL(2)
+ AS2( movd eax, mm2)
+ AS1( emms)
+
+ AddEpilogue
+}
+#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+#else
+int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B)
+{
+ assert (N%2 == 0);
+
+ Declare2Words(u);
+ AssignWord(u, 0);
+ for (size_t i=0; i<N; i+=2)
+ {
+ AddWithCarry(u, A[i], B[i]);
+ C[i] = LowWord(u);
+ AddWithCarry(u, A[i+1], B[i+1]);
+ C[i+1] = LowWord(u);
+ }
+ return int(GetCarry(u));
+}
+
+int CRYPTOPP_FASTCALL Baseline_Sub(size_t N, word *C, const word *A, const word *B)
+{
+ assert (N%2 == 0);
+
+ Declare2Words(u);
+ AssignWord(u, 0);
+ for (size_t i=0; i<N; i+=2)
+ {
+ SubtractWithBorrow(u, A[i], B[i]);
+ C[i] = LowWord(u);
+ SubtractWithBorrow(u, A[i+1], B[i+1]);
+ C[i+1] = LowWord(u);
+ }
+ return int(GetBorrow(u));
+}
+#endif
+
+static word LinearMultiply(word *C, const word *A, word B, size_t N)
+{
+ word carry=0;
+ for(unsigned i=0; i<N; i++)
+ {
+ Declare2Words(p);
+ MultiplyWords(p, A[i], B);
+ Acc2WordsBy1(p, carry);
+ C[i] = LowWord(p);
+ carry = HighWord(p);
+ }
+ return carry;
+}
+
+#ifndef CRYPTOPP_DOXYGEN_PROCESSING
+
+#define Mul_2 \
+ Mul_Begin(2) \
+ Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \
+ Mul_End(1, 1)
+
+#define Mul_4 \
+ Mul_Begin(4) \
+ Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \
+ Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \
+ Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \
+ Mul_SaveAcc(3, 1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) \
+ Mul_SaveAcc(4, 2, 3) Mul_Acc(3, 2) \
+ Mul_End(5, 3)
+
+#define Mul_8 \
+ Mul_Begin(8) \
+ Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \
+ Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \
+ Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \
+ Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \
+ Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \
+ Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \
+ Mul_SaveAcc(6, 0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \
+ Mul_SaveAcc(7, 1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) \
+ Mul_SaveAcc(8, 2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) \
+ Mul_SaveAcc(9, 3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) \
+ Mul_SaveAcc(10, 4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) \
+ Mul_SaveAcc(11, 5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) \
+ Mul_SaveAcc(12, 6, 7) Mul_Acc(7, 6) \
+ Mul_End(13, 7)
+
+#define Mul_16 \
+ Mul_Begin(16) \
+ Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \
+ Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \
+ Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \
+ Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \
+ Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \
+ Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \
+ Mul_SaveAcc(6, 0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \
+ Mul_SaveAcc(7, 0, 8) Mul_Acc(1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) Mul_Acc(8, 0) \
+ Mul_SaveAcc(8, 0, 9) Mul_Acc(1, 8) Mul_Acc(2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) Mul_Acc(8, 1) Mul_Acc(9, 0) \
+ Mul_SaveAcc(9, 0, 10) Mul_Acc(1, 9) Mul_Acc(2, 8) Mul_Acc(3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) Mul_Acc(8, 2) Mul_Acc(9, 1) Mul_Acc(10, 0) \
+ Mul_SaveAcc(10, 0, 11) Mul_Acc(1, 10) Mul_Acc(2, 9) Mul_Acc(3, 8) Mul_Acc(4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) Mul_Acc(8, 3) Mul_Acc(9, 2) Mul_Acc(10, 1) Mul_Acc(11, 0) \
+ Mul_SaveAcc(11, 0, 12) Mul_Acc(1, 11) Mul_Acc(2, 10) Mul_Acc(3, 9) Mul_Acc(4, 8) Mul_Acc(5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) Mul_Acc(8, 4) Mul_Acc(9, 3) Mul_Acc(10, 2) Mul_Acc(11, 1) Mul_Acc(12, 0) \
+ Mul_SaveAcc(12, 0, 13) Mul_Acc(1, 12) Mul_Acc(2, 11) Mul_Acc(3, 10) Mul_Acc(4, 9) Mul_Acc(5, 8) Mul_Acc(6, 7) Mul_Acc(7, 6) Mul_Acc(8, 5) Mul_Acc(9, 4) Mul_Acc(10, 3) Mul_Acc(11, 2) Mul_Acc(12, 1) Mul_Acc(13, 0) \
+ Mul_SaveAcc(13, 0, 14) Mul_Acc(1, 13) Mul_Acc(2, 12) Mul_Acc(3, 11) Mul_Acc(4, 10) Mul_Acc(5, 9) Mul_Acc(6, 8) Mul_Acc(7, 7) Mul_Acc(8, 6) Mul_Acc(9, 5) Mul_Acc(10, 4) Mul_Acc(11, 3) Mul_Acc(12, 2) Mul_Acc(13, 1) Mul_Acc(14, 0) \
+ Mul_SaveAcc(14, 0, 15) Mul_Acc(1, 14) Mul_Acc(2, 13) Mul_Acc(3, 12) Mul_Acc(4, 11) Mul_Acc(5, 10) Mul_Acc(6, 9) Mul_Acc(7, 8) Mul_Acc(8, 7) Mul_Acc(9, 6) Mul_Acc(10, 5) Mul_Acc(11, 4) Mul_Acc(12, 3) Mul_Acc(13, 2) Mul_Acc(14, 1) Mul_Acc(15, 0) \
+ Mul_SaveAcc(15, 1, 15) Mul_Acc(2, 14) Mul_Acc(3, 13) Mul_Acc(4, 12) Mul_Acc(5, 11) Mul_Acc(6, 10) Mul_Acc(7, 9) Mul_Acc(8, 8) Mul_Acc(9, 7) Mul_Acc(10, 6) Mul_Acc(11, 5) Mul_Acc(12, 4) Mul_Acc(13, 3) Mul_Acc(14, 2) Mul_Acc(15, 1) \
+ Mul_SaveAcc(16, 2, 15) Mul_Acc(3, 14) Mul_Acc(4, 13) Mul_Acc(5, 12) Mul_Acc(6, 11) Mul_Acc(7, 10) Mul_Acc(8, 9) Mul_Acc(9, 8) Mul_Acc(10, 7) Mul_Acc(11, 6) Mul_Acc(12, 5) Mul_Acc(13, 4) Mul_Acc(14, 3) Mul_Acc(15, 2) \
+ Mul_SaveAcc(17, 3, 15) Mul_Acc(4, 14) Mul_Acc(5, 13) Mul_Acc(6, 12) Mul_Acc(7, 11) Mul_Acc(8, 10) Mul_Acc(9, 9) Mul_Acc(10, 8) Mul_Acc(11, 7) Mul_Acc(12, 6) Mul_Acc(13, 5) Mul_Acc(14, 4) Mul_Acc(15, 3) \
+ Mul_SaveAcc(18, 4, 15) Mul_Acc(5, 14) Mul_Acc(6, 13) Mul_Acc(7, 12) Mul_Acc(8, 11) Mul_Acc(9, 10) Mul_Acc(10, 9) Mul_Acc(11, 8) Mul_Acc(12, 7) Mul_Acc(13, 6) Mul_Acc(14, 5) Mul_Acc(15, 4) \
+ Mul_SaveAcc(19, 5, 15) Mul_Acc(6, 14) Mul_Acc(7, 13) Mul_Acc(8, 12) Mul_Acc(9, 11) Mul_Acc(10, 10) Mul_Acc(11, 9) Mul_Acc(12, 8) Mul_Acc(13, 7) Mul_Acc(14, 6) Mul_Acc(15, 5) \
+ Mul_SaveAcc(20, 6, 15) Mul_Acc(7, 14) Mul_Acc(8, 13) Mul_Acc(9, 12) Mul_Acc(10, 11) Mul_Acc(11, 10) Mul_Acc(12, 9) Mul_Acc(13, 8) Mul_Acc(14, 7) Mul_Acc(15, 6) \
+ Mul_SaveAcc(21, 7, 15) Mul_Acc(8, 14) Mul_Acc(9, 13) Mul_Acc(10, 12) Mul_Acc(11, 11) Mul_Acc(12, 10) Mul_Acc(13, 9) Mul_Acc(14, 8) Mul_Acc(15, 7) \
+ Mul_SaveAcc(22, 8, 15) Mul_Acc(9, 14) Mul_Acc(10, 13) Mul_Acc(11, 12) Mul_Acc(12, 11) Mul_Acc(13, 10) Mul_Acc(14, 9) Mul_Acc(15, 8) \
+ Mul_SaveAcc(23, 9, 15) Mul_Acc(10, 14) Mul_Acc(11, 13) Mul_Acc(12, 12) Mul_Acc(13, 11) Mul_Acc(14, 10) Mul_Acc(15, 9) \
+ Mul_SaveAcc(24, 10, 15) Mul_Acc(11, 14) Mul_Acc(12, 13) Mul_Acc(13, 12) Mul_Acc(14, 11) Mul_Acc(15, 10) \
+ Mul_SaveAcc(25, 11, 15) Mul_Acc(12, 14) Mul_Acc(13, 13) Mul_Acc(14, 12) Mul_Acc(15, 11) \
+ Mul_SaveAcc(26, 12, 15) Mul_Acc(13, 14) Mul_Acc(14, 13) Mul_Acc(15, 12) \
+ Mul_SaveAcc(27, 13, 15) Mul_Acc(14, 14) Mul_Acc(15, 13) \
+ Mul_SaveAcc(28, 14, 15) Mul_Acc(15, 14) \
+ Mul_End(29, 15)
+
+#define Squ_2 \
+ Squ_Begin(2) \
+ Squ_End(2)
+
+#define Squ_4 \
+ Squ_Begin(4) \
+ Squ_SaveAcc(1, 0, 2) Squ_Diag(1) \
+ Squ_SaveAcc(2, 0, 3) Squ_Acc(1, 2) Squ_NonDiag \
+ Squ_SaveAcc(3, 1, 3) Squ_Diag(2) \
+ Squ_SaveAcc(4, 2, 3) Squ_NonDiag \
+ Squ_End(4)
+
+#define Squ_8 \
+ Squ_Begin(8) \
+ Squ_SaveAcc(1, 0, 2) Squ_Diag(1) \
+ Squ_SaveAcc(2, 0, 3) Squ_Acc(1, 2) Squ_NonDiag \
+ Squ_SaveAcc(3, 0, 4) Squ_Acc(1, 3) Squ_Diag(2) \
+ Squ_SaveAcc(4, 0, 5) Squ_Acc(1, 4) Squ_Acc(2, 3) Squ_NonDiag \
+ Squ_SaveAcc(5, 0, 6) Squ_Acc(1, 5) Squ_Acc(2, 4) Squ_Diag(3) \
+ Squ_SaveAcc(6, 0, 7) Squ_Acc(1, 6) Squ_Acc(2, 5) Squ_Acc(3, 4) Squ_NonDiag \
+ Squ_SaveAcc(7, 1, 7) Squ_Acc(2, 6) Squ_Acc(3, 5) Squ_Diag(4) \
+ Squ_SaveAcc(8, 2, 7) Squ_Acc(3, 6) Squ_Acc(4, 5) Squ_NonDiag \
+ Squ_SaveAcc(9, 3, 7) Squ_Acc(4, 6) Squ_Diag(5) \
+ Squ_SaveAcc(10, 4, 7) Squ_Acc(5, 6) Squ_NonDiag \
+ Squ_SaveAcc(11, 5, 7) Squ_Diag(6) \
+ Squ_SaveAcc(12, 6, 7) Squ_NonDiag \
+ Squ_End(8)
+
+#define Squ_16 \
+ Squ_Begin(16) \
+ Squ_SaveAcc(1, 0, 2) Squ_Diag(1) \
+ Squ_SaveAcc(2, 0, 3) Squ_Acc(1, 2) Squ_NonDiag \
+ Squ_SaveAcc(3, 0, 4) Squ_Acc(1, 3) Squ_Diag(2) \
+ Squ_SaveAcc(4, 0, 5) Squ_Acc(1, 4) Squ_Acc(2, 3) Squ_NonDiag \
+ Squ_SaveAcc(5, 0, 6) Squ_Acc(1, 5) Squ_Acc(2, 4) Squ_Diag(3) \
+ Squ_SaveAcc(6, 0, 7) Squ_Acc(1, 6) Squ_Acc(2, 5) Squ_Acc(3, 4) Squ_NonDiag \
+ Squ_SaveAcc(7, 0, 8) Squ_Acc(1, 7) Squ_Acc(2, 6) Squ_Acc(3, 5) Squ_Diag(4) \
+ Squ_SaveAcc(8, 0, 9) Squ_Acc(1, 8) Squ_Acc(2, 7) Squ_Acc(3, 6) Squ_Acc(4, 5) Squ_NonDiag \
+ Squ_SaveAcc(9, 0, 10) Squ_Acc(1, 9) Squ_Acc(2, 8) Squ_Acc(3, 7) Squ_Acc(4, 6) Squ_Diag(5) \
+ Squ_SaveAcc(10, 0, 11) Squ_Acc(1, 10) Squ_Acc(2, 9) Squ_Acc(3, 8) Squ_Acc(4, 7) Squ_Acc(5, 6) Squ_NonDiag \
+ Squ_SaveAcc(11, 0, 12) Squ_Acc(1, 11) Squ_Acc(2, 10) Squ_Acc(3, 9) Squ_Acc(4, 8) Squ_Acc(5, 7) Squ_Diag(6) \
+ Squ_SaveAcc(12, 0, 13) Squ_Acc(1, 12) Squ_Acc(2, 11) Squ_Acc(3, 10) Squ_Acc(4, 9) Squ_Acc(5, 8) Squ_Acc(6, 7) Squ_NonDiag \
+ Squ_SaveAcc(13, 0, 14) Squ_Acc(1, 13) Squ_Acc(2, 12) Squ_Acc(3, 11) Squ_Acc(4, 10) Squ_Acc(5, 9) Squ_Acc(6, 8) Squ_Diag(7) \
+ Squ_SaveAcc(14, 0, 15) Squ_Acc(1, 14) Squ_Acc(2, 13) Squ_Acc(3, 12) Squ_Acc(4, 11) Squ_Acc(5, 10) Squ_Acc(6, 9) Squ_Acc(7, 8) Squ_NonDiag \
+ Squ_SaveAcc(15, 1, 15) Squ_Acc(2, 14) Squ_Acc(3, 13) Squ_Acc(4, 12) Squ_Acc(5, 11) Squ_Acc(6, 10) Squ_Acc(7, 9) Squ_Diag(8) \
+ Squ_SaveAcc(16, 2, 15) Squ_Acc(3, 14) Squ_Acc(4, 13) Squ_Acc(5, 12) Squ_Acc(6, 11) Squ_Acc(7, 10) Squ_Acc(8, 9) Squ_NonDiag \
+ Squ_SaveAcc(17, 3, 15) Squ_Acc(4, 14) Squ_Acc(5, 13) Squ_Acc(6, 12) Squ_Acc(7, 11) Squ_Acc(8, 10) Squ_Diag(9) \
+ Squ_SaveAcc(18, 4, 15) Squ_Acc(5, 14) Squ_Acc(6, 13) Squ_Acc(7, 12) Squ_Acc(8, 11) Squ_Acc(9, 10) Squ_NonDiag \
+ Squ_SaveAcc(19, 5, 15) Squ_Acc(6, 14) Squ_Acc(7, 13) Squ_Acc(8, 12) Squ_Acc(9, 11) Squ_Diag(10) \
+ Squ_SaveAcc(20, 6, 15) Squ_Acc(7, 14) Squ_Acc(8, 13) Squ_Acc(9, 12) Squ_Acc(10, 11) Squ_NonDiag \
+ Squ_SaveAcc(21, 7, 15) Squ_Acc(8, 14) Squ_Acc(9, 13) Squ_Acc(10, 12) Squ_Diag(11) \
+ Squ_SaveAcc(22, 8, 15) Squ_Acc(9, 14) Squ_Acc(10, 13) Squ_Acc(11, 12) Squ_NonDiag \
+ Squ_SaveAcc(23, 9, 15) Squ_Acc(10, 14) Squ_Acc(11, 13) Squ_Diag(12) \
+ Squ_SaveAcc(24, 10, 15) Squ_Acc(11, 14) Squ_Acc(12, 13) Squ_NonDiag \
+ Squ_SaveAcc(25, 11, 15) Squ_Acc(12, 14) Squ_Diag(13) \
+ Squ_SaveAcc(26, 12, 15) Squ_Acc(13, 14) Squ_NonDiag \
+ Squ_SaveAcc(27, 13, 15) Squ_Diag(14) \
+ Squ_SaveAcc(28, 14, 15) Squ_NonDiag \
+ Squ_End(16)
+
+#define Bot_2 \
+ Mul_Begin(2) \
+ Bot_SaveAcc(0, 0, 1) Bot_Acc(1, 0) \
+ Bot_End(2)
+
+#define Bot_4 \
+ Mul_Begin(4) \
+ Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \
+ Mul_SaveAcc(1, 2, 0) Mul_Acc(1, 1) Mul_Acc(0, 2) \
+ Bot_SaveAcc(2, 0, 3) Bot_Acc(1, 2) Bot_Acc(2, 1) Bot_Acc(3, 0) \
+ Bot_End(4)
+
+#define Bot_8 \
+ Mul_Begin(8) \
+ Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \
+ Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \
+ Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \
+ Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \
+ Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \
+ Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \
+ Bot_SaveAcc(6, 0, 7) Bot_Acc(1, 6) Bot_Acc(2, 5) Bot_Acc(3, 4) Bot_Acc(4, 3) Bot_Acc(5, 2) Bot_Acc(6, 1) Bot_Acc(7, 0) \
+ Bot_End(8)
+
+#define Bot_16 \
+ Mul_Begin(16) \
+ Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \
+ Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \
+ Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \
+ Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \
+ Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \
+ Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \
+ Mul_SaveAcc(6, 0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \
+ Mul_SaveAcc(7, 0, 8) Mul_Acc(1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) Mul_Acc(8, 0) \
+ Mul_SaveAcc(8, 0, 9) Mul_Acc(1, 8) Mul_Acc(2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) Mul_Acc(8, 1) Mul_Acc(9, 0) \
+ Mul_SaveAcc(9, 0, 10) Mul_Acc(1, 9) Mul_Acc(2, 8) Mul_Acc(3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) Mul_Acc(8, 2) Mul_Acc(9, 1) Mul_Acc(10, 0) \
+ Mul_SaveAcc(10, 0, 11) Mul_Acc(1, 10) Mul_Acc(2, 9) Mul_Acc(3, 8) Mul_Acc(4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) Mul_Acc(8, 3) Mul_Acc(9, 2) Mul_Acc(10, 1) Mul_Acc(11, 0) \
+ Mul_SaveAcc(11, 0, 12) Mul_Acc(1, 11) Mul_Acc(2, 10) Mul_Acc(3, 9) Mul_Acc(4, 8) Mul_Acc(5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) Mul_Acc(8, 4) Mul_Acc(9, 3) Mul_Acc(10, 2) Mul_Acc(11, 1) Mul_Acc(12, 0) \
+ Mul_SaveAcc(12, 0, 13) Mul_Acc(1, 12) Mul_Acc(2, 11) Mul_Acc(3, 10) Mul_Acc(4, 9) Mul_Acc(5, 8) Mul_Acc(6, 7) Mul_Acc(7, 6) Mul_Acc(8, 5) Mul_Acc(9, 4) Mul_Acc(10, 3) Mul_Acc(11, 2) Mul_Acc(12, 1) Mul_Acc(13, 0) \
+ Mul_SaveAcc(13, 0, 14) Mul_Acc(1, 13) Mul_Acc(2, 12) Mul_Acc(3, 11) Mul_Acc(4, 10) Mul_Acc(5, 9) Mul_Acc(6, 8) Mul_Acc(7, 7) Mul_Acc(8, 6) Mul_Acc(9, 5) Mul_Acc(10, 4) Mul_Acc(11, 3) Mul_Acc(12, 2) Mul_Acc(13, 1) Mul_Acc(14, 0) \
+ Bot_SaveAcc(14, 0, 15) Bot_Acc(1, 14) Bot_Acc(2, 13) Bot_Acc(3, 12) Bot_Acc(4, 11) Bot_Acc(5, 10) Bot_Acc(6, 9) Bot_Acc(7, 8) Bot_Acc(8, 7) Bot_Acc(9, 6) Bot_Acc(10, 5) Bot_Acc(11, 4) Bot_Acc(12, 3) Bot_Acc(13, 2) Bot_Acc(14, 1) Bot_Acc(15, 0) \
+ Bot_End(16)
+
+#endif
+
+#if 0
+#define Mul_Begin(n) \
+ Declare2Words(p) \
+ Declare2Words(c) \
+ Declare2Words(d) \
+ MultiplyWords(p, A[0], B[0]) \
+ AssignWord(c, LowWord(p)) \
+ AssignWord(d, HighWord(p))
+
+#define Mul_Acc(i, j) \
+ MultiplyWords(p, A[i], B[j]) \
+ Acc2WordsBy1(c, LowWord(p)) \
+ Acc2WordsBy1(d, HighWord(p))
+
+#define Mul_SaveAcc(k, i, j) \
+ R[k] = LowWord(c); \
+ Add2WordsBy1(c, d, HighWord(c)) \
+ MultiplyWords(p, A[i], B[j]) \
+ AssignWord(d, HighWord(p)) \
+ Acc2WordsBy1(c, LowWord(p))
+
+#define Mul_End(n) \
+ R[2*n-3] = LowWord(c); \
+ Acc2WordsBy1(d, HighWord(c)) \
+ MultiplyWords(p, A[n-1], B[n-1])\
+ Acc2WordsBy2(d, p) \
+ R[2*n-2] = LowWord(d); \
+ R[2*n-1] = HighWord(d);
+
+#define Bot_SaveAcc(k, i, j) \
+ R[k] = LowWord(c); \
+ word e = LowWord(d) + HighWord(c); \
+ e += A[i] * B[j];
+
+#define Bot_Acc(i, j) \
+ e += A[i] * B[j];
+
+#define Bot_End(n) \
+ R[n-1] = e;
+#else
+#define Mul_Begin(n) \
+ Declare2Words(p) \
+ word c; \
+ Declare2Words(d) \
+ MultiplyWords(p, A[0], B[0]) \
+ c = LowWord(p); \
+ AssignWord(d, HighWord(p))
+
+#define Mul_Acc(i, j) \
+ MulAcc(c, d, A[i], B[j])
+
+#define Mul_SaveAcc(k, i, j) \
+ R[k] = c; \
+ c = LowWord(d); \
+ AssignWord(d, HighWord(d)) \
+ MulAcc(c, d, A[i], B[j])
+
+#define Mul_End(k, i) \
+ R[k] = c; \
+ MultiplyWords(p, A[i], B[i]) \
+ Acc2WordsBy2(p, d) \
+ R[k+1] = LowWord(p); \
+ R[k+2] = HighWord(p);
+
+#define Bot_SaveAcc(k, i, j) \
+ R[k] = c; \
+ c = LowWord(d); \
+ c += A[i] * B[j];
+
+#define Bot_Acc(i, j) \
+ c += A[i] * B[j];
+
+#define Bot_End(n) \
+ R[n-1] = c;
+#endif
+
+#define Squ_Begin(n) \
+ Declare2Words(p) \
+ word c; \
+ Declare2Words(d) \
+ Declare2Words(e) \
+ MultiplyWords(p, A[0], A[0]) \
+ R[0] = LowWord(p); \
+ AssignWord(e, HighWord(p)) \
+ MultiplyWords(p, A[0], A[1]) \
+ c = LowWord(p); \
+ AssignWord(d, HighWord(p)) \
+ Squ_NonDiag \
+
+#define Squ_NonDiag \
+ Double3Words(c, d)
+
+#define Squ_SaveAcc(k, i, j) \
+ Acc3WordsBy2(c, d, e) \
+ R[k] = c; \
+ MultiplyWords(p, A[i], A[j]) \
+ c = LowWord(p); \
+ AssignWord(d, HighWord(p)) \
+
+#define Squ_Acc(i, j) \
+ MulAcc(c, d, A[i], A[j])
+
+#define Squ_Diag(i) \
+ Squ_NonDiag \
+ MulAcc(c, d, A[i], A[i])
+
+#define Squ_End(n) \
+ Acc3WordsBy2(c, d, e) \
+ R[2*n-3] = c; \
+ MultiplyWords(p, A[n-1], A[n-1])\
+ Acc2WordsBy2(p, e) \
+ R[2*n-2] = LowWord(p); \
+ R[2*n-1] = HighWord(p);
+
+void Baseline_Multiply2(word *R, const word *A, const word *B)
+{
+ Mul_2
+}
+
+void Baseline_Multiply4(word *R, const word *A, const word *B)
+{
+ Mul_4
+}
+
+void Baseline_Multiply8(word *R, const word *A, const word *B)
+{
+ Mul_8
+}
+
+void Baseline_Square2(word *R, const word *A)
+{
+ Squ_2
+}
+
+void Baseline_Square4(word *R, const word *A)
+{
+ Squ_4
+}
+
+void Baseline_Square8(word *R, const word *A)
+{
+ Squ_8
+}
+
+void Baseline_MultiplyBottom2(word *R, const word *A, const word *B)
+{
+ Bot_2
+}
+
+void Baseline_MultiplyBottom4(word *R, const word *A, const word *B)
+{
+ Bot_4
+}
+
+void Baseline_MultiplyBottom8(word *R, const word *A, const word *B)
+{
+ Bot_8
+}
+
+#define Top_Begin(n) \
+ Declare2Words(p) \
+ word c; \
+ Declare2Words(d) \
+ MultiplyWords(p, A[0], B[n-2]);\
+ AssignWord(d, HighWord(p));
+
+#define Top_Acc(i, j) \
+ MultiplyWords(p, A[i], B[j]);\
+ Acc2WordsBy1(d, HighWord(p));
+
+#define Top_SaveAcc0(i, j) \
+ c = LowWord(d); \
+ AssignWord(d, HighWord(d)) \
+ MulAcc(c, d, A[i], B[j])
+
+#define Top_SaveAcc1(i, j) \
+ c = L<c; \
+ Acc2WordsBy1(d, c); \
+ c = LowWord(d); \
+ AssignWord(d, HighWord(d)) \
+ MulAcc(c, d, A[i], B[j])
+
+void Baseline_MultiplyTop2(word *R, const word *A, const word *B, word L)
+{
+ word T[4];
+ Baseline_Multiply2(T, A, B);
+ R[0] = T[2];
+ R[1] = T[3];
+}
+
+void Baseline_MultiplyTop4(word *R, const word *A, const word *B, word L)
+{
+ Top_Begin(4)
+ Top_Acc(1, 1) Top_Acc(2, 0) \
+ Top_SaveAcc0(0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \
+ Top_SaveAcc1(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) \
+ Mul_SaveAcc(0, 2, 3) Mul_Acc(3, 2) \
+ Mul_End(1, 3)
+}
+
+void Baseline_MultiplyTop8(word *R, const word *A, const word *B, word L)
+{
+ Top_Begin(8)
+ Top_Acc(1, 5) Top_Acc(2, 4) Top_Acc(3, 3) Top_Acc(4, 2) Top_Acc(5, 1) Top_Acc(6, 0) \
+ Top_SaveAcc0(0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \
+ Top_SaveAcc1(1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) \
+ Mul_SaveAcc(0, 2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) \
+ Mul_SaveAcc(1, 3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) \
+ Mul_SaveAcc(2, 4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) \
+ Mul_SaveAcc(3, 5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) \
+ Mul_SaveAcc(4, 6, 7) Mul_Acc(7, 6) \
+ Mul_End(5, 7)
+}
+
+#if !CRYPTOPP_INTEGER_SSE2 // save memory by not compiling these functions when SSE2 is available
+void Baseline_Multiply16(word *R, const word *A, const word *B)
+{
+ Mul_16
+}
+
+void Baseline_Square16(word *R, const word *A)
+{
+ Squ_16
+}
+
+void Baseline_MultiplyBottom16(word *R, const word *A, const word *B)
+{
+ Bot_16
+}
+
+void Baseline_MultiplyTop16(word *R, const word *A, const word *B, word L)
+{
+ Top_Begin(16)
+ Top_Acc(1, 13) Top_Acc(2, 12) Top_Acc(3, 11) Top_Acc(4, 10) Top_Acc(5, 9) Top_Acc(6, 8) Top_Acc(7, 7) Top_Acc(8, 6) Top_Acc(9, 5) Top_Acc(10, 4) Top_Acc(11, 3) Top_Acc(12, 2) Top_Acc(13, 1) Top_Acc(14, 0) \
+ Top_SaveAcc0(0, 15) Mul_Acc(1, 14) Mul_Acc(2, 13) Mul_Acc(3, 12) Mul_Acc(4, 11) Mul_Acc(5, 10) Mul_Acc(6, 9) Mul_Acc(7, 8) Mul_Acc(8, 7) Mul_Acc(9, 6) Mul_Acc(10, 5) Mul_Acc(11, 4) Mul_Acc(12, 3) Mul_Acc(13, 2) Mul_Acc(14, 1) Mul_Acc(15, 0) \
+ Top_SaveAcc1(1, 15) Mul_Acc(2, 14) Mul_Acc(3, 13) Mul_Acc(4, 12) Mul_Acc(5, 11) Mul_Acc(6, 10) Mul_Acc(7, 9) Mul_Acc(8, 8) Mul_Acc(9, 7) Mul_Acc(10, 6) Mul_Acc(11, 5) Mul_Acc(12, 4) Mul_Acc(13, 3) Mul_Acc(14, 2) Mul_Acc(15, 1) \
+ Mul_SaveAcc(0, 2, 15) Mul_Acc(3, 14) Mul_Acc(4, 13) Mul_Acc(5, 12) Mul_Acc(6, 11) Mul_Acc(7, 10) Mul_Acc(8, 9) Mul_Acc(9, 8) Mul_Acc(10, 7) Mul_Acc(11, 6) Mul_Acc(12, 5) Mul_Acc(13, 4) Mul_Acc(14, 3) Mul_Acc(15, 2) \
+ Mul_SaveAcc(1, 3, 15) Mul_Acc(4, 14) Mul_Acc(5, 13) Mul_Acc(6, 12) Mul_Acc(7, 11) Mul_Acc(8, 10) Mul_Acc(9, 9) Mul_Acc(10, 8) Mul_Acc(11, 7) Mul_Acc(12, 6) Mul_Acc(13, 5) Mul_Acc(14, 4) Mul_Acc(15, 3) \
+ Mul_SaveAcc(2, 4, 15) Mul_Acc(5, 14) Mul_Acc(6, 13) Mul_Acc(7, 12) Mul_Acc(8, 11) Mul_Acc(9, 10) Mul_Acc(10, 9) Mul_Acc(11, 8) Mul_Acc(12, 7) Mul_Acc(13, 6) Mul_Acc(14, 5) Mul_Acc(15, 4) \
+ Mul_SaveAcc(3, 5, 15) Mul_Acc(6, 14) Mul_Acc(7, 13) Mul_Acc(8, 12) Mul_Acc(9, 11) Mul_Acc(10, 10) Mul_Acc(11, 9) Mul_Acc(12, 8) Mul_Acc(13, 7) Mul_Acc(14, 6) Mul_Acc(15, 5) \
+ Mul_SaveAcc(4, 6, 15) Mul_Acc(7, 14) Mul_Acc(8, 13) Mul_Acc(9, 12) Mul_Acc(10, 11) Mul_Acc(11, 10) Mul_Acc(12, 9) Mul_Acc(13, 8) Mul_Acc(14, 7) Mul_Acc(15, 6) \
+ Mul_SaveAcc(5, 7, 15) Mul_Acc(8, 14) Mul_Acc(9, 13) Mul_Acc(10, 12) Mul_Acc(11, 11) Mul_Acc(12, 10) Mul_Acc(13, 9) Mul_Acc(14, 8) Mul_Acc(15, 7) \
+ Mul_SaveAcc(6, 8, 15) Mul_Acc(9, 14) Mul_Acc(10, 13) Mul_Acc(11, 12) Mul_Acc(12, 11) Mul_Acc(13, 10) Mul_Acc(14, 9) Mul_Acc(15, 8) \
+ Mul_SaveAcc(7, 9, 15) Mul_Acc(10, 14) Mul_Acc(11, 13) Mul_Acc(12, 12) Mul_Acc(13, 11) Mul_Acc(14, 10) Mul_Acc(15, 9) \
+ Mul_SaveAcc(8, 10, 15) Mul_Acc(11, 14) Mul_Acc(12, 13) Mul_Acc(13, 12) Mul_Acc(14, 11) Mul_Acc(15, 10) \
+ Mul_SaveAcc(9, 11, 15) Mul_Acc(12, 14) Mul_Acc(13, 13) Mul_Acc(14, 12) Mul_Acc(15, 11) \
+ Mul_SaveAcc(10, 12, 15) Mul_Acc(13, 14) Mul_Acc(14, 13) Mul_Acc(15, 12) \
+ Mul_SaveAcc(11, 13, 15) Mul_Acc(14, 14) Mul_Acc(15, 13) \
+ Mul_SaveAcc(12, 14, 15) Mul_Acc(15, 14) \
+ Mul_End(13, 15)
+}
+#endif
+
+// ********************************************************
+
+#if CRYPTOPP_INTEGER_SSE2
+
+CRYPTOPP_ALIGN_DATA(16) static const word32 s_maskLow16[4] CRYPTOPP_SECTION_ALIGN16 = {0xffff,0xffff,0xffff,0xffff};
+
+#undef Mul_Begin
+#undef Mul_Acc
+#undef Top_Begin
+#undef Top_Acc
+#undef Squ_Acc
+#undef Squ_NonDiag
+#undef Squ_Diag
+#undef Squ_SaveAcc
+#undef Squ_Begin
+#undef Mul_SaveAcc
+#undef Bot_Acc
+#undef Bot_SaveAcc
+#undef Bot_End
+#undef Squ_End
+#undef Mul_End
+
+#define SSE2_FinalSave(k) \
+ AS2( psllq xmm5, 16) \
+ AS2( paddq xmm4, xmm5) \
+ AS2( movq QWORD PTR [ecx+8*(k)], xmm4)
+
+#define SSE2_SaveShift(k) \
+ AS2( movq xmm0, xmm6) \
+ AS2( punpckhqdq xmm6, xmm0) \
+ AS2( movq xmm1, xmm7) \
+ AS2( punpckhqdq xmm7, xmm1) \
+ AS2( paddd xmm6, xmm0) \
+ AS2( pslldq xmm6, 4) \
+ AS2( paddd xmm7, xmm1) \
+ AS2( paddd xmm4, xmm6) \
+ AS2( pslldq xmm7, 4) \
+ AS2( movq xmm6, xmm4) \
+ AS2( paddd xmm5, xmm7) \
+ AS2( movq xmm7, xmm5) \
+ AS2( movd DWORD PTR [ecx+8*(k)], xmm4) \
+ AS2( psrlq xmm6, 16) \
+ AS2( paddq xmm6, xmm7) \
+ AS2( punpckhqdq xmm4, xmm0) \
+ AS2( punpckhqdq xmm5, xmm0) \
+ AS2( movq QWORD PTR [ecx+8*(k)+2], xmm6) \
+ AS2( psrlq xmm6, 3*16) \
+ AS2( paddd xmm4, xmm6) \
+
+#define Squ_SSE2_SaveShift(k) \
+ AS2( movq xmm0, xmm6) \
+ AS2( punpckhqdq xmm6, xmm0) \
+ AS2( movq xmm1, xmm7) \
+ AS2( punpckhqdq xmm7, xmm1) \
+ AS2( paddd xmm6, xmm0) \
+ AS2( pslldq xmm6, 4) \
+ AS2( paddd xmm7, xmm1) \
+ AS2( paddd xmm4, xmm6) \
+ AS2( pslldq xmm7, 4) \
+ AS2( movhlps xmm6, xmm4) \
+ AS2( movd DWORD PTR [ecx+8*(k)], xmm4) \
+ AS2( paddd xmm5, xmm7) \
+ AS2( movhps QWORD PTR [esp+12], xmm5)\
+ AS2( psrlq xmm4, 16) \
+ AS2( paddq xmm4, xmm5) \
+ AS2( movq QWORD PTR [ecx+8*(k)+2], xmm4) \
+ AS2( psrlq xmm4, 3*16) \
+ AS2( paddd xmm4, xmm6) \
+ AS2( movq QWORD PTR [esp+4], xmm4)\
+
+#define SSE2_FirstMultiply(i) \
+ AS2( movdqa xmm7, [esi+(i)*16])\
+ AS2( movdqa xmm5, [edi-(i)*16])\
+ AS2( pmuludq xmm5, xmm7) \
+ AS2( movdqa xmm4, [ebx])\
+ AS2( movdqa xmm6, xmm4) \
+ AS2( pand xmm4, xmm5) \
+ AS2( psrld xmm5, 16) \
+ AS2( pmuludq xmm7, [edx-(i)*16])\
+ AS2( pand xmm6, xmm7) \
+ AS2( psrld xmm7, 16)
+
+#define Squ_Begin(n) \
+ SquPrologue \
+ AS2( mov esi, esp)\
+ AS2( and esp, 0xfffffff0)\
+ AS2( lea edi, [esp-32*n])\
+ AS2( sub esp, 32*n+16)\
+ AS1( push esi)\
+ AS2( mov esi, edi) \
+ AS2( xor edx, edx) \
+ ASL(1) \
+ ASS( pshufd xmm0, [eax+edx], 3,1,2,0) \
+ ASS( pshufd xmm1, [eax+edx], 2,0,3,1) \
+ AS2( movdqa [edi+2*edx], xmm0) \
+ AS2( psrlq xmm0, 32) \
+ AS2( movdqa [edi+2*edx+16], xmm0) \
+ AS2( movdqa [edi+16*n+2*edx], xmm1) \
+ AS2( psrlq xmm1, 32) \
+ AS2( movdqa [edi+16*n+2*edx+16], xmm1) \
+ AS2( add edx, 16) \
+ AS2( cmp edx, 8*(n)) \
+ ASJ( jne, 1, b) \
+ AS2( lea edx, [edi+16*n])\
+ SSE2_FirstMultiply(0) \
+
+#define Squ_Acc(i) \
+ ASL(LSqu##i) \
+ AS2( movdqa xmm1, [esi+(i)*16]) \
+ AS2( movdqa xmm0, [edi-(i)*16]) \
+ AS2( movdqa xmm2, [ebx]) \
+ AS2( pmuludq xmm0, xmm1) \
+ AS2( pmuludq xmm1, [edx-(i)*16]) \
+ AS2( movdqa xmm3, xmm2) \
+ AS2( pand xmm2, xmm0) \
+ AS2( psrld xmm0, 16) \
+ AS2( paddd xmm4, xmm2) \
+ AS2( paddd xmm5, xmm0) \
+ AS2( pand xmm3, xmm1) \
+ AS2( psrld xmm1, 16) \
+ AS2( paddd xmm6, xmm3) \
+ AS2( paddd xmm7, xmm1) \
+
+#define Squ_Acc1(i)
+#define Squ_Acc2(i) ASC(call, LSqu##i)
+#define Squ_Acc3(i) Squ_Acc2(i)
+#define Squ_Acc4(i) Squ_Acc2(i)
+#define Squ_Acc5(i) Squ_Acc2(i)
+#define Squ_Acc6(i) Squ_Acc2(i)
+#define Squ_Acc7(i) Squ_Acc2(i)
+#define Squ_Acc8(i) Squ_Acc2(i)
+
+#define SSE2_End(E, n) \
+ SSE2_SaveShift(2*(n)-3) \
+ AS2( movdqa xmm7, [esi+16]) \
+ AS2( movdqa xmm0, [edi]) \
+ AS2( pmuludq xmm0, xmm7) \
+ AS2( movdqa xmm2, [ebx]) \
+ AS2( pmuludq xmm7, [edx]) \
+ AS2( movdqa xmm6, xmm2) \
+ AS2( pand xmm2, xmm0) \
+ AS2( psrld xmm0, 16) \
+ AS2( paddd xmm4, xmm2) \
+ AS2( paddd xmm5, xmm0) \
+ AS2( pand xmm6, xmm7) \
+ AS2( psrld xmm7, 16) \
+ SSE2_SaveShift(2*(n)-2) \
+ SSE2_FinalSave(2*(n)-1) \
+ AS1( pop esp)\
+ E
+
+#define Squ_End(n) SSE2_End(SquEpilogue, n)
+#define Mul_End(n) SSE2_End(MulEpilogue, n)
+#define Top_End(n) SSE2_End(TopEpilogue, n)
+
+#define Squ_Column1(k, i) \
+ Squ_SSE2_SaveShift(k) \
+ AS2( add esi, 16) \
+ SSE2_FirstMultiply(1)\
+ Squ_Acc##i(i) \
+ AS2( paddd xmm4, xmm4) \
+ AS2( paddd xmm5, xmm5) \
+ AS2( movdqa xmm3, [esi]) \
+ AS2( movq xmm1, QWORD PTR [esi+8]) \
+ AS2( pmuludq xmm1, xmm3) \
+ AS2( pmuludq xmm3, xmm3) \
+ AS2( movdqa xmm0, [ebx])\
+ AS2( movdqa xmm2, xmm0) \
+ AS2( pand xmm0, xmm1) \
+ AS2( psrld xmm1, 16) \
+ AS2( paddd xmm6, xmm0) \
+ AS2( paddd xmm7, xmm1) \
+ AS2( pand xmm2, xmm3) \
+ AS2( psrld xmm3, 16) \
+ AS2( paddd xmm6, xmm6) \
+ AS2( paddd xmm7, xmm7) \
+ AS2( paddd xmm4, xmm2) \
+ AS2( paddd xmm5, xmm3) \
+ AS2( movq xmm0, QWORD PTR [esp+4])\
+ AS2( movq xmm1, QWORD PTR [esp+12])\
+ AS2( paddd xmm4, xmm0)\
+ AS2( paddd xmm5, xmm1)\
+
+#define Squ_Column0(k, i) \
+ Squ_SSE2_SaveShift(k) \
+ AS2( add edi, 16) \
+ AS2( add edx, 16) \
+ SSE2_FirstMultiply(1)\
+ Squ_Acc##i(i) \
+ AS2( paddd xmm6, xmm6) \
+ AS2( paddd xmm7, xmm7) \
+ AS2( paddd xmm4, xmm4) \
+ AS2( paddd xmm5, xmm5) \
+ AS2( movq xmm0, QWORD PTR [esp+4])\
+ AS2( movq xmm1, QWORD PTR [esp+12])\
+ AS2( paddd xmm4, xmm0)\
+ AS2( paddd xmm5, xmm1)\
+
+#define SSE2_MulAdd45 \
+ AS2( movdqa xmm7, [esi]) \
+ AS2( movdqa xmm0, [edi]) \
+ AS2( pmuludq xmm0, xmm7) \
+ AS2( movdqa xmm2, [ebx]) \
+ AS2( pmuludq xmm7, [edx]) \
+ AS2( movdqa xmm6, xmm2) \
+ AS2( pand xmm2, xmm0) \
+ AS2( psrld xmm0, 16) \
+ AS2( paddd xmm4, xmm2) \
+ AS2( paddd xmm5, xmm0) \
+ AS2( pand xmm6, xmm7) \
+ AS2( psrld xmm7, 16)
+
+#define Mul_Begin(n) \
+ MulPrologue \
+ AS2( mov esi, esp)\
+ AS2( and esp, 0xfffffff0)\
+ AS2( sub esp, 48*n+16)\
+ AS1( push esi)\
+ AS2( xor edx, edx) \
+ ASL(1) \
+ ASS( pshufd xmm0, [eax+edx], 3,1,2,0) \
+ ASS( pshufd xmm1, [eax+edx], 2,0,3,1) \
+ ASS( pshufd xmm2, [edi+edx], 3,1,2,0) \
+ AS2( movdqa [esp+20+2*edx], xmm0) \
+ AS2( psrlq xmm0, 32) \
+ AS2( movdqa [esp+20+2*edx+16], xmm0) \
+ AS2( movdqa [esp+20+16*n+2*edx], xmm1) \
+ AS2( psrlq xmm1, 32) \
+ AS2( movdqa [esp+20+16*n+2*edx+16], xmm1) \
+ AS2( movdqa [esp+20+32*n+2*edx], xmm2) \
+ AS2( psrlq xmm2, 32) \
+ AS2( movdqa [esp+20+32*n+2*edx+16], xmm2) \
+ AS2( add edx, 16) \
+ AS2( cmp edx, 8*(n)) \
+ ASJ( jne, 1, b) \
+ AS2( lea edi, [esp+20])\
+ AS2( lea edx, [esp+20+16*n])\
+ AS2( lea esi, [esp+20+32*n])\
+ SSE2_FirstMultiply(0) \
+
+#define Mul_Acc(i) \
+ ASL(LMul##i) \
+ AS2( movdqa xmm1, [esi+i/2*(1-(i-2*(i/2))*2)*16]) \
+ AS2( movdqa xmm0, [edi-i/2*(1-(i-2*(i/2))*2)*16]) \
+ AS2( movdqa xmm2, [ebx]) \
+ AS2( pmuludq xmm0, xmm1) \
+ AS2( pmuludq xmm1, [edx-i/2*(1-(i-2*(i/2))*2)*16]) \
+ AS2( movdqa xmm3, xmm2) \
+ AS2( pand xmm2, xmm0) \
+ AS2( psrld xmm0, 16) \
+ AS2( paddd xmm4, xmm2) \
+ AS2( paddd xmm5, xmm0) \
+ AS2( pand xmm3, xmm1) \
+ AS2( psrld xmm1, 16) \
+ AS2( paddd xmm6, xmm3) \
+ AS2( paddd xmm7, xmm1) \
+
+#define Mul_Acc1(i)
+#define Mul_Acc2(i) ASC(call, LMul##i)
+#define Mul_Acc3(i) Mul_Acc2(i)
+#define Mul_Acc4(i) Mul_Acc2(i)
+#define Mul_Acc5(i) Mul_Acc2(i)
+#define Mul_Acc6(i) Mul_Acc2(i)
+#define Mul_Acc7(i) Mul_Acc2(i)
+#define Mul_Acc8(i) Mul_Acc2(i)
+#define Mul_Acc9(i) Mul_Acc2(i)
+#define Mul_Acc10(i) Mul_Acc2(i)
+#define Mul_Acc11(i) Mul_Acc2(i)
+#define Mul_Acc12(i) Mul_Acc2(i)
+#define Mul_Acc13(i) Mul_Acc2(i)
+#define Mul_Acc14(i) Mul_Acc2(i)
+#define Mul_Acc15(i) Mul_Acc2(i)
+#define Mul_Acc16(i) Mul_Acc2(i)
+
+#define Mul_Column1(k, i) \
+ SSE2_SaveShift(k) \
+ AS2( add esi, 16) \
+ SSE2_MulAdd45\
+ Mul_Acc##i(i) \
+
+#define Mul_Column0(k, i) \
+ SSE2_SaveShift(k) \
+ AS2( add edi, 16) \
+ AS2( add edx, 16) \
+ SSE2_MulAdd45\
+ Mul_Acc##i(i) \
+
+#define Bot_Acc(i) \
+ AS2( movdqa xmm1, [esi+i/2*(1-(i-2*(i/2))*2)*16]) \
+ AS2( movdqa xmm0, [edi-i/2*(1-(i-2*(i/2))*2)*16]) \
+ AS2( pmuludq xmm0, xmm1) \
+ AS2( pmuludq xmm1, [edx-i/2*(1-(i-2*(i/2))*2)*16]) \
+ AS2( paddq xmm4, xmm0) \
+ AS2( paddd xmm6, xmm1)
+
+#define Bot_SaveAcc(k) \
+ SSE2_SaveShift(k) \
+ AS2( add edi, 16) \
+ AS2( add edx, 16) \
+ AS2( movdqa xmm6, [esi]) \
+ AS2( movdqa xmm0, [edi]) \
+ AS2( pmuludq xmm0, xmm6) \
+ AS2( paddq xmm4, xmm0) \
+ AS2( psllq xmm5, 16) \
+ AS2( paddq xmm4, xmm5) \
+ AS2( pmuludq xmm6, [edx])
+
+#define Bot_End(n) \
+ AS2( movhlps xmm7, xmm6) \
+ AS2( paddd xmm6, xmm7) \
+ AS2( psllq xmm6, 32) \
+ AS2( paddd xmm4, xmm6) \
+ AS2( movq QWORD PTR [ecx+8*((n)-1)], xmm4) \
+ AS1( pop esp)\
+ MulEpilogue
+
+#define Top_Begin(n) \
+ TopPrologue \
+ AS2( mov edx, esp)\
+ AS2( and esp, 0xfffffff0)\
+ AS2( sub esp, 48*n+16)\
+ AS1( push edx)\
+ AS2( xor edx, edx) \
+ ASL(1) \
+ ASS( pshufd xmm0, [eax+edx], 3,1,2,0) \
+ ASS( pshufd xmm1, [eax+edx], 2,0,3,1) \
+ ASS( pshufd xmm2, [edi+edx], 3,1,2,0) \
+ AS2( movdqa [esp+20+2*edx], xmm0) \
+ AS2( psrlq xmm0, 32) \
+ AS2( movdqa [esp+20+2*edx+16], xmm0) \
+ AS2( movdqa [esp+20+16*n+2*edx], xmm1) \
+ AS2( psrlq xmm1, 32) \
+ AS2( movdqa [esp+20+16*n+2*edx+16], xmm1) \
+ AS2( movdqa [esp+20+32*n+2*edx], xmm2) \
+ AS2( psrlq xmm2, 32) \
+ AS2( movdqa [esp+20+32*n+2*edx+16], xmm2) \
+ AS2( add edx, 16) \
+ AS2( cmp edx, 8*(n)) \
+ ASJ( jne, 1, b) \
+ AS2( mov eax, esi) \
+ AS2( lea edi, [esp+20+00*n+16*(n/2-1)])\
+ AS2( lea edx, [esp+20+16*n+16*(n/2-1)])\
+ AS2( lea esi, [esp+20+32*n+16*(n/2-1)])\
+ AS2( pxor xmm4, xmm4)\
+ AS2( pxor xmm5, xmm5)
+
+#define Top_Acc(i) \
+ AS2( movq xmm0, QWORD PTR [esi+i/2*(1-(i-2*(i/2))*2)*16+8]) \
+ AS2( pmuludq xmm0, [edx-i/2*(1-(i-2*(i/2))*2)*16]) \
+ AS2( psrlq xmm0, 48) \
+ AS2( paddd xmm5, xmm0)\
+
+#define Top_Column0(i) \
+ AS2( psllq xmm5, 32) \
+ AS2( add edi, 16) \
+ AS2( add edx, 16) \
+ SSE2_MulAdd45\
+ Mul_Acc##i(i) \
+
+#define Top_Column1(i) \
+ SSE2_SaveShift(0) \
+ AS2( add esi, 16) \
+ SSE2_MulAdd45\
+ Mul_Acc##i(i) \
+ AS2( shr eax, 16) \
+ AS2( movd xmm0, eax)\
+ AS2( movd xmm1, [ecx+4])\
+ AS2( psrld xmm1, 16)\
+ AS2( pcmpgtd xmm1, xmm0)\
+ AS2( psrld xmm1, 31)\
+ AS2( paddd xmm4, xmm1)\
+
+void SSE2_Square4(word *C, const word *A)
+{
+ Squ_Begin(2)
+ Squ_Column0(0, 1)
+ Squ_End(2)
+}
+
+void SSE2_Square8(word *C, const word *A)
+{
+ Squ_Begin(4)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Squ_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Squ_Column0(0, 1)
+ Squ_Column1(1, 1)
+ Squ_Column0(2, 2)
+ Squ_Column1(3, 1)
+ Squ_Column0(4, 1)
+ Squ_End(4)
+}
+
+void SSE2_Square16(word *C, const word *A)
+{
+ Squ_Begin(8)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Squ_Acc(4) Squ_Acc(3) Squ_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Squ_Column0(0, 1)
+ Squ_Column1(1, 1)
+ Squ_Column0(2, 2)
+ Squ_Column1(3, 2)
+ Squ_Column0(4, 3)
+ Squ_Column1(5, 3)
+ Squ_Column0(6, 4)
+ Squ_Column1(7, 3)
+ Squ_Column0(8, 3)
+ Squ_Column1(9, 2)
+ Squ_Column0(10, 2)
+ Squ_Column1(11, 1)
+ Squ_Column0(12, 1)
+ Squ_End(8)
+}
+
+void SSE2_Square32(word *C, const word *A)
+{
+ Squ_Begin(16)
+ ASJ( jmp, 0, f)
+ Squ_Acc(8) Squ_Acc(7) Squ_Acc(6) Squ_Acc(5) Squ_Acc(4) Squ_Acc(3) Squ_Acc(2)
+ AS1( ret) ASL(0)
+ Squ_Column0(0, 1)
+ Squ_Column1(1, 1)
+ Squ_Column0(2, 2)
+ Squ_Column1(3, 2)
+ Squ_Column0(4, 3)
+ Squ_Column1(5, 3)
+ Squ_Column0(6, 4)
+ Squ_Column1(7, 4)
+ Squ_Column0(8, 5)
+ Squ_Column1(9, 5)
+ Squ_Column0(10, 6)
+ Squ_Column1(11, 6)
+ Squ_Column0(12, 7)
+ Squ_Column1(13, 7)
+ Squ_Column0(14, 8)
+ Squ_Column1(15, 7)
+ Squ_Column0(16, 7)
+ Squ_Column1(17, 6)
+ Squ_Column0(18, 6)
+ Squ_Column1(19, 5)
+ Squ_Column0(20, 5)
+ Squ_Column1(21, 4)
+ Squ_Column0(22, 4)
+ Squ_Column1(23, 3)
+ Squ_Column0(24, 3)
+ Squ_Column1(25, 2)
+ Squ_Column0(26, 2)
+ Squ_Column1(27, 1)
+ Squ_Column0(28, 1)
+ Squ_End(16)
+}
+
+void SSE2_Multiply4(word *C, const word *A, const word *B)
+{
+ Mul_Begin(2)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Mul_Column0(0, 2)
+ Mul_End(2)
+}
+
+void SSE2_Multiply8(word *C, const word *A, const word *B)
+{
+ Mul_Begin(4)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Mul_Column0(0, 2)
+ Mul_Column1(1, 3)
+ Mul_Column0(2, 4)
+ Mul_Column1(3, 3)
+ Mul_Column0(4, 2)
+ Mul_End(4)
+}
+
+void SSE2_Multiply16(word *C, const word *A, const word *B)
+{
+ Mul_Begin(8)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Mul_Column0(0, 2)
+ Mul_Column1(1, 3)
+ Mul_Column0(2, 4)
+ Mul_Column1(3, 5)
+ Mul_Column0(4, 6)
+ Mul_Column1(5, 7)
+ Mul_Column0(6, 8)
+ Mul_Column1(7, 7)
+ Mul_Column0(8, 6)
+ Mul_Column1(9, 5)
+ Mul_Column0(10, 4)
+ Mul_Column1(11, 3)
+ Mul_Column0(12, 2)
+ Mul_End(8)
+}
+
+void SSE2_Multiply32(word *C, const word *A, const word *B)
+{
+ Mul_Begin(16)
+ ASJ( jmp, 0, f)
+ Mul_Acc(16) Mul_Acc(15) Mul_Acc(14) Mul_Acc(13) Mul_Acc(12) Mul_Acc(11) Mul_Acc(10) Mul_Acc(9) Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+ Mul_Column0(0, 2)
+ Mul_Column1(1, 3)
+ Mul_Column0(2, 4)
+ Mul_Column1(3, 5)
+ Mul_Column0(4, 6)
+ Mul_Column1(5, 7)
+ Mul_Column0(6, 8)
+ Mul_Column1(7, 9)
+ Mul_Column0(8, 10)
+ Mul_Column1(9, 11)
+ Mul_Column0(10, 12)
+ Mul_Column1(11, 13)
+ Mul_Column0(12, 14)
+ Mul_Column1(13, 15)
+ Mul_Column0(14, 16)
+ Mul_Column1(15, 15)
+ Mul_Column0(16, 14)
+ Mul_Column1(17, 13)
+ Mul_Column0(18, 12)
+ Mul_Column1(19, 11)
+ Mul_Column0(20, 10)
+ Mul_Column1(21, 9)
+ Mul_Column0(22, 8)
+ Mul_Column1(23, 7)
+ Mul_Column0(24, 6)
+ Mul_Column1(25, 5)
+ Mul_Column0(26, 4)
+ Mul_Column1(27, 3)
+ Mul_Column0(28, 2)
+ Mul_End(16)
+}
+
+void SSE2_MultiplyBottom4(word *C, const word *A, const word *B)
+{
+ Mul_Begin(2)
+ Bot_SaveAcc(0) Bot_Acc(2)
+ Bot_End(2)
+}
+
+void SSE2_MultiplyBottom8(word *C, const word *A, const word *B)
+{
+ Mul_Begin(4)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Mul_Column0(0, 2)
+ Mul_Column1(1, 3)
+ Bot_SaveAcc(2) Bot_Acc(4) Bot_Acc(3) Bot_Acc(2)
+ Bot_End(4)
+}
+
+void SSE2_MultiplyBottom16(word *C, const word *A, const word *B)
+{
+ Mul_Begin(8)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Mul_Column0(0, 2)
+ Mul_Column1(1, 3)
+ Mul_Column0(2, 4)
+ Mul_Column1(3, 5)
+ Mul_Column0(4, 6)
+ Mul_Column1(5, 7)
+ Bot_SaveAcc(6) Bot_Acc(8) Bot_Acc(7) Bot_Acc(6) Bot_Acc(5) Bot_Acc(4) Bot_Acc(3) Bot_Acc(2)
+ Bot_End(8)
+}
+
+void SSE2_MultiplyBottom32(word *C, const word *A, const word *B)
+{
+ Mul_Begin(16)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(15) Mul_Acc(14) Mul_Acc(13) Mul_Acc(12) Mul_Acc(11) Mul_Acc(10) Mul_Acc(9) Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Mul_Column0(0, 2)
+ Mul_Column1(1, 3)
+ Mul_Column0(2, 4)
+ Mul_Column1(3, 5)
+ Mul_Column0(4, 6)
+ Mul_Column1(5, 7)
+ Mul_Column0(6, 8)
+ Mul_Column1(7, 9)
+ Mul_Column0(8, 10)
+ Mul_Column1(9, 11)
+ Mul_Column0(10, 12)
+ Mul_Column1(11, 13)
+ Mul_Column0(12, 14)
+ Mul_Column1(13, 15)
+ Bot_SaveAcc(14) Bot_Acc(16) Bot_Acc(15) Bot_Acc(14) Bot_Acc(13) Bot_Acc(12) Bot_Acc(11) Bot_Acc(10) Bot_Acc(9) Bot_Acc(8) Bot_Acc(7) Bot_Acc(6) Bot_Acc(5) Bot_Acc(4) Bot_Acc(3) Bot_Acc(2)
+ Bot_End(16)
+}
+
+void SSE2_MultiplyTop8(word *C, const word *A, const word *B, word L)
+{
+ Top_Begin(4)
+ Top_Acc(3) Top_Acc(2) Top_Acc(1)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Top_Column0(4)
+ Top_Column1(3)
+ Mul_Column0(0, 2)
+ Top_End(2)
+}
+
+void SSE2_MultiplyTop16(word *C, const word *A, const word *B, word L)
+{
+ Top_Begin(8)
+ Top_Acc(7) Top_Acc(6) Top_Acc(5) Top_Acc(4) Top_Acc(3) Top_Acc(2) Top_Acc(1)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Top_Column0(8)
+ Top_Column1(7)
+ Mul_Column0(0, 6)
+ Mul_Column1(1, 5)
+ Mul_Column0(2, 4)
+ Mul_Column1(3, 3)
+ Mul_Column0(4, 2)
+ Top_End(4)
+}
+
+void SSE2_MultiplyTop32(word *C, const word *A, const word *B, word L)
+{
+ Top_Begin(16)
+ Top_Acc(15) Top_Acc(14) Top_Acc(13) Top_Acc(12) Top_Acc(11) Top_Acc(10) Top_Acc(9) Top_Acc(8) Top_Acc(7) Top_Acc(6) Top_Acc(5) Top_Acc(4) Top_Acc(3) Top_Acc(2) Top_Acc(1)
+#ifndef __GNUC__
+ ASJ( jmp, 0, f)
+ Mul_Acc(16) Mul_Acc(15) Mul_Acc(14) Mul_Acc(13) Mul_Acc(12) Mul_Acc(11) Mul_Acc(10) Mul_Acc(9) Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
+ AS1( ret) ASL(0)
+#endif
+ Top_Column0(16)
+ Top_Column1(15)
+ Mul_Column0(0, 14)
+ Mul_Column1(1, 13)
+ Mul_Column0(2, 12)
+ Mul_Column1(3, 11)
+ Mul_Column0(4, 10)
+ Mul_Column1(5, 9)
+ Mul_Column0(6, 8)
+ Mul_Column1(7, 7)
+ Mul_Column0(8, 6)
+ Mul_Column1(9, 5)
+ Mul_Column0(10, 4)
+ Mul_Column1(11, 3)
+ Mul_Column0(12, 2)
+ Top_End(8)
+}
+
+#endif // #if CRYPTOPP_INTEGER_SSE2
+
+// ********************************************************
+
+typedef int (CRYPTOPP_FASTCALL * PAdd)(size_t N, word *C, const word *A, const word *B);
+typedef void (* PMul)(word *C, const word *A, const word *B);
+typedef void (* PSqu)(word *C, const word *A);
+typedef void (* PMulTop)(word *C, const word *A, const word *B, word L);
+
+#if CRYPTOPP_INTEGER_SSE2
+static PAdd s_pAdd = &Baseline_Add, s_pSub = &Baseline_Sub;
+static size_t s_recursionLimit = 8;
+#else
+static const size_t s_recursionLimit = 16;
+#endif
+
+static PMul s_pMul[9], s_pBot[9];
+static PSqu s_pSqu[9];
+static PMulTop s_pTop[9];
+
+static void SetFunctionPointers()
+{
+ s_pMul[0] = &Baseline_Multiply2;
+ s_pBot[0] = &Baseline_MultiplyBottom2;
+ s_pSqu[0] = &Baseline_Square2;
+ s_pTop[0] = &Baseline_MultiplyTop2;
+ s_pTop[1] = &Baseline_MultiplyTop4;
+
+#if CRYPTOPP_INTEGER_SSE2
+ if (HasSSE2())
+ {
+#if _MSC_VER != 1200 || defined(NDEBUG)
+ if (IsP4())
+ {
+ s_pAdd = &SSE2_Add;
+ s_pSub = &SSE2_Sub;
+ }
+#endif
+
+ s_recursionLimit = 32;
+
+ s_pMul[1] = &SSE2_Multiply4;
+ s_pMul[2] = &SSE2_Multiply8;
+ s_pMul[4] = &SSE2_Multiply16;
+ s_pMul[8] = &SSE2_Multiply32;
+
+ s_pBot[1] = &SSE2_MultiplyBottom4;
+ s_pBot[2] = &SSE2_MultiplyBottom8;
+ s_pBot[4] = &SSE2_MultiplyBottom16;
+ s_pBot[8] = &SSE2_MultiplyBottom32;
+
+ s_pSqu[1] = &SSE2_Square4;
+ s_pSqu[2] = &SSE2_Square8;
+ s_pSqu[4] = &SSE2_Square16;
+ s_pSqu[8] = &SSE2_Square32;
+
+ s_pTop[2] = &SSE2_MultiplyTop8;
+ s_pTop[4] = &SSE2_MultiplyTop16;
+ s_pTop[8] = &SSE2_MultiplyTop32;
+ }
+ else
+#endif
+ {
+ s_pMul[1] = &Baseline_Multiply4;
+ s_pMul[2] = &Baseline_Multiply8;
+
+ s_pBot[1] = &Baseline_MultiplyBottom4;
+ s_pBot[2] = &Baseline_MultiplyBottom8;
+
+ s_pSqu[1] = &Baseline_Square4;
+ s_pSqu[2] = &Baseline_Square8;
+
+ s_pTop[2] = &Baseline_MultiplyTop8;
+
+#if !CRYPTOPP_INTEGER_SSE2
+ s_pMul[4] = &Baseline_Multiply16;
+ s_pBot[4] = &Baseline_MultiplyBottom16;
+ s_pSqu[4] = &Baseline_Square16;
+ s_pTop[4] = &Baseline_MultiplyTop16;
+#endif
+ }
+}
+
+inline int Add(word *C, const word *A, const word *B, size_t N)
+{
+#if CRYPTOPP_INTEGER_SSE2
+ return s_pAdd(N, C, A, B);
+#else
+ return Baseline_Add(N, C, A, B);
+#endif
+}
+
+inline int Subtract(word *C, const word *A, const word *B, size_t N)
+{
+#if CRYPTOPP_INTEGER_SSE2
+ return s_pSub(N, C, A, B);
+#else
+ return Baseline_Sub(N, C, A, B);
+#endif
+}
+
+// ********************************************************
+
+
+#define A0 A
+#define A1 (A+N2)
+#define B0 B
+#define B1 (B+N2)
+
+#define T0 T
+#define T1 (T+N2)
+#define T2 (T+N)
+#define T3 (T+N+N2)
+
+#define R0 R
+#define R1 (R+N2)
+#define R2 (R+N)
+#define R3 (R+N+N2)
+
+// R[2*N] - result = A*B
+// T[2*N] - temporary work space
+// A[N] --- multiplier
+// B[N] --- multiplicant
+
+void RecursiveMultiply(word *R, word *T, const word *A, const word *B, size_t N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N <= s_recursionLimit)
+ s_pMul[N/4](R, A, B);
+ else
+ {
+ const size_t N2 = N/2;
+
+ size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2;
+ Subtract(R0, A + AN2, A + (N2 ^ AN2), N2);
+
+ size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2;
+ Subtract(R1, B + BN2, B + (N2 ^ BN2), N2);
+
+ RecursiveMultiply(R2, T2, A1, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ RecursiveMultiply(R0, T2, A0, B0, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1), R[01] holds A0*B0, R[23] holds A1*B1
+
+ int c2 = Add(R2, R2, R1, N2);
+ int c3 = c2;
+ c2 += Add(R1, R2, R0, N2);
+ c3 += Add(R2, R2, R3, N2);
+
+ if (AN2 == BN2)
+ c3 -= Subtract(R1, R1, T0, N);
+ else
+ c3 += Add(R1, R1, T0, N);
+
+ c3 += Increment(R2, N2, c2);
+ assert (c3 >= 0 && c3 <= 2);
+ Increment(R3, N2, c3);
+ }
+}
+
+// R[2*N] - result = A*A
+// T[2*N] - temporary work space
+// A[N] --- number to be squared
+
+void RecursiveSquare(word *R, word *T, const word *A, size_t N)
+{
+ assert(N && N%2==0);
+
+ if (N <= s_recursionLimit)
+ s_pSqu[N/4](R, A);
+ else
+ {
+ const size_t N2 = N/2;
+
+ RecursiveSquare(R0, T2, A0, N2);
+ RecursiveSquare(R2, T2, A1, N2);
+ RecursiveMultiply(T0, T2, A0, A1, N2);
+
+ int carry = Add(R1, R1, T0, N);
+ carry += Add(R1, R1, T0, N);
+ Increment(R3, N2, carry);
+ }
+}
+
+// R[N] - bottom half of A*B
+// T[3*N/2] - temporary work space
+// A[N] - multiplier
+// B[N] - multiplicant
+
+void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N <= s_recursionLimit)
+ s_pBot[N/4](R, A, B);
+ else
+ {
+ const size_t N2 = N/2;
+
+ RecursiveMultiply(R, T, A0, B0, N2);
+ RecursiveMultiplyBottom(T0, T1, A1, B0, N2);
+ Add(R1, R1, T0, N2);
+ RecursiveMultiplyBottom(T0, T1, A0, B1, N2);
+ Add(R1, R1, T0, N2);
+ }
+}
+
+// R[N] --- upper half of A*B
+// T[2*N] - temporary work space
+// L[N] --- lower half of A*B
+// A[N] --- multiplier
+// B[N] --- multiplicant
+
+void MultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, size_t N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N <= s_recursionLimit)
+ s_pTop[N/4](R, A, B, L[N-1]);
+ else
+ {
+ const size_t N2 = N/2;
+
+ size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2;
+ Subtract(R0, A + AN2, A + (N2 ^ AN2), N2);
+
+ size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2;
+ Subtract(R1, B + BN2, B + (N2 ^ BN2), N2);
+
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ RecursiveMultiply(R0, T2, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1) = A1*B0+A0*B1-A1*B1-A0*B0, R[01] holds A1*B1
+
+ int t, c3;
+ int c2 = Subtract(T2, L+N2, L, N2);
+
+ if (AN2 == BN2)
+ {
+ c2 -= Add(T2, T2, T0, N2);
+ t = (Compare(T2, R0, N2) == -1);
+ c3 = t - Subtract(T2, T2, T1, N2);
+ }
+ else
+ {
+ c2 += Subtract(T2, T2, T0, N2);
+ t = (Compare(T2, R0, N2) == -1);
+ c3 = t + Add(T2, T2, T1, N2);
+ }
+
+ c2 += t;
+ if (c2 >= 0)
+ c3 += Increment(T2, N2, c2);
+ else
+ c3 -= Decrement(T2, N2, -c2);
+ c3 += Add(R0, T2, R1, N2);
+
+ assert (c3 >= 0 && c3 <= 2);
+ Increment(R1, N2, c3);
+ }
+}
+
+inline void Multiply(word *R, word *T, const word *A, const word *B, size_t N)
+{
+ RecursiveMultiply(R, T, A, B, N);
+}
+
+inline void Square(word *R, word *T, const word *A, size_t N)
+{
+ RecursiveSquare(R, T, A, N);
+}
+
+inline void MultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N)
+{
+ RecursiveMultiplyBottom(R, T, A, B, N);
+}
+
+// R[NA+NB] - result = A*B
+// T[NA+NB] - temporary work space
+// A[NA] ---- multiplier
+// B[NB] ---- multiplicant
+
+void AsymmetricMultiply(word *R, word *T, const word *A, size_t NA, const word *B, size_t NB)
+{
+ if (NA == NB)
+ {
+ if (A == B)
+ Square(R, T, A, NA);
+ else
+ Multiply(R, T, A, B, NA);
+
+ return;
+ }
+
+ if (NA > NB)
+ {
+ std::swap(A, B);
+ std::swap(NA, NB);
+ }
+
+ assert(NB % NA == 0);
+
+ if (NA==2 && !A[1])
+ {
+ switch (A[0])
+ {
+ case 0:
+ SetWords(R, 0, NB+2);
+ return;
+ case 1:
+ CopyWords(R, B, NB);
+ R[NB] = R[NB+1] = 0;
+ return;
+ default:
+ R[NB] = LinearMultiply(R, B, A[0], NB);
+ R[NB+1] = 0;
+ return;
+ }
+ }
+
+ size_t i;
+ if ((NB/NA)%2 == 0)
+ {
+ Multiply(R, T, A, B, NA);
+ CopyWords(T+2*NA, R+NA, NA);
+
+ for (i=2*NA; i<NB; i+=2*NA)
+ Multiply(T+NA+i, T, A, B+i, NA);
+ for (i=NA; i<NB; i+=2*NA)
+ Multiply(R+i, T, A, B+i, NA);
+ }
+ else
+ {
+ for (i=0; i<NB; i+=2*NA)
+ Multiply(R+i, T, A, B+i, NA);
+ for (i=NA; i<NB; i+=2*NA)
+ Multiply(T+NA+i, T, A, B+i, NA);
+ }
+
+ if (Add(R+NA, R+NA, T+2*NA, NB-NA))
+ Increment(R+NB, NA);
+}
+
+// R[N] ----- result = A inverse mod 2**(WORD_BITS*N)
+// T[3*N/2] - temporary work space
+// A[N] ----- an odd number as input
+
+void RecursiveInverseModPower2(word *R, word *T, const word *A, size_t N)
+{
+ if (N==2)
+ {
+ T[0] = AtomicInverseModPower2(A[0]);
+ T[1] = 0;
+ s_pBot[0](T+2, T, A);
+ TwosComplement(T+2, 2);
+ Increment(T+2, 2, 2);
+ s_pBot[0](R, T, T+2);
+ }
+ else
+ {
+ const size_t N2 = N/2;
+ RecursiveInverseModPower2(R0, T0, A0, N2);
+ T0[0] = 1;
+ SetWords(T0+1, 0, N2-1);
+ MultiplyTop(R1, T1, T0, R0, A0, N2);
+ MultiplyBottom(T0, T1, R0, A1, N2);
+ Add(T0, R1, T0, N2);
+ TwosComplement(T0, N2);
+ MultiplyBottom(R1, T1, R0, T0, N2);
+ }
+}
+
+// R[N] --- result = X/(2**(WORD_BITS*N)) mod M
+// T[3*N] - temporary work space
+// X[2*N] - number to be reduced
+// M[N] --- modulus
+// U[N] --- multiplicative inverse of M mod 2**(WORD_BITS*N)
+
+void MontgomeryReduce(word *R, word *T, word *X, const word *M, const word *U, size_t N)
+{
+#if 1
+ MultiplyBottom(R, T, X, U, N);
+ MultiplyTop(T, T+N, X, R, M, N);
+ word borrow = Subtract(T, X+N, T, N);
+ // defend against timing attack by doing this Add even when not needed
+ word carry = Add(T+N, T, M, N);
+ assert(carry | !borrow);
+ CopyWords(R, T + ((0-borrow) & N), N);
+#elif 0
+ const word u = 0-U[0];
+ Declare2Words(p)
+ for (size_t i=0; i<N; i++)
+ {
+ const word t = u * X[i];
+ word c = 0;
+ for (size_t j=0; j<N; j+=2)
+ {
+ MultiplyWords(p, t, M[j]);
+ Acc2WordsBy1(p, X[i+j]);
+ Acc2WordsBy1(p, c);
+ X[i+j] = LowWord(p);
+ c = HighWord(p);
+ MultiplyWords(p, t, M[j+1]);
+ Acc2WordsBy1(p, X[i+j+1]);
+ Acc2WordsBy1(p, c);
+ X[i+j+1] = LowWord(p);
+ c = HighWord(p);
+ }
+
+ if (Increment(X+N+i, N-i, c))
+ while (!Subtract(X+N, X+N, M, N)) {}
+ }
+
+ memcpy(R, X+N, N*WORD_SIZE);
+#else
+ __m64 u = _mm_cvtsi32_si64(0-U[0]), p;
+ for (size_t i=0; i<N; i++)
+ {
+ __m64 t = _mm_cvtsi32_si64(X[i]);
+ t = _mm_mul_su32(t, u);
+ __m64 c = _mm_setzero_si64();
+ for (size_t j=0; j<N; j+=2)
+ {
+ p = _mm_mul_su32(t, _mm_cvtsi32_si64(M[j]));
+ p = _mm_add_si64(p, _mm_cvtsi32_si64(X[i+j]));
+ c = _mm_add_si64(c, p);
+ X[i+j] = _mm_cvtsi64_si32(c);
+ c = _mm_srli_si64(c, 32);
+ p = _mm_mul_su32(t, _mm_cvtsi32_si64(M[j+1]));
+ p = _mm_add_si64(p, _mm_cvtsi32_si64(X[i+j+1]));
+ c = _mm_add_si64(c, p);
+ X[i+j+1] = _mm_cvtsi64_si32(c);
+ c = _mm_srli_si64(c, 32);
+ }
+
+ if (Increment(X+N+i, N-i, _mm_cvtsi64_si32(c)))
+ while (!Subtract(X+N, X+N, M, N)) {}
+ }
+
+ memcpy(R, X+N, N*WORD_SIZE);
+ _mm_empty();
+#endif
+}
+
+// R[N] --- result = X/(2**(WORD_BITS*N/2)) mod M
+// T[2*N] - temporary work space
+// X[2*N] - number to be reduced
+// M[N] --- modulus
+// U[N/2] - multiplicative inverse of M mod 2**(WORD_BITS*N/2)
+// V[N] --- 2**(WORD_BITS*3*N/2) mod M
+
+void HalfMontgomeryReduce(word *R, word *T, const word *X, const word *M, const word *U, const word *V, size_t N)
+{
+ assert(N%2==0 && N>=4);
+
+#define M0 M
+#define M1 (M+N2)
+#define V0 V
+#define V1 (V+N2)
+
+#define X0 X
+#define X1 (X+N2)
+#define X2 (X+N)
+#define X3 (X+N+N2)
+
+ const size_t N2 = N/2;
+ Multiply(T0, T2, V0, X3, N2);
+ int c2 = Add(T0, T0, X0, N);
+ MultiplyBottom(T3, T2, T0, U, N2);
+ MultiplyTop(T2, R, T0, T3, M0, N2);
+ c2 -= Subtract(T2, T1, T2, N2);
+ Multiply(T0, R, T3, M1, N2);
+ c2 -= Subtract(T0, T2, T0, N2);
+ int c3 = -(int)Subtract(T1, X2, T1, N2);
+ Multiply(R0, T2, V1, X3, N2);
+ c3 += Add(R, R, T, N);
+
+ if (c2>0)
+ c3 += Increment(R1, N2);
+ else if (c2<0)
+ c3 -= Decrement(R1, N2, -c2);
+
+ assert(c3>=-1 && c3<=1);
+ if (c3>0)
+ Subtract(R, R, M, N);
+ else if (c3<0)
+ Add(R, R, M, N);
+
+#undef M0
+#undef M1
+#undef V0
+#undef V1
+
+#undef X0
+#undef X1
+#undef X2
+#undef X3
+}
+
+#undef A0
+#undef A1
+#undef B0
+#undef B1
+
+#undef T0
+#undef T1
+#undef T2
+#undef T3
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+
+/*
+// do a 3 word by 2 word divide, returns quotient and leaves remainder in A
+static word SubatomicDivide(word *A, word B0, word B1)
+{
+ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a word
+ assert(A[2] < B1 || (A[2]==B1 && A[1] < B0));
+
+ // estimate the quotient: do a 2 word by 1 word divide
+ word Q;
+ if (B1+1 == 0)
+ Q = A[2];
+ else
+ Q = DWord(A[1], A[2]).DividedBy(B1+1);
+
+ // now subtract Q*B from A
+ DWord p = DWord::Multiply(B0, Q);
+ DWord u = (DWord) A[0] - p.GetLowHalf();
+ A[0] = u.GetLowHalf();
+ u = (DWord) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - DWord::Multiply(B1, Q);
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+
+ // Q <= actual quotient, so fix it
+ while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
+ {
+ u = (DWord) A[0] - B0;
+ A[0] = u.GetLowHalf();
+ u = (DWord) A[1] - B1 - u.GetHighHalfAsBorrow();
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+ Q++;
+ assert(Q); // shouldn't overflow
+ }
+
+ return Q;
+}
+
+// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1
+static inline void AtomicDivide(word *Q, const word *A, const word *B)
+{
+ if (!B[0] && !B[1]) // if divisor is 0, we assume divisor==2**(2*WORD_BITS)
+ {
+ Q[0] = A[2];
+ Q[1] = A[3];
+ }
+ else
+ {
+ word T[4];
+ T[0] = A[0]; T[1] = A[1]; T[2] = A[2]; T[3] = A[3];
+ Q[1] = SubatomicDivide(T+1, B[0], B[1]);
+ Q[0] = SubatomicDivide(T, B[0], B[1]);
+
+#ifndef NDEBUG
+ // multiply quotient and divisor and add remainder, make sure it equals dividend
+ assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
+ word P[4];
+ LowLevel::Multiply2(P, Q, B);
+ Add(P, P, T, 4);
+ assert(memcmp(P, A, 4*WORD_SIZE)==0);
+#endif
+ }
+}
+*/
+
+static inline void AtomicDivide(word *Q, const word *A, const word *B)
+{
+ word T[4];
+ DWord q = DivideFourWordsByTwo<word, DWord>(T, DWord(A[0], A[1]), DWord(A[2], A[3]), DWord(B[0], B[1]));
+ Q[0] = q.GetLowHalf();
+ Q[1] = q.GetHighHalf();
+
+#ifndef NDEBUG
+ if (B[0] || B[1])
+ {
+ // multiply quotient and divisor and add remainder, make sure it equals dividend
+ assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
+ word P[4];
+ s_pMul[0](P, Q, B);
+ Add(P, P, T, 4);
+ assert(memcmp(P, A, 4*WORD_SIZE)==0);
+ }
+#endif
+}
+
+// for use by Divide(), corrects the underestimated quotient {Q1,Q0}
+static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B, size_t N)
+{
+ assert(N && N%2==0);
+
+ AsymmetricMultiply(T, T+N+2, Q, 2, B, N);
+
+ word borrow = Subtract(R, R, T, N+2);
+ assert(!borrow && !R[N+1]);
+
+ while (R[N] || Compare(R, B, N) >= 0)
+ {
+ R[N] -= Subtract(R, R, B, N);
+ Q[1] += (++Q[0]==0);
+ assert(Q[0] || Q[1]); // no overflow
+ }
+}
+
+// R[NB] -------- remainder = A%B
+// Q[NA-NB+2] --- quotient = A/B
+// T[NA+3*(NB+2)] - temp work space
+// A[NA] -------- dividend
+// B[NB] -------- divisor
+
+void Divide(word *R, word *Q, word *T, const word *A, size_t NA, const word *B, size_t NB)
+{
+ assert(NA && NB && NA%2==0 && NB%2==0);
+ assert(B[NB-1] || B[NB-2]);
+ assert(NB <= NA);
+
+ // set up temporary work space
+ word *const TA=T;
+ word *const TB=T+NA+2;
+ word *const TP=T+NA+2+NB;
+
+ // copy B into TB and normalize it so that TB has highest bit set to 1
+ unsigned shiftWords = (B[NB-1]==0);
+ TB[0] = TB[NB-1] = 0;
+ CopyWords(TB+shiftWords, B, NB-shiftWords);
+ unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]);
+ assert(shiftBits < WORD_BITS);
+ ShiftWordsLeftByBits(TB, NB, shiftBits);
+
+ // copy A into TA and normalize it
+ TA[0] = TA[NA] = TA[NA+1] = 0;
+ CopyWords(TA+shiftWords, A, NA);
+ ShiftWordsLeftByBits(TA, NA+2, shiftBits);
+
+ if (TA[NA+1]==0 && TA[NA] <= 1)
+ {
+ Q[NA-NB+1] = Q[NA-NB] = 0;
+ while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0)
+ {
+ TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB);
+ ++Q[NA-NB];
+ }
+ }
+ else
+ {
+ NA+=2;
+ assert(Compare(TA+NA-NB, TB, NB) < 0);
+ }
+
+ word BT[2];
+ BT[0] = TB[NB-2] + 1;
+ BT[1] = TB[NB-1] + (BT[0]==0);
+
+ // start reducing TA mod TB, 2 words at a time
+ for (size_t i=NA-2; i>=NB; i-=2)
+ {
+ AtomicDivide(Q+i-NB, TA+i-2, BT);
+ CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB);
+ }
+
+ // copy TA into R, and denormalize it
+ CopyWords(R, TA+shiftWords, NB);
+ ShiftWordsRightByBits(R, NB, shiftBits);
+}
+
+static inline size_t EvenWordCount(const word *X, size_t N)
+{
+ while (N && X[N-2]==0 && X[N-1]==0)
+ N-=2;
+ return N;
+}
+
+// return k
+// R[N] --- result = A^(-1) * 2^k mod M
+// T[4*N] - temporary work space
+// A[NA] -- number to take inverse of
+// M[N] --- modulus
+
+unsigned int AlmostInverse(word *R, word *T, const word *A, size_t NA, const word *M, size_t N)
+{
+ assert(NA<=N && N && N%2==0);
+
+ word *b = T;
+ word *c = T+N;
+ word *f = T+2*N;
+ word *g = T+3*N;
+ size_t bcLen=2, fgLen=EvenWordCount(M, N);
+ unsigned int k=0;
+ bool s=false;
+
+ SetWords(T, 0, 3*N);
+ b[0]=1;
+ CopyWords(f, A, NA);
+ CopyWords(g, M, N);
+
+ while (1)
+ {
+ word t=f[0];
+ while (!t)
+ {
+ if (EvenWordCount(f, fgLen)==0)
+ {
+ SetWords(R, 0, N);
+ return 0;
+ }
+
+ ShiftWordsRightByWords(f, fgLen, 1);
+ bcLen += 2 * (c[bcLen-1] != 0);
+ assert(bcLen <= N);
+ ShiftWordsLeftByWords(c, bcLen, 1);
+ k+=WORD_BITS;
+ t=f[0];
+ }
+
+ unsigned int i = TrailingZeros(t);
+ t >>= i;
+ k += i;
+
+ if (t==1 && f[1]==0 && EvenWordCount(f+2, fgLen-2)==0)
+ {
+ if (s)
+ Subtract(R, M, b, N);
+ else
+ CopyWords(R, b, N);
+ return k;
+ }
+
+ ShiftWordsRightByBits(f, fgLen, i);
+ t = ShiftWordsLeftByBits(c, bcLen, i);
+ c[bcLen] += t;
+ bcLen += 2 * (t!=0);
+ assert(bcLen <= N);
+
+ bool swap = Compare(f, g, fgLen)==-1;
+ ConditionalSwapPointers(swap, f, g);
+ ConditionalSwapPointers(swap, b, c);
+ s ^= swap;
+
+ fgLen -= 2 * !(f[fgLen-2] | f[fgLen-1]);
+
+ Subtract(f, f, g, fgLen);
+ t = Add(b, b, c, bcLen);
+ b[bcLen] += t;
+ bcLen += 2*t;
+ assert(bcLen <= N);
+ }
+}
+
+// R[N] - result = A/(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void DivideByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ {
+ if (R[0]%2==0)
+ ShiftWordsRightByBits(R, N, 1);
+ else
+ {
+ word carry = Add(R, R, M, N);
+ ShiftWordsRightByBits(R, N, 1);
+ R[N-1] += carry<<(WORD_BITS-1);
+ }
+ }
+}
+
+// R[N] - result = A*(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void MultiplyByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0)
+ Subtract(R, R, M, N);
+}
+
+// ******************************************************************
+
+InitializeInteger::InitializeInteger()
+{
+ if (!g_pAssignIntToInteger)
+ {
+ SetFunctionPointers();
+ g_pAssignIntToInteger = AssignIntToInteger;
+ }
+}
+
+static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8};
+
+static inline size_t RoundupSize(size_t n)
+{
+ if (n<=8)
+ return RoundupSizeTable[n];
+ else if (n<=16)
+ return 16;
+ else if (n<=32)
+ return 32;
+ else if (n<=64)
+ return 64;
+ else return size_t(1) << BitPrecision(n-1);
+}
+
+Integer::Integer()
+ : reg(2), sign(POSITIVE)
+{
+ reg[0] = reg[1] = 0;
+}
+
+Integer::Integer(const Integer& t)
+ : reg(RoundupSize(t.WordCount())), sign(t.sign)
+{
+ CopyWords(reg, t.reg, reg.size());
+}
+
+Integer::Integer(Sign s, lword value)
+ : reg(2), sign(s)
+{
+ reg[0] = word(value);
+ reg[1] = word(SafeRightShift<WORD_BITS>(value));
+}
+
+Integer::Integer(signed long value)
+ : reg(2)
+{
+ if (value >= 0)
+ sign = POSITIVE;
+ else
+ {
+ sign = NEGATIVE;
+ value = -value;
+ }
+ reg[0] = word(value);
+ reg[1] = word(SafeRightShift<WORD_BITS>((unsigned long)value));
+}
+
+Integer::Integer(Sign s, word high, word low)
+ : reg(2), sign(s)
+{
+ reg[0] = low;
+ reg[1] = high;
+}
+
+bool Integer::IsConvertableToLong() const
+{
+ if (ByteCount() > sizeof(long))
+ return false;
+
+ unsigned long value = (unsigned long)reg[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>((unsigned long)reg[1]);
+
+ if (sign==POSITIVE)
+ return (signed long)value >= 0;
+ else
+ return -(signed long)value < 0;
+}
+
+signed long Integer::ConvertToLong() const
+{
+ assert(IsConvertableToLong());
+
+ unsigned long value = (unsigned long)reg[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>((unsigned long)reg[1]);
+ return sign==POSITIVE ? value : -(signed long)value;
+}
+
+Integer::Integer(BufferedTransformation &encodedInteger, size_t byteCount, Signedness s)
+{
+ Decode(encodedInteger, byteCount, s);
+}
+
+Integer::Integer(const byte *encodedInteger, size_t byteCount, Signedness s)
+{
+ Decode(encodedInteger, byteCount, s);
+}
+
+Integer::Integer(BufferedTransformation &bt)
+{
+ BERDecode(bt);
+}
+
+Integer::Integer(RandomNumberGenerator &rng, size_t bitcount)
+{
+ Randomize(rng, bitcount);
+}
+
+Integer::Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod)
+{
+ if (!Randomize(rng, min, max, rnType, equiv, mod))
+ throw Integer::RandomNumberNotFound();
+}
+
+Integer Integer::Power2(size_t e)
+{
+ Integer r((word)0, BitsToWords(e+1));
+ r.SetBit(e);
+ return r;
+}
+
+template <long i>
+struct NewInteger
+{
+ Integer * operator()() const
+ {
+ return new Integer(i);
+ }
+};
+
+const Integer &Integer::Zero()
+{
+ return Singleton<Integer>().Ref();
+}
+
+const Integer &Integer::One()
+{
+ return Singleton<Integer, NewInteger<1> >().Ref();
+}
+
+const Integer &Integer::Two()
+{
+ return Singleton<Integer, NewInteger<2> >().Ref();
+}
+
+bool Integer::operator!() const
+{
+ return IsNegative() ? false : (reg[0]==0 && WordCount()==0);
+}
+
+Integer& Integer::operator=(const Integer& t)
+{
+ if (this != &t)
+ {
+ if (reg.size() != t.reg.size() || t.reg[t.reg.size()/2] == 0)
+ reg.New(RoundupSize(t.WordCount()));
+ CopyWords(reg, t.reg, reg.size());
+ sign = t.sign;
+ }
+ return *this;
+}
+
+bool Integer::GetBit(size_t n) const
+{
+ if (n/WORD_BITS >= reg.size())
+ return 0;
+ else
+ return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1);
+}
+
+void Integer::SetBit(size_t n, bool value)
+{
+ if (value)
+ {
+ reg.CleanGrow(RoundupSize(BitsToWords(n+1)));
+ reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
+ }
+ else
+ {
+ if (n/WORD_BITS < reg.size())
+ reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
+ }
+}
+
+byte Integer::GetByte(size_t n) const
+{
+ if (n/WORD_SIZE >= reg.size())
+ return 0;
+ else
+ return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
+}
+
+void Integer::SetByte(size_t n, byte value)
+{
+ reg.CleanGrow(RoundupSize(BytesToWords(n+1)));
+ reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
+ reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
+}
+
+lword Integer::GetBits(size_t i, size_t n) const
+{
+ lword v = 0;
+ assert(n <= sizeof(v)*8);
+ for (unsigned int j=0; j<n; j++)
+ v |= lword(GetBit(i+j)) << j;
+ return v;
+}
+
+Integer Integer::operator-() const
+{
+ Integer result(*this);
+ result.Negate();
+ return result;
+}
+
+Integer Integer::AbsoluteValue() const
+{
+ Integer result(*this);
+ result.sign = POSITIVE;
+ return result;
+}
+
+void Integer::swap(Integer &a)
+{
+ reg.swap(a.reg);
+ std::swap(sign, a.sign);
+}
+
+Integer::Integer(word value, size_t length)
+ : reg(RoundupSize(length)), sign(POSITIVE)
+{
+ reg[0] = value;
+ SetWords(reg+1, 0, reg.size()-1);
+}
+
+template <class T>
+static Integer StringToInteger(const T *str)
+{
+ int radix;
+ // GCC workaround
+ // std::char_traits<wchar_t>::length() not defined in GCC 3.2 and STLport 4.5.3
+ unsigned int length;
+ for (length = 0; str[length] != 0; length++) {}
+
+ Integer v;
+
+ if (length == 0)
+ return v;
+
+ switch (str[length-1])
+ {
+ case 'h':
+ case 'H':
+ radix=16;
+ break;
+ case 'o':
+ case 'O':
+ radix=8;
+ break;
+ case 'b':
+ case 'B':
+ radix=2;
+ break;
+ default:
+ radix=10;
+ }
+
+ if (length > 2 && str[0] == '0' && str[1] == 'x')
+ radix = 16;
+
+ for (unsigned i=0; i<length; i++)
+ {
+ int digit;
+
+ if (str[i] >= '0' && str[i] <= '9')
+ digit = str[i] - '0';
+ else if (str[i] >= 'A' && str[i] <= 'F')
+ digit = str[i] - 'A' + 10;
+ else if (str[i] >= 'a' && str[i] <= 'f')
+ digit = str[i] - 'a' + 10;
+ else
+ digit = radix;
+
+ if (digit < radix)
+ {
+ v *= radix;
+ v += digit;
+ }
+ }
+
+ if (str[0] == '-')
+ v.Negate();
+
+ return v;
+}
+
+Integer::Integer(const char *str)
+ : reg(2), sign(POSITIVE)
+{
+ *this = StringToInteger(str);
+}
+
+Integer::Integer(const wchar_t *str)
+ : reg(2), sign(POSITIVE)
+{
+ *this = StringToInteger(str);
+}
+
+unsigned int Integer::WordCount() const
+{
+ return (unsigned int)CountWords(reg, reg.size());
+}
+
+unsigned int Integer::ByteCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]);
+ else
+ return 0;
+}
+
+unsigned int Integer::BitCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]);
+ else
+ return 0;
+}
+
+void Integer::Decode(const byte *input, size_t inputLen, Signedness s)
+{
+ StringStore store(input, inputLen);
+ Decode(store, inputLen, s);
+}
+
+void Integer::Decode(BufferedTransformation &bt, size_t inputLen, Signedness s)
+{
+ assert(bt.MaxRetrievable() >= inputLen);
+
+ byte b;
+ bt.Peek(b);
+ sign = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE;
+
+ while (inputLen>0 && (sign==POSITIVE ? b==0 : b==0xff))
+ {
+ bt.Skip(1);
+ inputLen--;
+ bt.Peek(b);
+ }
+
+ reg.CleanNew(RoundupSize(BytesToWords(inputLen)));
+
+ for (size_t i=inputLen; i > 0; i--)
+ {
+ bt.Get(b);
+ reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8;
+ }
+
+ if (sign == NEGATIVE)
+ {
+ for (size_t i=inputLen; i<reg.size()*WORD_SIZE; i++)
+ reg[i/WORD_SIZE] |= word(0xff) << (i%WORD_SIZE)*8;
+ TwosComplement(reg, reg.size());
+ }
+}
+
+size_t Integer::MinEncodedSize(Signedness signedness) const
+{
+ unsigned int outputLen = STDMAX(1U, ByteCount());
+ if (signedness == UNSIGNED)
+ return outputLen;
+ if (NotNegative() && (GetByte(outputLen-1) & 0x80))
+ outputLen++;
+ if (IsNegative() && *this < -Power2(outputLen*8-1))
+ outputLen++;
+ return outputLen;
+}
+
+void Integer::Encode(byte *output, size_t outputLen, Signedness signedness) const
+{
+ ArraySink sink(output, outputLen);
+ Encode(sink, outputLen, signedness);
+}
+
+void Integer::Encode(BufferedTransformation &bt, size_t outputLen, Signedness signedness) const
+{
+ if (signedness == UNSIGNED || NotNegative())
+ {
+ for (size_t i=outputLen; i > 0; i--)
+ bt.Put(GetByte(i-1));
+ }
+ else
+ {
+ // take two's complement of *this
+ Integer temp = Integer::Power2(8*STDMAX((size_t)ByteCount(), outputLen)) + *this;
+ temp.Encode(bt, outputLen, UNSIGNED);
+ }
+}
+
+void Integer::DEREncode(BufferedTransformation &bt) const
+{
+ DERGeneralEncoder enc(bt, INTEGER);
+ Encode(enc, MinEncodedSize(SIGNED), SIGNED);
+ enc.MessageEnd();
+}
+
+void Integer::BERDecode(const byte *input, size_t len)
+{
+ StringStore store(input, len);
+ BERDecode(store);
+}
+
+void Integer::BERDecode(BufferedTransformation &bt)
+{
+ BERGeneralDecoder dec(bt, INTEGER);
+ if (!dec.IsDefiniteLength() || dec.MaxRetrievable() < dec.RemainingLength())
+ BERDecodeError();
+ Decode(dec, (size_t)dec.RemainingLength(), SIGNED);
+ dec.MessageEnd();
+}
+
+void Integer::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const
+{
+ DERGeneralEncoder enc(bt, OCTET_STRING);
+ Encode(enc, length);
+ enc.MessageEnd();
+}
+
+void Integer::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length)
+{
+ BERGeneralDecoder dec(bt, OCTET_STRING);
+ if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
+ BERDecodeError();
+ Decode(dec, length);
+ dec.MessageEnd();
+}
+
+size_t Integer::OpenPGPEncode(byte *output, size_t len) const
+{
+ ArraySink sink(output, len);
+ return OpenPGPEncode(sink);
+}
+
+size_t Integer::OpenPGPEncode(BufferedTransformation &bt) const
+{
+ word16 bitCount = BitCount();
+ bt.PutWord16(bitCount);
+ size_t byteCount = BitsToBytes(bitCount);
+ Encode(bt, byteCount);
+ return 2 + byteCount;
+}
+
+void Integer::OpenPGPDecode(const byte *input, size_t len)
+{
+ StringStore store(input, len);
+ OpenPGPDecode(store);
+}
+
+void Integer::OpenPGPDecode(BufferedTransformation &bt)
+{
+ word16 bitCount;
+ if (bt.GetWord16(bitCount) != 2 || bt.MaxRetrievable() < BitsToBytes(bitCount))
+ throw OpenPGPDecodeErr();
+ Decode(bt, BitsToBytes(bitCount));
+}
+
+void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits)
+{
+ const size_t nbytes = nbits/8 + 1;
+ SecByteBlock buf(nbytes);
+ rng.GenerateBlock(buf, nbytes);
+ if (nbytes)
+ buf[0] = (byte)Crop(buf[0], nbits % 8);
+ Decode(buf, nbytes, UNSIGNED);
+}
+
+void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max)
+{
+ if (min > max)
+ throw InvalidArgument("Integer: Min must be no greater than Max");
+
+ Integer range = max - min;
+ const unsigned int nbits = range.BitCount();
+
+ do
+ {
+ Randomize(rng, nbits);
+ }
+ while (*this > range);
+
+ *this += min;
+}
+
+bool Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod)
+{
+ return GenerateRandomNoThrow(rng, MakeParameters("Min", min)("Max", max)("RandomNumberType", rnType)("EquivalentTo", equiv)("Mod", mod));
+}
+
+class KDF2_RNG : public RandomNumberGenerator
+{
+public:
+ KDF2_RNG(const byte *seed, size_t seedSize)
+ : m_counter(0), m_counterAndSeed(seedSize + 4)
+ {
+ memcpy(m_counterAndSeed + 4, seed, seedSize);
+ }
+
+ void GenerateBlock(byte *output, size_t size)
+ {
+ PutWord(false, BIG_ENDIAN_ORDER, m_counterAndSeed, m_counter);
+ ++m_counter;
+ P1363_KDF2<SHA1>::DeriveKey(output, size, m_counterAndSeed, m_counterAndSeed.size(), NULL, 0);
+ }
+
+private:
+ word32 m_counter;
+ SecByteBlock m_counterAndSeed;
+};
+
+bool Integer::GenerateRandomNoThrow(RandomNumberGenerator &i_rng, const NameValuePairs &params)
+{
+ Integer min = params.GetValueWithDefault("Min", Integer::Zero());
+ Integer max;
+ if (!params.GetValue("Max", max))
+ {
+ int bitLength;
+ if (params.GetIntValue("BitLength", bitLength))
+ max = Integer::Power2(bitLength);
+ else
+ throw InvalidArgument("Integer: missing Max argument");
+ }
+ if (min > max)
+ throw InvalidArgument("Integer: Min must be no greater than Max");
+
+ Integer equiv = params.GetValueWithDefault("EquivalentTo", Integer::Zero());
+ Integer mod = params.GetValueWithDefault("Mod", Integer::One());
+
+ if (equiv.IsNegative() || equiv >= mod)
+ throw InvalidArgument("Integer: invalid EquivalentTo and/or Mod argument");
+
+ Integer::RandomNumberType rnType = params.GetValueWithDefault("RandomNumberType", Integer::ANY);
+
+ member_ptr<KDF2_RNG> kdf2Rng;
+ ConstByteArrayParameter seed;
+ if (params.GetValue(Name::Seed(), seed))
+ {
+ ByteQueue bq;
+ DERSequenceEncoder seq(bq);
+ min.DEREncode(seq);
+ max.DEREncode(seq);
+ equiv.DEREncode(seq);
+ mod.DEREncode(seq);
+ DEREncodeUnsigned(seq, rnType);
+ DEREncodeOctetString(seq, seed.begin(), seed.size());
+ seq.MessageEnd();
+
+ SecByteBlock finalSeed((size_t)bq.MaxRetrievable());
+ bq.Get(finalSeed, finalSeed.size());
+ kdf2Rng.reset(new KDF2_RNG(finalSeed.begin(), finalSeed.size()));
+ }
+ RandomNumberGenerator &rng = kdf2Rng.get() ? (RandomNumberGenerator &)*kdf2Rng : i_rng;
+
+ switch (rnType)
+ {
+ case ANY:
+ if (mod == One())
+ Randomize(rng, min, max);
+ else
+ {
+ Integer min1 = min + (equiv-min)%mod;
+ if (max < min1)
+ return false;
+ Randomize(rng, Zero(), (max - min1) / mod);
+ *this *= mod;
+ *this += min1;
+ }
+ return true;
+
+ case PRIME:
+ {
+ const PrimeSelector *pSelector = params.GetValueWithDefault(Name::PointerToPrimeSelector(), (const PrimeSelector *)NULL);
+
+ int i;
+ i = 0;
+ while (1)
+ {
+ if (++i==16)
+ {
+ // check if there are any suitable primes in [min, max]
+ Integer first = min;
+ if (FirstPrime(first, max, equiv, mod, pSelector))
+ {
+ // if there is only one suitable prime, we're done
+ *this = first;
+ if (!FirstPrime(first, max, equiv, mod, pSelector))
+ return true;
+ }
+ else
+ return false;
+ }
+
+ Randomize(rng, min, max);
+ if (FirstPrime(*this, STDMIN(*this+mod*PrimeSearchInterval(max), max), equiv, mod, pSelector))
+ return true;
+ }
+ }
+
+ default:
+ throw InvalidArgument("Integer: invalid RandomNumberType argument");
+ }
+}
+
+std::istream& operator>>(std::istream& in, Integer &a)
+{
+ char c;
+ unsigned int length = 0;
+ SecBlock<char> str(length + 16);
+
+ std::ws(in);
+
+ do
+ {
+ in.read(&c, 1);
+ str[length++] = c;
+ if (length >= str.size())
+ str.Grow(length + 16);
+ }
+ while (in && (c=='-' || c=='x' || (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F') || c=='h' || c=='H' || c=='o' || c=='O' || c==',' || c=='.'));
+
+ if (in.gcount())
+ in.putback(c);
+ str[length-1] = '\0';
+ a = Integer(str);
+
+ return in;
+}
+
+std::ostream& operator<<(std::ostream& out, const Integer &a)
+{
+ // Get relevant conversion specifications from ostream.
+ long f = out.flags() & std::ios::basefield; // Get base digits.
+ int base, block;
+ char suffix;
+ switch(f)
+ {
+ case std::ios::oct :
+ base = 8;
+ block = 8;
+ suffix = 'o';
+ break;
+ case std::ios::hex :
+ base = 16;
+ block = 4;
+ suffix = 'h';
+ break;
+ default :
+ base = 10;
+ block = 3;
+ suffix = '.';
+ }
+
+ Integer temp1=a, temp2;
+
+ if (a.IsNegative())
+ {
+ out << '-';
+ temp1.Negate();
+ }
+
+ if (!a)
+ out << '0';
+
+ static const char upper[]="0123456789ABCDEF";
+ static const char lower[]="0123456789abcdef";
+
+ const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower;
+ unsigned i=0;
+ SecBlock<char> s(a.BitCount() / (BitPrecision(base)-1) + 1);
+
+ while (!!temp1)
+ {
+ word digit;
+ Integer::Divide(digit, temp2, temp1, base);
+ s[i++]=vec[digit];
+ temp1.swap(temp2);
+ }
+
+ while (i--)
+ {
+ out << s[i];
+// if (i && !(i%block))
+// out << ",";
+ }
+ return out << suffix;
+}
+
+Integer& Integer::operator++()
+{
+ if (NotNegative())
+ {
+ if (Increment(reg, reg.size()))
+ {
+ reg.CleanGrow(2*reg.size());
+ reg[reg.size()/2]=1;
+ }
+ }
+ else
+ {
+ word borrow = Decrement(reg, reg.size());
+ assert(!borrow);
+ if (WordCount()==0)
+ *this = Zero();
+ }
+ return *this;
+}
+
+Integer& Integer::operator--()
+{
+ if (IsNegative())
+ {
+ if (Increment(reg, reg.size()))
+ {
+ reg.CleanGrow(2*reg.size());
+ reg[reg.size()/2]=1;
+ }
+ }
+ else
+ {
+ if (Decrement(reg, reg.size()))
+ *this = -One();
+ }
+ return *this;
+}
+
+void PositiveAdd(Integer &sum, const Integer &a, const Integer& b)
+{
+ int carry;
+ if (a.reg.size() == b.reg.size())
+ carry = Add(sum.reg, a.reg, b.reg, a.reg.size());
+ else if (a.reg.size() > b.reg.size())
+ {
+ carry = Add(sum.reg, a.reg, b.reg, b.reg.size());
+ CopyWords(sum.reg+b.reg.size(), a.reg+b.reg.size(), a.reg.size()-b.reg.size());
+ carry = Increment(sum.reg+b.reg.size(), a.reg.size()-b.reg.size(), carry);
+ }
+ else
+ {
+ carry = Add(sum.reg, a.reg, b.reg, a.reg.size());
+ CopyWords(sum.reg+a.reg.size(), b.reg+a.reg.size(), b.reg.size()-a.reg.size());
+ carry = Increment(sum.reg+a.reg.size(), b.reg.size()-a.reg.size(), carry);
+ }
+
+ if (carry)
+ {
+ sum.reg.CleanGrow(2*sum.reg.size());
+ sum.reg[sum.reg.size()/2] = 1;
+ }
+ sum.sign = Integer::POSITIVE;
+}
+
+void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b)
+{
+ unsigned aSize = a.WordCount();
+ aSize += aSize%2;
+ unsigned bSize = b.WordCount();
+ bSize += bSize%2;
+
+ if (aSize == bSize)
+ {
+ if (Compare(a.reg, b.reg, aSize) >= 0)
+ {
+ Subtract(diff.reg, a.reg, b.reg, aSize);
+ diff.sign = Integer::POSITIVE;
+ }
+ else
+ {
+ Subtract(diff.reg, b.reg, a.reg, aSize);
+ diff.sign = Integer::NEGATIVE;
+ }
+ }
+ else if (aSize > bSize)
+ {
+ word borrow = Subtract(diff.reg, a.reg, b.reg, bSize);
+ CopyWords(diff.reg+bSize, a.reg+bSize, aSize-bSize);
+ borrow = Decrement(diff.reg+bSize, aSize-bSize, borrow);
+ assert(!borrow);
+ diff.sign = Integer::POSITIVE;
+ }
+ else
+ {
+ word borrow = Subtract(diff.reg, b.reg, a.reg, aSize);
+ CopyWords(diff.reg+aSize, b.reg+aSize, bSize-aSize);
+ borrow = Decrement(diff.reg+aSize, bSize-aSize, borrow);
+ assert(!borrow);
+ diff.sign = Integer::NEGATIVE;
+ }
+}
+
+// MSVC .NET 2003 workaround
+template <class T> inline const T& STDMAX2(const T& a, const T& b)
+{
+ return a < b ? b : a;
+}
+
+Integer Integer::Plus(const Integer& b) const
+{
+ Integer sum((word)0, STDMAX2(reg.size(), b.reg.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveAdd(sum, *this, b);
+ else
+ PositiveSubtract(sum, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ PositiveSubtract(sum, b, *this);
+ else
+ {
+ PositiveAdd(sum, *this, b);
+ sum.sign = Integer::NEGATIVE;
+ }
+ }
+ return sum;
+}
+
+Integer& Integer::operator+=(const Integer& t)
+{
+ reg.CleanGrow(t.reg.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveAdd(*this, *this, t);
+ else
+ PositiveSubtract(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, t, *this);
+ else
+ {
+ PositiveAdd(*this, *this, t);
+ sign = Integer::NEGATIVE;
+ }
+ }
+ return *this;
+}
+
+Integer Integer::Minus(const Integer& b) const
+{
+ Integer diff((word)0, STDMAX2(reg.size(), b.reg.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveSubtract(diff, *this, b);
+ else
+ PositiveAdd(diff, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ {
+ PositiveAdd(diff, *this, b);
+ diff.sign = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(diff, b, *this);
+ }
+ return diff;
+}
+
+Integer& Integer::operator-=(const Integer& t)
+{
+ reg.CleanGrow(t.reg.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, *this, t);
+ else
+ PositiveAdd(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ {
+ PositiveAdd(*this, *this, t);
+ sign = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(*this, t, *this);
+ }
+ return *this;
+}
+
+Integer& Integer::operator<<=(size_t n)
+{
+ const size_t wordCount = WordCount();
+ const size_t shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = (unsigned int)(n % WORD_BITS);
+
+ reg.CleanGrow(RoundupSize(wordCount+BitsToWords(n)));
+ ShiftWordsLeftByWords(reg, wordCount + shiftWords, shiftWords);
+ ShiftWordsLeftByBits(reg+shiftWords, wordCount+BitsToWords(shiftBits), shiftBits);
+ return *this;
+}
+
+Integer& Integer::operator>>=(size_t n)
+{
+ const size_t wordCount = WordCount();
+ const size_t shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = (unsigned int)(n % WORD_BITS);
+
+ ShiftWordsRightByWords(reg, wordCount, shiftWords);
+ if (wordCount > shiftWords)
+ ShiftWordsRightByBits(reg, wordCount-shiftWords, shiftBits);
+ if (IsNegative() && WordCount()==0) // avoid -0
+ *this = Zero();
+ return *this;
+}
+
+void PositiveMultiply(Integer &product, const Integer &a, const Integer &b)
+{
+ size_t aSize = RoundupSize(a.WordCount());
+ size_t bSize = RoundupSize(b.WordCount());
+
+ product.reg.CleanNew(RoundupSize(aSize+bSize));
+ product.sign = Integer::POSITIVE;
+
+ IntegerSecBlock workspace(aSize + bSize);
+ AsymmetricMultiply(product.reg, workspace, a.reg, aSize, b.reg, bSize);
+}
+
+void Multiply(Integer &product, const Integer &a, const Integer &b)
+{
+ PositiveMultiply(product, a, b);
+
+ if (a.NotNegative() != b.NotNegative())
+ product.Negate();
+}
+
+Integer Integer::Times(const Integer &b) const
+{
+ Integer product;
+ Multiply(product, *this, b);
+ return product;
+}
+
+/*
+void PositiveDivide(Integer &remainder, Integer &quotient,
+ const Integer &dividend, const Integer &divisor)
+{
+ remainder.reg.CleanNew(divisor.reg.size());
+ remainder.sign = Integer::POSITIVE;
+ quotient.reg.New(0);
+ quotient.sign = Integer::POSITIVE;
+ unsigned i=dividend.BitCount();
+ while (i--)
+ {
+ word overflow = ShiftWordsLeftByBits(remainder.reg, remainder.reg.size(), 1);
+ remainder.reg[0] |= dividend[i];
+ if (overflow || remainder >= divisor)
+ {
+ Subtract(remainder.reg, remainder.reg, divisor.reg, remainder.reg.size());
+ quotient.SetBit(i);
+ }
+ }
+}
+*/
+
+void PositiveDivide(Integer &remainder, Integer &quotient,
+ const Integer &a, const Integer &b)
+{
+ unsigned aSize = a.WordCount();
+ unsigned bSize = b.WordCount();
+
+ if (!bSize)
+ throw Integer::DivideByZero();
+
+ if (aSize < bSize)
+ {
+ remainder = a;
+ remainder.sign = Integer::POSITIVE;
+ quotient = Integer::Zero();
+ return;
+ }
+
+ aSize += aSize%2; // round up to next even number
+ bSize += bSize%2;
+
+ remainder.reg.CleanNew(RoundupSize(bSize));
+ remainder.sign = Integer::POSITIVE;
+ quotient.reg.CleanNew(RoundupSize(aSize-bSize+2));
+ quotient.sign = Integer::POSITIVE;
+
+ IntegerSecBlock T(aSize+3*(bSize+2));
+ Divide(remainder.reg, quotient.reg, T, a.reg, aSize, b.reg, bSize);
+}
+
+void Integer::Divide(Integer &remainder, Integer &quotient, const Integer &dividend, const Integer &divisor)
+{
+ PositiveDivide(remainder, quotient, dividend, divisor);
+
+ if (dividend.IsNegative())
+ {
+ quotient.Negate();
+ if (remainder.NotZero())
+ {
+ --quotient;
+ remainder = divisor.AbsoluteValue() - remainder;
+ }
+ }
+
+ if (divisor.IsNegative())
+ quotient.Negate();
+}
+
+void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n)
+{
+ q = a;
+ q >>= n;
+
+ const size_t wordCount = BitsToWords(n);
+ if (wordCount <= a.WordCount())
+ {
+ r.reg.resize(RoundupSize(wordCount));
+ CopyWords(r.reg, a.reg, wordCount);
+ SetWords(r.reg+wordCount, 0, r.reg.size()-wordCount);
+ if (n % WORD_BITS != 0)
+ r.reg[wordCount-1] %= (word(1) << (n % WORD_BITS));
+ }
+ else
+ {
+ r.reg.resize(RoundupSize(a.WordCount()));
+ CopyWords(r.reg, a.reg, r.reg.size());
+ }
+ r.sign = POSITIVE;
+
+ if (a.IsNegative() && r.NotZero())
+ {
+ --q;
+ r = Power2(n) - r;
+ }
+}
+
+Integer Integer::DividedBy(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+Integer Integer::Modulo(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return remainder;
+}
+
+void Integer::Divide(word &remainder, Integer &quotient, const Integer &dividend, word divisor)
+{
+ if (!divisor)
+ throw Integer::DivideByZero();
+
+ assert(divisor);
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ {
+ quotient = dividend >> (BitPrecision(divisor)-1);
+ remainder = dividend.reg[0] & (divisor-1);
+ return;
+ }
+
+ unsigned int i = dividend.WordCount();
+ quotient.reg.CleanNew(RoundupSize(i));
+ remainder = 0;
+ while (i--)
+ {
+ quotient.reg[i] = DWord(dividend.reg[i], remainder) / divisor;
+ remainder = DWord(dividend.reg[i], remainder) % divisor;
+ }
+
+ if (dividend.NotNegative())
+ quotient.sign = POSITIVE;
+ else
+ {
+ quotient.sign = NEGATIVE;
+ if (remainder)
+ {
+ --quotient;
+ remainder = divisor - remainder;
+ }
+ }
+}
+
+Integer Integer::DividedBy(word b) const
+{
+ word remainder;
+ Integer quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+word Integer::Modulo(word divisor) const
+{
+ if (!divisor)
+ throw Integer::DivideByZero();
+
+ assert(divisor);
+
+ word remainder;
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ remainder = reg[0] & (divisor-1);
+ else
+ {
+ unsigned int i = WordCount();
+
+ if (divisor <= 5)
+ {
+ DWord sum(0, 0);
+ while (i--)
+ sum += reg[i];
+ remainder = sum % divisor;
+ }
+ else
+ {
+ remainder = 0;
+ while (i--)
+ remainder = DWord(reg[i], remainder) % divisor;
+ }
+ }
+
+ if (IsNegative() && remainder)
+ remainder = divisor - remainder;
+
+ return remainder;
+}
+
+void Integer::Negate()
+{
+ if (!!(*this)) // don't flip sign if *this==0
+ sign = Sign(1-sign);
+}
+
+int Integer::PositiveCompare(const Integer& t) const
+{
+ unsigned size = WordCount(), tSize = t.WordCount();
+
+ if (size == tSize)
+ return CryptoPP::Compare(reg, t.reg, size);
+ else
+ return size > tSize ? 1 : -1;
+}
+
+int Integer::Compare(const Integer& t) const
+{
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ return PositiveCompare(t);
+ else
+ return 1;
+ }
+ else
+ {
+ if (t.NotNegative())
+ return -1;
+ else
+ return -PositiveCompare(t);
+ }
+}
+
+Integer Integer::SquareRoot() const
+{
+ if (!IsPositive())
+ return Zero();
+
+ // overestimate square root
+ Integer x, y = Power2((BitCount()+1)/2);
+ assert(y*y >= *this);
+
+ do
+ {
+ x = y;
+ y = (x + *this/x) >> 1;
+ } while (y<x);
+
+ return x;
+}
+
+bool Integer::IsSquare() const
+{
+ Integer r = SquareRoot();
+ return *this == r.Squared();
+}
+
+bool Integer::IsUnit() const
+{
+ return (WordCount() == 1) && (reg[0] == 1);
+}
+
+Integer Integer::MultiplicativeInverse() const
+{
+ return IsUnit() ? *this : Zero();
+}
+
+Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m)
+{
+ return x*y%m;
+}
+
+Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m)
+{
+ ModularArithmetic mr(m);
+ return mr.Exponentiate(x, e);
+}
+
+Integer Integer::Gcd(const Integer &a, const Integer &b)
+{
+ return EuclideanDomainOf<Integer>().Gcd(a, b);
+}
+
+Integer Integer::InverseMod(const Integer &m) const
+{
+ assert(m.NotNegative());
+
+ if (IsNegative())
+ return Modulo(m).InverseMod(m);
+
+ if (m.IsEven())
+ {
+ if (!m || IsEven())
+ return Zero(); // no inverse
+ if (*this == One())
+ return One();
+
+ Integer u = m.Modulo(*this).InverseMod(*this);
+ return !u ? Zero() : (m*(*this-u)+1)/(*this);
+ }
+
+ SecBlock<word> T(m.reg.size() * 4);
+ Integer r((word)0, m.reg.size());
+ unsigned k = AlmostInverse(r.reg, T, reg, reg.size(), m.reg, m.reg.size());
+ DivideByPower2Mod(r.reg, r.reg, k, m.reg, m.reg.size());
+ return r;
+}
+
+word Integer::InverseMod(word mod) const
+{
+ word g0 = mod, g1 = *this % mod;
+ word v0 = 0, v1 = 1;
+ word y;
+
+ while (g1)
+ {
+ if (g1 == 1)
+ return v1;
+ y = g0 / g1;
+ g0 = g0 % g1;
+ v0 += y * v1;
+
+ if (!g0)
+ break;
+ if (g0 == 1)
+ return mod-v0;
+ y = g1 / g0;
+ g1 = g1 % g0;
+ v1 += y * v0;
+ }
+ return 0;
+}
+
+// ********************************************************
+
+ModularArithmetic::ModularArithmetic(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ OID oid(seq);
+ if (oid != ASN1::prime_field())
+ BERDecodeError();
+ m_modulus.BERDecode(seq);
+ seq.MessageEnd();
+ m_result.reg.resize(m_modulus.reg.size());
+}
+
+void ModularArithmetic::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ ASN1::prime_field().DEREncode(seq);
+ m_modulus.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+void ModularArithmetic::DEREncodeElement(BufferedTransformation &out, const Element &a) const
+{
+ a.DEREncodeAsOctetString(out, MaxElementByteLength());
+}
+
+void ModularArithmetic::BERDecodeElement(BufferedTransformation &in, Element &a) const
+{
+ a.BERDecodeAsOctetString(in, MaxElementByteLength());
+}
+
+const Integer& ModularArithmetic::Half(const Integer &a) const
+{
+ if (a.reg.size()==m_modulus.reg.size())
+ {
+ CryptoPP::DivideByPower2Mod(m_result.reg.begin(), a.reg, 1, m_modulus.reg, a.reg.size());
+ return m_result;
+ }
+ else
+ return m_result1 = (a.IsEven() ? (a >> 1) : ((a+m_modulus) >> 1));
+}
+
+const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const
+{
+ if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size())
+ {
+ if (CryptoPP::Add(m_result.reg.begin(), a.reg, b.reg, a.reg.size())
+ || Compare(m_result.reg, m_modulus.reg, a.reg.size()) >= 0)
+ {
+ CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size());
+ }
+ return m_result;
+ }
+ else
+ {
+ m_result1 = a+b;
+ if (m_result1 >= m_modulus)
+ m_result1 -= m_modulus;
+ return m_result1;
+ }
+}
+
+Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const
+{
+ if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size())
+ {
+ if (CryptoPP::Add(a.reg, a.reg, b.reg, a.reg.size())
+ || Compare(a.reg, m_modulus.reg, a.reg.size()) >= 0)
+ {
+ CryptoPP::Subtract(a.reg, a.reg, m_modulus.reg, a.reg.size());
+ }
+ }
+ else
+ {
+ a+=b;
+ if (a>=m_modulus)
+ a-=m_modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Subtract(const Integer &a, const Integer &b) const
+{
+ if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size())
+ {
+ if (CryptoPP::Subtract(m_result.reg.begin(), a.reg, b.reg, a.reg.size()))
+ CryptoPP::Add(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size());
+ return m_result;
+ }
+ else
+ {
+ m_result1 = a-b;
+ if (m_result1.IsNegative())
+ m_result1 += m_modulus;
+ return m_result1;
+ }
+}
+
+Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const
+{
+ if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size())
+ {
+ if (CryptoPP::Subtract(a.reg, a.reg, b.reg, a.reg.size()))
+ CryptoPP::Add(a.reg, a.reg, m_modulus.reg, a.reg.size());
+ }
+ else
+ {
+ a-=b;
+ if (a.IsNegative())
+ a+=m_modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Inverse(const Integer &a) const
+{
+ if (!a)
+ return a;
+
+ CopyWords(m_result.reg.begin(), m_modulus.reg, m_modulus.reg.size());
+ if (CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, a.reg, a.reg.size()))
+ Decrement(m_result.reg.begin()+a.reg.size(), m_modulus.reg.size()-a.reg.size());
+
+ return m_result;
+}
+
+Integer ModularArithmetic::CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const
+{
+ if (m_modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(m_modulus);
+ return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1, dr.ConvertIn(y), e2));
+ }
+ else
+ return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);
+}
+
+void ModularArithmetic::SimultaneousExponentiate(Integer *results, const Integer &base, const Integer *exponents, unsigned int exponentsCount) const
+{
+ if (m_modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(m_modulus);
+ dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents, exponentsCount);
+ for (unsigned int i=0; i<exponentsCount; i++)
+ results[i] = dr.ConvertOut(results[i]);
+ }
+ else
+ AbstractRing<Integer>::SimultaneousExponentiate(results, base, exponents, exponentsCount);
+}
+
+MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m) // modulus must be odd
+ : ModularArithmetic(m),
+ m_u((word)0, m_modulus.reg.size()),
+ m_workspace(5*m_modulus.reg.size())
+{
+ if (!m_modulus.IsOdd())
+ throw InvalidArgument("MontgomeryRepresentation: Montgomery representation requires an odd modulus");
+
+ RecursiveInverseModPower2(m_u.reg, m_workspace, m_modulus.reg, m_modulus.reg.size());
+}
+
+const Integer& MontgomeryRepresentation::Multiply(const Integer &a, const Integer &b) const
+{
+ word *const T = m_workspace.begin();
+ word *const R = m_result.reg.begin();
+ const size_t N = m_modulus.reg.size();
+ assert(a.reg.size()<=N && b.reg.size()<=N);
+
+ AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size(), b.reg, b.reg.size());
+ SetWords(T+a.reg.size()+b.reg.size(), 0, 2*N-a.reg.size()-b.reg.size());
+ MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
+ return m_result;
+}
+
+const Integer& MontgomeryRepresentation::Square(const Integer &a) const
+{
+ word *const T = m_workspace.begin();
+ word *const R = m_result.reg.begin();
+ const size_t N = m_modulus.reg.size();
+ assert(a.reg.size()<=N);
+
+ CryptoPP::Square(T, T+2*N, a.reg, a.reg.size());
+ SetWords(T+2*a.reg.size(), 0, 2*N-2*a.reg.size());
+ MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
+ return m_result;
+}
+
+Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const
+{
+ word *const T = m_workspace.begin();
+ word *const R = m_result.reg.begin();
+ const size_t N = m_modulus.reg.size();
+ assert(a.reg.size()<=N);
+
+ CopyWords(T, a.reg, a.reg.size());
+ SetWords(T+a.reg.size(), 0, 2*N-a.reg.size());
+ MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
+ return m_result;
+}
+
+const Integer& MontgomeryRepresentation::MultiplicativeInverse(const Integer &a) const
+{
+// return (EuclideanMultiplicativeInverse(a, modulus)<<(2*WORD_BITS*modulus.reg.size()))%modulus;
+ word *const T = m_workspace.begin();
+ word *const R = m_result.reg.begin();
+ const size_t N = m_modulus.reg.size();
+ assert(a.reg.size()<=N);
+
+ CopyWords(T, a.reg, a.reg.size());
+ SetWords(T+a.reg.size(), 0, 2*N-a.reg.size());
+ MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
+ unsigned k = AlmostInverse(R, T, R, N, m_modulus.reg, N);
+
+// cout << "k=" << k << " N*32=" << 32*N << endl;
+
+ if (k>N*WORD_BITS)
+ DivideByPower2Mod(R, R, k-N*WORD_BITS, m_modulus.reg, N);
+ else
+ MultiplyByPower2Mod(R, R, N*WORD_BITS-k, m_modulus.reg, N);
+
+ return m_result;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/integer.h b/lib/cryptopp/integer.h
new file mode 100644
index 000000000..6d844fa57
--- /dev/null
+++ b/lib/cryptopp/integer.h
@@ -0,0 +1,420 @@
+#ifndef CRYPTOPP_INTEGER_H
+#define CRYPTOPP_INTEGER_H
+
+/** \file */
+
+#include "cryptlib.h"
+#include "secblock.h"
+
+#include <iosfwd>
+#include <algorithm>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+struct InitializeInteger // used to initialize static variables
+{
+ InitializeInteger();
+};
+
+typedef SecBlock<word, AllocatorWithCleanup<word, CRYPTOPP_BOOL_X86> > IntegerSecBlock;
+
+//! multiple precision integer and basic arithmetics
+/*! This class can represent positive and negative integers
+ with absolute value less than (256**sizeof(word)) ** (256**sizeof(int)).
+ \nosubgrouping
+*/
+class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object
+{
+public:
+ //! \name ENUMS, EXCEPTIONS, and TYPEDEFS
+ //@{
+ //! division by zero exception
+ class DivideByZero : public Exception
+ {
+ public:
+ DivideByZero() : Exception(OTHER_ERROR, "Integer: division by zero") {}
+ };
+
+ //!
+ class RandomNumberNotFound : public Exception
+ {
+ public:
+ RandomNumberNotFound() : Exception(OTHER_ERROR, "Integer: no integer satisfies the given parameters") {}
+ };
+
+ //!
+ enum Sign {POSITIVE=0, NEGATIVE=1};
+
+ //!
+ enum Signedness {
+ //!
+ UNSIGNED,
+ //!
+ SIGNED};
+
+ //!
+ enum RandomNumberType {
+ //!
+ ANY,
+ //!
+ PRIME};
+ //@}
+
+ //! \name CREATORS
+ //@{
+ //! creates the zero integer
+ Integer();
+
+ //! copy constructor
+ Integer(const Integer& t);
+
+ //! convert from signed long
+ Integer(signed long value);
+
+ //! convert from lword
+ Integer(Sign s, lword value);
+
+ //! convert from two words
+ Integer(Sign s, word highWord, word lowWord);
+
+ //! convert from string
+ /*! str can be in base 2, 8, 10, or 16. Base is determined by a
+ case insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10.
+ */
+ explicit Integer(const char *str);
+ explicit Integer(const wchar_t *str);
+
+ //! convert from big-endian byte array
+ Integer(const byte *encodedInteger, size_t byteCount, Signedness s=UNSIGNED);
+
+ //! convert from big-endian form stored in a BufferedTransformation
+ Integer(BufferedTransformation &bt, size_t byteCount, Signedness s=UNSIGNED);
+
+ //! convert from BER encoded byte array stored in a BufferedTransformation object
+ explicit Integer(BufferedTransformation &bt);
+
+ //! create a random integer
+ /*! The random integer created is uniformly distributed over [0, 2**bitcount). */
+ Integer(RandomNumberGenerator &rng, size_t bitcount);
+
+ //! avoid calling constructors for these frequently used integers
+ static const Integer & CRYPTOPP_API Zero();
+ //! avoid calling constructors for these frequently used integers
+ static const Integer & CRYPTOPP_API One();
+ //! avoid calling constructors for these frequently used integers
+ static const Integer & CRYPTOPP_API Two();
+
+ //! create a random integer of special type
+ /*! Ideally, the random integer created should be uniformly distributed
+ over {x | min <= x <= max and x is of rnType and x % mod == equiv}.
+ However the actual distribution may not be uniform because sequential
+ search is used to find an appropriate number from a random starting
+ point.
+ May return (with very small probability) a pseudoprime when a prime
+ is requested and max > lastSmallPrime*lastSmallPrime (lastSmallPrime
+ is declared in nbtheory.h).
+ \throw RandomNumberNotFound if the set is empty.
+ */
+ Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY, const Integer &equiv=Zero(), const Integer &mod=One());
+
+ //! return the integer 2**e
+ static Integer CRYPTOPP_API Power2(size_t e);
+ //@}
+
+ //! \name ENCODE/DECODE
+ //@{
+ //! minimum number of bytes to encode this integer
+ /*! MinEncodedSize of 0 is 1 */
+ size_t MinEncodedSize(Signedness=UNSIGNED) const;
+ //! encode in big-endian format
+ /*! unsigned means encode absolute value, signed means encode two's complement if negative.
+ if outputLen < MinEncodedSize, the most significant bytes will be dropped
+ if outputLen > MinEncodedSize, the most significant bytes will be padded
+ */
+ void Encode(byte *output, size_t outputLen, Signedness=UNSIGNED) const;
+ //!
+ void Encode(BufferedTransformation &bt, size_t outputLen, Signedness=UNSIGNED) const;
+
+ //! encode using Distinguished Encoding Rules, put result into a BufferedTransformation object
+ void DEREncode(BufferedTransformation &bt) const;
+
+ //! encode absolute value as big-endian octet string
+ void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const;
+
+ //! encode absolute value in OpenPGP format, return length of output
+ size_t OpenPGPEncode(byte *output, size_t bufferSize) const;
+ //! encode absolute value in OpenPGP format, put result into a BufferedTransformation object
+ size_t OpenPGPEncode(BufferedTransformation &bt) const;
+
+ //!
+ void Decode(const byte *input, size_t inputLen, Signedness=UNSIGNED);
+ //!
+ //* Precondition: bt.MaxRetrievable() >= inputLen
+ void Decode(BufferedTransformation &bt, size_t inputLen, Signedness=UNSIGNED);
+
+ //!
+ void BERDecode(const byte *input, size_t inputLen);
+ //!
+ void BERDecode(BufferedTransformation &bt);
+
+ //! decode nonnegative value as big-endian octet string
+ void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length);
+
+ class OpenPGPDecodeErr : public Exception
+ {
+ public:
+ OpenPGPDecodeErr() : Exception(INVALID_DATA_FORMAT, "OpenPGP decode error") {}
+ };
+
+ //!
+ void OpenPGPDecode(const byte *input, size_t inputLen);
+ //!
+ void OpenPGPDecode(BufferedTransformation &bt);
+ //@}
+
+ //! \name ACCESSORS
+ //@{
+ //! return true if *this can be represented as a signed long
+ bool IsConvertableToLong() const;
+ //! return equivalent signed long if possible, otherwise undefined
+ signed long ConvertToLong() const;
+
+ //! number of significant bits = floor(log2(abs(*this))) + 1
+ unsigned int BitCount() const;
+ //! number of significant bytes = ceiling(BitCount()/8)
+ unsigned int ByteCount() const;
+ //! number of significant words = ceiling(ByteCount()/sizeof(word))
+ unsigned int WordCount() const;
+
+ //! return the i-th bit, i=0 being the least significant bit
+ bool GetBit(size_t i) const;
+ //! return the i-th byte
+ byte GetByte(size_t i) const;
+ //! return n lowest bits of *this >> i
+ lword GetBits(size_t i, size_t n) const;
+
+ //!
+ bool IsZero() const {return !*this;}
+ //!
+ bool NotZero() const {return !IsZero();}
+ //!
+ bool IsNegative() const {return sign == NEGATIVE;}
+ //!
+ bool NotNegative() const {return !IsNegative();}
+ //!
+ bool IsPositive() const {return NotNegative() && NotZero();}
+ //!
+ bool NotPositive() const {return !IsPositive();}
+ //!
+ bool IsEven() const {return GetBit(0) == 0;}
+ //!
+ bool IsOdd() const {return GetBit(0) == 1;}
+ //@}
+
+ //! \name MANIPULATORS
+ //@{
+ //!
+ Integer& operator=(const Integer& t);
+
+ //!
+ Integer& operator+=(const Integer& t);
+ //!
+ Integer& operator-=(const Integer& t);
+ //!
+ Integer& operator*=(const Integer& t) {return *this = Times(t);}
+ //!
+ Integer& operator/=(const Integer& t) {return *this = DividedBy(t);}
+ //!
+ Integer& operator%=(const Integer& t) {return *this = Modulo(t);}
+ //!
+ Integer& operator/=(word t) {return *this = DividedBy(t);}
+ //!
+ Integer& operator%=(word t) {return *this = Integer(POSITIVE, 0, Modulo(t));}
+
+ //!
+ Integer& operator<<=(size_t);
+ //!
+ Integer& operator>>=(size_t);
+
+ //!
+ void Randomize(RandomNumberGenerator &rng, size_t bitcount);
+ //!
+ void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max);
+ //! set this Integer to a random element of {x | min <= x <= max and x is of rnType and x % mod == equiv}
+ /*! returns false if the set is empty */
+ bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One());
+
+ bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs);
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs)
+ {
+ if (!GenerateRandomNoThrow(rng, params))
+ throw RandomNumberNotFound();
+ }
+
+ //! set the n-th bit to value
+ void SetBit(size_t n, bool value=1);
+ //! set the n-th byte to value
+ void SetByte(size_t n, byte value);
+
+ //!
+ void Negate();
+ //!
+ void SetPositive() {sign = POSITIVE;}
+ //!
+ void SetNegative() {if (!!(*this)) sign = NEGATIVE;}
+
+ //!
+ void swap(Integer &a);
+ //@}
+
+ //! \name UNARY OPERATORS
+ //@{
+ //!
+ bool operator!() const;
+ //!
+ Integer operator+() const {return *this;}
+ //!
+ Integer operator-() const;
+ //!
+ Integer& operator++();
+ //!
+ Integer& operator--();
+ //!
+ Integer operator++(int) {Integer temp = *this; ++*this; return temp;}
+ //!
+ Integer operator--(int) {Integer temp = *this; --*this; return temp;}
+ //@}
+
+ //! \name BINARY OPERATORS
+ //@{
+ //! signed comparison
+ /*! \retval -1 if *this < a
+ \retval 0 if *this = a
+ \retval 1 if *this > a
+ */
+ int Compare(const Integer& a) const;
+
+ //!
+ Integer Plus(const Integer &b) const;
+ //!
+ Integer Minus(const Integer &b) const;
+ //!
+ Integer Times(const Integer &b) const;
+ //!
+ Integer DividedBy(const Integer &b) const;
+ //!
+ Integer Modulo(const Integer &b) const;
+ //!
+ Integer DividedBy(word b) const;
+ //!
+ word Modulo(word b) const;
+
+ //!
+ Integer operator>>(size_t n) const {return Integer(*this)>>=n;}
+ //!
+ Integer operator<<(size_t n) const {return Integer(*this)<<=n;}
+ //@}
+
+ //! \name OTHER ARITHMETIC FUNCTIONS
+ //@{
+ //!
+ Integer AbsoluteValue() const;
+ //!
+ Integer Doubled() const {return Plus(*this);}
+ //!
+ Integer Squared() const {return Times(*this);}
+ //! extract square root, if negative return 0, else return floor of square root
+ Integer SquareRoot() const;
+ //! return whether this integer is a perfect square
+ bool IsSquare() const;
+
+ //! is 1 or -1
+ bool IsUnit() const;
+ //! return inverse if 1 or -1, otherwise return 0
+ Integer MultiplicativeInverse() const;
+
+ //! modular multiplication
+ CRYPTOPP_DLL friend Integer CRYPTOPP_API a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m);
+ //! modular exponentiation
+ CRYPTOPP_DLL friend Integer CRYPTOPP_API a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m);
+
+ //! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
+ static void CRYPTOPP_API Divide(Integer &r, Integer &q, const Integer &a, const Integer &d);
+ //! use a faster division algorithm when divisor is short
+ static void CRYPTOPP_API Divide(word &r, Integer &q, const Integer &a, word d);
+
+ //! returns same result as Divide(r, q, a, Power2(n)), but faster
+ static void CRYPTOPP_API DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n);
+
+ //! greatest common divisor
+ static Integer CRYPTOPP_API Gcd(const Integer &a, const Integer &n);
+ //! calculate multiplicative inverse of *this mod n
+ Integer InverseMod(const Integer &n) const;
+ //!
+ word InverseMod(word n) const;
+ //@}
+
+ //! \name INPUT/OUTPUT
+ //@{
+ //!
+ friend CRYPTOPP_DLL std::istream& CRYPTOPP_API operator>>(std::istream& in, Integer &a);
+ //!
+ friend CRYPTOPP_DLL std::ostream& CRYPTOPP_API operator<<(std::ostream& out, const Integer &a);
+ //@}
+
+private:
+ friend class ModularArithmetic;
+ friend class MontgomeryRepresentation;
+ friend class HalfMontgomeryRepresentation;
+
+ Integer(word value, size_t length);
+
+ int PositiveCompare(const Integer &t) const;
+ friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b);
+ friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b);
+ friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b);
+ friend void PositiveDivide(Integer &remainder, Integer &quotient, const Integer &dividend, const Integer &divisor);
+
+ IntegerSecBlock reg;
+ Sign sign;
+};
+
+//!
+inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;}
+//!
+inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;}
+//!
+inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;}
+//!
+inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;}
+//!
+inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;}
+//!
+inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;}
+//!
+inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);}
+//!
+inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);}
+//!
+inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);}
+//!
+inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);}
+//!
+inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);}
+//!
+inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);}
+//!
+inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);}
+
+NAMESPACE_END
+
+#ifndef __BORLANDC__
+NAMESPACE_BEGIN(std)
+inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b)
+{
+ a.swap(b);
+}
+NAMESPACE_END
+#endif
+
+#endif
diff --git a/lib/cryptopp/iterhash.cpp b/lib/cryptopp/iterhash.cpp
new file mode 100644
index 000000000..1e31e9fb3
--- /dev/null
+++ b/lib/cryptopp/iterhash.cpp
@@ -0,0 +1,160 @@
+// iterhash.cpp - written and placed in the public domain by Wei Dai
+
+#ifndef __GNUC__
+#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
+#endif
+
+#include "iterhash.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, size_t len)
+{
+ HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi;
+ if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo)
+ m_countHi++; // carry from low to high
+ m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len);
+ if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0)
+ throw HashInputTooLong(this->AlgorithmName());
+
+ unsigned int blockSize = this->BlockSize();
+ unsigned int num = ModPowerOf2(oldCountLo, blockSize);
+ T* dataBuf = this->DataBuf();
+ byte* data = (byte *)dataBuf;
+
+ if (num != 0) // process left over data
+ {
+ if (num+len >= blockSize)
+ {
+ memcpy(data+num, input, blockSize-num);
+ HashBlock(dataBuf);
+ input += (blockSize-num);
+ len -= (blockSize-num);
+ num = 0;
+ // drop through and do the rest
+ }
+ else
+ {
+ memcpy(data+num, input, len);
+ return;
+ }
+ }
+
+ // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
+ if (len >= blockSize)
+ {
+ if (input == data)
+ {
+ assert(len == blockSize);
+ HashBlock(dataBuf);
+ return;
+ }
+ else if (IsAligned<T>(input))
+ {
+ size_t leftOver = HashMultipleBlocks((T *)input, len);
+ input += (len - leftOver);
+ len = leftOver;
+ }
+ else
+ do
+ { // copy input first if it's not aligned correctly
+ memcpy(data, input, blockSize);
+ HashBlock(dataBuf);
+ input+=blockSize;
+ len-=blockSize;
+ } while (len >= blockSize);
+ }
+
+ if (len && data != input)
+ memcpy(data, input, len);
+}
+
+template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(size_t &size)
+{
+ unsigned int blockSize = this->BlockSize();
+ unsigned int num = ModPowerOf2(m_countLo, blockSize);
+ size = blockSize - num;
+ return (byte *)DataBuf() + num;
+}
+
+template <class T, class BASE> size_t IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, size_t length)
+{
+ unsigned int blockSize = this->BlockSize();
+ bool noReverse = NativeByteOrderIs(this->GetByteOrder());
+ T* dataBuf = this->DataBuf();
+ do
+ {
+ if (noReverse)
+ this->HashEndianCorrectedBlock(input);
+ else
+ {
+ ByteReverse(dataBuf, input, this->BlockSize());
+ this->HashEndianCorrectedBlock(dataBuf);
+ }
+
+ input += blockSize/sizeof(T);
+ length -= blockSize;
+ }
+ while (length >= blockSize);
+ return length;
+}
+
+template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
+{
+ unsigned int blockSize = this->BlockSize();
+ unsigned int num = ModPowerOf2(m_countLo, blockSize);
+ T* dataBuf = this->DataBuf();
+ byte* data = (byte *)dataBuf;
+ data[num++] = padFirst;
+ if (num <= lastBlockSize)
+ memset(data+num, 0, lastBlockSize-num);
+ else
+ {
+ memset(data+num, 0, blockSize-num);
+ HashBlock(dataBuf);
+ memset(data, 0, lastBlockSize);
+ }
+}
+
+template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
+{
+ m_countLo = m_countHi = 0;
+ Init();
+}
+
+template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(byte *digest, size_t size)
+{
+ this->ThrowIfInvalidTruncatedSize(size);
+
+ T* dataBuf = this->DataBuf();
+ T* stateBuf = this->StateBuf();
+ unsigned int blockSize = this->BlockSize();
+ ByteOrder order = this->GetByteOrder();
+
+ PadLastBlock(blockSize - 2*sizeof(HashWordType));
+ dataBuf[blockSize/sizeof(T)-2+order] = ConditionalByteReverse(order, this->GetBitCountLo());
+ dataBuf[blockSize/sizeof(T)-1-order] = ConditionalByteReverse(order, this->GetBitCountHi());
+
+ HashBlock(dataBuf);
+
+ if (IsAligned<HashWordType>(digest) && size%sizeof(HashWordType)==0)
+ ConditionalByteReverse<HashWordType>(order, (HashWordType *)digest, stateBuf, size);
+ else
+ {
+ ConditionalByteReverse<HashWordType>(order, stateBuf, stateBuf, this->DigestSize());
+ memcpy(digest, stateBuf, size);
+ }
+
+ this->Restart(); // reinit for next use
+}
+
+#ifdef __GNUC__
+ template class IteratedHashBase<word64, HashTransformation>;
+ template class IteratedHashBase<word64, MessageAuthenticationCode>;
+
+ template class IteratedHashBase<word32, HashTransformation>;
+ template class IteratedHashBase<word32, MessageAuthenticationCode>;
+#endif
+
+NAMESPACE_END
diff --git a/lib/cryptopp/iterhash.h b/lib/cryptopp/iterhash.h
new file mode 100644
index 000000000..cce9e8211
--- /dev/null
+++ b/lib/cryptopp/iterhash.h
@@ -0,0 +1,106 @@
+#ifndef CRYPTOPP_ITERHASH_H
+#define CRYPTOPP_ITERHASH_H
+
+#include "cryptlib.h"
+#include "secblock.h"
+#include "misc.h"
+#include "simple.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! exception thrown when trying to hash more data than is allowed by a hash function
+class CRYPTOPP_DLL HashInputTooLong : public InvalidDataFormat
+{
+public:
+ explicit HashInputTooLong(const std::string &alg)
+ : InvalidDataFormat("IteratedHashBase: input data exceeds maximum allowed by hash function " + alg) {}
+};
+
+//! _
+template <class T, class BASE>
+class CRYPTOPP_NO_VTABLE IteratedHashBase : public BASE
+{
+public:
+ typedef T HashWordType;
+
+ IteratedHashBase() : m_countLo(0), m_countHi(0) {}
+ unsigned int OptimalBlockSize() const {return this->BlockSize();}
+ unsigned int OptimalDataAlignment() const {return GetAlignmentOf<T>();}
+ void Update(const byte *input, size_t length);
+ byte * CreateUpdateSpace(size_t &size);
+ void Restart();
+ void TruncatedFinal(byte *digest, size_t size);
+
+protected:
+ inline T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
+ inline T GetBitCountLo() const {return m_countLo << 3;}
+
+ void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
+ virtual void Init() =0;
+
+ virtual ByteOrder GetByteOrder() const =0;
+ virtual void HashEndianCorrectedBlock(const HashWordType *data) =0;
+ virtual size_t HashMultipleBlocks(const T *input, size_t length);
+ void HashBlock(const HashWordType *input) {HashMultipleBlocks(input, this->BlockSize());}
+
+ virtual T* DataBuf() =0;
+ virtual T* StateBuf() =0;
+
+private:
+ T m_countLo, m_countHi;
+};
+
+//! _
+template <class T_HashWordType, class T_Endianness, unsigned int T_BlockSize, class T_Base = HashTransformation>
+class CRYPTOPP_NO_VTABLE IteratedHash : public IteratedHashBase<T_HashWordType, T_Base>
+{
+public:
+ typedef T_Endianness ByteOrderClass;
+ typedef T_HashWordType HashWordType;
+
+ CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize)
+ // BCB2006 workaround: can't use BLOCKSIZE here
+ CRYPTOPP_COMPILE_ASSERT((T_BlockSize & (T_BlockSize - 1)) == 0); // blockSize is a power of 2
+ unsigned int BlockSize() const {return T_BlockSize;}
+
+ ByteOrder GetByteOrder() const {return T_Endianness::ToEnum();}
+
+ inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, size_t byteCount)
+ {
+ ConditionalByteReverse(T_Endianness::ToEnum(), out, in, byteCount);
+ }
+
+protected:
+ T_HashWordType* DataBuf() {return this->m_data;}
+ FixedSizeSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType)> m_data;
+};
+
+//! _
+template <class T_HashWordType, class T_Endianness, unsigned int T_BlockSize, unsigned int T_StateSize, class T_Transform, unsigned int T_DigestSize = 0, bool T_StateAligned = false>
+class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform
+ : public ClonableImpl<T_Transform, AlgorithmImpl<IteratedHash<T_HashWordType, T_Endianness, T_BlockSize>, T_Transform> >
+{
+public:
+ CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize)
+ unsigned int DigestSize() const {return DIGESTSIZE;};
+
+protected:
+ IteratedHashWithStaticTransform() {this->Init();}
+ void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_state, data);}
+ void Init() {T_Transform::InitState(this->m_state);}
+
+ T_HashWordType* StateBuf() {return this->m_state;}
+ FixedSizeAlignedSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType), T_StateAligned> m_state;
+};
+
+#ifndef __GNUC__
+ CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word64, HashTransformation>;
+ CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase<word64, MessageAuthenticationCode>;
+
+ CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word32, HashTransformation>;
+ CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase<word32, MessageAuthenticationCode>;
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/lubyrack.h b/lib/cryptopp/lubyrack.h
new file mode 100644
index 000000000..e8fd2f748
--- /dev/null
+++ b/lib/cryptopp/lubyrack.h
@@ -0,0 +1,141 @@
+// lubyrack.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_LUBYRACK_H
+#define CRYPTOPP_LUBYRACK_H
+
+/** \file */
+
+#include "simple.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T> struct DigestSizeDoubleWorkaround // VC60 workaround
+{
+ CRYPTOPP_CONSTANT(RESULT = 2*T::DIGESTSIZE)
+};
+
+//! algorithm info
+template <class T>
+struct LR_Info : public VariableKeyLength<16, 0, 2*(INT_MAX/2), 2>, public FixedBlockSize<DigestSizeDoubleWorkaround<T>::RESULT>
+{
+ static std::string StaticAlgorithmName() {return std::string("LR/")+T::StaticAlgorithmName();}
+};
+
+//! Luby-Rackoff
+template <class T>
+class LR : public LR_Info<T>, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<LR_Info<T> >
+ {
+ public:
+ // VC60 workaround: have to define these functions within class definition
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
+ {
+ this->AssertValidKeyLength(length);
+
+ L = length/2;
+ buffer.New(2*S);
+ digest.New(S);
+ key.Assign(userKey, 2*L);
+ }
+
+ protected:
+ CRYPTOPP_CONSTANT(S=T::DIGESTSIZE)
+ unsigned int L; // key length / 2
+ SecByteBlock key;
+
+ mutable T hm;
+ mutable SecByteBlock buffer, digest;
+ };
+
+ class CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+
+#define KL this->key
+#define KR this->key+this->L
+#define BL this->buffer
+#define BR this->buffer+this->S
+#define IL inBlock
+#define IR inBlock+this->S
+#define OL outBlock
+#define OR outBlock+this->S
+
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+ {
+ this->hm.Update(KL, this->L);
+ this->hm.Update(IL, this->S);
+ this->hm.Final(BR);
+ xorbuf(BR, IR, this->S);
+
+ this->hm.Update(KR, this->L);
+ this->hm.Update(BR, this->S);
+ this->hm.Final(BL);
+ xorbuf(BL, IL, this->S);
+
+ this->hm.Update(KL, this->L);
+ this->hm.Update(BL, this->S);
+ this->hm.Final(this->digest);
+ xorbuf(BR, this->digest, this->S);
+
+ this->hm.Update(KR, this->L);
+ this->hm.Update(OR, this->S);
+ this->hm.Final(this->digest);
+ xorbuf(BL, this->digest, this->S);
+
+ if (xorBlock)
+ xorbuf(outBlock, xorBlock, this->buffer, 2*this->S);
+ else
+ memcpy_s(outBlock, 2*this->S, this->buffer, 2*this->S);
+ }
+ };
+
+ class CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+ {
+ this->hm.Update(KR, this->L);
+ this->hm.Update(IR, this->S);
+ this->hm.Final(BL);
+ xorbuf(BL, IL, this->S);
+
+ this->hm.Update(KL, this->L);
+ this->hm.Update(BL, this->S);
+ this->hm.Final(BR);
+ xorbuf(BR, IR, this->S);
+
+ this->hm.Update(KR, this->L);
+ this->hm.Update(BR, this->S);
+ this->hm.Final(this->digest);
+ xorbuf(BL, this->digest, this->S);
+
+ this->hm.Update(KL, this->L);
+ this->hm.Update(OL, this->S);
+ this->hm.Final(this->digest);
+ xorbuf(BR, this->digest, this->S);
+
+ if (xorBlock)
+ xorbuf(outBlock, xorBlock, this->buffer, 2*this->S);
+ else
+ memcpy(outBlock, this->buffer, 2*this->S);
+ }
+#undef KL
+#undef KR
+#undef BL
+#undef BR
+#undef IL
+#undef IR
+#undef OL
+#undef OR
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/luc.cpp b/lib/cryptopp/luc.cpp
new file mode 100644
index 000000000..43cd2ed21
--- /dev/null
+++ b/lib/cryptopp/luc.cpp
@@ -0,0 +1,210 @@
+// luc.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "luc.h"
+#include "asn.h"
+#include "nbtheory.h"
+#include "sha.h"
+#include "algparam.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void LUC_TestInstantiations()
+{
+ LUC_HMP<SHA>::Signer t1;
+ LUCFunction t2;
+ InvertibleLUCFunction t3;
+}
+
+void DL_Algorithm_LUC_HMP::Sign(const DL_GroupParameters<Integer> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
+{
+ const Integer &q = params.GetSubgroupOrder();
+ r = params.ExponentiateBase(k);
+ s = (k + x*(r+e)) % q;
+}
+
+bool DL_Algorithm_LUC_HMP::Verify(const DL_GroupParameters<Integer> &params, const DL_PublicKey<Integer> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
+{
+ Integer p = params.GetGroupOrder()-1;
+ const Integer &q = params.GetSubgroupOrder();
+
+ Integer Vsg = params.ExponentiateBase(s);
+ Integer Vry = publicKey.ExponentiatePublicElement((r+e)%q);
+ return (Vsg*Vsg + Vry*Vry + r*r) % p == (Vsg * Vry * r + 4) % p;
+}
+
+Integer DL_BasePrecomputation_LUC::Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const
+{
+ return Lucas(exponent, m_g, static_cast<const DL_GroupPrecomputation_LUC &>(group).GetModulus());
+}
+
+void DL_GroupParameters_LUC::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
+{
+ for (unsigned int i=0; i<exponentsCount; i++)
+ results[i] = Lucas(exponents[i], base, GetModulus());
+}
+
+void LUCFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ m_n.BERDecode(seq);
+ m_e.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void LUCFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ m_n.DEREncode(seq);
+ m_e.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer LUCFunction::ApplyFunction(const Integer &x) const
+{
+ DoQuickSanityCheck();
+ return Lucas(m_e, x, m_n);
+}
+
+bool LUCFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = true;
+ pass = pass && m_n > Integer::One() && m_n.IsOdd();
+ pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n;
+ return pass;
+}
+
+bool LUCFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
+ ;
+}
+
+void LUCFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
+ ;
+}
+
+// *****************************************************************************
+// private key operations:
+
+class LUCPrimeSelector : public PrimeSelector
+{
+public:
+ LUCPrimeSelector(const Integer &e) : m_e(e) {}
+ bool IsAcceptable(const Integer &candidate) const
+ {
+ return RelativelyPrime(m_e, candidate+1) && RelativelyPrime(m_e, candidate-1);
+ }
+ Integer m_e;
+};
+
+void InvertibleLUCFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ int modulusSize = 2048;
+ alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
+
+ if (modulusSize < 16)
+ throw InvalidArgument("InvertibleLUCFunction: specified modulus size is too small");
+
+ m_e = alg.GetValueWithDefault("PublicExponent", Integer(17));
+
+ if (m_e < 5 || m_e.IsEven())
+ throw InvalidArgument("InvertibleLUCFunction: invalid public exponent");
+
+ LUCPrimeSelector selector(m_e);
+ AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize)
+ ("PointerToPrimeSelector", selector.GetSelectorPointer());
+ m_p.GenerateRandom(rng, primeParam);
+ m_q.GenerateRandom(rng, primeParam);
+
+ m_n = m_p * m_q;
+ m_u = m_q.InverseMod(m_p);
+}
+
+void InvertibleLUCFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e)
+{
+ GenerateRandom(rng, MakeParameters("ModulusSize", (int)keybits)("PublicExponent", e));
+}
+
+void InvertibleLUCFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+
+ Integer version(seq);
+ if (!!version) // make sure version is 0
+ BERDecodeError();
+
+ m_n.BERDecode(seq);
+ m_e.BERDecode(seq);
+ m_p.BERDecode(seq);
+ m_q.BERDecode(seq);
+ m_u.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void InvertibleLUCFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+
+ const byte version[] = {INTEGER, 1, 0};
+ seq.Put(version, sizeof(version));
+ m_n.DEREncode(seq);
+ m_e.DEREncode(seq);
+ m_p.DEREncode(seq);
+ m_q.DEREncode(seq);
+ m_u.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer InvertibleLUCFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
+{
+ // not clear how to do blinding with LUC
+ DoQuickSanityCheck();
+ return InverseLucas(m_e, x, m_q, m_p, m_u);
+}
+
+bool InvertibleLUCFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = LUCFunction::Validate(rng, level);
+ pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
+ pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
+ pass = pass && m_u.IsPositive() && m_u < m_p;
+ if (level >= 1)
+ {
+ pass = pass && m_p * m_q == m_n;
+ pass = pass && RelativelyPrime(m_e, m_p+1);
+ pass = pass && RelativelyPrime(m_e, m_p-1);
+ pass = pass && RelativelyPrime(m_e, m_q+1);
+ pass = pass && RelativelyPrime(m_e, m_q-1);
+ pass = pass && m_u * m_q % m_p == 1;
+ }
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
+ return pass;
+}
+
+bool InvertibleLUCFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper<LUCFunction>(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+void InvertibleLUCFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper<LUCFunction>(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/luc.h b/lib/cryptopp/luc.h
new file mode 100644
index 000000000..730776d57
--- /dev/null
+++ b/lib/cryptopp/luc.h
@@ -0,0 +1,236 @@
+#ifndef CRYPTOPP_LUC_H
+#define CRYPTOPP_LUC_H
+
+/** \file
+*/
+
+#include "pkcspad.h"
+#include "oaep.h"
+#include "integer.h"
+#include "dh.h"
+
+#include <limits.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! The LUC function.
+/*! This class is here for historical and pedagogical interest. It has no
+ practical advantages over other trapdoor functions and probably shouldn't
+ be used in production software. The discrete log based LUC schemes
+ defined later in this .h file may be of more practical interest.
+*/
+class LUCFunction : public TrapdoorFunction, public PublicKey
+{
+ typedef LUCFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n, const Integer &e)
+ {m_n = n; m_e = e;}
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ Integer ApplyFunction(const Integer &x) const;
+ Integer PreimageBound() const {return m_n;}
+ Integer ImageBound() const {return m_n;}
+
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ // non-derived interface
+ const Integer & GetModulus() const {return m_n;}
+ const Integer & GetPublicExponent() const {return m_e;}
+
+ void SetModulus(const Integer &n) {m_n = n;}
+ void SetPublicExponent(const Integer &e) {m_e = e;}
+
+protected:
+ Integer m_n, m_e;
+};
+
+//! _
+class InvertibleLUCFunction : public LUCFunction, public TrapdoorFunctionInverse, public PrivateKey
+{
+ typedef InvertibleLUCFunction ThisClass;
+
+public:
+ void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &eStart=17);
+ void Initialize(const Integer &n, const Integer &e, const Integer &p, const Integer &q, const Integer &u)
+ {m_n = n; m_e = e; m_p = p; m_q = q; m_u = u;}
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const;
+
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+ /*! parameters: (ModulusSize, PublicExponent (default 17)) */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+
+ // non-derived interface
+ const Integer& GetPrime1() const {return m_p;}
+ const Integer& GetPrime2() const {return m_q;}
+ const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;}
+
+ void SetPrime1(const Integer &p) {m_p = p;}
+ void SetPrime2(const Integer &q) {m_q = q;}
+ void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;}
+
+protected:
+ Integer m_p, m_q, m_u;
+};
+
+struct LUC
+{
+ static std::string StaticAlgorithmName() {return "LUC";}
+ typedef LUCFunction PublicKey;
+ typedef InvertibleLUCFunction PrivateKey;
+};
+
+//! LUC cryptosystem
+template <class STANDARD>
+struct LUCES : public TF_ES<STANDARD, LUC>
+{
+};
+
+//! LUC signature scheme with appendix
+template <class STANDARD, class H>
+struct LUCSS : public TF_SS<STANDARD, H, LUC>
+{
+};
+
+// analagous to the RSA schemes defined in PKCS #1 v2.0
+typedef LUCES<OAEP<SHA> >::Decryptor LUCES_OAEP_SHA_Decryptor;
+typedef LUCES<OAEP<SHA> >::Encryptor LUCES_OAEP_SHA_Encryptor;
+
+typedef LUCSS<PKCS1v15, SHA>::Signer LUCSSA_PKCS1v15_SHA_Signer;
+typedef LUCSS<PKCS1v15, SHA>::Verifier LUCSSA_PKCS1v15_SHA_Verifier;
+
+// ********************************************************
+
+// no actual precomputation
+class DL_GroupPrecomputation_LUC : public DL_GroupPrecomputation<Integer>
+{
+public:
+ const AbstractGroup<Element> & GetGroup() const {assert(false); throw 0;}
+ Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);}
+ void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);}
+
+ // non-inherited
+ void SetModulus(const Integer &v) {m_p = v;}
+ const Integer & GetModulus() const {return m_p;}
+
+private:
+ Integer m_p;
+};
+
+//! _
+class DL_BasePrecomputation_LUC : public DL_FixedBasePrecomputation<Integer>
+{
+public:
+ // DL_FixedBasePrecomputation
+ bool IsInitialized() const {return m_g.NotZero();}
+ void SetBase(const DL_GroupPrecomputation<Element> &group, const Integer &base) {m_g = base;}
+ const Integer & GetBase(const DL_GroupPrecomputation<Element> &group) const {return m_g;}
+ void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage) {}
+ void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) {}
+ void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const {}
+ Integer Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const;
+ Integer CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Integer> &pc2, const Integer &exponent2) const
+ {throw NotImplemented("DL_BasePrecomputation_LUC: CascadeExponentiate not implemented");} // shouldn't be called
+
+private:
+ Integer m_g;
+};
+
+//! _
+class DL_GroupParameters_LUC : public DL_GroupParameters_IntegerBasedImpl<DL_GroupPrecomputation_LUC, DL_BasePrecomputation_LUC>
+{
+public:
+ // DL_GroupParameters
+ bool IsIdentity(const Integer &element) const {return element == Integer::Two();}
+ void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
+ Element MultiplyElements(const Element &a, const Element &b) const
+ {throw NotImplemented("LUC_GroupParameters: MultiplyElements can not be implemented");}
+ Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
+ {throw NotImplemented("LUC_GroupParameters: MultiplyElements can not be implemented");}
+
+ // NameValuePairs interface
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
+ }
+
+private:
+ int GetFieldType() const {return 2;}
+};
+
+//! _
+class DL_GroupParameters_LUC_DefaultSafePrime : public DL_GroupParameters_LUC
+{
+public:
+ typedef NoCofactorMultiplication DefaultCofactorOption;
+
+protected:
+ unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
+};
+
+//! _
+class DL_Algorithm_LUC_HMP : public DL_ElgamalLikeSignatureAlgorithm<Integer>
+{
+public:
+ static const char * StaticAlgorithmName() {return "LUC-HMP";}
+
+ void Sign(const DL_GroupParameters<Integer> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const;
+ bool Verify(const DL_GroupParameters<Integer> &params, const DL_PublicKey<Integer> &publicKey, const Integer &e, const Integer &r, const Integer &s) const;
+
+ size_t RLen(const DL_GroupParameters<Integer> &params) const
+ {return params.GetGroupOrder().ByteCount();}
+};
+
+//! _
+struct DL_SignatureKeys_LUC
+{
+ typedef DL_GroupParameters_LUC GroupParameters;
+ typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
+ typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
+};
+
+//! LUC-HMP, based on "Digital signature schemes based on Lucas functions" by Patrick Horster, Markus Michels, Holger Petersen
+template <class H>
+struct LUC_HMP : public DL_SS<DL_SignatureKeys_LUC, DL_Algorithm_LUC_HMP, DL_SignatureMessageEncodingMethod_DSA, H>
+{
+};
+
+//! _
+struct DL_CryptoKeys_LUC
+{
+ typedef DL_GroupParameters_LUC_DefaultSafePrime GroupParameters;
+ typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
+ typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
+};
+
+//! LUC-IES
+template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
+struct LUC_IES
+ : public DL_ES<
+ DL_CryptoKeys_LUC,
+ DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
+ DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
+ DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
+ LUC_IES<> >
+{
+ static std::string StaticAlgorithmName() {return "LUC-IES";} // non-standard name
+};
+
+// ********************************************************
+
+//! LUC-DH
+typedef DH_Domain<DL_GroupParameters_LUC_DefaultSafePrime> LUC_DH;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/md2.cpp b/lib/cryptopp/md2.cpp
new file mode 100644
index 000000000..41f714b59
--- /dev/null
+++ b/lib/cryptopp/md2.cpp
@@ -0,0 +1,120 @@
+// md2.cpp - modified by Wei Dai from Andrew M. Kuchling's md2.c
+// The original code and all modifications are in the public domain.
+
+// This is the original introductory comment:
+
+/*
+ * md2.c : MD2 hash algorithm.
+ *
+ * Part of the Python Cryptography Toolkit, version 1.1
+ *
+ * Distribute and use freely; there are no restrictions on further
+ * dissemination and usage except those imposed by the laws of your
+ * country of residence.
+ *
+ */
+
+#include "pch.h"
+#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
+#include "md2.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+namespace Weak1 {
+
+MD2::MD2()
+ : m_X(48), m_C(16), m_buf(16)
+{
+ Init();
+}
+
+void MD2::Init()
+{
+ memset(m_X, 0, 48);
+ memset(m_C, 0, 16);
+ memset(m_buf, 0, 16);
+ m_count = 0;
+}
+
+void MD2::Update(const byte *buf, size_t len)
+{
+ static const byte S[256] = {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+ };
+
+ while (len)
+ {
+ unsigned int L = UnsignedMin(16U-m_count, len);
+ memcpy(m_buf+m_count, buf, L);
+ m_count+=L;
+ buf+=L;
+ len-=L;
+ if (m_count==16)
+ {
+ byte t;
+ int i,j;
+
+ m_count=0;
+ memcpy(m_X+16, m_buf, 16);
+ t=m_C[15];
+ for(i=0; i<16; i++)
+ {
+ m_X[32+i]=m_X[16+i]^m_X[i];
+ t=m_C[i]^=S[m_buf[i]^t];
+ }
+
+ t=0;
+ for(i=0; i<18; i++)
+ {
+ for(j=0; j<48; j+=8)
+ {
+ t=m_X[j+0]^=S[t];
+ t=m_X[j+1]^=S[t];
+ t=m_X[j+2]^=S[t];
+ t=m_X[j+3]^=S[t];
+ t=m_X[j+4]^=S[t];
+ t=m_X[j+5]^=S[t];
+ t=m_X[j+6]^=S[t];
+ t=m_X[j+7]^=S[t];
+ }
+ t=(t+i) & 0xFF;
+ }
+ }
+ }
+}
+
+void MD2::TruncatedFinal(byte *hash, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ byte padding[16];
+ word32 padlen;
+ unsigned int i;
+
+ padlen= 16-m_count;
+ for(i=0; i<padlen; i++) padding[i]=(byte)padlen;
+ Update(padding, padlen);
+ Update(m_C, 16);
+ memcpy(hash, m_X, size);
+
+ Init();
+}
+
+}
+NAMESPACE_END
diff --git a/lib/cryptopp/md2.h b/lib/cryptopp/md2.h
new file mode 100644
index 000000000..b0837c882
--- /dev/null
+++ b/lib/cryptopp/md2.h
@@ -0,0 +1,46 @@
+#ifndef CRYPTOPP_MD2_H
+#define CRYPTOPP_MD2_H
+
+#include "cryptlib.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+namespace Weak1 {
+
+/// <a href="http://www.cryptolounge.org/wiki/MD2">MD2</a>
+class MD2 : public HashTransformation
+{
+public:
+ MD2();
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *hash, size_t size);
+ unsigned int DigestSize() const {return DIGESTSIZE;}
+ unsigned int BlockSize() const {return BLOCKSIZE;}
+ static const char * StaticAlgorithmName() {return "MD2";}
+
+ CRYPTOPP_CONSTANT(DIGESTSIZE = 16)
+ CRYPTOPP_CONSTANT(BLOCKSIZE = 16)
+
+private:
+ void Transform();
+ void Init();
+ SecByteBlock m_X, m_C, m_buf;
+ unsigned int m_count;
+};
+
+}
+#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
+namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
+#else
+using namespace Weak1; // import Weak1 into CryptoPP with warning
+#ifdef __GNUC__
+#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
+#else
+#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
+#endif
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/md4.cpp b/lib/cryptopp/md4.cpp
new file mode 100644
index 000000000..9ed639cb9
--- /dev/null
+++ b/lib/cryptopp/md4.cpp
@@ -0,0 +1,110 @@
+// md4.cpp - modified by Wei Dai from Andrew M. Kuchling's md4.c
+// The original code and all modifications are in the public domain.
+
+// This is the original introductory comment:
+
+/*
+ * md4.c : MD4 hash algorithm.
+ *
+ * Part of the Python Cryptography Toolkit, version 1.1
+ *
+ * Distribute and use freely; there are no restrictions on further
+ * dissemination and usage except those imposed by the laws of your
+ * country of residence.
+ *
+ */
+
+#include "pch.h"
+#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
+#include "md4.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+namespace Weak1 {
+
+void MD4::InitState(HashWordType *state)
+{
+ state[0] = 0x67452301L;
+ state[1] = 0xefcdab89L;
+ state[2] = 0x98badcfeL;
+ state[3] = 0x10325476L;
+}
+
+void MD4::Transform (word32 *digest, const word32 *in)
+{
+// #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+ word32 A, B, C, D;
+
+ A=digest[0];
+ B=digest[1];
+ C=digest[2];
+ D=digest[3];
+
+#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+in[k],s);
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 1, 7);
+ function(C,D,A,B, 2,11);
+ function(B,C,D,A, 3,19);
+ function(A,B,C,D, 4, 3);
+ function(D,A,B,C, 5, 7);
+ function(C,D,A,B, 6,11);
+ function(B,C,D,A, 7,19);
+ function(A,B,C,D, 8, 3);
+ function(D,A,B,C, 9, 7);
+ function(C,D,A,B,10,11);
+ function(B,C,D,A,11,19);
+ function(A,B,C,D,12, 3);
+ function(D,A,B,C,13, 7);
+ function(C,D,A,B,14,11);
+ function(B,C,D,A,15,19);
+
+#undef function
+#define function(a,b,c,d,k,s) a=rotlFixed(a+G(b,c,d)+in[k]+0x5a827999,s);
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 4, 5);
+ function(C,D,A,B, 8, 9);
+ function(B,C,D,A,12,13);
+ function(A,B,C,D, 1, 3);
+ function(D,A,B,C, 5, 5);
+ function(C,D,A,B, 9, 9);
+ function(B,C,D,A,13,13);
+ function(A,B,C,D, 2, 3);
+ function(D,A,B,C, 6, 5);
+ function(C,D,A,B,10, 9);
+ function(B,C,D,A,14,13);
+ function(A,B,C,D, 3, 3);
+ function(D,A,B,C, 7, 5);
+ function(C,D,A,B,11, 9);
+ function(B,C,D,A,15,13);
+
+#undef function
+#define function(a,b,c,d,k,s) a=rotlFixed(a+H(b,c,d)+in[k]+0x6ed9eba1,s);
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 8, 9);
+ function(C,D,A,B, 4,11);
+ function(B,C,D,A,12,15);
+ function(A,B,C,D, 2, 3);
+ function(D,A,B,C,10, 9);
+ function(C,D,A,B, 6,11);
+ function(B,C,D,A,14,15);
+ function(A,B,C,D, 1, 3);
+ function(D,A,B,C, 9, 9);
+ function(C,D,A,B, 5,11);
+ function(B,C,D,A,13,15);
+ function(A,B,C,D, 3, 3);
+ function(D,A,B,C,11, 9);
+ function(C,D,A,B, 7,11);
+ function(B,C,D,A,15,15);
+
+ digest[0]+=A;
+ digest[1]+=B;
+ digest[2]+=C;
+ digest[3]+=D;
+}
+
+}
+NAMESPACE_END
diff --git a/lib/cryptopp/md4.h b/lib/cryptopp/md4.h
new file mode 100644
index 000000000..53387003c
--- /dev/null
+++ b/lib/cryptopp/md4.h
@@ -0,0 +1,35 @@
+#ifndef CRYPTOPP_MD4_H
+#define CRYPTOPP_MD4_H
+
+#include "iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+namespace Weak1 {
+
+//! <a href="http://www.weidai.com/scan-mirror/md.html#MD4">MD4</a>
+/*! \warning MD4 is considered insecure, and should not be used
+ unless you absolutely need it for compatibility. */
+class MD4 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, 16, MD4>
+{
+public:
+ static void InitState(HashWordType *state);
+ static void Transform(word32 *digest, const word32 *data);
+ static const char *StaticAlgorithmName() {return "MD4";}
+};
+
+}
+#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
+namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
+#else
+using namespace Weak1; // import Weak1 into CryptoPP with warning
+#ifdef __GNUC__
+#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
+#else
+#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
+#endif
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/md5.cpp b/lib/cryptopp/md5.cpp
new file mode 100644
index 000000000..a52297816
--- /dev/null
+++ b/lib/cryptopp/md5.cpp
@@ -0,0 +1,118 @@
+// md5.cpp - modified by Wei Dai from Colin Plumb's public domain md5.c
+// any modifications are placed in the public domain
+
+#include "pch.h"
+#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
+#include "md5.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+namespace Weak1 {
+
+void MD5_TestInstantiations()
+{
+ MD5 x;
+}
+
+void MD5::InitState(HashWordType *state)
+{
+ state[0] = 0x67452301L;
+ state[1] = 0xefcdab89L;
+ state[2] = 0x98badcfeL;
+ state[3] = 0x10325476L;
+}
+
+void MD5::Transform (word32 *digest, const word32 *in)
+{
+// #define F1(x, y, z) (x & y | ~x & z)
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+ w = rotlFixed(w + f(x, y, z) + data, s) + x
+
+ word32 a, b, c, d;
+
+ a=digest[0];
+ b=digest[1];
+ c=digest[2];
+ d=digest[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ digest[0]+=a;
+ digest[1]+=b;
+ digest[2]+=c;
+ digest[3]+=d;
+}
+
+}
+NAMESPACE_END
diff --git a/lib/cryptopp/md5.h b/lib/cryptopp/md5.h
new file mode 100644
index 000000000..73ec5326c
--- /dev/null
+++ b/lib/cryptopp/md5.h
@@ -0,0 +1,33 @@
+#ifndef CRYPTOPP_MD5_H
+#define CRYPTOPP_MD5_H
+
+#include "iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+namespace Weak1 {
+
+//! <a href="http://www.cryptolounge.org/wiki/MD5">MD5</a>
+class MD5 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, 16, MD5>
+{
+public:
+ static void InitState(HashWordType *state);
+ static void Transform(word32 *digest, const word32 *data);
+ static const char * StaticAlgorithmName() {return "MD5";}
+};
+
+}
+#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
+namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
+#else
+using namespace Weak1; // import Weak1 into CryptoPP with warning
+#ifdef __GNUC__
+#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
+#else
+#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
+#endif
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/mdc.h b/lib/cryptopp/mdc.h
new file mode 100644
index 000000000..cc90cdc45
--- /dev/null
+++ b/lib/cryptopp/mdc.h
@@ -0,0 +1,72 @@
+ // mdc.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_MDC_H
+#define CRYPTOPP_MDC_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+template <class T>
+struct MDC_Info : public FixedBlockSize<T::DIGESTSIZE>, public FixedKeyLength<T::BLOCKSIZE>
+{
+ static std::string StaticAlgorithmName() {return std::string("MDC/")+T::StaticAlgorithmName();}
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/cs.html#MDC">MDC</a>
+/*! a construction by Peter Gutmann to turn an iterated hash function into a PRF */
+template <class T>
+class MDC : public MDC_Info<T>
+{
+ class CRYPTOPP_NO_VTABLE Enc : public BlockCipherImpl<MDC_Info<T> >
+ {
+ typedef typename T::HashWordType HashWordType;
+
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
+ {
+ this->AssertValidKeyLength(length);
+ memcpy_s(m_key, m_key.size(), userKey, this->KEYLENGTH);
+ T::CorrectEndianess(Key(), Key(), this->KEYLENGTH);
+ }
+
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+ {
+ T::CorrectEndianess(Buffer(), (HashWordType *)inBlock, this->BLOCKSIZE);
+ T::Transform(Buffer(), Key());
+ if (xorBlock)
+ {
+ T::CorrectEndianess(Buffer(), Buffer(), this->BLOCKSIZE);
+ xorbuf(outBlock, xorBlock, m_buffer, this->BLOCKSIZE);
+ }
+ else
+ T::CorrectEndianess((HashWordType *)outBlock, Buffer(), this->BLOCKSIZE);
+ }
+
+ bool IsPermutation() const {return false;}
+
+ unsigned int OptimalDataAlignment() const {return sizeof(HashWordType);}
+
+ private:
+ HashWordType *Key() {return (HashWordType *)m_key.data();}
+ const HashWordType *Key() const {return (const HashWordType *)m_key.data();}
+ HashWordType *Buffer() const {return (HashWordType *)m_buffer.data();}
+
+ // VC60 workaround: bug triggered if using FixedSizeAllocatorWithCleanup
+ FixedSizeSecBlock<byte, MDC_Info<T>::KEYLENGTH, AllocatorWithCleanup<byte> > m_key;
+ mutable FixedSizeSecBlock<byte, MDC_Info<T>::BLOCKSIZE, AllocatorWithCleanup<byte> > m_buffer;
+ };
+
+public:
+ //! use BlockCipher interface
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/misc.cpp b/lib/cryptopp/misc.cpp
new file mode 100644
index 000000000..93760e3a3
--- /dev/null
+++ b/lib/cryptopp/misc.cpp
@@ -0,0 +1,189 @@
+// misc.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "misc.h"
+#include "words.h"
+#include <new>
+
+#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX)
+#include <malloc.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void xorbuf(byte *buf, const byte *mask, size_t count)
+{
+ size_t i;
+
+ if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
+ {
+ if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
+ {
+ for (i=0; i<count/8; i++)
+ ((word64*)buf)[i] ^= ((word64*)mask)[i];
+ count -= 8*i;
+ if (!count)
+ return;
+ buf += 8*i;
+ mask += 8*i;
+ }
+
+ for (i=0; i<count/4; i++)
+ ((word32*)buf)[i] ^= ((word32*)mask)[i];
+ count -= 4*i;
+ if (!count)
+ return;
+ buf += 4*i;
+ mask += 4*i;
+ }
+
+ for (i=0; i<count; i++)
+ buf[i] ^= mask[i];
+}
+
+void xorbuf(byte *output, const byte *input, const byte *mask, size_t count)
+{
+ size_t i;
+
+ if (IsAligned<word32>(output) && IsAligned<word32>(input) && IsAligned<word32>(mask))
+ {
+ if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(output) && IsAligned<word64>(input) && IsAligned<word64>(mask))
+ {
+ for (i=0; i<count/8; i++)
+ ((word64*)output)[i] = ((word64*)input)[i] ^ ((word64*)mask)[i];
+ count -= 8*i;
+ if (!count)
+ return;
+ output += 8*i;
+ input += 8*i;
+ mask += 8*i;
+ }
+
+ for (i=0; i<count/4; i++)
+ ((word32*)output)[i] = ((word32*)input)[i] ^ ((word32*)mask)[i];
+ count -= 4*i;
+ if (!count)
+ return;
+ output += 4*i;
+ input += 4*i;
+ mask += 4*i;
+ }
+
+ for (i=0; i<count; i++)
+ output[i] = input[i] ^ mask[i];
+}
+
+bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
+{
+ size_t i;
+ byte acc8 = 0;
+
+ if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
+ {
+ word32 acc32 = 0;
+ if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
+ {
+ word64 acc64 = 0;
+ for (i=0; i<count/8; i++)
+ acc64 |= ((word64*)buf)[i] ^ ((word64*)mask)[i];
+ count -= 8*i;
+ if (!count)
+ return acc64 == 0;
+ buf += 8*i;
+ mask += 8*i;
+ acc32 = word32(acc64) | word32(acc64>>32);
+ }
+
+ for (i=0; i<count/4; i++)
+ acc32 |= ((word32*)buf)[i] ^ ((word32*)mask)[i];
+ count -= 4*i;
+ if (!count)
+ return acc32 == 0;
+ buf += 4*i;
+ mask += 4*i;
+ acc8 = byte(acc32) | byte(acc32>>8) | byte(acc32>>16) | byte(acc32>>24);
+ }
+
+ for (i=0; i<count; i++)
+ acc8 |= buf[i] ^ mask[i];
+ return acc8 == 0;
+}
+
+#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) && !defined(ANDROID_NDK)
+using std::new_handler;
+using std::set_new_handler;
+#endif
+
+void CallNewHandler()
+{
+#if !defined(ANDROID_NDK)
+ new_handler newHandler = set_new_handler(NULL);
+ if (newHandler)
+ set_new_handler(newHandler);
+
+ if (newHandler)
+ newHandler();
+ else
+ throw std::bad_alloc();
+#endif
+}
+
+#if CRYPTOPP_BOOL_ALIGN16_ENABLED
+
+void * AlignedAllocate(size_t size)
+{
+ byte *p;
+#ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
+ while (!(p = (byte *)_mm_malloc(size, 16)))
+#elif defined(CRYPTOPP_MEMALIGN_AVAILABLE)
+ while (!(p = (byte *)memalign(16, size)))
+#elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16)
+ while (!(p = (byte *)malloc(size)))
+#else
+ while (!(p = (byte *)malloc(size + 16)))
+#endif
+ CallNewHandler();
+
+#ifdef CRYPTOPP_NO_ALIGNED_ALLOC
+ size_t adjustment = 16-((size_t)p%16);
+ p += adjustment;
+ p[-1] = (byte)adjustment;
+#endif
+
+ assert(IsAlignedOn(p, 16));
+ return p;
+}
+
+void AlignedDeallocate(void *p)
+{
+#ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
+ _mm_free(p);
+#elif defined(CRYPTOPP_NO_ALIGNED_ALLOC)
+ p = (byte *)p - ((byte *)p)[-1];
+ free(p);
+#else
+ free(p);
+#endif
+}
+
+#endif
+
+void * UnalignedAllocate(size_t size)
+{
+ void *p;
+ while (!(p = malloc(size)))
+ CallNewHandler();
+ return p;
+}
+
+void UnalignedDeallocate(void *p)
+{
+ free(p);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/misc.h b/lib/cryptopp/misc.h
new file mode 100644
index 000000000..2b326dd60
--- /dev/null
+++ b/lib/cryptopp/misc.h
@@ -0,0 +1,1282 @@
+#ifndef CRYPTOPP_MISC_H
+#define CRYPTOPP_MISC_H
+
+#include "cryptlib.h"
+#include "smartptr.h"
+#include <string.h> // for memcpy and memmove
+
+#ifdef _MSC_VER
+ #if _MSC_VER >= 1400
+ // VC2005 workaround: disable declarations that conflict with winnt.h
+ #define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1
+ #define _interlockedbittestandreset CRYPTOPP_DISABLED_INTRINSIC_2
+ #define _interlockedbittestandset64 CRYPTOPP_DISABLED_INTRINSIC_3
+ #define _interlockedbittestandreset64 CRYPTOPP_DISABLED_INTRINSIC_4
+ #include <intrin.h>
+ #undef _interlockedbittestandset
+ #undef _interlockedbittestandreset
+ #undef _interlockedbittestandset64
+ #undef _interlockedbittestandreset64
+ #define CRYPTOPP_FAST_ROTATE(x) 1
+ #elif _MSC_VER >= 1300
+ #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64)
+ #else
+ #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
+ #endif
+#elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \
+ (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM)))
+ #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
+#elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) // depend on GCC's peephole optimization to generate rotate instructions
+ #define CRYPTOPP_FAST_ROTATE(x) 1
+#else
+ #define CRYPTOPP_FAST_ROTATE(x) 0
+#endif
+
+#ifdef __BORLANDC__
+#include <mem.h>
+#endif
+
+#if defined(__GNUC__) && defined(__linux__)
+#define CRYPTOPP_BYTESWAP_AVAILABLE
+#include <byteswap.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ************** compile-time assertion ***************
+
+template <bool b>
+struct CompileAssert
+{
+ static char dummy[2*b-1];
+};
+
+#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
+#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance)
+#else
+#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
+#endif
+#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
+#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
+
+// ************** misc classes ***************
+
+class CRYPTOPP_DLL Empty
+{
+};
+
+//! _
+template <class BASE1, class BASE2>
+class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2
+{
+};
+
+//! _
+template <class BASE1, class BASE2, class BASE3>
+class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3
+{
+};
+
+template <class T>
+class ObjectHolder
+{
+protected:
+ T m_object;
+};
+
+class NotCopyable
+{
+public:
+ NotCopyable() {}
+private:
+ NotCopyable(const NotCopyable &);
+ void operator=(const NotCopyable &);
+};
+
+template <class T>
+struct NewObject
+{
+ T* operator()() const {return new T;}
+};
+
+/*! This function safely initializes a static object in a multithreaded environment without using locks (for portability).
+ Note that if two threads call Ref() at the same time, they may get back different references, and one object
+ may end up being memory leaked. This is by design.
+*/
+template <class T, class F = NewObject<T>, int instance=0>
+class Singleton
+{
+public:
+ Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {}
+
+ // prevent this function from being inlined
+ CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const;
+
+private:
+ F m_objectFactory;
+};
+
+template <class T, class F, int instance>
+const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
+{
+ static volatile simple_ptr<T> s_pObject;
+ T *p = s_pObject.m_p;
+
+ if (p)
+ return *p;
+
+ T *newObject = m_objectFactory();
+ p = s_pObject.m_p;
+
+ if (p)
+ {
+ delete newObject;
+ return *p;
+ }
+
+ s_pObject.m_p = newObject;
+ return *newObject;
+}
+
+// ************** misc functions ***************
+
+#if (!__STDC_WANT_SECURE_LIB__ && !defined(_MEMORY_S_DEFINED))
+inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
+{
+ if (count > sizeInBytes)
+ throw InvalidArgument("memcpy_s: buffer overflow");
+ memcpy(dest, src, count);
+}
+
+inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
+{
+ if (count > sizeInBytes)
+ throw InvalidArgument("memmove_s: buffer overflow");
+ memmove(dest, src, count);
+}
+
+#if __BORLANDC__ >= 0x620
+// C++Builder 2010 workaround: can't use std::memcpy_s because it doesn't allow 0 lengths
+#define memcpy_s CryptoPP::memcpy_s
+#define memmove_s CryptoPP::memmove_s
+#endif
+#endif
+
+inline void * memset_z(void *ptr, int value, size_t num)
+{
+// avoid extranous warning on GCC 4.3.2 Ubuntu 8.10
+#if CRYPTOPP_GCC_VERSION >= 30001
+ if (__builtin_constant_p(num) && num==0)
+ return ptr;
+#endif
+ return memset(ptr, value, num);
+}
+
+// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
+template <class T> inline const T& STDMIN(const T& a, const T& b)
+{
+ return b < a ? b : a;
+}
+
+template <class T1, class T2> inline const T1 UnsignedMin(const T1& a, const T2& b)
+{
+ CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0));
+ assert(a==0 || a>0); // GCC workaround: get rid of the warning "comparison is always true due to limited range of data type"
+ assert(b>=0);
+
+ if (sizeof(T1)<=sizeof(T2))
+ return b < (T2)a ? (T1)b : a;
+ else
+ return (T1)b < a ? (T1)b : a;
+}
+
+template <class T> inline const T& STDMAX(const T& a, const T& b)
+{
+ return a < b ? b : a;
+}
+
+#define RETURN_IF_NONZERO(x) size_t returnedValue = x; if (returnedValue) return returnedValue
+
+// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack
+#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
+// these may be faster on other CPUs/compilers
+// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
+// #define GETBYTE(x, y) (((byte *)&(x))[y])
+
+#define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y)))
+
+template <class T>
+unsigned int Parity(T value)
+{
+ for (unsigned int i=8*sizeof(value)/2; i>0; i/=2)
+ value ^= value >> i;
+ return (unsigned int)value&1;
+}
+
+template <class T>
+unsigned int BytePrecision(const T &value)
+{
+ if (!value)
+ return 0;
+
+ unsigned int l=0, h=8*sizeof(value);
+
+ while (h-l > 8)
+ {
+ unsigned int t = (l+h)/2;
+ if (value >> t)
+ l = t;
+ else
+ h = t;
+ }
+
+ return h/8;
+}
+
+template <class T>
+unsigned int BitPrecision(const T &value)
+{
+ if (!value)
+ return 0;
+
+ unsigned int l=0, h=8*sizeof(value);
+
+ while (h-l > 1)
+ {
+ unsigned int t = (l+h)/2;
+ if (value >> t)
+ l = t;
+ else
+ h = t;
+ }
+
+ return h;
+}
+
+inline unsigned int TrailingZeros(word32 v)
+{
+#if defined(__GNUC__) && CRYPTOPP_GCC_VERSION >= 30400
+ return __builtin_ctz(v);
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+ unsigned long result;
+ _BitScanForward(&result, v);
+ return result;
+#else
+ // from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
+ static const int MultiplyDeBruijnBitPosition[32] =
+ {
+ 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+ 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
+ };
+ return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27];
+#endif
+}
+
+inline unsigned int TrailingZeros(word64 v)
+{
+#if defined(__GNUC__) && CRYPTOPP_GCC_VERSION >= 30400
+ return __builtin_ctzll(v);
+#elif defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(_M_X64) || defined(_M_IA64))
+ unsigned long result;
+ _BitScanForward64(&result, v);
+ return result;
+#else
+ return word32(v) ? TrailingZeros(word32(v)) : 32 + TrailingZeros(word32(v>>32));
+#endif
+}
+
+template <class T>
+inline T Crop(T value, size_t size)
+{
+ if (size < 8*sizeof(value))
+ return T(value & ((T(1) << size) - 1));
+ else
+ return value;
+}
+
+template <class T1, class T2>
+inline bool SafeConvert(T1 from, T2 &to)
+{
+ to = (T2)from;
+ if (from != to || (from > 0) != (to > 0))
+ return false;
+ return true;
+}
+
+inline size_t BitsToBytes(size_t bitCount)
+{
+ return ((bitCount+7)/(8));
+}
+
+inline size_t BytesToWords(size_t byteCount)
+{
+ return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
+}
+
+inline size_t BitsToWords(size_t bitCount)
+{
+ return ((bitCount+WORD_BITS-1)/(WORD_BITS));
+}
+
+inline size_t BitsToDwords(size_t bitCount)
+{
+ return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS));
+}
+
+CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count);
+CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count);
+
+CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count);
+
+template <class T>
+inline bool IsPowerOf2(const T &n)
+{
+ return n > 0 && (n & (n-1)) == 0;
+}
+
+template <class T1, class T2>
+inline T2 ModPowerOf2(const T1 &a, const T2 &b)
+{
+ assert(IsPowerOf2(b));
+ return T2(a) & (b-1);
+}
+
+template <class T1, class T2>
+inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m)
+{
+ if (IsPowerOf2(m))
+ return n - ModPowerOf2(n, m);
+ else
+ return n - n%m;
+}
+
+template <class T1, class T2>
+inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
+{
+ if (n+m-1 < n)
+ throw InvalidArgument("RoundUpToMultipleOf: integer overflow");
+ return RoundDownToMultipleOf(n+m-1, m);
+}
+
+template <class T>
+inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround
+{
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ if (sizeof(T) < 16)
+ return 1;
+#endif
+
+#if (_MSC_VER >= 1300)
+ return __alignof(T);
+#elif defined(__GNUC__)
+ return __alignof__(T);
+#elif CRYPTOPP_BOOL_SLOW_WORD64
+ return UnsignedMin(4U, sizeof(T));
+#else
+ return sizeof(T);
+#endif
+}
+
+inline bool IsAlignedOn(const void *p, unsigned int alignment)
+{
+ return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0);
+}
+
+template <class T>
+inline bool IsAligned(const void *p, T *dummy=NULL) // VC60 workaround
+{
+ return IsAlignedOn(p, GetAlignmentOf<T>());
+}
+
+#ifdef IS_LITTLE_ENDIAN
+ typedef LittleEndian NativeByteOrder;
+#else
+ typedef BigEndian NativeByteOrder;
+#endif
+
+inline ByteOrder GetNativeByteOrder()
+{
+ return NativeByteOrder::ToEnum();
+}
+
+inline bool NativeByteOrderIs(ByteOrder order)
+{
+ return order == GetNativeByteOrder();
+}
+
+template <class T>
+std::string IntToString(T a, unsigned int base = 10)
+{
+ if (a == 0)
+ return "0";
+ bool negate = false;
+ if (a < 0)
+ {
+ negate = true;
+ a = 0-a; // VC .NET does not like -a
+ }
+ std::string result;
+ while (a > 0)
+ {
+ T digit = a % base;
+ result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
+ a /= base;
+ }
+ if (negate)
+ result = "-" + result;
+ return result;
+}
+
+template <class T1, class T2>
+inline T1 SaturatingSubtract(const T1 &a, const T2 &b)
+{
+ return T1((a > b) ? (a - b) : 0);
+}
+
+template <class T>
+inline CipherDir GetCipherDir(const T &obj)
+{
+ return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
+}
+
+CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler();
+
+inline void IncrementCounterByOne(byte *inout, unsigned int s)
+{
+ for (int i=s-1, carry=1; i>=0 && carry; i--)
+ carry = !++inout[i];
+}
+
+inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
+{
+ int i, carry;
+ for (i=s-1, carry=1; i>=0 && carry; i--)
+ carry = ((output[i] = input[i]+1) == 0);
+ memcpy_s(output, s, input, i+1);
+}
+
+template <class T>
+inline void ConditionalSwap(bool c, T &a, T &b)
+{
+ T t = c * (a ^ b);
+ a ^= t;
+ b ^= t;
+}
+
+template <class T>
+inline void ConditionalSwapPointers(bool c, T &a, T &b)
+{
+ ptrdiff_t t = c * (a - b);
+ a -= t;
+ b += t;
+}
+
+// see http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/protect-secrets.html
+// and https://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data
+template <class T>
+void SecureWipeBuffer(T *buf, size_t n)
+{
+ // GCC 4.3.2 on Cygwin optimizes away the first store if this loop is done in the forward direction
+ volatile T *p = buf+n;
+ while (n--)
+ *(--p) = 0;
+}
+
+#if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)
+
+template<> inline void SecureWipeBuffer(byte *buf, size_t n)
+{
+ volatile byte *p = buf;
+#ifdef __GNUC__
+ asm volatile("rep stosb" : "+c"(n), "+D"(p) : "a"(0) : "memory");
+#else
+ __stosb((byte *)(size_t)p, 0, n);
+#endif
+}
+
+template<> inline void SecureWipeBuffer(word16 *buf, size_t n)
+{
+ volatile word16 *p = buf;
+#ifdef __GNUC__
+ asm volatile("rep stosw" : "+c"(n), "+D"(p) : "a"(0) : "memory");
+#else
+ __stosw((word16 *)(size_t)p, 0, n);
+#endif
+}
+
+template<> inline void SecureWipeBuffer(word32 *buf, size_t n)
+{
+ volatile word32 *p = buf;
+#ifdef __GNUC__
+ asm volatile("rep stosl" : "+c"(n), "+D"(p) : "a"(0) : "memory");
+#else
+ __stosd((unsigned long *)(size_t)p, 0, n);
+#endif
+}
+
+template<> inline void SecureWipeBuffer(word64 *buf, size_t n)
+{
+#if CRYPTOPP_BOOL_X64
+ volatile word64 *p = buf;
+#ifdef __GNUC__
+ asm volatile("rep stosq" : "+c"(n), "+D"(p) : "a"(0) : "memory");
+#else
+ __stosq((word64 *)(size_t)p, 0, n);
+#endif
+#else
+ SecureWipeBuffer((word32 *)buf, 2*n);
+#endif
+}
+
+#endif // #if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)
+
+template <class T>
+inline void SecureWipeArray(T *buf, size_t n)
+{
+ if (sizeof(T) % 8 == 0 && GetAlignmentOf<T>() % GetAlignmentOf<word64>() == 0)
+ SecureWipeBuffer((word64 *)buf, n * (sizeof(T)/8));
+ else if (sizeof(T) % 4 == 0 && GetAlignmentOf<T>() % GetAlignmentOf<word32>() == 0)
+ SecureWipeBuffer((word32 *)buf, n * (sizeof(T)/4));
+ else if (sizeof(T) % 2 == 0 && GetAlignmentOf<T>() % GetAlignmentOf<word16>() == 0)
+ SecureWipeBuffer((word16 *)buf, n * (sizeof(T)/2));
+ else
+ SecureWipeBuffer((byte *)buf, n * sizeof(T));
+}
+
+// this function uses wcstombs(), which assumes that setlocale() has been called
+static std::string StringNarrow(const wchar_t *str, bool throwOnError = true)
+{
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4996) // 'wcstombs': This function or variable may be unsafe.
+#endif
+ size_t size = wcstombs(NULL, str, 0);
+ if (size == size_t(0)-1)
+ {
+ if (throwOnError)
+ throw InvalidArgument("StringNarrow: wcstombs() call failed");
+ else
+ return std::string();
+ }
+ std::string result(size, 0);
+ wcstombs(&result[0], str, size);
+ return result;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+}
+
+#if CRYPTOPP_BOOL_ALIGN16_ENABLED
+CRYPTOPP_DLL void * CRYPTOPP_API AlignedAllocate(size_t size);
+CRYPTOPP_DLL void CRYPTOPP_API AlignedDeallocate(void *p);
+#endif
+
+CRYPTOPP_DLL void * CRYPTOPP_API UnalignedAllocate(size_t size);
+CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *p);
+
+// ************** rotate functions ***************
+
+template <class T> inline T rotlFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return y ? T((x<<y) | (x>>(sizeof(T)*8-y))) : x;
+}
+
+template <class T> inline T rotrFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return y ? T((x>>y) | (x<<(sizeof(T)*8-y))) : x;
+}
+
+template <class T> inline T rotlVariable(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrVariable(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotlMod(T x, unsigned int y)
+{
+ y %= sizeof(T)*8;
+ return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrMod(T x, unsigned int y)
+{
+ y %= sizeof(T)*8;
+ return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+#ifdef _MSC_VER
+
+template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _lrotl(x, y) : x;
+}
+
+template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _lrotr(x, y) : x;
+}
+
+template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _lrotl(x, y);
+}
+
+template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _lrotr(x, y);
+}
+
+template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
+{
+ return _lrotl(x, y);
+}
+
+template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
+{
+ return _lrotr(x, y);
+}
+
+#endif // #ifdef _MSC_VER
+
+#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+// Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when using these instructions
+
+template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _rotl64(x, y) : x;
+}
+
+template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _rotr64(x, y) : x;
+}
+
+template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _rotl64(x, y);
+}
+
+template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _rotr64(x, y);
+}
+
+template<> inline word64 rotlMod<word64>(word64 x, unsigned int y)
+{
+ return _rotl64(x, y);
+}
+
+template<> inline word64 rotrMod<word64>(word64 x, unsigned int y)
+{
+ return _rotr64(x, y);
+}
+
+#endif // #if _MSC_VER >= 1310
+
+#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER)
+// Intel C++ Compiler 10.0 gives undefined externals with these
+
+template<> inline word16 rotlFixed<word16>(word16 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _rotl16(x, y) : x;
+}
+
+template<> inline word16 rotrFixed<word16>(word16 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _rotr16(x, y) : x;
+}
+
+template<> inline word16 rotlVariable<word16>(word16 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _rotl16(x, y);
+}
+
+template<> inline word16 rotrVariable<word16>(word16 x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _rotr16(x, y);
+}
+
+template<> inline word16 rotlMod<word16>(word16 x, unsigned int y)
+{
+ return _rotl16(x, y);
+}
+
+template<> inline word16 rotrMod<word16>(word16 x, unsigned int y)
+{
+ return _rotr16(x, y);
+}
+
+template<> inline byte rotlFixed<byte>(byte x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _rotl8(x, y) : x;
+}
+
+template<> inline byte rotrFixed<byte>(byte x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return y ? _rotr8(x, y) : x;
+}
+
+template<> inline byte rotlVariable<byte>(byte x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _rotl8(x, y);
+}
+
+template<> inline byte rotrVariable<byte>(byte x, unsigned int y)
+{
+ assert(y < 8*sizeof(x));
+ return _rotr8(x, y);
+}
+
+template<> inline byte rotlMod<byte>(byte x, unsigned int y)
+{
+ return _rotl8(x, y);
+}
+
+template<> inline byte rotrMod<byte>(byte x, unsigned int y)
+{
+ return _rotr8(x, y);
+}
+
+#endif // #if _MSC_VER >= 1400
+
+#if (defined(__MWERKS__) && TARGET_CPU_PPC)
+
+template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
+{
+ assert(y < 32);
+ return y ? __rlwinm(x,y,0,31) : x;
+}
+
+template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
+{
+ assert(y < 32);
+ return y ? __rlwinm(x,32-y,0,31) : x;
+}
+
+template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
+{
+ assert(y < 32);
+ return (__rlwnm(x,y,0,31));
+}
+
+template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
+{
+ assert(y < 32);
+ return (__rlwnm(x,32-y,0,31));
+}
+
+template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
+{
+ return (__rlwnm(x,y,0,31));
+}
+
+template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
+{
+ return (__rlwnm(x,32-y,0,31));
+}
+
+#endif // #if (defined(__MWERKS__) && TARGET_CPU_PPC)
+
+// ************** endian reversal ***************
+
+template <class T>
+inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
+{
+ if (order == LITTLE_ENDIAN_ORDER)
+ return GETBYTE(value, index);
+ else
+ return GETBYTE(value, sizeof(T)-index-1);
+}
+
+inline byte ByteReverse(byte value)
+{
+ return value;
+}
+
+inline word16 ByteReverse(word16 value)
+{
+#ifdef CRYPTOPP_BYTESWAP_AVAILABLE
+ return bswap_16(value);
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
+ return _byteswap_ushort(value);
+#else
+ return rotlFixed(value, 8U);
+#endif
+}
+
+inline word32 ByteReverse(word32 value)
+{
+#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE)
+ __asm__ ("bswap %0" : "=r" (value) : "0" (value));
+ return value;
+#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
+ return bswap_32(value);
+#elif defined(__MWERKS__) && TARGET_CPU_PPC
+ return (word32)__lwbrx(&value,0);
+#elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL))
+ return _byteswap_ulong(value);
+#elif CRYPTOPP_FAST_ROTATE(32)
+ // 5 instructions with rotate instruction, 9 without
+ return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
+#else
+ // 6 instructions with rotate instruction, 8 without
+ value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+ return rotlFixed(value, 16U);
+#endif
+}
+
+inline word64 ByteReverse(word64 value)
+{
+#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__)
+ __asm__ ("bswap %0" : "=r" (value) : "0" (value));
+ return value;
+#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
+ return bswap_64(value);
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
+ return _byteswap_uint64(value);
+#elif CRYPTOPP_BOOL_SLOW_WORD64
+ return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
+#else
+ value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
+ value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
+ return rotlFixed(value, 32U);
+#endif
+}
+
+inline byte BitReverse(byte value)
+{
+ value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
+ value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
+ return rotlFixed(value, 4U);
+}
+
+inline word16 BitReverse(word16 value)
+{
+ value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
+ value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
+ value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
+ return ByteReverse(value);
+}
+
+inline word32 BitReverse(word32 value)
+{
+ value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
+ value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
+ value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
+ return ByteReverse(value);
+}
+
+inline word64 BitReverse(word64 value)
+{
+#if CRYPTOPP_BOOL_SLOW_WORD64
+ return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
+#else
+ value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
+ value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
+ value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
+ return ByteReverse(value);
+#endif
+}
+
+template <class T>
+inline T BitReverse(T value)
+{
+ if (sizeof(T) == 1)
+ return (T)BitReverse((byte)value);
+ else if (sizeof(T) == 2)
+ return (T)BitReverse((word16)value);
+ else if (sizeof(T) == 4)
+ return (T)BitReverse((word32)value);
+ else
+ {
+ assert(sizeof(T) == 8);
+ return (T)BitReverse((word64)value);
+ }
+}
+
+template <class T>
+inline T ConditionalByteReverse(ByteOrder order, T value)
+{
+ return NativeByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+template <class T>
+void ByteReverse(T *out, const T *in, size_t byteCount)
+{
+ assert(byteCount % sizeof(T) == 0);
+ size_t count = byteCount/sizeof(T);
+ for (size_t i=0; i<count; i++)
+ out[i] = ByteReverse(in[i]);
+}
+
+template <class T>
+inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount)
+{
+ if (!NativeByteOrderIs(order))
+ ByteReverse(out, in, byteCount);
+ else if (in != out)
+ memcpy_s(out, byteCount, in, byteCount);
+}
+
+template <class T>
+inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
+{
+ const size_t U = sizeof(T);
+ assert(inlen <= outlen*U);
+ memcpy_s(out, outlen*U, in, inlen);
+ memset_z((byte *)out+inlen, 0, outlen*U-inlen);
+ ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
+}
+
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *)
+{
+ return block[0];
+}
+
+inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *)
+{
+ return (order == BIG_ENDIAN_ORDER)
+ ? block[1] | (block[0] << 8)
+ : block[0] | (block[1] << 8);
+}
+
+inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *)
+{
+ return (order == BIG_ENDIAN_ORDER)
+ ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
+ : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
+}
+
+inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *)
+{
+ return (order == BIG_ENDIAN_ORDER)
+ ?
+ (word64(block[7]) |
+ (word64(block[6]) << 8) |
+ (word64(block[5]) << 16) |
+ (word64(block[4]) << 24) |
+ (word64(block[3]) << 32) |
+ (word64(block[2]) << 40) |
+ (word64(block[1]) << 48) |
+ (word64(block[0]) << 56))
+ :
+ (word64(block[0]) |
+ (word64(block[1]) << 8) |
+ (word64(block[2]) << 16) |
+ (word64(block[3]) << 24) |
+ (word64(block[4]) << 32) |
+ (word64(block[5]) << 40) |
+ (word64(block[6]) << 48) |
+ (word64(block[7]) << 56));
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock)
+{
+ block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock)
+{
+ if (order == BIG_ENDIAN_ORDER)
+ {
+ if (xorBlock)
+ {
+ block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ }
+ else
+ {
+ block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ }
+ }
+ else
+ {
+ if (xorBlock)
+ {
+ block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ }
+ else
+ {
+ block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ }
+ }
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word32 value, const byte *xorBlock)
+{
+ if (order == BIG_ENDIAN_ORDER)
+ {
+ if (xorBlock)
+ {
+ block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ }
+ else
+ {
+ block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ }
+ }
+ else
+ {
+ if (xorBlock)
+ {
+ block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ }
+ else
+ {
+ block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ }
+ }
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock)
+{
+ if (order == BIG_ENDIAN_ORDER)
+ {
+ if (xorBlock)
+ {
+ block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+ block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+ block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+ block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+ block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ }
+ else
+ {
+ block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+ block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+ block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+ block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+ block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ }
+ }
+ else
+ {
+ if (xorBlock)
+ {
+ block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+ block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+ block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+ block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+ }
+ else
+ {
+ block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+ block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+ block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+ block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+ block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+ block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+ block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+ block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+ }
+ }
+}
+#endif // #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+
+template <class T>
+inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
+{
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ if (!assumeAligned)
+ return UnalignedGetWordNonTemplate(order, block, (T*)NULL);
+ assert(IsAligned<T>(block));
+#endif
+ return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
+}
+
+template <class T>
+inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
+{
+ result = GetWord<T>(assumeAligned, order, block);
+}
+
+template <class T>
+inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
+{
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ if (!assumeAligned)
+ return UnalignedPutWordNonTemplate(order, block, value, xorBlock);
+ assert(IsAligned<T>(block));
+ assert(IsAligned<T>(xorBlock));
+#endif
+ *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast<const T *>(xorBlock) : 0);
+}
+
+template <class T, class B, bool A=false>
+class GetBlock
+{
+public:
+ GetBlock(const void *block)
+ : m_block((const byte *)block) {}
+
+ template <class U>
+ inline GetBlock<T, B, A> & operator()(U &x)
+ {
+ CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
+ x = GetWord<T>(A, B::ToEnum(), m_block);
+ m_block += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_block;
+};
+
+template <class T, class B, bool A=false>
+class PutBlock
+{
+public:
+ PutBlock(const void *xorBlock, void *block)
+ : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
+
+ template <class U>
+ inline PutBlock<T, B, A> & operator()(U x)
+ {
+ PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
+ m_block += sizeof(T);
+ if (m_xorBlock)
+ m_xorBlock += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_xorBlock;
+ byte *m_block;
+};
+
+template <class T, class B, bool GA=false, bool PA=false>
+struct BlockGetAndPut
+{
+ // function needed because of C++ grammatical ambiguity between expression-statements and declarations
+ static inline GetBlock<T, B, GA> Get(const void *block) {return GetBlock<T, B, GA>(block);}
+ typedef PutBlock<T, B, PA> Put;
+};
+
+template <class T>
+std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
+{
+ if (!NativeByteOrderIs(order))
+ value = ByteReverse(value);
+
+ return std::string((char *)&value, sizeof(value));
+}
+
+template <class T>
+T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
+{
+ T value = 0;
+ memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value)));
+ return NativeByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+// ************** help remove warning on g++ ***************
+
+template <bool overflow> struct SafeShifter;
+
+template<> struct SafeShifter<true>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+};
+
+template<> struct SafeShifter<false>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return value >> bits;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return value << bits;
+ }
+};
+
+template <unsigned int bits, class T>
+inline T SafeRightShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
+}
+
+template <unsigned int bits, class T>
+inline T SafeLeftShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
+}
+
+// ************** use one buffer for multiple data members ***************
+
+#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);} size_t SS1() {return sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/modarith.h b/lib/cryptopp/modarith.h
new file mode 100644
index 000000000..c0368e3fb
--- /dev/null
+++ b/lib/cryptopp/modarith.h
@@ -0,0 +1,158 @@
+#ifndef CRYPTOPP_MODARITH_H
+#define CRYPTOPP_MODARITH_H
+
+// implementations are in integer.cpp
+
+#include "cryptlib.h"
+#include "misc.h"
+#include "integer.h"
+#include "algebra.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<Integer>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<Integer>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<Integer>;
+
+//! ring of congruence classes modulo n
+/*! \note this implementation represents each congruence class as the smallest non-negative integer in that class */
+class CRYPTOPP_DLL ModularArithmetic : public AbstractRing<Integer>
+{
+public:
+
+ typedef int RandomizationParameter;
+ typedef Integer Element;
+
+ ModularArithmetic(const Integer &modulus = Integer::One())
+ : m_modulus(modulus), m_result((word)0, modulus.reg.size()) {}
+
+ ModularArithmetic(const ModularArithmetic &ma)
+ : m_modulus(ma.m_modulus), m_result((word)0, m_modulus.reg.size()) {}
+
+ ModularArithmetic(BufferedTransformation &bt); // construct from BER encoded parameters
+
+ virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);}
+
+ void DEREncode(BufferedTransformation &bt) const;
+
+ void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
+ void BERDecodeElement(BufferedTransformation &in, Element &a) const;
+
+ const Integer& GetModulus() const {return m_modulus;}
+ void SetModulus(const Integer &newModulus) {m_modulus = newModulus; m_result.reg.resize(m_modulus.reg.size());}
+
+ virtual bool IsMontgomeryRepresentation() const {return false;}
+
+ virtual Integer ConvertIn(const Integer &a) const
+ {return a%m_modulus;}
+
+ virtual Integer ConvertOut(const Integer &a) const
+ {return a;}
+
+ const Integer& Half(const Integer &a) const;
+
+ bool Equal(const Integer &a, const Integer &b) const
+ {return a==b;}
+
+ const Integer& Identity() const
+ {return Integer::Zero();}
+
+ const Integer& Add(const Integer &a, const Integer &b) const;
+
+ Integer& Accumulate(Integer &a, const Integer &b) const;
+
+ const Integer& Inverse(const Integer &a) const;
+
+ const Integer& Subtract(const Integer &a, const Integer &b) const;
+
+ Integer& Reduce(Integer &a, const Integer &b) const;
+
+ const Integer& Double(const Integer &a) const
+ {return Add(a, a);}
+
+ const Integer& MultiplicativeIdentity() const
+ {return Integer::One();}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const
+ {return m_result1 = a*b%m_modulus;}
+
+ const Integer& Square(const Integer &a) const
+ {return m_result1 = a.Squared()%m_modulus;}
+
+ bool IsUnit(const Integer &a) const
+ {return Integer::Gcd(a, m_modulus).IsUnit();}
+
+ const Integer& MultiplicativeInverse(const Integer &a) const
+ {return m_result1 = a.InverseMod(m_modulus);}
+
+ const Integer& Divide(const Integer &a, const Integer &b) const
+ {return Multiply(a, MultiplicativeInverse(b));}
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const;
+
+ void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
+
+ unsigned int MaxElementBitLength() const
+ {return (m_modulus-1).BitCount();}
+
+ unsigned int MaxElementByteLength() const
+ {return (m_modulus-1).ByteCount();}
+
+ Element RandomElement( RandomNumberGenerator &rng , const RandomizationParameter &ignore_for_now = 0 ) const
+ // left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct
+ {
+ return Element( rng , Integer( (long) 0) , m_modulus - Integer( (long) 1 ) ) ;
+ }
+
+ bool operator==(const ModularArithmetic &rhs) const
+ {return m_modulus == rhs.m_modulus;}
+
+ static const RandomizationParameter DefaultRandomizationParameter ;
+
+protected:
+ Integer m_modulus;
+ mutable Integer m_result, m_result1;
+
+};
+
+// const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ;
+
+//! do modular arithmetics in Montgomery representation for increased speed
+/*! \note the Montgomery representation represents each congruence class [a] as a*r%n, where r is a convenient power of 2 */
+class CRYPTOPP_DLL MontgomeryRepresentation : public ModularArithmetic
+{
+public:
+ MontgomeryRepresentation(const Integer &modulus); // modulus must be odd
+
+ virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);}
+
+ bool IsMontgomeryRepresentation() const {return true;}
+
+ Integer ConvertIn(const Integer &a) const
+ {return (a<<(WORD_BITS*m_modulus.reg.size()))%m_modulus;}
+
+ Integer ConvertOut(const Integer &a) const;
+
+ const Integer& MultiplicativeIdentity() const
+ {return m_result1 = Integer::Power2(WORD_BITS*m_modulus.reg.size())%m_modulus;}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const;
+
+ const Integer& Square(const Integer &a) const;
+
+ const Integer& MultiplicativeInverse(const Integer &a) const;
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const
+ {return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
+ {AbstractRing<Integer>::SimultaneousExponentiate(results, base, exponents, exponentsCount);}
+
+private:
+ Integer m_u;
+ mutable IntegerSecBlock m_workspace;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/modes.cpp b/lib/cryptopp/modes.cpp
new file mode 100644
index 000000000..46332284b
--- /dev/null
+++ b/lib/cryptopp/modes.cpp
@@ -0,0 +1,245 @@
+// modes.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "modes.h"
+
+#ifndef NDEBUG
+#include "des.h"
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifndef NDEBUG
+void Modes_TestInstantiations()
+{
+ CFB_Mode<DES>::Encryption m0;
+ CFB_Mode<DES>::Decryption m1;
+ OFB_Mode<DES>::Encryption m2;
+ CTR_Mode<DES>::Encryption m3;
+ ECB_Mode<DES>::Encryption m4;
+ CBC_Mode<DES>::Encryption m5;
+}
+#endif
+
+void CFB_ModePolicy::Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount)
+{
+ assert(m_cipher->IsForwardTransformation()); // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
+ assert(m_feedbackSize == BlockSize());
+
+ unsigned int s = BlockSize();
+ if (dir == ENCRYPTION)
+ {
+ m_cipher->ProcessAndXorBlock(m_register, input, output);
+ m_cipher->AdvancedProcessBlocks(output, input+s, output+s, (iterationCount-1)*s, 0);
+ memcpy(m_register, output+(iterationCount-1)*s, s);
+ }
+ else
+ {
+ memcpy(m_temp, input+(iterationCount-1)*s, s); // make copy first in case of in-place decryption
+ m_cipher->AdvancedProcessBlocks(input, input+s, output+s, (iterationCount-1)*s, BlockTransformation::BT_ReverseDirection);
+ m_cipher->ProcessAndXorBlock(m_register, input, output);
+ memcpy(m_register, m_temp, s);
+ }
+}
+
+void CFB_ModePolicy::TransformRegister()
+{
+ assert(m_cipher->IsForwardTransformation()); // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
+ m_cipher->ProcessBlock(m_register, m_temp);
+ unsigned int updateSize = BlockSize()-m_feedbackSize;
+ memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize);
+ memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize);
+}
+
+void CFB_ModePolicy::CipherResynchronize(const byte *iv, size_t length)
+{
+ assert(length == BlockSize());
+ CopyOrZero(m_register, iv, length);
+ TransformRegister();
+}
+
+void CFB_ModePolicy::SetFeedbackSize(unsigned int feedbackSize)
+{
+ if (feedbackSize > BlockSize())
+ throw InvalidArgument("CFB_Mode: invalid feedback size");
+ m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
+}
+
+void CFB_ModePolicy::ResizeBuffers()
+{
+ CipherModeBase::ResizeBuffers();
+ m_temp.New(BlockSize());
+}
+
+void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
+{
+ assert(m_cipher->IsForwardTransformation()); // OFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
+ unsigned int s = BlockSize();
+ m_cipher->ProcessBlock(m_register, keystreamBuffer);
+ if (iterationCount > 1)
+ m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULL, keystreamBuffer+s, s*(iterationCount-1), 0);
+ memcpy(m_register, keystreamBuffer+s*(iterationCount-1), s);
+}
+
+void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
+{
+ assert(length == BlockSize());
+ CopyOrZero(m_register, iv, length);
+}
+
+void CTR_ModePolicy::SeekToIteration(lword iterationCount)
+{
+ int carry=0;
+ for (int i=BlockSize()-1; i>=0; i--)
+ {
+ unsigned int sum = m_register[i] + byte(iterationCount) + carry;
+ m_counterArray[i] = (byte) sum;
+ carry = sum >> 8;
+ iterationCount >>= 8;
+ }
+}
+
+void CTR_ModePolicy::IncrementCounterBy256()
+{
+ IncrementCounterByOne(m_counterArray, BlockSize()-1);
+}
+
+void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
+{
+ assert(m_cipher->IsForwardTransformation()); // CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
+ unsigned int s = BlockSize();
+ unsigned int inputIncrement = input ? s : 0;
+
+ while (iterationCount)
+ {
+ byte lsb = m_counterArray[s-1];
+ size_t blocks = UnsignedMin(iterationCount, 256U-lsb);
+ m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter|BlockTransformation::BT_AllowParallel);
+ if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0)
+ IncrementCounterBy256();
+
+ output += blocks*s;
+ input += blocks*inputIncrement;
+ iterationCount -= blocks;
+ }
+}
+
+void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
+{
+ assert(length == BlockSize());
+ CopyOrZero(m_register, iv, length);
+ m_counterArray = m_register;
+}
+
+void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+{
+ m_cipher->SetKey(key, length, params);
+ ResizeBuffers();
+ if (IsResynchronizable())
+ {
+ size_t ivLength;
+ const byte *iv = GetIVAndThrowIfInvalid(params, ivLength);
+ Resynchronize(iv, (int)ivLength);
+ }
+}
+
+void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length)
+{
+ assert(length%BlockSize()==0);
+ m_cipher->AdvancedProcessBlocks(inString, NULL, outString, length, BlockTransformation::BT_AllowParallel);
+}
+
+void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length)
+{
+ if (!length)
+ return;
+ assert(length%BlockSize()==0);
+
+ unsigned int blockSize = BlockSize();
+ m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput);
+ if (length > blockSize)
+ m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput);
+ memcpy(m_register, outString + length - blockSize, blockSize);
+}
+
+void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
+{
+ if (length <= BlockSize())
+ {
+ if (!m_stolenIV)
+ throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
+
+ // steal from IV
+ memcpy(outString, m_register, length);
+ outString = m_stolenIV;
+ }
+ else
+ {
+ // steal from next to last block
+ xorbuf(m_register, inString, BlockSize());
+ m_cipher->ProcessBlock(m_register);
+ inString += BlockSize();
+ length -= BlockSize();
+ memcpy(outString+BlockSize(), m_register, length);
+ }
+
+ // output last full ciphertext block
+ xorbuf(m_register, inString, length);
+ m_cipher->ProcessBlock(m_register);
+ memcpy(outString, m_register, BlockSize());
+}
+
+void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length)
+{
+ if (!length)
+ return;
+ assert(length%BlockSize()==0);
+
+ unsigned int blockSize = BlockSize();
+ memcpy(m_temp, inString+length-blockSize, blockSize); // save copy now in case of in-place decryption
+ if (length > blockSize)
+ m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection|BlockTransformation::BT_AllowParallel);
+ m_cipher->ProcessAndXorBlock(inString, m_register, outString);
+ m_register.swap(m_temp);
+}
+
+void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
+{
+ const byte *pn, *pn1;
+ bool stealIV = length <= BlockSize();
+
+ if (stealIV)
+ {
+ pn = inString;
+ pn1 = m_register;
+ }
+ else
+ {
+ pn = inString + BlockSize();
+ pn1 = inString;
+ length -= BlockSize();
+ }
+
+ // decrypt last partial plaintext block
+ memcpy(m_temp, pn1, BlockSize());
+ m_cipher->ProcessBlock(m_temp);
+ xorbuf(m_temp, pn, length);
+
+ if (stealIV)
+ memcpy(outString, m_temp, length);
+ else
+ {
+ memcpy(outString+BlockSize(), m_temp, length);
+ // decrypt next to last plaintext block
+ memcpy(m_temp, pn, length);
+ m_cipher->ProcessBlock(m_temp);
+ xorbuf(outString, m_temp, m_register, BlockSize());
+ }
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/modes.h b/lib/cryptopp/modes.h
new file mode 100644
index 000000000..c0c30c476
--- /dev/null
+++ b/lib/cryptopp/modes.h
@@ -0,0 +1,422 @@
+#ifndef CRYPTOPP_MODES_H
+#define CRYPTOPP_MODES_H
+
+/*! \file
+*/
+
+#include "cryptlib.h"
+#include "secblock.h"
+#include "misc.h"
+#include "strciphr.h"
+#include "argnames.h"
+#include "algparam.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes.
+
+/*! Each class derived from this one defines two types, Encryption and Decryption,
+ both of which implement the SymmetricCipher interface.
+ For each mode there are two classes, one of which is a template class,
+ and the other one has a name that ends in "_ExternalCipher".
+ The "external cipher" mode objects hold a reference to the underlying block cipher,
+ instead of holding an instance of it. The reference must be passed in to the constructor.
+ For the "cipher holder" classes, the CIPHER template parameter should be a class
+ derived from BlockCipherDocumentation, for example DES or AES.
+*/
+struct CipherModeDocumentation : public SymmetricCipherDocumentation
+{
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher
+{
+public:
+ size_t MinKeyLength() const {return m_cipher->MinKeyLength();}
+ size_t MaxKeyLength() const {return m_cipher->MaxKeyLength();}
+ size_t DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
+ size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);}
+ bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);}
+
+ unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();}
+
+ unsigned int IVSize() const {return BlockSize();}
+ virtual IV_Requirement IVRequirement() const =0;
+
+ void SetCipher(BlockCipher &cipher)
+ {
+ this->ThrowIfResynchronizable();
+ this->m_cipher = &cipher;
+ this->ResizeBuffers();
+ }
+
+ void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
+ {
+ this->ThrowIfInvalidIV(iv);
+ this->m_cipher = &cipher;
+ this->ResizeBuffers();
+ this->SetFeedbackSize(feedbackSize);
+ if (this->IsResynchronizable())
+ this->Resynchronize(iv);
+ }
+
+protected:
+ CipherModeBase() : m_cipher(NULL) {}
+ inline unsigned int BlockSize() const {assert(m_register.size() > 0); return (unsigned int)m_register.size();}
+ virtual void SetFeedbackSize(unsigned int feedbackSize)
+ {
+ if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
+ throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
+ }
+ virtual void ResizeBuffers()
+ {
+ m_register.New(m_cipher->BlockSize());
+ }
+
+ BlockCipher *m_cipher;
+ AlignedSecByteBlock m_register;
+};
+
+template <class POLICY_INTERFACE>
+class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
+{
+ unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
+ void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
+};
+
+template <class POLICY_INTERFACE>
+void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
+{
+ m_cipher->SetKey(key, length, params);
+ ResizeBuffers();
+ int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
+ SetFeedbackSize(feedbackSize);
+}
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
+{
+public:
+ IV_Requirement IVRequirement() const {return RANDOM_IV;}
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";}
+
+protected:
+ unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
+ byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
+ bool CanIterate() const {return m_feedbackSize == BlockSize();}
+ void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount);
+ void TransformRegister();
+ void CipherResynchronize(const byte *iv, size_t length);
+ void SetFeedbackSize(unsigned int feedbackSize);
+ void ResizeBuffers();
+
+ SecByteBlock m_temp;
+ unsigned int m_feedbackSize;
+};
+
+inline void CopyOrZero(void *dest, const void *src, size_t s)
+{
+ if (src)
+ memcpy_s(dest, s, src, s);
+ else
+ memset(dest, 0, s);
+}
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
+{
+public:
+ bool CipherIsRandomAccess() const {return false;}
+ IV_Requirement IVRequirement() const {return UNIQUE_IV;}
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";}
+
+private:
+ unsigned int GetBytesPerIteration() const {return BlockSize();}
+ unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
+ void WriteKeystream(byte *keystreamBuffer, size_t iterationCount);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
+{
+public:
+ bool CipherIsRandomAccess() const {return true;}
+ IV_Requirement IVRequirement() const {return RANDOM_IV;}
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";}
+
+protected:
+ virtual void IncrementCounterBy256();
+
+ unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
+ unsigned int GetBytesPerIteration() const {return BlockSize();}
+ unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
+ void WriteKeystream(byte *buffer, size_t iterationCount)
+ {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
+ bool CanOperateKeystream() const {return true;}
+ void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
+ void SeekToIteration(lword iterationCount);
+
+ AlignedSecByteBlock m_counterArray;
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase
+{
+public:
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+ unsigned int MandatoryBlockSize() const {return BlockSize();}
+ bool IsRandomAccess() const {return false;}
+ bool IsSelfInverting() const {return false;}
+ bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
+ void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
+
+protected:
+ bool RequireAlignedInput() const {return true;}
+ void ResizeBuffers()
+ {
+ CipherModeBase::ResizeBuffers();
+ m_buffer.New(BlockSize());
+ }
+
+ SecByteBlock m_buffer;
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase
+{
+public:
+ void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs)
+ {m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();}
+ IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
+ unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
+ void ProcessData(byte *outString, const byte *inString, size_t length);
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";}
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase
+{
+public:
+ IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
+ bool RequireAlignedInput() const {return false;}
+ unsigned int MinLastBlockSize() const {return 0;}
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC";}
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase
+{
+public:
+ void ProcessData(byte *outString, const byte *inString, size_t length);
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption
+{
+public:
+ void SetStolenIV(byte *iv) {m_stolenIV = iv;}
+ unsigned int MinLastBlockSize() const {return BlockSize()+1;}
+ void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";}
+
+protected:
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+ {
+ CBC_Encryption::UncheckedSetKey(key, length, params);
+ m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
+ }
+
+ byte *m_stolenIV;
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase
+{
+public:
+ void ProcessData(byte *outString, const byte *inString, size_t length);
+
+protected:
+ void ResizeBuffers()
+ {
+ BlockOrientedCipherModeBase::ResizeBuffers();
+ m_temp.New(BlockSize());
+ }
+ AlignedSecByteBlock m_temp;
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
+{
+public:
+ unsigned int MinLastBlockSize() const {return BlockSize()+1;}
+ void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
+};
+
+//! _
+template <class CIPHER, class BASE>
+class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder<CIPHER>, public AlgorithmImpl<BASE, CipherModeFinalTemplate_CipherHolder<CIPHER, BASE> >
+{
+public:
+ CipherModeFinalTemplate_CipherHolder()
+ {
+ this->m_cipher = &this->m_object;
+ this->ResizeBuffers();
+ }
+ CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length)
+ {
+ this->m_cipher = &this->m_object;
+ this->SetKey(key, length);
+ }
+ CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv)
+ {
+ this->m_cipher = &this->m_object;
+ this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize())));
+ }
+ CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize)
+ {
+ this->m_cipher = &this->m_object;
+ this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize));
+ }
+
+ static std::string CRYPTOPP_API StaticAlgorithmName()
+ {return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();}
+};
+
+//! _
+template <class BASE>
+class CipherModeFinalTemplate_ExternalCipher : public BASE
+{
+public:
+ CipherModeFinalTemplate_ExternalCipher() {}
+ CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher)
+ {this->SetCipher(cipher);}
+ CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
+ {this->SetCipherWithIV(cipher, iv, feedbackSize);}
+
+ std::string AlgorithmName() const
+ {return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();}
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
+
+//! CFB mode
+template <class CIPHER>
+struct CFB_Mode : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
+};
+
+//! CFB mode, external cipher
+struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
+ typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
+};
+
+//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A
+template <class CIPHER>
+struct CFB_FIPS_Mode : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
+};
+
+//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A, external cipher
+struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
+ typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >;
+
+//! OFB mode
+template <class CIPHER>
+struct OFB_Mode : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
+ typedef Encryption Decryption;
+};
+
+//! OFB mode, external cipher
+struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
+ typedef Encryption Decryption;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > >;
+
+//! CTR mode
+template <class CIPHER>
+struct CTR_Mode : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
+ typedef Encryption Decryption;
+};
+
+//! CTR mode, external cipher
+struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
+ typedef Encryption Decryption;
+};
+
+//! ECB mode
+template <class CIPHER>
+struct ECB_Mode : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
+
+//! ECB mode, external cipher
+struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
+ typedef Encryption Decryption;
+};
+
+//! CBC mode
+template <class CIPHER>
+struct CBC_Mode : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>;
+CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>;
+
+//! CBC mode, external cipher
+struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
+ typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
+};
+
+//! CBC mode with ciphertext stealing
+template <class CIPHER>
+struct CBC_CTS_Mode : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
+ typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>;
+CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>;
+
+//! CBC mode with ciphertext stealing, external cipher
+struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
+{
+ typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
+ typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
+typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
+typedef OFB_Mode_ExternalCipher::Encryption OFB;
+typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/modexppc.h b/lib/cryptopp/modexppc.h
new file mode 100644
index 000000000..fbe701279
--- /dev/null
+++ b/lib/cryptopp/modexppc.h
@@ -0,0 +1,34 @@
+#ifndef CRYPTOPP_MODEXPPC_H
+#define CRYPTOPP_MODEXPPC_H
+
+#include "modarith.h"
+#include "eprecomp.h"
+#include "smartptr.h"
+#include "pubkey.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<Integer>;
+
+class ModExpPrecomputation : public DL_GroupPrecomputation<Integer>
+{
+public:
+ // DL_GroupPrecomputation
+ bool NeedConversions() const {return true;}
+ Element ConvertIn(const Element &v) const {return m_mr->ConvertIn(v);}
+ virtual Element ConvertOut(const Element &v) const {return m_mr->ConvertOut(v);}
+ const AbstractGroup<Element> & GetGroup() const {return m_mr->MultiplicativeGroup();}
+ Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);}
+ void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);}
+
+ // non-inherited
+ void SetModulus(const Integer &v) {m_mr.reset(new MontgomeryRepresentation(v));}
+ const Integer & GetModulus() const {return m_mr->GetModulus();}
+
+private:
+ value_ptr<MontgomeryRepresentation> m_mr;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/mqueue.cpp b/lib/cryptopp/mqueue.cpp
new file mode 100644
index 000000000..1d645d83d
--- /dev/null
+++ b/lib/cryptopp/mqueue.cpp
@@ -0,0 +1,174 @@
+// mqueue.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "mqueue.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+MessageQueue::MessageQueue(unsigned int nodeSize)
+ : m_queue(nodeSize), m_lengths(1, 0U), m_messageCounts(1, 0U)
+{
+}
+
+size_t MessageQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ if (begin >= MaxRetrievable())
+ return 0;
+
+ return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking);
+}
+
+size_t MessageQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ transferBytes = STDMIN(MaxRetrievable(), transferBytes);
+ size_t blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking);
+ m_lengths.front() -= transferBytes;
+ return blockedBytes;
+}
+
+bool MessageQueue::GetNextMessage()
+{
+ if (NumberOfMessages() > 0 && !AnyRetrievable())
+ {
+ m_lengths.pop_front();
+ if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1)
+ m_messageCounts.pop_front();
+ return true;
+ }
+ else
+ return false;
+}
+
+unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
+{
+ ByteQueue::Walker walker(m_queue);
+ std::deque<lword>::const_iterator it = m_lengths.begin();
+ unsigned int i;
+ for (i=0; i<count && it != --m_lengths.end(); ++i, ++it)
+ {
+ walker.TransferTo(target, *it, channel);
+ if (GetAutoSignalPropagation())
+ target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
+ }
+ return i;
+}
+
+void MessageQueue::swap(MessageQueue &rhs)
+{
+ m_queue.swap(rhs.m_queue);
+ m_lengths.swap(rhs.m_lengths);
+}
+
+const byte * MessageQueue::Spy(size_t &contiguousSize) const
+{
+ const byte *result = m_queue.Spy(contiguousSize);
+ contiguousSize = UnsignedMin(contiguousSize, MaxRetrievable());
+ return result;
+}
+
+// *************************************************************
+
+unsigned int EqualityComparisonFilter::MapChannel(const std::string &channel) const
+{
+ if (channel == m_firstChannel)
+ return 0;
+ else if (channel == m_secondChannel)
+ return 1;
+ else
+ return 2;
+}
+
+size_t EqualityComparisonFilter::ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ if (!blocking)
+ throw BlockingInputOnly("EqualityComparisonFilter");
+
+ unsigned int i = MapChannel(channel);
+
+ if (i == 2)
+ return Output(3, inString, length, messageEnd, blocking, channel);
+ else if (m_mismatchDetected)
+ return 0;
+ else
+ {
+ MessageQueue &q1 = m_q[i], &q2 = m_q[1-i];
+
+ if (q2.AnyMessages() && q2.MaxRetrievable() < length)
+ goto mismatch;
+
+ while (length > 0 && q2.AnyRetrievable())
+ {
+ size_t len = length;
+ const byte *data = q2.Spy(len);
+ len = STDMIN(len, length);
+ if (memcmp(inString, data, len) != 0)
+ goto mismatch;
+ inString += len;
+ length -= len;
+ q2.Skip(len);
+ }
+
+ q1.Put(inString, length);
+
+ if (messageEnd)
+ {
+ if (q2.AnyRetrievable())
+ goto mismatch;
+ else if (q2.AnyMessages())
+ q2.GetNextMessage();
+ else if (q2.NumberOfMessageSeries() > 0)
+ goto mismatch;
+ else
+ q1.MessageEnd();
+ }
+
+ return 0;
+
+mismatch:
+ return HandleMismatchDetected(blocking);
+ }
+}
+
+bool EqualityComparisonFilter::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
+{
+ unsigned int i = MapChannel(channel);
+
+ if (i == 2)
+ {
+ OutputMessageSeriesEnd(4, propagation, blocking, channel);
+ return false;
+ }
+ else if (m_mismatchDetected)
+ return false;
+ else
+ {
+ MessageQueue &q1 = m_q[i], &q2 = m_q[1-i];
+
+ if (q2.AnyRetrievable() || q2.AnyMessages())
+ goto mismatch;
+ else if (q2.NumberOfMessageSeries() > 0)
+ return Output(2, (const byte *)"\1", 1, 0, blocking) != 0;
+ else
+ q1.MessageSeriesEnd();
+
+ return false;
+
+mismatch:
+ return HandleMismatchDetected(blocking);
+ }
+}
+
+bool EqualityComparisonFilter::HandleMismatchDetected(bool blocking)
+{
+ m_mismatchDetected = true;
+ if (m_throwIfNotEqual)
+ throw MismatchDetected();
+ return Output(1, (const byte *)"\0", 1, 0, blocking) != 0;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/mqueue.h b/lib/cryptopp/mqueue.h
new file mode 100644
index 000000000..efa57a7cf
--- /dev/null
+++ b/lib/cryptopp/mqueue.h
@@ -0,0 +1,100 @@
+#ifndef CRYPTOPP_MQUEUE_H
+#define CRYPTOPP_MQUEUE_H
+
+#include "queue.h"
+#include "filters.h"
+#include <deque>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Message Queue
+class CRYPTOPP_DLL MessageQueue : public AutoSignaling<BufferedTransformation>
+{
+public:
+ MessageQueue(unsigned int nodeSize=256);
+
+ void IsolatedInitialize(const NameValuePairs &parameters)
+ {m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);}
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+ {
+ m_queue.Put(begin, length);
+ m_lengths.back() += length;
+ if (messageEnd)
+ {
+ m_lengths.push_back(0);
+ m_messageCounts.back()++;
+ }
+ return 0;
+ }
+ bool IsolatedFlush(bool hardFlush, bool blocking) {return false;}
+ bool IsolatedMessageSeriesEnd(bool blocking)
+ {m_messageCounts.push_back(0); return false;}
+
+ lword MaxRetrievable() const
+ {return m_lengths.front();}
+ bool AnyRetrievable() const
+ {return m_lengths.front() > 0;}
+
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+
+ lword TotalBytesRetrievable() const
+ {return m_queue.MaxRetrievable();}
+ unsigned int NumberOfMessages() const
+ {return (unsigned int)m_lengths.size()-1;}
+ bool GetNextMessage();
+
+ unsigned int NumberOfMessagesInThisSeries() const
+ {return m_messageCounts[0];}
+ unsigned int NumberOfMessageSeries() const
+ {return (unsigned int)m_messageCounts.size()-1;}
+
+ unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
+
+ const byte * Spy(size_t &contiguousSize) const;
+
+ void swap(MessageQueue &rhs);
+
+private:
+ ByteQueue m_queue;
+ std::deque<lword> m_lengths;
+ std::deque<unsigned int> m_messageCounts;
+};
+
+
+//! A filter that checks messages on two channels for equality
+class CRYPTOPP_DLL EqualityComparisonFilter : public Unflushable<Multichannel<Filter> >
+{
+public:
+ struct MismatchDetected : public Exception {MismatchDetected() : Exception(DATA_INTEGRITY_CHECK_FAILED, "EqualityComparisonFilter: did not receive the same data on two channels") {}};
+
+ /*! if throwIfNotEqual is false, this filter will output a '\\0' byte when it detects a mismatch, '\\1' otherwise */
+ EqualityComparisonFilter(BufferedTransformation *attachment=NULL, bool throwIfNotEqual=true, const std::string &firstChannel="0", const std::string &secondChannel="1")
+ : m_throwIfNotEqual(throwIfNotEqual), m_mismatchDetected(false)
+ , m_firstChannel(firstChannel), m_secondChannel(secondChannel)
+ {Detach(attachment);}
+
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+ bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
+
+private:
+ unsigned int MapChannel(const std::string &channel) const;
+ bool HandleMismatchDetected(bool blocking);
+
+ bool m_throwIfNotEqual, m_mismatchDetected;
+ std::string m_firstChannel, m_secondChannel;
+ MessageQueue m_q[2];
+};
+
+NAMESPACE_END
+
+#ifndef __BORLANDC__
+NAMESPACE_BEGIN(std)
+template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b)
+{
+ a.swap(b);
+}
+NAMESPACE_END
+#endif
+
+#endif
diff --git a/lib/cryptopp/mqv.cpp b/lib/cryptopp/mqv.cpp
new file mode 100644
index 000000000..c427561b2
--- /dev/null
+++ b/lib/cryptopp/mqv.cpp
@@ -0,0 +1,13 @@
+// mqv.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "mqv.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void TestInstantiations_MQV()
+{
+ MQV mqv;
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/mqv.h b/lib/cryptopp/mqv.h
new file mode 100644
index 000000000..2683817b0
--- /dev/null
+++ b/lib/cryptopp/mqv.h
@@ -0,0 +1,141 @@
+#ifndef CRYPTOPP_MQV_H
+#define CRYPTOPP_MQV_H
+
+/** \file
+*/
+
+#include "gfpcrypt.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption>
+class MQV_Domain : public AuthenticatedKeyAgreementDomain
+{
+public:
+ typedef GROUP_PARAMETERS GroupParameters;
+ typedef typename GroupParameters::Element Element;
+ typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
+
+ MQV_Domain() {}
+
+ MQV_Domain(const GroupParameters &params)
+ : m_groupParameters(params) {}
+
+ MQV_Domain(BufferedTransformation &bt)
+ {m_groupParameters.BERDecode(bt);}
+
+ template <class T1, class T2>
+ MQV_Domain(T1 v1, T2 v2)
+ {m_groupParameters.Initialize(v1, v2);}
+
+ template <class T1, class T2, class T3>
+ MQV_Domain(T1 v1, T2 v2, T3 v3)
+ {m_groupParameters.Initialize(v1, v2, v3);}
+
+ template <class T1, class T2, class T3, class T4>
+ MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
+ {m_groupParameters.Initialize(v1, v2, v3, v4);}
+
+ const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
+ GroupParameters & AccessGroupParameters() {return m_groupParameters;}
+
+ CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
+
+ unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
+ unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
+ unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
+
+ void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
+ {
+ Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
+ x.Encode(privateKey, StaticPrivateKeyLength());
+ }
+
+ void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
+ {
+ const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
+ Integer x(privateKey, StaticPrivateKeyLength());
+ Element y = params.ExponentiateBase(x);
+ params.EncodeElement(true, y, publicKey);
+ }
+
+ unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
+ unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
+
+ void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
+ {
+ const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
+ Integer x(rng, Integer::One(), params.GetMaxExponent());
+ x.Encode(privateKey, StaticPrivateKeyLength());
+ Element y = params.ExponentiateBase(x);
+ params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
+ }
+
+ void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
+ {
+ memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
+ }
+
+ bool Agree(byte *agreedValue,
+ const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
+ const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
+ bool validateStaticOtherPublicKey=true) const
+ {
+ try
+ {
+ const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
+ Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
+ Element VV = params.DecodeElement(ephemeralOtherPublicKey, true);
+
+ Integer s(staticPrivateKey, StaticPrivateKeyLength());
+ Integer u(ephemeralPrivateKey, StaticPrivateKeyLength());
+ Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false);
+
+ const Integer &r = params.GetSubgroupOrder();
+ Integer h2 = Integer::Power2((r.BitCount()+1)/2);
+ Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r;
+ Integer tt = h2 + params.ConvertElementToInteger(VV) % h2;
+
+ if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION)
+ {
+ Element P = params.ExponentiateElement(WW, tt);
+ P = m_groupParameters.MultiplyElements(P, VV);
+ Element R[2];
+ const Integer e2[2] = {r, e};
+ params.SimultaneousExponentiate(R, P, e2, 2);
+ if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1]))
+ return false;
+ params.EncodeElement(false, R[1], agreedValue);
+ }
+ else
+ {
+ const Integer &k = params.GetCofactor();
+ if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
+ e = ModularArithmetic(r).Divide(e, k);
+ Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r));
+ if (params.IsIdentity(P))
+ return false;
+ params.EncodeElement(false, P, agreedValue);
+ }
+ }
+ catch (DL_BadElement &)
+ {
+ return false;
+ }
+ return true;
+ }
+
+private:
+ DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
+ const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;}
+
+ GroupParameters m_groupParameters;
+};
+
+//! Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a>
+typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/nbtheory.cpp b/lib/cryptopp/nbtheory.cpp
new file mode 100644
index 000000000..3fdea4e69
--- /dev/null
+++ b/lib/cryptopp/nbtheory.cpp
@@ -0,0 +1,1123 @@
+// nbtheory.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "nbtheory.h"
+#include "modarith.h"
+#include "algparam.h"
+
+#include <math.h>
+#include <vector>
+
+#ifdef _OPENMP
+// needed in MSVC 2005 to generate correct manifest
+#include <omp.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+const word s_lastSmallPrime = 32719;
+
+struct NewPrimeTable
+{
+ std::vector<word16> * operator()() const
+ {
+ const unsigned int maxPrimeTableSize = 3511;
+
+ std::auto_ptr<std::vector<word16> > pPrimeTable(new std::vector<word16>);
+ std::vector<word16> &primeTable = *pPrimeTable;
+ primeTable.reserve(maxPrimeTableSize);
+
+ primeTable.push_back(2);
+ unsigned int testEntriesEnd = 1;
+
+ for (unsigned int p=3; p<=s_lastSmallPrime; p+=2)
+ {
+ unsigned int j;
+ for (j=1; j<testEntriesEnd; j++)
+ if (p%primeTable[j] == 0)
+ break;
+ if (j == testEntriesEnd)
+ {
+ primeTable.push_back(p);
+ testEntriesEnd = UnsignedMin(54U, primeTable.size());
+ }
+ }
+
+ return pPrimeTable.release();
+ }
+};
+
+const word16 * GetPrimeTable(unsigned int &size)
+{
+ const std::vector<word16> &primeTable = Singleton<std::vector<word16>, NewPrimeTable>().Ref();
+ size = (unsigned int)primeTable.size();
+ return &primeTable[0];
+}
+
+bool IsSmallPrime(const Integer &p)
+{
+ unsigned int primeTableSize;
+ const word16 * primeTable = GetPrimeTable(primeTableSize);
+
+ if (p.IsPositive() && p <= primeTable[primeTableSize-1])
+ return std::binary_search(primeTable, primeTable+primeTableSize, (word16)p.ConvertToLong());
+ else
+ return false;
+}
+
+bool TrialDivision(const Integer &p, unsigned bound)
+{
+ unsigned int primeTableSize;
+ const word16 * primeTable = GetPrimeTable(primeTableSize);
+
+ assert(primeTable[primeTableSize-1] >= bound);
+
+ unsigned int i;
+ for (i = 0; primeTable[i]<bound; i++)
+ if ((p % primeTable[i]) == 0)
+ return true;
+
+ if (bound == primeTable[i])
+ return (p % bound == 0);
+ else
+ return false;
+}
+
+bool SmallDivisorsTest(const Integer &p)
+{
+ unsigned int primeTableSize;
+ const word16 * primeTable = GetPrimeTable(primeTableSize);
+ return !TrialDivision(p, primeTable[primeTableSize-1]);
+}
+
+bool IsFermatProbablePrime(const Integer &n, const Integer &b)
+{
+ if (n <= 3)
+ return n==2 || n==3;
+
+ assert(n>3 && b>1 && b<n-1);
+ return a_exp_b_mod_c(b, n-1, n)==1;
+}
+
+bool IsStrongProbablePrime(const Integer &n, const Integer &b)
+{
+ if (n <= 3)
+ return n==2 || n==3;
+
+ assert(n>3 && b>1 && b<n-1);
+
+ if ((n.IsEven() && n!=2) || GCD(b, n) != 1)
+ return false;
+
+ Integer nminus1 = (n-1);
+ unsigned int a;
+
+ // calculate a = largest power of 2 that divides (n-1)
+ for (a=0; ; a++)
+ if (nminus1.GetBit(a))
+ break;
+ Integer m = nminus1>>a;
+
+ Integer z = a_exp_b_mod_c(b, m, n);
+ if (z==1 || z==nminus1)
+ return true;
+ for (unsigned j=1; j<a; j++)
+ {
+ z = z.Squared()%n;
+ if (z==nminus1)
+ return true;
+ if (z==1)
+ return false;
+ }
+ return false;
+}
+
+bool RabinMillerTest(RandomNumberGenerator &rng, const Integer &n, unsigned int rounds)
+{
+ if (n <= 3)
+ return n==2 || n==3;
+
+ assert(n>3);
+
+ Integer b;
+ for (unsigned int i=0; i<rounds; i++)
+ {
+ b.Randomize(rng, 2, n-2);
+ if (!IsStrongProbablePrime(n, b))
+ return false;
+ }
+ return true;
+}
+
+bool IsLucasProbablePrime(const Integer &n)
+{
+ if (n <= 1)
+ return false;
+
+ if (n.IsEven())
+ return n==2;
+
+ assert(n>2);
+
+ Integer b=3;
+ unsigned int i=0;
+ int j;
+
+ while ((j=Jacobi(b.Squared()-4, n)) == 1)
+ {
+ if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square
+ return false;
+ ++b; ++b;
+ }
+
+ if (j==0)
+ return false;
+ else
+ return Lucas(n+1, b, n)==2;
+}
+
+bool IsStrongLucasProbablePrime(const Integer &n)
+{
+ if (n <= 1)
+ return false;
+
+ if (n.IsEven())
+ return n==2;
+
+ assert(n>2);
+
+ Integer b=3;
+ unsigned int i=0;
+ int j;
+
+ while ((j=Jacobi(b.Squared()-4, n)) == 1)
+ {
+ if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square
+ return false;
+ ++b; ++b;
+ }
+
+ if (j==0)
+ return false;
+
+ Integer n1 = n+1;
+ unsigned int a;
+
+ // calculate a = largest power of 2 that divides n1
+ for (a=0; ; a++)
+ if (n1.GetBit(a))
+ break;
+ Integer m = n1>>a;
+
+ Integer z = Lucas(m, b, n);
+ if (z==2 || z==n-2)
+ return true;
+ for (i=1; i<a; i++)
+ {
+ z = (z.Squared()-2)%n;
+ if (z==n-2)
+ return true;
+ if (z==2)
+ return false;
+ }
+ return false;
+}
+
+struct NewLastSmallPrimeSquared
+{
+ Integer * operator()() const
+ {
+ return new Integer(Integer(s_lastSmallPrime).Squared());
+ }
+};
+
+bool IsPrime(const Integer &p)
+{
+ if (p <= s_lastSmallPrime)
+ return IsSmallPrime(p);
+ else if (p <= Singleton<Integer, NewLastSmallPrimeSquared>().Ref())
+ return SmallDivisorsTest(p);
+ else
+ return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p);
+}
+
+bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level)
+{
+ bool pass = IsPrime(p) && RabinMillerTest(rng, p, 1);
+ if (level >= 1)
+ pass = pass && RabinMillerTest(rng, p, 10);
+ return pass;
+}
+
+unsigned int PrimeSearchInterval(const Integer &max)
+{
+ return max.BitCount();
+}
+
+static inline bool FastProbablePrimeTest(const Integer &n)
+{
+ return IsStrongProbablePrime(n,2);
+}
+
+AlgorithmParameters MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength)
+{
+ if (productBitLength < 16)
+ throw InvalidArgument("invalid bit length");
+
+ Integer minP, maxP;
+
+ if (productBitLength%2==0)
+ {
+ minP = Integer(182) << (productBitLength/2-8);
+ maxP = Integer::Power2(productBitLength/2)-1;
+ }
+ else
+ {
+ minP = Integer::Power2((productBitLength-1)/2);
+ maxP = Integer(181) << ((productBitLength+1)/2-8);
+ }
+
+ return MakeParameters("RandomNumberType", Integer::PRIME)("Min", minP)("Max", maxP);
+}
+
+class PrimeSieve
+{
+public:
+ // delta == 1 or -1 means double sieve with p = 2*q + delta
+ PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta=0);
+ bool NextCandidate(Integer &c);
+
+ void DoSieve();
+ static void SieveSingle(std::vector<bool> &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv);
+
+ Integer m_first, m_last, m_step;
+ signed int m_delta;
+ word m_next;
+ std::vector<bool> m_sieve;
+};
+
+PrimeSieve::PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta)
+ : m_first(first), m_last(last), m_step(step), m_delta(delta), m_next(0)
+{
+ DoSieve();
+}
+
+bool PrimeSieve::NextCandidate(Integer &c)
+{
+ bool safe = SafeConvert(std::find(m_sieve.begin()+m_next, m_sieve.end(), false) - m_sieve.begin(), m_next);
+ assert(safe);
+ if (m_next == m_sieve.size())
+ {
+ m_first += long(m_sieve.size())*m_step;
+ if (m_first > m_last)
+ return false;
+ else
+ {
+ m_next = 0;
+ DoSieve();
+ return NextCandidate(c);
+ }
+ }
+ else
+ {
+ c = m_first + long(m_next)*m_step;
+ ++m_next;
+ return true;
+ }
+}
+
+void PrimeSieve::SieveSingle(std::vector<bool> &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv)
+{
+ if (stepInv)
+ {
+ size_t sieveSize = sieve.size();
+ size_t j = (word32(p-(first%p))*stepInv) % p;
+ // if the first multiple of p is p, skip it
+ if (first.WordCount() <= 1 && first + step*long(j) == p)
+ j += p;
+ for (; j < sieveSize; j += p)
+ sieve[j] = true;
+ }
+}
+
+void PrimeSieve::DoSieve()
+{
+ unsigned int primeTableSize;
+ const word16 * primeTable = GetPrimeTable(primeTableSize);
+
+ const unsigned int maxSieveSize = 32768;
+ unsigned int sieveSize = STDMIN(Integer(maxSieveSize), (m_last-m_first)/m_step+1).ConvertToLong();
+
+ m_sieve.clear();
+ m_sieve.resize(sieveSize, false);
+
+ if (m_delta == 0)
+ {
+ for (unsigned int i = 0; i < primeTableSize; ++i)
+ SieveSingle(m_sieve, primeTable[i], m_first, m_step, (word16)m_step.InverseMod(primeTable[i]));
+ }
+ else
+ {
+ assert(m_step%2==0);
+ Integer qFirst = (m_first-m_delta) >> 1;
+ Integer halfStep = m_step >> 1;
+ for (unsigned int i = 0; i < primeTableSize; ++i)
+ {
+ word16 p = primeTable[i];
+ word16 stepInv = (word16)m_step.InverseMod(p);
+ SieveSingle(m_sieve, p, m_first, m_step, stepInv);
+
+ word16 halfStepInv = 2*stepInv < p ? 2*stepInv : 2*stepInv-p;
+ SieveSingle(m_sieve, p, qFirst, halfStep, halfStepInv);
+ }
+ }
+}
+
+bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector)
+{
+ assert(!equiv.IsNegative() && equiv < mod);
+
+ Integer gcd = GCD(equiv, mod);
+ if (gcd != Integer::One())
+ {
+ // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv)
+ if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd)))
+ {
+ p = gcd;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ unsigned int primeTableSize;
+ const word16 * primeTable = GetPrimeTable(primeTableSize);
+
+ if (p <= primeTable[primeTableSize-1])
+ {
+ const word16 *pItr;
+
+ --p;
+ if (p.IsPositive())
+ pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong());
+ else
+ pItr = primeTable;
+
+ while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr))))
+ ++pItr;
+
+ if (pItr < primeTable+primeTableSize)
+ {
+ p = *pItr;
+ return p <= max;
+ }
+
+ p = primeTable[primeTableSize-1]+1;
+ }
+
+ assert(p > primeTable[primeTableSize-1]);
+
+ if (mod.IsOdd())
+ return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector);
+
+ p += (equiv-p)%mod;
+
+ if (p>max)
+ return false;
+
+ PrimeSieve sieve(p, max, mod);
+
+ while (sieve.NextCandidate(p))
+ {
+ if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p))
+ return true;
+ }
+
+ return false;
+}
+
+// the following two functions are based on code and comments provided by Preda Mihailescu
+static bool ProvePrime(const Integer &p, const Integer &q)
+{
+ assert(p < q*q*q);
+ assert(p % q == 1);
+
+// this is the Quisquater test. Numbers p having passed the Lucas - Lehmer test
+// for q and verifying p < q^3 can only be built up of two factors, both = 1 mod q,
+// or be prime. The next two lines build the discriminant of a quadratic equation
+// which holds iff p is built up of two factors (excercise ... )
+
+ Integer r = (p-1)/q;
+ if (((r%q).Squared()-4*(r/q)).IsSquare())
+ return false;
+
+ unsigned int primeTableSize;
+ const word16 * primeTable = GetPrimeTable(primeTableSize);
+
+ assert(primeTableSize >= 50);
+ for (int i=0; i<50; i++)
+ {
+ Integer b = a_exp_b_mod_c(primeTable[i], r, p);
+ if (b != 1)
+ return a_exp_b_mod_c(b, q, p) == 1;
+ }
+ return false;
+}
+
+Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int pbits)
+{
+ Integer p;
+ Integer minP = Integer::Power2(pbits-1);
+ Integer maxP = Integer::Power2(pbits) - 1;
+
+ if (maxP <= Integer(s_lastSmallPrime).Squared())
+ {
+ // Randomize() will generate a prime provable by trial division
+ p.Randomize(rng, minP, maxP, Integer::PRIME);
+ return p;
+ }
+
+ unsigned int qbits = (pbits+2)/3 + 1 + rng.GenerateWord32(0, pbits/36);
+ Integer q = MihailescuProvablePrime(rng, qbits);
+ Integer q2 = q<<1;
+
+ while (true)
+ {
+ // this initializes the sieve to search in the arithmetic
+ // progression p = p_0 + \lambda * q2 = p_0 + 2 * \lambda * q,
+ // with q the recursively generated prime above. We will be able
+ // to use Lucas tets for proving primality. A trick of Quisquater
+ // allows taking q > cubic_root(p) rather then square_root: this
+ // decreases the recursion.
+
+ p.Randomize(rng, minP, maxP, Integer::ANY, 1, q2);
+ PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*q2, maxP), q2);
+
+ while (sieve.NextCandidate(p))
+ {
+ if (FastProbablePrimeTest(p) && ProvePrime(p, q))
+ return p;
+ }
+ }
+
+ // not reached
+ return p;
+}
+
+Integer MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits)
+{
+ const unsigned smallPrimeBound = 29, c_opt=10;
+ Integer p;
+
+ unsigned int primeTableSize;
+ const word16 * primeTable = GetPrimeTable(primeTableSize);
+
+ if (bits < smallPrimeBound)
+ {
+ do
+ p.Randomize(rng, Integer::Power2(bits-1), Integer::Power2(bits)-1, Integer::ANY, 1, 2);
+ while (TrialDivision(p, 1 << ((bits+1)/2)));
+ }
+ else
+ {
+ const unsigned margin = bits > 50 ? 20 : (bits-10)/2;
+ double relativeSize;
+ do
+ relativeSize = pow(2.0, double(rng.GenerateWord32())/0xffffffff - 1);
+ while (bits * relativeSize >= bits - margin);
+
+ Integer a,b;
+ Integer q = MaurerProvablePrime(rng, unsigned(bits*relativeSize));
+ Integer I = Integer::Power2(bits-2)/q;
+ Integer I2 = I << 1;
+ unsigned int trialDivisorBound = (unsigned int)STDMIN((unsigned long)primeTable[primeTableSize-1], (unsigned long)bits*bits/c_opt);
+ bool success = false;
+ while (!success)
+ {
+ p.Randomize(rng, I, I2, Integer::ANY);
+ p *= q; p <<= 1; ++p;
+ if (!TrialDivision(p, trialDivisorBound))
+ {
+ a.Randomize(rng, 2, p-1, Integer::ANY);
+ b = a_exp_b_mod_c(a, (p-1)/q, p);
+ success = (GCD(b-1, p) == 1) && (a_exp_b_mod_c(b, q, p) == 1);
+ }
+ }
+ }
+ return p;
+}
+
+Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u)
+{
+ // isn't operator overloading great?
+ return p * (u * (xq-xp) % q) + xp;
+/*
+ Integer t1 = xq-xp;
+ cout << hex << t1 << endl;
+ Integer t2 = u * t1;
+ cout << hex << t2 << endl;
+ Integer t3 = t2 % q;
+ cout << hex << t3 << endl;
+ Integer t4 = p * t3;
+ cout << hex << t4 << endl;
+ Integer t5 = t4 + xp;
+ cout << hex << t5 << endl;
+ return t5;
+*/
+}
+
+Integer ModularSquareRoot(const Integer &a, const Integer &p)
+{
+ if (p%4 == 3)
+ return a_exp_b_mod_c(a, (p+1)/4, p);
+
+ Integer q=p-1;
+ unsigned int r=0;
+ while (q.IsEven())
+ {
+ r++;
+ q >>= 1;
+ }
+
+ Integer n=2;
+ while (Jacobi(n, p) != -1)
+ ++n;
+
+ Integer y = a_exp_b_mod_c(n, q, p);
+ Integer x = a_exp_b_mod_c(a, (q-1)/2, p);
+ Integer b = (x.Squared()%p)*a%p;
+ x = a*x%p;
+ Integer tempb, t;
+
+ while (b != 1)
+ {
+ unsigned m=0;
+ tempb = b;
+ do
+ {
+ m++;
+ b = b.Squared()%p;
+ if (m==r)
+ return Integer::Zero();
+ }
+ while (b != 1);
+
+ t = y;
+ for (unsigned i=0; i<r-m-1; i++)
+ t = t.Squared()%p;
+ y = t.Squared()%p;
+ r = m;
+ x = x*t%p;
+ b = tempb*y%p;
+ }
+
+ assert(x.Squared()%p == a);
+ return x;
+}
+
+bool SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p)
+{
+ Integer D = (b.Squared() - 4*a*c) % p;
+ switch (Jacobi(D, p))
+ {
+ default:
+ assert(false); // not reached
+ return false;
+ case -1:
+ return false;
+ case 0:
+ r1 = r2 = (-b*(a+a).InverseMod(p)) % p;
+ assert(((r1.Squared()*a + r1*b + c) % p).IsZero());
+ return true;
+ case 1:
+ Integer s = ModularSquareRoot(D, p);
+ Integer t = (a+a).InverseMod(p);
+ r1 = (s-b)*t % p;
+ r2 = (-s-b)*t % p;
+ assert(((r1.Squared()*a + r1*b + c) % p).IsZero());
+ assert(((r2.Squared()*a + r2*b + c) % p).IsZero());
+ return true;
+ }
+}
+
+Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
+ const Integer &p, const Integer &q, const Integer &u)
+{
+ Integer p2, q2;
+ #pragma omp parallel
+ #pragma omp sections
+ {
+ #pragma omp section
+ p2 = ModularExponentiation((a % p), dp, p);
+ #pragma omp section
+ q2 = ModularExponentiation((a % q), dq, q);
+ }
+ return CRT(p2, p, q2, q, u);
+}
+
+Integer ModularRoot(const Integer &a, const Integer &e,
+ const Integer &p, const Integer &q)
+{
+ Integer dp = EuclideanMultiplicativeInverse(e, p-1);
+ Integer dq = EuclideanMultiplicativeInverse(e, q-1);
+ Integer u = EuclideanMultiplicativeInverse(p, q);
+ assert(!!dp && !!dq && !!u);
+ return ModularRoot(a, dp, dq, p, q, u);
+}
+
+/*
+Integer GCDI(const Integer &x, const Integer &y)
+{
+ Integer a=x, b=y;
+ unsigned k=0;
+
+ assert(!!a && !!b);
+
+ while (a[0]==0 && b[0]==0)
+ {
+ a >>= 1;
+ b >>= 1;
+ k++;
+ }
+
+ while (a[0]==0)
+ a >>= 1;
+
+ while (b[0]==0)
+ b >>= 1;
+
+ while (1)
+ {
+ switch (a.Compare(b))
+ {
+ case -1:
+ b -= a;
+ while (b[0]==0)
+ b >>= 1;
+ break;
+
+ case 0:
+ return (a <<= k);
+
+ case 1:
+ a -= b;
+ while (a[0]==0)
+ a >>= 1;
+ break;
+
+ default:
+ assert(false);
+ }
+ }
+}
+
+Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b)
+{
+ assert(b.Positive());
+
+ if (a.Negative())
+ return EuclideanMultiplicativeInverse(a%b, b);
+
+ if (b[0]==0)
+ {
+ if (!b || a[0]==0)
+ return Integer::Zero(); // no inverse
+ if (a==1)
+ return 1;
+ Integer u = EuclideanMultiplicativeInverse(b, a);
+ if (!u)
+ return Integer::Zero(); // no inverse
+ else
+ return (b*(a-u)+1)/a;
+ }
+
+ Integer u=1, d=a, v1=b, v3=b, t1, t3, b2=(b+1)>>1;
+
+ if (a[0])
+ {
+ t1 = Integer::Zero();
+ t3 = -b;
+ }
+ else
+ {
+ t1 = b2;
+ t3 = a>>1;
+ }
+
+ while (!!t3)
+ {
+ while (t3[0]==0)
+ {
+ t3 >>= 1;
+ if (t1[0]==0)
+ t1 >>= 1;
+ else
+ {
+ t1 >>= 1;
+ t1 += b2;
+ }
+ }
+ if (t3.Positive())
+ {
+ u = t1;
+ d = t3;
+ }
+ else
+ {
+ v1 = b-t1;
+ v3 = -t3;
+ }
+ t1 = u-v1;
+ t3 = d-v3;
+ if (t1.Negative())
+ t1 += b;
+ }
+ if (d==1)
+ return u;
+ else
+ return Integer::Zero(); // no inverse
+}
+*/
+
+int Jacobi(const Integer &aIn, const Integer &bIn)
+{
+ assert(bIn.IsOdd());
+
+ Integer b = bIn, a = aIn%bIn;
+ int result = 1;
+
+ while (!!a)
+ {
+ unsigned i=0;
+ while (a.GetBit(i)==0)
+ i++;
+ a>>=i;
+
+ if (i%2==1 && (b%8==3 || b%8==5))
+ result = -result;
+
+ if (a%4==3 && b%4==3)
+ result = -result;
+
+ std::swap(a, b);
+ a %= b;
+ }
+
+ return (b==1) ? result : 0;
+}
+
+Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n)
+{
+ unsigned i = e.BitCount();
+ if (i==0)
+ return Integer::Two();
+
+ MontgomeryRepresentation m(n);
+ Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(Integer::Two());
+ Integer v=p, v1=m.Subtract(m.Square(p), two);
+
+ i--;
+ while (i--)
+ {
+ if (e.GetBit(i))
+ {
+ // v = (v*v1 - p) % m;
+ v = m.Subtract(m.Multiply(v,v1), p);
+ // v1 = (v1*v1 - 2) % m;
+ v1 = m.Subtract(m.Square(v1), two);
+ }
+ else
+ {
+ // v1 = (v*v1 - p) % m;
+ v1 = m.Subtract(m.Multiply(v,v1), p);
+ // v = (v*v - 2) % m;
+ v = m.Subtract(m.Square(v), two);
+ }
+ }
+ return m.ConvertOut(v);
+}
+
+// This is Peter Montgomery's unpublished Lucas sequence evalutation algorithm.
+// The total number of multiplies and squares used is less than the binary
+// algorithm (see above). Unfortunately I can't get it to run as fast as
+// the binary algorithm because of the extra overhead.
+/*
+Integer Lucas(const Integer &n, const Integer &P, const Integer &modulus)
+{
+ if (!n)
+ return 2;
+
+#define f(A, B, C) m.Subtract(m.Multiply(A, B), C)
+#define X2(A) m.Subtract(m.Square(A), two)
+#define X3(A) m.Multiply(A, m.Subtract(m.Square(A), three))
+
+ MontgomeryRepresentation m(modulus);
+ Integer two=m.ConvertIn(2), three=m.ConvertIn(3);
+ Integer A=m.ConvertIn(P), B, C, p, d=n, e, r, t, T, U;
+
+ while (d!=1)
+ {
+ p = d;
+ unsigned int b = WORD_BITS * p.WordCount();
+ Integer alpha = (Integer(5)<<(2*b-2)).SquareRoot() - Integer::Power2(b-1);
+ r = (p*alpha)>>b;
+ e = d-r;
+ B = A;
+ C = two;
+ d = r;
+
+ while (d!=e)
+ {
+ if (d<e)
+ {
+ swap(d, e);
+ swap(A, B);
+ }
+
+ unsigned int dm2 = d[0], em2 = e[0];
+ unsigned int dm3 = d%3, em3 = e%3;
+
+// if ((dm6+em6)%3 == 0 && d <= e + (e>>2))
+ if ((dm3+em3==0 || dm3+em3==3) && (t = e, t >>= 2, t += e, d <= t))
+ {
+ // #1
+// t = (d+d-e)/3;
+// t = d; t += d; t -= e; t /= 3;
+// e = (e+e-d)/3;
+// e += e; e -= d; e /= 3;
+// d = t;
+
+// t = (d+e)/3
+ t = d; t += e; t /= 3;
+ e -= t;
+ d -= t;
+
+ T = f(A, B, C);
+ U = f(T, A, B);
+ B = f(T, B, A);
+ A = U;
+ continue;
+ }
+
+// if (dm6 == em6 && d <= e + (e>>2))
+ if (dm3 == em3 && dm2 == em2 && (t = e, t >>= 2, t += e, d <= t))
+ {
+ // #2
+// d = (d-e)>>1;
+ d -= e; d >>= 1;
+ B = f(A, B, C);
+ A = X2(A);
+ continue;
+ }
+
+// if (d <= (e<<2))
+ if (d <= (t = e, t <<= 2))
+ {
+ // #3
+ d -= e;
+ C = f(A, B, C);
+ swap(B, C);
+ continue;
+ }
+
+ if (dm2 == em2)
+ {
+ // #4
+// d = (d-e)>>1;
+ d -= e; d >>= 1;
+ B = f(A, B, C);
+ A = X2(A);
+ continue;
+ }
+
+ if (dm2 == 0)
+ {
+ // #5
+ d >>= 1;
+ C = f(A, C, B);
+ A = X2(A);
+ continue;
+ }
+
+ if (dm3 == 0)
+ {
+ // #6
+// d = d/3 - e;
+ d /= 3; d -= e;
+ T = X2(A);
+ C = f(T, f(A, B, C), C);
+ swap(B, C);
+ A = f(T, A, A);
+ continue;
+ }
+
+ if (dm3+em3==0 || dm3+em3==3)
+ {
+ // #7
+// d = (d-e-e)/3;
+ d -= e; d -= e; d /= 3;
+ T = f(A, B, C);
+ B = f(T, A, B);
+ A = X3(A);
+ continue;
+ }
+
+ if (dm3 == em3)
+ {
+ // #8
+// d = (d-e)/3;
+ d -= e; d /= 3;
+ T = f(A, B, C);
+ C = f(A, C, B);
+ B = T;
+ A = X3(A);
+ continue;
+ }
+
+ assert(em2 == 0);
+ // #9
+ e >>= 1;
+ C = f(C, B, A);
+ B = X2(B);
+ }
+
+ A = f(A, B, C);
+ }
+
+#undef f
+#undef X2
+#undef X3
+
+ return m.ConvertOut(A);
+}
+*/
+
+Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u)
+{
+ Integer d = (m*m-4);
+ Integer p2, q2;
+ #pragma omp parallel
+ #pragma omp sections
+ {
+ #pragma omp section
+ {
+ p2 = p-Jacobi(d,p);
+ p2 = Lucas(EuclideanMultiplicativeInverse(e,p2), m, p);
+ }
+ #pragma omp section
+ {
+ q2 = q-Jacobi(d,q);
+ q2 = Lucas(EuclideanMultiplicativeInverse(e,q2), m, q);
+ }
+ }
+ return CRT(p2, p, q2, q, u);
+}
+
+unsigned int FactoringWorkFactor(unsigned int n)
+{
+ // extrapolated from the table in Odlyzko's "The Future of Integer Factorization"
+ // updated to reflect the factoring of RSA-130
+ if (n<5) return 0;
+ else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5);
+}
+
+unsigned int DiscreteLogWorkFactor(unsigned int n)
+{
+ // assuming discrete log takes about the same time as factoring
+ if (n<5) return 0;
+ else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5);
+}
+
+// ********************************************************
+
+void PrimeAndGenerator::Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits)
+{
+ // no prime exists for delta = -1, qbits = 4, and pbits = 5
+ assert(qbits > 4);
+ assert(pbits > qbits);
+
+ if (qbits+1 == pbits)
+ {
+ Integer minP = Integer::Power2(pbits-1);
+ Integer maxP = Integer::Power2(pbits) - 1;
+ bool success = false;
+
+ while (!success)
+ {
+ p.Randomize(rng, minP, maxP, Integer::ANY, 6+5*delta, 12);
+ PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*12, maxP), 12, delta);
+
+ while (sieve.NextCandidate(p))
+ {
+ assert(IsSmallPrime(p) || SmallDivisorsTest(p));
+ q = (p-delta) >> 1;
+ assert(IsSmallPrime(q) || SmallDivisorsTest(q));
+ if (FastProbablePrimeTest(q) && FastProbablePrimeTest(p) && IsPrime(q) && IsPrime(p))
+ {
+ success = true;
+ break;
+ }
+ }
+ }
+
+ if (delta == 1)
+ {
+ // find g such that g is a quadratic residue mod p, then g has order q
+ // g=4 always works, but this way we get the smallest quadratic residue (other than 1)
+ for (g=2; Jacobi(g, p) != 1; ++g) {}
+ // contributed by Walt Tuvell: g should be the following according to the Law of Quadratic Reciprocity
+ assert((p%8==1 || p%8==7) ? g==2 : (p%12==1 || p%12==11) ? g==3 : g==4);
+ }
+ else
+ {
+ assert(delta == -1);
+ // find g such that g*g-4 is a quadratic non-residue,
+ // and such that g has order q
+ for (g=3; ; ++g)
+ if (Jacobi(g*g-4, p)==-1 && Lucas(q, g, p)==2)
+ break;
+ }
+ }
+ else
+ {
+ Integer minQ = Integer::Power2(qbits-1);
+ Integer maxQ = Integer::Power2(qbits) - 1;
+ Integer minP = Integer::Power2(pbits-1);
+ Integer maxP = Integer::Power2(pbits) - 1;
+
+ do
+ {
+ q.Randomize(rng, minQ, maxQ, Integer::PRIME);
+ } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, delta%q, q));
+
+ // find a random g of order q
+ if (delta==1)
+ {
+ do
+ {
+ Integer h(rng, 2, p-2, Integer::ANY);
+ g = a_exp_b_mod_c(h, (p-1)/q, p);
+ } while (g <= 1);
+ assert(a_exp_b_mod_c(g, q, p)==1);
+ }
+ else
+ {
+ assert(delta==-1);
+ do
+ {
+ Integer h(rng, 3, p-1, Integer::ANY);
+ if (Jacobi(h*h-4, p)==1)
+ continue;
+ g = Lucas((p+1)/q, h, p);
+ } while (g <= 2);
+ assert(Lucas(q, g, p) == 2);
+ }
+ }
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/nbtheory.h b/lib/cryptopp/nbtheory.h
new file mode 100644
index 000000000..636479269
--- /dev/null
+++ b/lib/cryptopp/nbtheory.h
@@ -0,0 +1,131 @@
+// nbtheory.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_NBTHEORY_H
+#define CRYPTOPP_NBTHEORY_H
+
+#include "integer.h"
+#include "algparam.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// obtain pointer to small prime table and get its size
+CRYPTOPP_DLL const word16 * CRYPTOPP_API GetPrimeTable(unsigned int &size);
+
+// ************ primality testing ****************
+
+// generate a provable prime
+CRYPTOPP_DLL Integer CRYPTOPP_API MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
+CRYPTOPP_DLL Integer CRYPTOPP_API MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
+
+CRYPTOPP_DLL bool CRYPTOPP_API IsSmallPrime(const Integer &p);
+
+// returns true if p is divisible by some prime less than bound
+// bound not be greater than the largest entry in the prime table
+CRYPTOPP_DLL bool CRYPTOPP_API TrialDivision(const Integer &p, unsigned bound);
+
+// returns true if p is NOT divisible by small primes
+CRYPTOPP_DLL bool CRYPTOPP_API SmallDivisorsTest(const Integer &p);
+
+// These is no reason to use these two, use the ones below instead
+CRYPTOPP_DLL bool CRYPTOPP_API IsFermatProbablePrime(const Integer &n, const Integer &b);
+CRYPTOPP_DLL bool CRYPTOPP_API IsLucasProbablePrime(const Integer &n);
+
+CRYPTOPP_DLL bool CRYPTOPP_API IsStrongProbablePrime(const Integer &n, const Integer &b);
+CRYPTOPP_DLL bool CRYPTOPP_API IsStrongLucasProbablePrime(const Integer &n);
+
+// Rabin-Miller primality test, i.e. repeating the strong probable prime test
+// for several rounds with random bases
+CRYPTOPP_DLL bool CRYPTOPP_API RabinMillerTest(RandomNumberGenerator &rng, const Integer &w, unsigned int rounds);
+
+// primality test, used to generate primes
+CRYPTOPP_DLL bool CRYPTOPP_API IsPrime(const Integer &p);
+
+// more reliable than IsPrime(), used to verify primes generated by others
+CRYPTOPP_DLL bool CRYPTOPP_API VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1);
+
+class CRYPTOPP_DLL PrimeSelector
+{
+public:
+ const PrimeSelector *GetSelectorPointer() const {return this;}
+ virtual bool IsAcceptable(const Integer &candidate) const =0;
+};
+
+// use a fast sieve to find the first probable prime in {x | p<=x<=max and x%mod==equiv}
+// returns true iff successful, value of p is undefined if no such prime exists
+CRYPTOPP_DLL bool CRYPTOPP_API FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector);
+
+CRYPTOPP_DLL unsigned int CRYPTOPP_API PrimeSearchInterval(const Integer &max);
+
+CRYPTOPP_DLL AlgorithmParameters CRYPTOPP_API MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength);
+
+// ********** other number theoretic functions ************
+
+inline Integer GCD(const Integer &a, const Integer &b)
+ {return Integer::Gcd(a,b);}
+inline bool RelativelyPrime(const Integer &a, const Integer &b)
+ {return Integer::Gcd(a,b) == Integer::One();}
+inline Integer LCM(const Integer &a, const Integer &b)
+ {return a/Integer::Gcd(a,b)*b;}
+inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b)
+ {return a.InverseMod(b);}
+
+// use Chinese Remainder Theorem to calculate x given x mod p and x mod q, and u = inverse of p mod q
+CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u);
+
+// if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise
+// check a number theory book for what Jacobi symbol means when b is not prime
+CRYPTOPP_DLL int CRYPTOPP_API Jacobi(const Integer &a, const Integer &b);
+
+// calculates the Lucas function V_e(p, 1) mod n
+CRYPTOPP_DLL Integer CRYPTOPP_API Lucas(const Integer &e, const Integer &p, const Integer &n);
+// calculates x such that m==Lucas(e, x, p*q), p q primes, u=inverse of p mod q
+CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u);
+
+inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m)
+ {return a_exp_b_mod_c(a, e, m);}
+// returns x such that x*x%p == a, p prime
+CRYPTOPP_DLL Integer CRYPTOPP_API ModularSquareRoot(const Integer &a, const Integer &p);
+// returns x such that a==ModularExponentiation(x, e, p*q), p q primes,
+// and e relatively prime to (p-1)*(q-1)
+// dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1))
+// and u=inverse of p mod q
+CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u);
+
+// find r1 and r2 such that ax^2 + bx + c == 0 (mod p) for x in {r1, r2}, p prime
+// returns true if solutions exist
+CRYPTOPP_DLL bool CRYPTOPP_API SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p);
+
+// returns log base 2 of estimated number of operations to calculate discrete log or factor a number
+CRYPTOPP_DLL unsigned int CRYPTOPP_API DiscreteLogWorkFactor(unsigned int bitlength);
+CRYPTOPP_DLL unsigned int CRYPTOPP_API FactoringWorkFactor(unsigned int bitlength);
+
+// ********************************************************
+
+//! generator of prime numbers of special forms
+class CRYPTOPP_DLL PrimeAndGenerator
+{
+public:
+ PrimeAndGenerator() {}
+ // generate a random prime p of the form 2*q+delta, where delta is 1 or -1 and q is also prime
+ // Precondition: pbits > 5
+ // warning: this is slow, because primes of this form are harder to find
+ PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits)
+ {Generate(delta, rng, pbits, pbits-1);}
+ // generate a random prime p of the form 2*r*q+delta, where q is also prime
+ // Precondition: qbits > 4 && pbits > qbits
+ PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits)
+ {Generate(delta, rng, pbits, qbits);}
+
+ void Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits);
+
+ const Integer& Prime() const {return p;}
+ const Integer& SubPrime() const {return q;}
+ const Integer& Generator() const {return g;}
+
+private:
+ Integer p, q, g;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/network.cpp b/lib/cryptopp/network.cpp
new file mode 100644
index 000000000..9b7198d16
--- /dev/null
+++ b/lib/cryptopp/network.cpp
@@ -0,0 +1,550 @@
+// network.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "network.h"
+#include "wait.h"
+
+#define CRYPTOPP_TRACE_NETWORK 0
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef HIGHRES_TIMER_AVAILABLE
+
+lword LimitedBandwidth::ComputeCurrentTransceiveLimit()
+{
+ if (!m_maxBytesPerSecond)
+ return ULONG_MAX;
+
+ double curTime = GetCurTimeAndCleanUp();
+ lword total = 0;
+ for (OpQueue::size_type i=0; i!=m_ops.size(); ++i)
+ total += m_ops[i].second;
+ return SaturatingSubtract(m_maxBytesPerSecond, total);
+}
+
+double LimitedBandwidth::TimeToNextTransceive()
+{
+ if (!m_maxBytesPerSecond)
+ return 0;
+
+ if (!m_nextTransceiveTime)
+ ComputeNextTransceiveTime();
+
+ return SaturatingSubtract(m_nextTransceiveTime, m_timer.ElapsedTimeAsDouble());
+}
+
+void LimitedBandwidth::NoteTransceive(lword size)
+{
+ if (m_maxBytesPerSecond)
+ {
+ double curTime = GetCurTimeAndCleanUp();
+ m_ops.push_back(std::make_pair(curTime, size));
+ m_nextTransceiveTime = 0;
+ }
+}
+
+void LimitedBandwidth::ComputeNextTransceiveTime()
+{
+ double curTime = GetCurTimeAndCleanUp();
+ lword total = 0;
+ for (unsigned int i=0; i!=m_ops.size(); ++i)
+ total += m_ops[i].second;
+ m_nextTransceiveTime =
+ (total < m_maxBytesPerSecond) ? curTime : m_ops.front().first + 1000;
+}
+
+double LimitedBandwidth::GetCurTimeAndCleanUp()
+{
+ if (!m_maxBytesPerSecond)
+ return 0;
+
+ double curTime = m_timer.ElapsedTimeAsDouble();
+ while (m_ops.size() && (m_ops.front().first + 1000 < curTime))
+ m_ops.pop_front();
+ return curTime;
+}
+
+void LimitedBandwidth::GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack)
+{
+ double nextTransceiveTime = TimeToNextTransceive();
+ if (nextTransceiveTime)
+ container.ScheduleEvent(nextTransceiveTime, CallStack("LimitedBandwidth::GetWaitObjects()", &callStack));
+}
+
+// *************************************************************
+
+size_t NonblockingSource::GeneralPump2(
+ lword& byteCount, bool blockingOutput,
+ unsigned long maxTime, bool checkDelimiter, byte delimiter)
+{
+ m_blockedBySpeedLimit = false;
+
+ if (!GetMaxBytesPerSecond())
+ {
+ size_t ret = DoPump(byteCount, blockingOutput, maxTime, checkDelimiter, delimiter);
+ m_doPumpBlocked = (ret != 0);
+ return ret;
+ }
+
+ bool forever = (maxTime == INFINITE_TIME);
+ unsigned long timeToGo = maxTime;
+ Timer timer(Timer::MILLISECONDS, forever);
+ lword maxSize = byteCount;
+ byteCount = 0;
+
+ timer.StartTimer();
+
+ while (true)
+ {
+ lword curMaxSize = UnsignedMin(ComputeCurrentTransceiveLimit(), maxSize - byteCount);
+
+ if (curMaxSize || m_doPumpBlocked)
+ {
+ if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
+ size_t ret = DoPump(curMaxSize, blockingOutput, timeToGo, checkDelimiter, delimiter);
+ m_doPumpBlocked = (ret != 0);
+ if (curMaxSize)
+ {
+ NoteTransceive(curMaxSize);
+ byteCount += curMaxSize;
+ }
+ if (ret)
+ return ret;
+ }
+
+ if (maxSize != ULONG_MAX && byteCount >= maxSize)
+ break;
+
+ if (!forever)
+ {
+ timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
+ if (!timeToGo)
+ break;
+ }
+
+ double waitTime = TimeToNextTransceive();
+ if (!forever && waitTime > timeToGo)
+ {
+ m_blockedBySpeedLimit = true;
+ break;
+ }
+
+ WaitObjectContainer container;
+ LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSource::GeneralPump2() - speed limit", 0));
+ container.Wait((unsigned long)waitTime);
+ }
+
+ return 0;
+}
+
+size_t NonblockingSource::PumpMessages2(unsigned int &messageCount, bool blocking)
+{
+ if (messageCount == 0)
+ return 0;
+
+ messageCount = 0;
+
+ lword byteCount;
+ do {
+ byteCount = LWORD_MAX;
+ RETURN_IF_NONZERO(Pump2(byteCount, blocking));
+ } while(byteCount == LWORD_MAX);
+
+ if (!m_messageEndSent && SourceExhausted())
+ {
+ RETURN_IF_NONZERO(AttachedTransformation()->Put2(NULL, 0, GetAutoSignalPropagation(), true));
+ m_messageEndSent = true;
+ messageCount = 1;
+ }
+ return 0;
+}
+
+lword NonblockingSink::TimedFlush(unsigned long maxTime, size_t targetSize)
+{
+ m_blockedBySpeedLimit = false;
+
+ size_t curBufSize = GetCurrentBufferSize();
+ if (curBufSize <= targetSize && (targetSize || !EofPending()))
+ return 0;
+
+ if (!GetMaxBytesPerSecond())
+ return DoFlush(maxTime, targetSize);
+
+ bool forever = (maxTime == INFINITE_TIME);
+ unsigned long timeToGo = maxTime;
+ Timer timer(Timer::MILLISECONDS, forever);
+ lword totalFlushed = 0;
+
+ timer.StartTimer();
+
+ while (true)
+ {
+ size_t flushSize = UnsignedMin(curBufSize - targetSize, ComputeCurrentTransceiveLimit());
+ if (flushSize || EofPending())
+ {
+ if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
+ size_t ret = (size_t)DoFlush(timeToGo, curBufSize - flushSize);
+ if (ret)
+ {
+ NoteTransceive(ret);
+ curBufSize -= ret;
+ totalFlushed += ret;
+ }
+ }
+
+ if (curBufSize <= targetSize && (targetSize || !EofPending()))
+ break;
+
+ if (!forever)
+ {
+ timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
+ if (!timeToGo)
+ break;
+ }
+
+ double waitTime = TimeToNextTransceive();
+ if (!forever && waitTime > timeToGo)
+ {
+ m_blockedBySpeedLimit = true;
+ break;
+ }
+
+ WaitObjectContainer container;
+ LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSink::TimedFlush() - speed limit", 0));
+ container.Wait((unsigned long)waitTime);
+ }
+
+ return totalFlushed;
+}
+
+bool NonblockingSink::IsolatedFlush(bool hardFlush, bool blocking)
+{
+ TimedFlush(blocking ? INFINITE_TIME : 0);
+ return hardFlush && (!!GetCurrentBufferSize() || EofPending());
+}
+
+// *************************************************************
+
+NetworkSource::NetworkSource(BufferedTransformation *attachment)
+ : NonblockingSource(attachment), m_buf(1024*16)
+ , m_waitingForResult(false), m_outputBlocked(false)
+ , m_dataBegin(0), m_dataEnd(0)
+{
+}
+
+unsigned int NetworkSource::GetMaxWaitObjectCount() const
+{
+ return LimitedBandwidth::GetMaxWaitObjectCount()
+ + GetReceiver().GetMaxWaitObjectCount()
+ + AttachedTransformation()->GetMaxWaitObjectCount();
+}
+
+void NetworkSource::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ if (BlockedBySpeedLimit())
+ LimitedBandwidth::GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - speed limit", &callStack));
+ else if (!m_outputBlocked)
+ {
+ if (m_dataBegin == m_dataEnd)
+ AccessReceiver().GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - no data", &callStack));
+ else
+ container.SetNoWait(CallStack("NetworkSource::GetWaitObjects() - have data", &callStack));
+ }
+
+ AttachedTransformation()->GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - attachment", &callStack));
+}
+
+size_t NetworkSource::DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter)
+{
+ NetworkReceiver &receiver = AccessReceiver();
+
+ lword maxSize = byteCount;
+ byteCount = 0;
+ bool forever = maxTime == INFINITE_TIME;
+ Timer timer(Timer::MILLISECONDS, forever);
+ BufferedTransformation *t = AttachedTransformation();
+
+ if (m_outputBlocked)
+ goto DoOutput;
+
+ while (true)
+ {
+ if (m_dataBegin == m_dataEnd)
+ {
+ if (receiver.EofReceived())
+ break;
+
+ if (m_waitingForResult)
+ {
+ if (receiver.MustWaitForResult() &&
+ !receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
+ CallStack("NetworkSource::DoPump() - wait receive result", 0)))
+ break;
+
+ unsigned int recvResult = receiver.GetReceiveResult();
+#if CRYPTOPP_TRACE_NETWORK
+ OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
+#endif
+ m_dataEnd += recvResult;
+ m_waitingForResult = false;
+
+ if (!receiver.MustWaitToReceive() && !receiver.EofReceived() && m_dataEnd != m_buf.size())
+ goto ReceiveNoWait;
+ }
+ else
+ {
+ m_dataEnd = m_dataBegin = 0;
+
+ if (receiver.MustWaitToReceive())
+ {
+ if (!receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
+ CallStack("NetworkSource::DoPump() - wait receive", 0)))
+ break;
+
+ receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd);
+ m_waitingForResult = true;
+ }
+ else
+ {
+ReceiveNoWait:
+ m_waitingForResult = true;
+ // call Receive repeatedly as long as data is immediately available,
+ // because some receivers tend to return data in small pieces
+#if CRYPTOPP_TRACE_NETWORK
+ OutputDebugString((IntToString((unsigned int)this) + ": Receiving " + IntToString(m_buf.size()-m_dataEnd) + " bytes\n").c_str());
+#endif
+ while (receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd))
+ {
+ unsigned int recvResult = receiver.GetReceiveResult();
+#if CRYPTOPP_TRACE_NETWORK
+ OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
+#endif
+ m_dataEnd += recvResult;
+ if (receiver.EofReceived() || m_dataEnd > m_buf.size() /2)
+ {
+ m_waitingForResult = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_putSize = UnsignedMin(m_dataEnd - m_dataBegin, maxSize - byteCount);
+
+ if (checkDelimiter)
+ m_putSize = std::find(m_buf+m_dataBegin, m_buf+m_dataBegin+m_putSize, delimiter) - (m_buf+m_dataBegin);
+
+DoOutput:
+ size_t result = t->PutModifiable2(m_buf+m_dataBegin, m_putSize, 0, forever || blockingOutput);
+ if (result)
+ {
+ if (t->Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
+ CallStack("NetworkSource::DoPump() - wait attachment", 0)))
+ goto DoOutput;
+ else
+ {
+ m_outputBlocked = true;
+ return result;
+ }
+ }
+ m_outputBlocked = false;
+
+ byteCount += m_putSize;
+ m_dataBegin += m_putSize;
+ if (checkDelimiter && m_dataBegin < m_dataEnd && m_buf[m_dataBegin] == delimiter)
+ break;
+ if (maxSize != ULONG_MAX && byteCount == maxSize)
+ break;
+ // once time limit is reached, return even if there is more data waiting
+ // but make 0 a special case so caller can request a large amount of data to be
+ // pumped as long as it is immediately available
+ if (maxTime > 0 && timer.ElapsedTime() > maxTime)
+ break;
+ }
+ }
+
+ return 0;
+}
+
+// *************************************************************
+
+NetworkSink::NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound)
+ : m_maxBufferSize(maxBufferSize), m_autoFlushBound(autoFlushBound)
+ , m_needSendResult(false), m_wasBlocked(false), m_eofState(EOF_NONE)
+ , m_buffer(STDMIN(16U*1024U+256, maxBufferSize)), m_skipBytes(0)
+ , m_speedTimer(Timer::MILLISECONDS), m_byteCountSinceLastTimerReset(0)
+ , m_currentSpeed(0), m_maxObservedSpeed(0)
+{
+}
+
+float NetworkSink::ComputeCurrentSpeed()
+{
+ if (m_speedTimer.ElapsedTime() > 1000)
+ {
+ m_currentSpeed = m_byteCountSinceLastTimerReset * 1000 / m_speedTimer.ElapsedTime();
+ m_maxObservedSpeed = STDMAX(m_currentSpeed, m_maxObservedSpeed * 0.98f);
+ m_byteCountSinceLastTimerReset = 0;
+ m_speedTimer.StartTimer();
+// OutputDebugString(("max speed: " + IntToString((int)m_maxObservedSpeed) + " current speed: " + IntToString((int)m_currentSpeed) + "\n").c_str());
+ }
+ return m_currentSpeed;
+}
+
+float NetworkSink::GetMaxObservedSpeed() const
+{
+ lword m = GetMaxBytesPerSecond();
+ return m ? STDMIN(m_maxObservedSpeed, float(CRYPTOPP_VC6_INT64 m)) : m_maxObservedSpeed;
+}
+
+unsigned int NetworkSink::GetMaxWaitObjectCount() const
+{
+ return LimitedBandwidth::GetMaxWaitObjectCount() + GetSender().GetMaxWaitObjectCount();
+}
+
+void NetworkSink::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ if (BlockedBySpeedLimit())
+ LimitedBandwidth::GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - speed limit", &callStack));
+ else if (m_wasBlocked)
+ AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - was blocked", &callStack));
+ else if (!m_buffer.IsEmpty())
+ AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - buffer not empty", &callStack));
+ else if (EofPending())
+ AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - EOF pending", &callStack));
+}
+
+size_t NetworkSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ if (m_eofState == EOF_DONE)
+ {
+ if (length || messageEnd)
+ throw Exception(Exception::OTHER_ERROR, "NetworkSink::Put2() being called after EOF had been sent");
+
+ return 0;
+ }
+
+ if (m_eofState > EOF_NONE)
+ goto EofSite;
+
+ {
+ if (m_skipBytes)
+ {
+ assert(length >= m_skipBytes);
+ inString += m_skipBytes;
+ length -= m_skipBytes;
+ }
+
+ m_buffer.Put(inString, length);
+
+ if (!blocking || m_buffer.CurrentSize() > m_autoFlushBound)
+ TimedFlush(0, 0);
+
+ size_t targetSize = messageEnd ? 0 : m_maxBufferSize;
+ if (blocking)
+ TimedFlush(INFINITE_TIME, targetSize);
+
+ if (m_buffer.CurrentSize() > targetSize)
+ {
+ assert(!blocking);
+ m_wasBlocked = true;
+ m_skipBytes += length;
+ size_t blockedBytes = UnsignedMin(length, m_buffer.CurrentSize() - targetSize);
+ return STDMAX<size_t>(blockedBytes, 1);
+ }
+
+ m_wasBlocked = false;
+ m_skipBytes = 0;
+ }
+
+ if (messageEnd)
+ {
+ m_eofState = EOF_PENDING_SEND;
+
+ EofSite:
+ TimedFlush(blocking ? INFINITE_TIME : 0, 0);
+ if (m_eofState != EOF_DONE)
+ return 1;
+ }
+
+ return 0;
+}
+
+lword NetworkSink::DoFlush(unsigned long maxTime, size_t targetSize)
+{
+ NetworkSender &sender = AccessSender();
+
+ bool forever = maxTime == INFINITE_TIME;
+ Timer timer(Timer::MILLISECONDS, forever);
+ unsigned int totalFlushSize = 0;
+
+ while (true)
+ {
+ if (m_buffer.CurrentSize() <= targetSize)
+ break;
+
+ if (m_needSendResult)
+ {
+ if (sender.MustWaitForResult() &&
+ !sender.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
+ CallStack("NetworkSink::DoFlush() - wait send result", 0)))
+ break;
+
+ unsigned int sendResult = sender.GetSendResult();
+#if CRYPTOPP_TRACE_NETWORK
+ OutputDebugString((IntToString((unsigned int)this) + ": Sent " + IntToString(sendResult) + " bytes\n").c_str());
+#endif
+ m_buffer.Skip(sendResult);
+ totalFlushSize += sendResult;
+ m_needSendResult = false;
+
+ if (!m_buffer.AnyRetrievable())
+ break;
+ }
+
+ unsigned long timeOut = maxTime ? SaturatingSubtract(maxTime, timer.ElapsedTime()) : 0;
+ if (sender.MustWaitToSend() && !sender.Wait(timeOut, CallStack("NetworkSink::DoFlush() - wait send", 0)))
+ break;
+
+ size_t contiguousSize = 0;
+ const byte *block = m_buffer.Spy(contiguousSize);
+
+#if CRYPTOPP_TRACE_NETWORK
+ OutputDebugString((IntToString((unsigned int)this) + ": Sending " + IntToString(contiguousSize) + " bytes\n").c_str());
+#endif
+ sender.Send(block, contiguousSize);
+ m_needSendResult = true;
+
+ if (maxTime > 0 && timeOut == 0)
+ break; // once time limit is reached, return even if there is more data waiting
+ }
+
+ m_byteCountSinceLastTimerReset += totalFlushSize;
+ ComputeCurrentSpeed();
+
+ if (m_buffer.IsEmpty() && !m_needSendResult)
+ {
+ if (m_eofState == EOF_PENDING_SEND)
+ {
+ sender.SendEof();
+ m_eofState = sender.MustWaitForEof() ? EOF_PENDING_DELIVERY : EOF_DONE;
+ }
+
+ while (m_eofState == EOF_PENDING_DELIVERY)
+ {
+ unsigned long timeOut = maxTime ? SaturatingSubtract(maxTime, timer.ElapsedTime()) : 0;
+ if (!sender.Wait(timeOut, CallStack("NetworkSink::DoFlush() - wait EOF", 0)))
+ break;
+
+ if (sender.EofSent())
+ m_eofState = EOF_DONE;
+ }
+ }
+
+ return totalFlushSize;
+}
+
+#endif // #ifdef HIGHRES_TIMER_AVAILABLE
+
+NAMESPACE_END
diff --git a/lib/cryptopp/network.h b/lib/cryptopp/network.h
new file mode 100644
index 000000000..96cd4567e
--- /dev/null
+++ b/lib/cryptopp/network.h
@@ -0,0 +1,235 @@
+#ifndef CRYPTOPP_NETWORK_H
+#define CRYPTOPP_NETWORK_H
+
+#include "config.h"
+
+#ifdef HIGHRES_TIMER_AVAILABLE
+
+#include "filters.h"
+#include "hrtimer.h"
+
+#include <deque>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+class LimitedBandwidth
+{
+public:
+ LimitedBandwidth(lword maxBytesPerSecond = 0)
+ : m_maxBytesPerSecond(maxBytesPerSecond), m_timer(Timer::MILLISECONDS)
+ , m_nextTransceiveTime(0)
+ { m_timer.StartTimer(); }
+
+ lword GetMaxBytesPerSecond() const
+ { return m_maxBytesPerSecond; }
+
+ void SetMaxBytesPerSecond(lword v)
+ { m_maxBytesPerSecond = v; }
+
+ lword ComputeCurrentTransceiveLimit();
+
+ double TimeToNextTransceive();
+
+ void NoteTransceive(lword size);
+
+public:
+ /*! GetWaitObjects() must be called despite the 0 return from GetMaxWaitObjectCount();
+ the 0 is because the ScheduleEvent() method is used instead of adding a wait object */
+ unsigned int GetMaxWaitObjectCount() const { return 0; }
+ void GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack);
+
+private:
+ lword m_maxBytesPerSecond;
+
+ typedef std::deque<std::pair<double, lword> > OpQueue;
+ OpQueue m_ops;
+
+ Timer m_timer;
+ double m_nextTransceiveTime;
+
+ void ComputeNextTransceiveTime();
+ double GetCurTimeAndCleanUp();
+};
+
+//! a Source class that can pump from a device for a specified amount of time.
+class CRYPTOPP_NO_VTABLE NonblockingSource : public AutoSignaling<Source>, public LimitedBandwidth
+{
+public:
+ NonblockingSource(BufferedTransformation *attachment)
+ : m_messageEndSent(false) , m_doPumpBlocked(false), m_blockedBySpeedLimit(false) {Detach(attachment);}
+
+ //! \name NONBLOCKING SOURCE
+ //@{
+
+ //! pump up to maxSize bytes using at most maxTime milliseconds
+ /*! If checkDelimiter is true, pump up to delimiter, which itself is not extracted or pumped. */
+ size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n');
+
+ lword GeneralPump(lword maxSize=LWORD_MAX, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n')
+ {
+ GeneralPump2(maxSize, true, maxTime, checkDelimiter, delimiter);
+ return maxSize;
+ }
+ lword TimedPump(unsigned long maxTime)
+ {return GeneralPump(LWORD_MAX, maxTime);}
+ lword PumpLine(byte delimiter='\n', lword maxSize=1024)
+ {return GeneralPump(maxSize, INFINITE_TIME, true, delimiter);}
+
+ size_t Pump2(lword &byteCount, bool blocking=true)
+ {return GeneralPump2(byteCount, blocking, blocking ? INFINITE_TIME : 0);}
+ size_t PumpMessages2(unsigned int &messageCount, bool blocking=true);
+ //@}
+
+protected:
+ virtual size_t DoPump(lword &byteCount, bool blockingOutput,
+ unsigned long maxTime, bool checkDelimiter, byte delimiter) =0;
+
+ bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
+
+private:
+ bool m_messageEndSent, m_doPumpBlocked, m_blockedBySpeedLimit;
+};
+
+//! Network Receiver
+class CRYPTOPP_NO_VTABLE NetworkReceiver : public Waitable
+{
+public:
+ virtual bool MustWaitToReceive() {return false;}
+ virtual bool MustWaitForResult() {return false;}
+ //! receive data from network source, returns whether result is immediately available
+ virtual bool Receive(byte* buf, size_t bufLen) =0;
+ virtual unsigned int GetReceiveResult() =0;
+ virtual bool EofReceived() const =0;
+};
+
+class CRYPTOPP_NO_VTABLE NonblockingSinkInfo
+{
+public:
+ virtual ~NonblockingSinkInfo() {}
+ virtual size_t GetMaxBufferSize() const =0;
+ virtual size_t GetCurrentBufferSize() const =0;
+ virtual bool EofPending() const =0;
+ //! compute the current speed of this sink in bytes per second
+ virtual float ComputeCurrentSpeed() =0;
+ //! get the maximum observed speed of this sink in bytes per second
+ virtual float GetMaxObservedSpeed() const =0;
+};
+
+//! a Sink class that queues input and can flush to a device for a specified amount of time.
+class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink, public NonblockingSinkInfo, public LimitedBandwidth
+{
+public:
+ NonblockingSink() : m_blockedBySpeedLimit(false) {}
+
+ bool IsolatedFlush(bool hardFlush, bool blocking);
+
+ //! flush to device for no more than maxTime milliseconds
+ /*! This function will repeatedly attempt to flush data to some device, until
+ the queue is empty, or a total of maxTime milliseconds have elapsed.
+ If maxTime == 0, at least one attempt will be made to flush some data, but
+ it is likely that not all queued data will be flushed, even if the device
+ is ready to receive more data without waiting. If you want to flush as much data
+ as possible without waiting for the device, call this function in a loop.
+ For example: while (sink.TimedFlush(0) > 0) {}
+ \return number of bytes flushed
+ */
+ lword TimedFlush(unsigned long maxTime, size_t targetSize = 0);
+
+ virtual void SetMaxBufferSize(size_t maxBufferSize) =0;
+ //! set a bound which will cause sink to flush if exceeded by GetCurrentBufferSize()
+ virtual void SetAutoFlushBound(size_t bound) =0;
+
+protected:
+ virtual lword DoFlush(unsigned long maxTime, size_t targetSize) = 0;
+
+ bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
+
+private:
+ bool m_blockedBySpeedLimit;
+};
+
+//! Network Sender
+class CRYPTOPP_NO_VTABLE NetworkSender : public Waitable
+{
+public:
+ virtual bool MustWaitToSend() {return false;}
+ virtual bool MustWaitForResult() {return false;}
+ virtual void Send(const byte* buf, size_t bufLen) =0;
+ virtual unsigned int GetSendResult() =0;
+ virtual bool MustWaitForEof() {return false;}
+ virtual void SendEof() =0;
+ virtual bool EofSent() {return false;} // implement if MustWaitForEof() == true
+};
+
+//! Network Source
+class CRYPTOPP_NO_VTABLE NetworkSource : public NonblockingSource
+{
+public:
+ NetworkSource(BufferedTransformation *attachment);
+
+ unsigned int GetMaxWaitObjectCount() const;
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+
+ bool SourceExhausted() const {return m_dataBegin == m_dataEnd && GetReceiver().EofReceived();}
+
+protected:
+ size_t DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter);
+
+ virtual NetworkReceiver & AccessReceiver() =0;
+ const NetworkReceiver & GetReceiver() const {return const_cast<NetworkSource *>(this)->AccessReceiver();}
+
+private:
+ SecByteBlock m_buf;
+ size_t m_putSize, m_dataBegin, m_dataEnd;
+ bool m_waitingForResult, m_outputBlocked;
+};
+
+//! Network Sink
+class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink
+{
+public:
+ NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound);
+
+ unsigned int GetMaxWaitObjectCount() const;
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
+
+ void SetMaxBufferSize(size_t maxBufferSize) {m_maxBufferSize = maxBufferSize; m_buffer.SetNodeSize(UnsignedMin(maxBufferSize, 16U*1024U+256U));}
+ void SetAutoFlushBound(size_t bound) {m_autoFlushBound = bound;}
+
+ size_t GetMaxBufferSize() const {return m_maxBufferSize;}
+ size_t GetCurrentBufferSize() const {return (size_t)m_buffer.CurrentSize();}
+
+ void ClearBuffer() { m_buffer.Clear(); }
+
+ bool EofPending() const { return m_eofState > EOF_NONE && m_eofState < EOF_DONE; }
+
+ //! compute the current speed of this sink in bytes per second
+ float ComputeCurrentSpeed();
+ //! get the maximum observed speed of this sink in bytes per second
+ float GetMaxObservedSpeed() const;
+
+protected:
+ lword DoFlush(unsigned long maxTime, size_t targetSize);
+
+ virtual NetworkSender & AccessSender() =0;
+ const NetworkSender & GetSender() const {return const_cast<NetworkSink *>(this)->AccessSender();}
+
+private:
+ enum EofState { EOF_NONE, EOF_PENDING_SEND, EOF_PENDING_DELIVERY, EOF_DONE };
+
+ size_t m_maxBufferSize, m_autoFlushBound;
+ bool m_needSendResult, m_wasBlocked;
+ EofState m_eofState;
+ ByteQueue m_buffer;
+ size_t m_skipBytes;
+ Timer m_speedTimer;
+ float m_byteCountSinceLastTimerReset, m_currentSpeed, m_maxObservedSpeed;
+};
+
+NAMESPACE_END
+
+#endif // #ifdef HIGHRES_TIMER_AVAILABLE
+
+#endif
diff --git a/lib/cryptopp/nr.h b/lib/cryptopp/nr.h
new file mode 100644
index 000000000..c398e3550
--- /dev/null
+++ b/lib/cryptopp/nr.h
@@ -0,0 +1,6 @@
+#ifndef CRYPTOPP_NR_H
+#define CRYPTOPP_NR_H
+
+#include "gfpcrypt.h"
+
+#endif
diff --git a/lib/cryptopp/oaep.cpp b/lib/cryptopp/oaep.cpp
new file mode 100644
index 000000000..1d474be52
--- /dev/null
+++ b/lib/cryptopp/oaep.cpp
@@ -0,0 +1,97 @@
+// oaep.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "oaep.h"
+#include <functional>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ********************************************************
+
+size_t OAEP_Base::MaxUnpaddedLength(size_t paddedLength) const
+{
+ return SaturatingSubtract(paddedLength/8, 1+2*DigestSize());
+}
+
+void OAEP_Base::Pad(RandomNumberGenerator &rng, const byte *input, size_t inputLength, byte *oaepBlock, size_t oaepBlockLen, const NameValuePairs &parameters) const
+{
+ assert (inputLength <= MaxUnpaddedLength(oaepBlockLen));
+
+ // convert from bit length to byte length
+ if (oaepBlockLen % 8 != 0)
+ {
+ oaepBlock[0] = 0;
+ oaepBlock++;
+ }
+ oaepBlockLen /= 8;
+
+ std::auto_ptr<HashTransformation> pHash(NewHash());
+ const size_t hLen = pHash->DigestSize();
+ const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen;
+ byte *const maskedSeed = oaepBlock;
+ byte *const maskedDB = oaepBlock+seedLen;
+
+ ConstByteArrayParameter encodingParameters;
+ parameters.GetValue(Name::EncodingParameters(), encodingParameters);
+
+ // DB = pHash || 00 ... || 01 || M
+ pHash->CalculateDigest(maskedDB, encodingParameters.begin(), encodingParameters.size());
+ memset(maskedDB+hLen, 0, dbLen-hLen-inputLength-1);
+ maskedDB[dbLen-inputLength-1] = 0x01;
+ memcpy(maskedDB+dbLen-inputLength, input, inputLength);
+
+ rng.GenerateBlock(maskedSeed, seedLen);
+ std::auto_ptr<MaskGeneratingFunction> pMGF(NewMGF());
+ pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen);
+ pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen);
+}
+
+DecodingResult OAEP_Base::Unpad(const byte *oaepBlock, size_t oaepBlockLen, byte *output, const NameValuePairs &parameters) const
+{
+ bool invalid = false;
+
+ // convert from bit length to byte length
+ if (oaepBlockLen % 8 != 0)
+ {
+ invalid = (oaepBlock[0] != 0) || invalid;
+ oaepBlock++;
+ }
+ oaepBlockLen /= 8;
+
+ std::auto_ptr<HashTransformation> pHash(NewHash());
+ const size_t hLen = pHash->DigestSize();
+ const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen;
+
+ invalid = (oaepBlockLen < 2*hLen+1) || invalid;
+
+ SecByteBlock t(oaepBlock, oaepBlockLen);
+ byte *const maskedSeed = t;
+ byte *const maskedDB = t+seedLen;
+
+ std::auto_ptr<MaskGeneratingFunction> pMGF(NewMGF());
+ pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen);
+ pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen);
+
+ ConstByteArrayParameter encodingParameters;
+ parameters.GetValue(Name::EncodingParameters(), encodingParameters);
+
+ // DB = pHash' || 00 ... || 01 || M
+ byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01);
+ invalid = (M == maskedDB+dbLen) || invalid;
+ invalid = (std::find_if(maskedDB+hLen, M, std::bind2nd(std::not_equal_to<byte>(), 0)) != M) || invalid;
+ invalid = !pHash->VerifyDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()) || invalid;
+
+ if (invalid)
+ return DecodingResult();
+
+ M++;
+ memcpy(output, M, maskedDB+dbLen-M);
+ return DecodingResult(maskedDB+dbLen-M);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/oaep.h b/lib/cryptopp/oaep.h
new file mode 100644
index 000000000..4bf6b0d83
--- /dev/null
+++ b/lib/cryptopp/oaep.h
@@ -0,0 +1,42 @@
+#ifndef CRYPTOPP_OAEP_H
+#define CRYPTOPP_OAEP_H
+
+#include "pubkey.h"
+#include "sha.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL OAEP_Base : public PK_EncryptionMessageEncodingMethod
+{
+public:
+ bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
+ size_t MaxUnpaddedLength(size_t paddedLength) const;
+ void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs &parameters) const;
+ DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs &parameters) const;
+
+protected:
+ virtual unsigned int DigestSize() const =0;
+ virtual HashTransformation * NewHash() const =0;
+ virtual MaskGeneratingFunction * NewMGF() const =0;
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/ca.html#cem_OAEP-MGF1">EME-OAEP</a>, for use with classes derived from TF_ES
+template <class H, class MGF=P1363_MGF1>
+class OAEP : public OAEP_Base, public EncryptionStandard
+{
+public:
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("OAEP-") + MGF::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
+ typedef OAEP<H, MGF> EncryptionMessageEncodingMethod;
+
+protected:
+ unsigned int DigestSize() const {return H::DIGESTSIZE;}
+ HashTransformation * NewHash() const {return new H;}
+ MaskGeneratingFunction * NewMGF() const {return new MGF;}
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS OAEP<SHA>;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/oids.h b/lib/cryptopp/oids.h
new file mode 100644
index 000000000..8b1030150
--- /dev/null
+++ b/lib/cryptopp/oids.h
@@ -0,0 +1,123 @@
+#ifndef CRYPTOPP_OIDS_H
+#define CRYPTOPP_OIDS_H
+
+// crypto-related ASN.1 object identifiers
+
+#include "asn.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+NAMESPACE_BEGIN(ASN1)
+
+#define DEFINE_OID(value, name) inline OID name() {return value;}
+
+DEFINE_OID(1, iso)
+ DEFINE_OID(iso()+2, member_body)
+ DEFINE_OID(member_body()+840, iso_us)
+ DEFINE_OID(iso_us()+10040, ansi_x9_57)
+ DEFINE_OID(ansi_x9_57()+4+1, id_dsa)
+ DEFINE_OID(iso_us()+10045, ansi_x9_62)
+ DEFINE_OID(ansi_x9_62()+1, id_fieldType)
+ DEFINE_OID(id_fieldType()+1, prime_field)
+ DEFINE_OID(id_fieldType()+2, characteristic_two_field)
+ DEFINE_OID(characteristic_two_field()+3, id_characteristic_two_basis)
+ DEFINE_OID(id_characteristic_two_basis()+1, gnBasis)
+ DEFINE_OID(id_characteristic_two_basis()+2, tpBasis)
+ DEFINE_OID(id_characteristic_two_basis()+3, ppBasis)
+ DEFINE_OID(ansi_x9_62()+2, id_publicKeyType)
+ DEFINE_OID(id_publicKeyType()+1, id_ecPublicKey)
+ DEFINE_OID(ansi_x9_62()+3, ansi_x9_62_curves)
+ DEFINE_OID(ansi_x9_62_curves()+1, ansi_x9_62_curves_prime)
+ DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1)
+ DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1)
+ DEFINE_OID(iso_us()+113549, rsadsi)
+ DEFINE_OID(rsadsi()+1, pkcs)
+ DEFINE_OID(pkcs()+1, pkcs_1)
+ DEFINE_OID(pkcs_1()+1, rsaEncryption);
+ DEFINE_OID(rsadsi()+2, rsadsi_digestAlgorithm)
+ DEFINE_OID(rsadsi_digestAlgorithm()+2, id_md2)
+ DEFINE_OID(rsadsi_digestAlgorithm()+5, id_md5)
+ DEFINE_OID(iso()+3, identified_organization);
+ DEFINE_OID(identified_organization()+14, oiw);
+ DEFINE_OID(oiw()+3, oiw_secsig);
+ DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms);
+ DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1);
+
+ DEFINE_OID(identified_organization()+36, teletrust);
+ DEFINE_OID(teletrust()+3, teletrust_algorithm)
+ DEFINE_OID(teletrust_algorithm()+2+1, id_ripemd160)
+ DEFINE_OID(teletrust_algorithm()+3+2+8+1, teletrust_ellipticCurve)
+ DEFINE_OID(teletrust_ellipticCurve()+1+1, brainpoolP160r1)
+ DEFINE_OID(teletrust_ellipticCurve()+1+3, brainpoolP192r1)
+ DEFINE_OID(teletrust_ellipticCurve()+1+5, brainpoolP224r1)
+ DEFINE_OID(teletrust_ellipticCurve()+1+7, brainpoolP256r1)
+ DEFINE_OID(teletrust_ellipticCurve()+1+9, brainpoolP320r1)
+ DEFINE_OID(teletrust_ellipticCurve()+1+11, brainpoolP384r1)
+ DEFINE_OID(teletrust_ellipticCurve()+1+13, brainpoolP512r1)
+
+ DEFINE_OID(identified_organization()+132, certicom);
+ DEFINE_OID(certicom()+0, certicom_ellipticCurve);
+ // these are sorted by curve type and then by OID
+ // first curves based on GF(p)
+ DEFINE_OID(certicom_ellipticCurve()+6, secp112r1);
+ DEFINE_OID(certicom_ellipticCurve()+7, secp112r2);
+ DEFINE_OID(certicom_ellipticCurve()+8, secp160r1);
+ DEFINE_OID(certicom_ellipticCurve()+9, secp160k1);
+ DEFINE_OID(certicom_ellipticCurve()+10, secp256k1);
+ DEFINE_OID(certicom_ellipticCurve()+28, secp128r1);
+ DEFINE_OID(certicom_ellipticCurve()+29, secp128r2);
+ DEFINE_OID(certicom_ellipticCurve()+30, secp160r2);
+ DEFINE_OID(certicom_ellipticCurve()+31, secp192k1);
+ DEFINE_OID(certicom_ellipticCurve()+32, secp224k1);
+ DEFINE_OID(certicom_ellipticCurve()+33, secp224r1);
+ DEFINE_OID(certicom_ellipticCurve()+34, secp384r1);
+ DEFINE_OID(certicom_ellipticCurve()+35, secp521r1);
+ // then curves based on GF(2^n)
+ DEFINE_OID(certicom_ellipticCurve()+1, sect163k1);
+ DEFINE_OID(certicom_ellipticCurve()+2, sect163r1);
+ DEFINE_OID(certicom_ellipticCurve()+3, sect239k1);
+ DEFINE_OID(certicom_ellipticCurve()+4, sect113r1);
+ DEFINE_OID(certicom_ellipticCurve()+5, sect113r2);
+ DEFINE_OID(certicom_ellipticCurve()+15, sect163r2);
+ DEFINE_OID(certicom_ellipticCurve()+16, sect283k1);
+ DEFINE_OID(certicom_ellipticCurve()+17, sect283r1);
+ DEFINE_OID(certicom_ellipticCurve()+22, sect131r1);
+ DEFINE_OID(certicom_ellipticCurve()+23, sect131r2);
+ DEFINE_OID(certicom_ellipticCurve()+24, sect193r1);
+ DEFINE_OID(certicom_ellipticCurve()+25, sect193r2);
+ DEFINE_OID(certicom_ellipticCurve()+26, sect233k1);
+ DEFINE_OID(certicom_ellipticCurve()+27, sect233r1);
+ DEFINE_OID(certicom_ellipticCurve()+36, sect409k1);
+ DEFINE_OID(certicom_ellipticCurve()+37, sect409r1);
+ DEFINE_OID(certicom_ellipticCurve()+38, sect571k1);
+ DEFINE_OID(certicom_ellipticCurve()+39, sect571r1);
+DEFINE_OID(2, joint_iso_ccitt)
+ DEFINE_OID(joint_iso_ccitt()+16, country)
+ DEFINE_OID(country()+840, joint_iso_ccitt_us)
+ DEFINE_OID(joint_iso_ccitt_us()+1, us_organization)
+ DEFINE_OID(us_organization()+101, us_gov)
+ DEFINE_OID(us_gov()+3, csor)
+ DEFINE_OID(csor()+4, nistalgorithms)
+ DEFINE_OID(nistalgorithms()+1, aes)
+ DEFINE_OID(aes()+1, id_aes128_ECB)
+ DEFINE_OID(aes()+2, id_aes128_cbc)
+ DEFINE_OID(aes()+3, id_aes128_ofb)
+ DEFINE_OID(aes()+4, id_aes128_cfb)
+ DEFINE_OID(aes()+21, id_aes192_ECB)
+ DEFINE_OID(aes()+22, id_aes192_cbc)
+ DEFINE_OID(aes()+23, id_aes192_ofb)
+ DEFINE_OID(aes()+24, id_aes192_cfb)
+ DEFINE_OID(aes()+41, id_aes256_ECB)
+ DEFINE_OID(aes()+42, id_aes256_cbc)
+ DEFINE_OID(aes()+43, id_aes256_ofb)
+ DEFINE_OID(aes()+44, id_aes256_cfb)
+ DEFINE_OID(nistalgorithms()+2, nist_hashalgs)
+ DEFINE_OID(nist_hashalgs()+1, id_sha256)
+ DEFINE_OID(nist_hashalgs()+2, id_sha384)
+ DEFINE_OID(nist_hashalgs()+3, id_sha512)
+
+NAMESPACE_END
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/osrng.cpp b/lib/cryptopp/osrng.cpp
new file mode 100644
index 000000000..76e486b4e
--- /dev/null
+++ b/lib/cryptopp/osrng.cpp
@@ -0,0 +1,192 @@
+// osrng.cpp - written and placed in the public domain by Wei Dai
+
+// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool.
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "osrng.h"
+
+#ifdef OS_RNG_AVAILABLE
+
+#include "rng.h"
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#include <windows.h>
+#include <wincrypt.h>
+#endif
+
+#ifdef CRYPTOPP_UNIX_AVAILABLE
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE)
+OS_RNG_Err::OS_RNG_Err(const std::string &operation)
+ : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " +
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+ "0x" + IntToString(GetLastError(), 16)
+#else
+ IntToString(errno)
+#endif
+ )
+{
+}
+#endif
+
+#ifdef NONBLOCKING_RNG_AVAILABLE
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+
+MicrosoftCryptoProvider::MicrosoftCryptoProvider()
+{
+ if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ throw OS_RNG_Err("CryptAcquireContext");
+}
+
+MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
+{
+ CryptReleaseContext(m_hProvider, 0);
+}
+
+#endif
+
+NonblockingRng::NonblockingRng()
+{
+#ifndef CRYPTOPP_WIN32_AVAILABLE
+ m_fd = open("/dev/urandom",O_RDONLY);
+ if (m_fd == -1)
+ throw OS_RNG_Err("open /dev/urandom");
+#endif
+}
+
+NonblockingRng::~NonblockingRng()
+{
+#ifndef CRYPTOPP_WIN32_AVAILABLE
+ close(m_fd);
+#endif
+}
+
+void NonblockingRng::GenerateBlock(byte *output, size_t size)
+{
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+# ifdef WORKAROUND_MS_BUG_Q258000
+ const MicrosoftCryptoProvider &m_Provider = Singleton<MicrosoftCryptoProvider>().Ref();
+# endif
+ if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output))
+ throw OS_RNG_Err("CryptGenRandom");
+#else
+ while (size)
+ {
+ ssize_t len = read(m_fd, output, size);
+
+ if (len < 0)
+ {
+ // /dev/urandom reads CAN give EAGAIN errors! (maybe EINTR as well)
+ if (errno != EINTR && errno != EAGAIN)
+ throw OS_RNG_Err("read /dev/urandom");
+
+ continue;
+ }
+
+ output += len;
+ size -= len;
+ }
+#endif
+}
+
+#endif
+
+// *************************************************************
+
+#ifdef BLOCKING_RNG_AVAILABLE
+
+#ifndef CRYPTOPP_BLOCKING_RNG_FILENAME
+#ifdef __OpenBSD__
+#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom"
+#else
+#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random"
+#endif
+#endif
+
+BlockingRng::BlockingRng()
+{
+ m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME,O_RDONLY);
+ if (m_fd == -1)
+ throw OS_RNG_Err("open " CRYPTOPP_BLOCKING_RNG_FILENAME);
+}
+
+BlockingRng::~BlockingRng()
+{
+ close(m_fd);
+}
+
+void BlockingRng::GenerateBlock(byte *output, size_t size)
+{
+ while (size)
+ {
+ // on some systems /dev/random will block until all bytes
+ // are available, on others it returns immediately
+ ssize_t len = read(m_fd, output, size);
+ if (len < 0)
+ {
+ // /dev/random reads CAN give EAGAIN errors! (maybe EINTR as well)
+ if (errno != EINTR && errno != EAGAIN)
+ throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME);
+
+ continue;
+ }
+
+ size -= len;
+ output += len;
+ if (size)
+ sleep(1);
+ }
+}
+
+#endif
+
+// *************************************************************
+
+void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size)
+{
+#ifdef NONBLOCKING_RNG_AVAILABLE
+ if (blocking)
+#endif
+ {
+#ifdef BLOCKING_RNG_AVAILABLE
+ BlockingRng rng;
+ rng.GenerateBlock(output, size);
+#endif
+ }
+
+#ifdef BLOCKING_RNG_AVAILABLE
+ if (!blocking)
+#endif
+ {
+#ifdef NONBLOCKING_RNG_AVAILABLE
+ NonblockingRng rng;
+ rng.GenerateBlock(output, size);
+#endif
+ }
+}
+
+void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize)
+{
+ SecByteBlock seed(seedSize);
+ OS_GenerateRandomBlock(blocking, seed, seedSize);
+ IncorporateEntropy(seed, seedSize);
+}
+
+NAMESPACE_END
+
+#endif
+
+#endif
diff --git a/lib/cryptopp/osrng.h b/lib/cryptopp/osrng.h
new file mode 100644
index 000000000..ae07d057b
--- /dev/null
+++ b/lib/cryptopp/osrng.h
@@ -0,0 +1,156 @@
+#ifndef CRYPTOPP_OSRNG_H
+#define CRYPTOPP_OSRNG_H
+
+//! \file
+
+#include "config.h"
+
+#ifdef OS_RNG_AVAILABLE
+
+#include "randpool.h"
+#include "rng.h"
+#include "aes.h"
+#include "sha.h"
+#include "fips140.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Exception class for Operating-System Random Number Generator.
+class CRYPTOPP_DLL OS_RNG_Err : public Exception
+{
+public:
+ OS_RNG_Err(const std::string &operation);
+};
+
+#ifdef NONBLOCKING_RNG_AVAILABLE
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+class CRYPTOPP_DLL MicrosoftCryptoProvider
+{
+public:
+ MicrosoftCryptoProvider();
+ ~MicrosoftCryptoProvider();
+#if defined(_WIN64)
+ typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include <windows.h>
+#else
+ typedef unsigned long ProviderHandle;
+#endif
+ ProviderHandle GetProviderHandle() const {return m_hProvider;}
+private:
+ ProviderHandle m_hProvider;
+};
+
+#pragma comment(lib, "advapi32.lib")
+#endif
+
+//! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom
+class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
+{
+public:
+ NonblockingRng();
+ ~NonblockingRng();
+ void GenerateBlock(byte *output, size_t size);
+
+protected:
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+# ifndef WORKAROUND_MS_BUG_Q258000
+ MicrosoftCryptoProvider m_Provider;
+# endif
+#else
+ int m_fd;
+#endif
+};
+
+#endif
+
+#ifdef BLOCKING_RNG_AVAILABLE
+
+//! encapsulate /dev/random, or /dev/srandom on OpenBSD
+class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
+{
+public:
+ BlockingRng();
+ ~BlockingRng();
+ void GenerateBlock(byte *output, size_t size);
+
+protected:
+ int m_fd;
+};
+
+#endif
+
+CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);
+
+//! Automaticly Seeded Randomness Pool
+/*! This class seeds itself using an operating system provided RNG. */
+class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
+{
+public:
+ //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available
+ explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
+ {Reseed(blocking, seedSize);}
+ void Reseed(bool blocking = false, unsigned int seedSize = 32);
+};
+
+//! RNG from ANSI X9.17 Appendix C, seeded using an OS provided RNG
+template <class BLOCK_CIPHER>
+class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
+{
+public:
+ //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available
+ explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
+ {if (autoSeed) Reseed(blocking);}
+ void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0);
+ // exposed for testing
+ void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
+
+ bool CanIncorporateEntropy() const {return true;}
+ void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
+ void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) {m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
+
+private:
+ member_ptr<RandomNumberGenerator> m_rng;
+};
+
+template <class BLOCK_CIPHER>
+void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
+{
+ m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
+}
+
+template <class BLOCK_CIPHER>
+void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
+{
+ SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
+ const byte *key;
+ do
+ {
+ OS_GenerateRandomBlock(blocking, seed, seed.size());
+ if (length > 0)
+ {
+ SHA256 hash;
+ hash.Update(seed, seed.size());
+ hash.Update(input, length);
+ hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size()));
+ }
+ key = seed + BLOCK_CIPHER::BLOCKSIZE;
+ } // check that seed and key don't have same value
+ while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0);
+
+ Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL);
+}
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
+
+//! this is AutoSeededX917RNG\<AES\> in FIPS mode, otherwise it's AutoSeededRandomPool
+#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
+typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
+#else
+typedef AutoSeededRandomPool DefaultAutoSeededRNG;
+#endif
+
+NAMESPACE_END
+
+#endif
+
+#endif
diff --git a/lib/cryptopp/pch.cpp b/lib/cryptopp/pch.cpp
new file mode 100644
index 000000000..1d9f38c57
--- /dev/null
+++ b/lib/cryptopp/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/lib/cryptopp/pch.h b/lib/cryptopp/pch.h
new file mode 100644
index 000000000..418c39076
--- /dev/null
+++ b/lib/cryptopp/pch.h
@@ -0,0 +1,21 @@
+#ifndef CRYPTOPP_PCH_H
+#define CRYPTOPP_PCH_H
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+
+ #include "cpu.h"
+
+#else
+
+ #include "config.h"
+
+ #ifdef USE_PRECOMPILED_HEADERS
+ #include "simple.h"
+ #include "secblock.h"
+ #include "misc.h"
+ #include "smartptr.h"
+ #endif
+
+#endif
+
+#endif
diff --git a/lib/cryptopp/pkcspad.cpp b/lib/cryptopp/pkcspad.cpp
new file mode 100644
index 000000000..e1f1d1e23
--- /dev/null
+++ b/lib/cryptopp/pkcspad.cpp
@@ -0,0 +1,124 @@
+// pkcspad.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_PKCSPAD_CPP // SunCC workaround: compiler could cause this file to be included twice
+#define CRYPTOPP_PKCSPAD_CPP
+
+#include "pkcspad.h"
+#include <assert.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// more in dll.cpp
+template<> const byte PKCS_DigestDecoration<Weak1::MD2>::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,0x04,0x10};
+template<> const unsigned int PKCS_DigestDecoration<Weak1::MD2>::length = sizeof(PKCS_DigestDecoration<Weak1::MD2>::decoration);
+
+template<> const byte PKCS_DigestDecoration<Weak1::MD5>::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10};
+template<> const unsigned int PKCS_DigestDecoration<Weak1::MD5>::length = sizeof(PKCS_DigestDecoration<Weak1::MD5>::decoration);
+
+template<> const byte PKCS_DigestDecoration<RIPEMD160>::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14};
+template<> const unsigned int PKCS_DigestDecoration<RIPEMD160>::length = sizeof(PKCS_DigestDecoration<RIPEMD160>::decoration);
+
+template<> const byte PKCS_DigestDecoration<Tiger>::decoration[] = {0x30,0x29,0x30,0x0D,0x06,0x09,0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0C,0x02,0x05,0x00,0x04,0x18};
+template<> const unsigned int PKCS_DigestDecoration<Tiger>::length = sizeof(PKCS_DigestDecoration<Tiger>::decoration);
+
+size_t PKCS_EncryptionPaddingScheme::MaxUnpaddedLength(size_t paddedLength) const
+{
+ return SaturatingSubtract(paddedLength/8, 10U);
+}
+
+void PKCS_EncryptionPaddingScheme::Pad(RandomNumberGenerator &rng, const byte *input, size_t inputLen, byte *pkcsBlock, size_t pkcsBlockLen, const NameValuePairs &parameters) const
+{
+ assert (inputLen <= MaxUnpaddedLength(pkcsBlockLen)); // this should be checked by caller
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ pkcsBlock[0] = 0;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ pkcsBlock[0] = 2; // block type 2
+
+ // pad with non-zero random bytes
+ for (unsigned i = 1; i < pkcsBlockLen-inputLen-1; i++)
+ pkcsBlock[i] = (byte)rng.GenerateWord32(1, 0xff);
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
+ memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, size_t pkcsBlockLen, byte *output, const NameValuePairs &parameters) const
+{
+ bool invalid = false;
+ size_t maxOutputLen = MaxUnpaddedLength(pkcsBlockLen);
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ invalid = (pkcsBlock[0] != 0) || invalid;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ // Require block type 2.
+ invalid = (pkcsBlock[0] != 2) || invalid;
+
+ // skip past the padding until we find the separator
+ size_t i=1;
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
+ }
+ assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
+
+ size_t outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return DecodingResult();
+
+ memcpy (output, pkcsBlock+i, outputLen);
+ return DecodingResult(outputLen);
+}
+
+// ********************************************************
+
+#ifndef CRYPTOPP_IMPORTS
+
+void PKCS1v15_SignatureMessageEncodingMethod::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
+
+ size_t pkcsBlockLen = representativeBitLength;
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ representative[0] = 0;
+ representative++;
+ }
+ pkcsBlockLen /= 8;
+
+ representative[0] = 1; // block type 1
+
+ unsigned int digestSize = hash.DigestSize();
+ byte *pPadding = representative + 1;
+ byte *pDigest = representative + pkcsBlockLen - digestSize;
+ byte *pHashId = pDigest - hashIdentifier.second;
+ byte *pSeparator = pHashId - 1;
+
+ // pad with 0xff
+ memset(pPadding, 0xff, pSeparator-pPadding);
+ *pSeparator = 0;
+ memcpy(pHashId, hashIdentifier.first, hashIdentifier.second);
+ hash.Final(pDigest);
+}
+
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/pkcspad.h b/lib/cryptopp/pkcspad.h
new file mode 100644
index 000000000..6371c7698
--- /dev/null
+++ b/lib/cryptopp/pkcspad.h
@@ -0,0 +1,94 @@
+#ifndef CRYPTOPP_PKCSPAD_H
+#define CRYPTOPP_PKCSPAD_H
+
+#include "cryptlib.h"
+#include "pubkey.h"
+
+#ifdef CRYPTOPP_IS_DLL
+#include "sha.h"
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! <a href="http://www.weidai.com/scan-mirror/ca.html#cem_PKCS1-1.5">EME-PKCS1-v1_5</a>
+class PKCS_EncryptionPaddingScheme : public PK_EncryptionMessageEncodingMethod
+{
+public:
+ static const char * StaticAlgorithmName() {return "EME-PKCS1-v1_5";}
+
+ size_t MaxUnpaddedLength(size_t paddedLength) const;
+ void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs &parameters) const;
+ DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs &parameters) const;
+};
+
+template <class H> class PKCS_DigestDecoration
+{
+public:
+ static const byte decoration[];
+ static const unsigned int length;
+};
+
+// PKCS_DigestDecoration can be instantiated with the following
+// classes as specified in PKCS#1 v2.0 and P1363a
+class SHA1;
+class RIPEMD160;
+class Tiger;
+class SHA224;
+class SHA256;
+class SHA384;
+class SHA512;
+namespace Weak1 {
+class MD2;
+class MD5;
+}
+// end of list
+
+#ifdef CRYPTOPP_IS_DLL
+CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration<SHA1>;
+CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration<SHA224>;
+CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration<SHA256>;
+CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration<SHA384>;
+CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration<SHA512>;
+#endif
+
+//! <a href="http://www.weidai.com/scan-mirror/sig.html#sem_PKCS1-1.5">EMSA-PKCS1-v1_5</a>
+class CRYPTOPP_DLL PKCS1v15_SignatureMessageEncodingMethod : public PK_DeterministicSignatureMessageEncodingMethod
+{
+public:
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA-PKCS1-v1_5";}
+
+ size_t MinRepresentativeBitLength(size_t hashIdentifierSize, size_t digestSize) const
+ {return 8 * (digestSize + hashIdentifierSize + 10);}
+
+ void ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const;
+
+ struct HashIdentifierLookup
+ {
+ template <class H> struct HashIdentifierLookup2
+ {
+ static HashIdentifier Lookup()
+ {
+ return HashIdentifier(PKCS_DigestDecoration<H>::decoration, PKCS_DigestDecoration<H>::length);
+ }
+ };
+ };
+};
+
+//! PKCS #1 version 1.5, for use with RSAES and RSASS
+/*! Only the following hash functions are supported by this signature standard:
+ \dontinclude pkcspad.h
+ \skip can be instantiated
+ \until end of list
+*/
+struct PKCS1v15 : public SignatureStandard, public EncryptionStandard
+{
+ typedef PKCS_EncryptionPaddingScheme EncryptionMessageEncodingMethod;
+ typedef PKCS1v15_SignatureMessageEncodingMethod SignatureMessageEncodingMethod;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/polynomi.cpp b/lib/cryptopp/polynomi.cpp
new file mode 100644
index 000000000..734cae926
--- /dev/null
+++ b/lib/cryptopp/polynomi.cpp
@@ -0,0 +1,577 @@
+// polynomi.cpp - written and placed in the public domain by Wei Dai
+
+// Part of the code for polynomial evaluation and interpolation
+// originally came from Hal Finney's public domain secsplit.c.
+
+#include "pch.h"
+#include "polynomi.h"
+#include "secblock.h"
+
+#include <sstream>
+#include <iostream>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T>
+void PolynomialOver<T>::Randomize(RandomNumberGenerator &rng, const RandomizationParameter &parameter, const Ring &ring)
+{
+ m_coefficients.resize(parameter.m_coefficientCount);
+ for (unsigned int i=0; i<m_coefficients.size(); ++i)
+ m_coefficients[i] = ring.RandomElement(rng, parameter.m_coefficientParameter);
+}
+
+template <class T>
+void PolynomialOver<T>::FromStr(const char *str, const Ring &ring)
+{
+ std::istringstream in((char *)str);
+ bool positive = true;
+ CoefficientType coef;
+ unsigned int power;
+
+ while (in)
+ {
+ std::ws(in);
+ if (in.peek() == 'x')
+ coef = ring.MultiplicativeIdentity();
+ else
+ in >> coef;
+
+ std::ws(in);
+ if (in.peek() == 'x')
+ {
+ in.get();
+ std::ws(in);
+ if (in.peek() == '^')
+ {
+ in.get();
+ in >> power;
+ }
+ else
+ power = 1;
+ }
+ else
+ power = 0;
+
+ if (!positive)
+ coef = ring.Inverse(coef);
+
+ SetCoefficient(power, coef, ring);
+
+ std::ws(in);
+ switch (in.get())
+ {
+ case '+':
+ positive = true;
+ break;
+ case '-':
+ positive = false;
+ break;
+ default:
+ return; // something's wrong with the input string
+ }
+ }
+}
+
+template <class T>
+unsigned int PolynomialOver<T>::CoefficientCount(const Ring &ring) const
+{
+ unsigned count = m_coefficients.size();
+ while (count && ring.Equal(m_coefficients[count-1], ring.Identity()))
+ count--;
+ const_cast<std::vector<CoefficientType> &>(m_coefficients).resize(count);
+ return count;
+}
+
+template <class T>
+typename PolynomialOver<T>::CoefficientType PolynomialOver<T>::GetCoefficient(unsigned int i, const Ring &ring) const
+{
+ return (i < m_coefficients.size()) ? m_coefficients[i] : ring.Identity();
+}
+
+template <class T>
+PolynomialOver<T>& PolynomialOver<T>::operator=(const PolynomialOver<T>& t)
+{
+ if (this != &t)
+ {
+ m_coefficients.resize(t.m_coefficients.size());
+ for (unsigned int i=0; i<m_coefficients.size(); i++)
+ m_coefficients[i] = t.m_coefficients[i];
+ }
+ return *this;
+}
+
+template <class T>
+PolynomialOver<T>& PolynomialOver<T>::Accumulate(const PolynomialOver<T>& t, const Ring &ring)
+{
+ unsigned int count = t.CoefficientCount(ring);
+
+ if (count > CoefficientCount(ring))
+ m_coefficients.resize(count, ring.Identity());
+
+ for (unsigned int i=0; i<count; i++)
+ ring.Accumulate(m_coefficients[i], t.GetCoefficient(i, ring));
+
+ return *this;
+}
+
+template <class T>
+PolynomialOver<T>& PolynomialOver<T>::Reduce(const PolynomialOver<T>& t, const Ring &ring)
+{
+ unsigned int count = t.CoefficientCount(ring);
+
+ if (count > CoefficientCount(ring))
+ m_coefficients.resize(count, ring.Identity());
+
+ for (unsigned int i=0; i<count; i++)
+ ring.Reduce(m_coefficients[i], t.GetCoefficient(i, ring));
+
+ return *this;
+}
+
+template <class T>
+typename PolynomialOver<T>::CoefficientType PolynomialOver<T>::EvaluateAt(const CoefficientType &x, const Ring &ring) const
+{
+ int degree = Degree(ring);
+
+ if (degree < 0)
+ return ring.Identity();
+
+ CoefficientType result = m_coefficients[degree];
+ for (int j=degree-1; j>=0; j--)
+ {
+ result = ring.Multiply(result, x);
+ ring.Accumulate(result, m_coefficients[j]);
+ }
+ return result;
+}
+
+template <class T>
+PolynomialOver<T>& PolynomialOver<T>::ShiftLeft(unsigned int n, const Ring &ring)
+{
+ unsigned int i = CoefficientCount(ring) + n;
+ m_coefficients.resize(i, ring.Identity());
+ while (i > n)
+ {
+ i--;
+ m_coefficients[i] = m_coefficients[i-n];
+ }
+ while (i)
+ {
+ i--;
+ m_coefficients[i] = ring.Identity();
+ }
+ return *this;
+}
+
+template <class T>
+PolynomialOver<T>& PolynomialOver<T>::ShiftRight(unsigned int n, const Ring &ring)
+{
+ unsigned int count = CoefficientCount(ring);
+ if (count > n)
+ {
+ for (unsigned int i=0; i<count-n; i++)
+ m_coefficients[i] = m_coefficients[i+n];
+ m_coefficients.resize(count-n, ring.Identity());
+ }
+ else
+ m_coefficients.resize(0, ring.Identity());
+ return *this;
+}
+
+template <class T>
+void PolynomialOver<T>::SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring)
+{
+ if (i >= m_coefficients.size())
+ m_coefficients.resize(i+1, ring.Identity());
+ m_coefficients[i] = value;
+}
+
+template <class T>
+void PolynomialOver<T>::Negate(const Ring &ring)
+{
+ unsigned int count = CoefficientCount(ring);
+ for (unsigned int i=0; i<count; i++)
+ m_coefficients[i] = ring.Inverse(m_coefficients[i]);
+}
+
+template <class T>
+void PolynomialOver<T>::swap(PolynomialOver<T> &t)
+{
+ m_coefficients.swap(t.m_coefficients);
+}
+
+template <class T>
+bool PolynomialOver<T>::Equals(const PolynomialOver<T>& t, const Ring &ring) const
+{
+ unsigned int count = CoefficientCount(ring);
+
+ if (count != t.CoefficientCount(ring))
+ return false;
+
+ for (unsigned int i=0; i<count; i++)
+ if (!ring.Equal(m_coefficients[i], t.m_coefficients[i]))
+ return false;
+
+ return true;
+}
+
+template <class T>
+PolynomialOver<T> PolynomialOver<T>::Plus(const PolynomialOver<T>& t, const Ring &ring) const
+{
+ unsigned int i;
+ unsigned int count = CoefficientCount(ring);
+ unsigned int tCount = t.CoefficientCount(ring);
+
+ if (count > tCount)
+ {
+ PolynomialOver<T> result(ring, count);
+
+ for (i=0; i<tCount; i++)
+ result.m_coefficients[i] = ring.Add(m_coefficients[i], t.m_coefficients[i]);
+ for (; i<count; i++)
+ result.m_coefficients[i] = m_coefficients[i];
+
+ return result;
+ }
+ else
+ {
+ PolynomialOver<T> result(ring, tCount);
+
+ for (i=0; i<count; i++)
+ result.m_coefficients[i] = ring.Add(m_coefficients[i], t.m_coefficients[i]);
+ for (; i<tCount; i++)
+ result.m_coefficients[i] = t.m_coefficients[i];
+
+ return result;
+ }
+}
+
+template <class T>
+PolynomialOver<T> PolynomialOver<T>::Minus(const PolynomialOver<T>& t, const Ring &ring) const
+{
+ unsigned int i;
+ unsigned int count = CoefficientCount(ring);
+ unsigned int tCount = t.CoefficientCount(ring);
+
+ if (count > tCount)
+ {
+ PolynomialOver<T> result(ring, count);
+
+ for (i=0; i<tCount; i++)
+ result.m_coefficients[i] = ring.Subtract(m_coefficients[i], t.m_coefficients[i]);
+ for (; i<count; i++)
+ result.m_coefficients[i] = m_coefficients[i];
+
+ return result;
+ }
+ else
+ {
+ PolynomialOver<T> result(ring, tCount);
+
+ for (i=0; i<count; i++)
+ result.m_coefficients[i] = ring.Subtract(m_coefficients[i], t.m_coefficients[i]);
+ for (; i<tCount; i++)
+ result.m_coefficients[i] = ring.Inverse(t.m_coefficients[i]);
+
+ return result;
+ }
+}
+
+template <class T>
+PolynomialOver<T> PolynomialOver<T>::Inverse(const Ring &ring) const
+{
+ unsigned int count = CoefficientCount(ring);
+ PolynomialOver<T> result(ring, count);
+
+ for (unsigned int i=0; i<count; i++)
+ result.m_coefficients[i] = ring.Inverse(m_coefficients[i]);
+
+ return result;
+}
+
+template <class T>
+PolynomialOver<T> PolynomialOver<T>::Times(const PolynomialOver<T>& t, const Ring &ring) const
+{
+ if (IsZero(ring) || t.IsZero(ring))
+ return PolynomialOver<T>();
+
+ unsigned int count1 = CoefficientCount(ring), count2 = t.CoefficientCount(ring);
+ PolynomialOver<T> result(ring, count1 + count2 - 1);
+
+ for (unsigned int i=0; i<count1; i++)
+ for (unsigned int j=0; j<count2; j++)
+ ring.Accumulate(result.m_coefficients[i+j], ring.Multiply(m_coefficients[i], t.m_coefficients[j]));
+
+ return result;
+}
+
+template <class T>
+PolynomialOver<T> PolynomialOver<T>::DividedBy(const PolynomialOver<T>& t, const Ring &ring) const
+{
+ PolynomialOver<T> remainder, quotient;
+ Divide(remainder, quotient, *this, t, ring);
+ return quotient;
+}
+
+template <class T>
+PolynomialOver<T> PolynomialOver<T>::Modulo(const PolynomialOver<T>& t, const Ring &ring) const
+{
+ PolynomialOver<T> remainder, quotient;
+ Divide(remainder, quotient, *this, t, ring);
+ return remainder;
+}
+
+template <class T>
+PolynomialOver<T> PolynomialOver<T>::MultiplicativeInverse(const Ring &ring) const
+{
+ return Degree(ring)==0 ? ring.MultiplicativeInverse(m_coefficients[0]) : ring.Identity();
+}
+
+template <class T>
+bool PolynomialOver<T>::IsUnit(const Ring &ring) const
+{
+ return Degree(ring)==0 && ring.IsUnit(m_coefficients[0]);
+}
+
+template <class T>
+std::istream& PolynomialOver<T>::Input(std::istream &in, const Ring &ring)
+{
+ char c;
+ unsigned int length = 0;
+ SecBlock<char> str(length + 16);
+ bool paren = false;
+
+ std::ws(in);
+
+ if (in.peek() == '(')
+ {
+ paren = true;
+ in.get();
+ }
+
+ do
+ {
+ in.read(&c, 1);
+ str[length++] = c;
+ if (length >= str.size())
+ str.Grow(length + 16);
+ }
+ // if we started with a left paren, then read until we find a right paren,
+ // otherwise read until the end of the line
+ while (in && ((paren && c != ')') || (!paren && c != '\n')));
+
+ str[length-1] = '\0';
+ *this = PolynomialOver<T>(str, ring);
+
+ return in;
+}
+
+template <class T>
+std::ostream& PolynomialOver<T>::Output(std::ostream &out, const Ring &ring) const
+{
+ unsigned int i = CoefficientCount(ring);
+ if (i)
+ {
+ bool firstTerm = true;
+
+ while (i--)
+ {
+ if (m_coefficients[i] != ring.Identity())
+ {
+ if (firstTerm)
+ {
+ firstTerm = false;
+ if (!i || !ring.Equal(m_coefficients[i], ring.MultiplicativeIdentity()))
+ out << m_coefficients[i];
+ }
+ else
+ {
+ CoefficientType inverse = ring.Inverse(m_coefficients[i]);
+ std::ostringstream pstr, nstr;
+
+ pstr << m_coefficients[i];
+ nstr << inverse;
+
+ if (pstr.str().size() <= nstr.str().size())
+ {
+ out << " + ";
+ if (!i || !ring.Equal(m_coefficients[i], ring.MultiplicativeIdentity()))
+ out << m_coefficients[i];
+ }
+ else
+ {
+ out << " - ";
+ if (!i || !ring.Equal(inverse, ring.MultiplicativeIdentity()))
+ out << inverse;
+ }
+ }
+
+ switch (i)
+ {
+ case 0:
+ break;
+ case 1:
+ out << "x";
+ break;
+ default:
+ out << "x^" << i;
+ }
+ }
+ }
+ }
+ else
+ {
+ out << ring.Identity();
+ }
+ return out;
+}
+
+template <class T>
+void PolynomialOver<T>::Divide(PolynomialOver<T> &r, PolynomialOver<T> &q, const PolynomialOver<T> &a, const PolynomialOver<T> &d, const Ring &ring)
+{
+ unsigned int i = a.CoefficientCount(ring);
+ const int dDegree = d.Degree(ring);
+
+ if (dDegree < 0)
+ throw DivideByZero();
+
+ r = a;
+ q.m_coefficients.resize(STDMAX(0, int(i - dDegree)));
+
+ while (i > (unsigned int)dDegree)
+ {
+ --i;
+ q.m_coefficients[i-dDegree] = ring.Divide(r.m_coefficients[i], d.m_coefficients[dDegree]);
+ for (int j=0; j<=dDegree; j++)
+ ring.Reduce(r.m_coefficients[i-dDegree+j], ring.Multiply(q.m_coefficients[i-dDegree], d.m_coefficients[j]));
+ }
+
+ r.CoefficientCount(ring); // resize r.m_coefficients
+}
+
+// ********************************************************
+
+// helper function for Interpolate() and InterpolateAt()
+template <class T>
+void RingOfPolynomialsOver<T>::CalculateAlpha(std::vector<CoefficientType> &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const
+{
+ for (unsigned int j=0; j<n; ++j)
+ alpha[j] = y[j];
+
+ for (unsigned int k=1; k<n; ++k)
+ {
+ for (unsigned int j=n-1; j>=k; --j)
+ {
+ m_ring.Reduce(alpha[j], alpha[j-1]);
+
+ CoefficientType d = m_ring.Subtract(x[j], x[j-k]);
+ if (!m_ring.IsUnit(d))
+ throw InterpolationFailed();
+ alpha[j] = m_ring.Divide(alpha[j], d);
+ }
+ }
+}
+
+template <class T>
+typename RingOfPolynomialsOver<T>::Element RingOfPolynomialsOver<T>::Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const
+{
+ assert(n > 0);
+
+ std::vector<CoefficientType> alpha(n);
+ CalculateAlpha(alpha, x, y, n);
+
+ std::vector<CoefficientType> coefficients((size_t)n, m_ring.Identity());
+ coefficients[0] = alpha[n-1];
+
+ for (int j=n-2; j>=0; --j)
+ {
+ for (unsigned int i=n-j-1; i>0; i--)
+ coefficients[i] = m_ring.Subtract(coefficients[i-1], m_ring.Multiply(coefficients[i], x[j]));
+
+ coefficients[0] = m_ring.Subtract(alpha[j], m_ring.Multiply(coefficients[0], x[j]));
+ }
+
+ return PolynomialOver<T>(coefficients.begin(), coefficients.end());
+}
+
+template <class T>
+typename RingOfPolynomialsOver<T>::CoefficientType RingOfPolynomialsOver<T>::InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const
+{
+ assert(n > 0);
+
+ std::vector<CoefficientType> alpha(n);
+ CalculateAlpha(alpha, x, y, n);
+
+ CoefficientType result = alpha[n-1];
+ for (int j=n-2; j>=0; --j)
+ {
+ result = m_ring.Multiply(result, m_ring.Subtract(position, x[j]));
+ m_ring.Accumulate(result, alpha[j]);
+ }
+ return result;
+}
+
+template <class Ring, class Element>
+void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n)
+{
+ for (unsigned int i=0; i<n; i++)
+ {
+ Element t = ring.MultiplicativeIdentity();
+ for (unsigned int j=0; j<n; j++)
+ if (i != j)
+ t = ring.Multiply(t, ring.Subtract(x[i], x[j]));
+ w[i] = ring.MultiplicativeInverse(t);
+ }
+}
+
+template <class Ring, class Element>
+void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n)
+{
+ assert(n > 0);
+
+ std::vector<Element> a(2*n-1);
+ unsigned int i;
+
+ for (i=0; i<n; i++)
+ a[n-1+i] = ring.Subtract(position, x[i]);
+
+ for (i=n-1; i>1; i--)
+ a[i-1] = ring.Multiply(a[2*i], a[2*i-1]);
+
+ a[0] = ring.MultiplicativeIdentity();
+
+ for (i=0; i<n-1; i++)
+ {
+ std::swap(a[2*i+1], a[2*i+2]);
+ a[2*i+1] = ring.Multiply(a[i], a[2*i+1]);
+ a[2*i+2] = ring.Multiply(a[i], a[2*i+2]);
+ }
+
+ for (i=0; i<n; i++)
+ v[i] = ring.Multiply(a[n-1+i], w[i]);
+}
+
+template <class Ring, class Element>
+Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n)
+{
+ Element result = ring.Identity();
+ for (unsigned int i=0; i<n; i++)
+ ring.Accumulate(result, ring.Multiply(y[i], v[i]));
+ return result;
+}
+
+// ********************************************************
+
+template <class T, int instance>
+const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::Zero()
+{
+ return Singleton<ThisType>().Ref();
+}
+
+template <class T, int instance>
+const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::One()
+{
+ return Singleton<ThisType, NewOnePolynomial>().Ref();
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/polynomi.h b/lib/cryptopp/polynomi.h
new file mode 100644
index 000000000..cddadaeaf
--- /dev/null
+++ b/lib/cryptopp/polynomi.h
@@ -0,0 +1,459 @@
+#ifndef CRYPTOPP_POLYNOMI_H
+#define CRYPTOPP_POLYNOMI_H
+
+/*! \file */
+
+#include "cryptlib.h"
+#include "misc.h"
+#include "algebra.h"
+
+#include <iosfwd>
+#include <vector>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! represents single-variable polynomials over arbitrary rings
+/*! \nosubgrouping */
+template <class T> class PolynomialOver
+{
+public:
+ //! \name ENUMS, EXCEPTIONS, and TYPEDEFS
+ //@{
+ //! division by zero exception
+ class DivideByZero : public Exception
+ {
+ public:
+ DivideByZero() : Exception(OTHER_ERROR, "PolynomialOver<T>: division by zero") {}
+ };
+
+ //! specify the distribution for randomization functions
+ class RandomizationParameter
+ {
+ public:
+ RandomizationParameter(unsigned int coefficientCount, const typename T::RandomizationParameter &coefficientParameter )
+ : m_coefficientCount(coefficientCount), m_coefficientParameter(coefficientParameter) {}
+
+ private:
+ unsigned int m_coefficientCount;
+ typename T::RandomizationParameter m_coefficientParameter;
+ friend class PolynomialOver<T>;
+ };
+
+ typedef T Ring;
+ typedef typename T::Element CoefficientType;
+ //@}
+
+ //! \name CREATORS
+ //@{
+ //! creates the zero polynomial
+ PolynomialOver() {}
+
+ //!
+ PolynomialOver(const Ring &ring, unsigned int count)
+ : m_coefficients((size_t)count, ring.Identity()) {}
+
+ //! copy constructor
+ PolynomialOver(const PolynomialOver<Ring> &t)
+ : m_coefficients(t.m_coefficients.size()) {*this = t;}
+
+ //! construct constant polynomial
+ PolynomialOver(const CoefficientType &element)
+ : m_coefficients(1, element) {}
+
+ //! construct polynomial with specified coefficients, starting from coefficient of x^0
+ template <typename Iterator> PolynomialOver(Iterator begin, Iterator end)
+ : m_coefficients(begin, end) {}
+
+ //! convert from string
+ PolynomialOver(const char *str, const Ring &ring) {FromStr(str, ring);}
+
+ //! convert from big-endian byte array
+ PolynomialOver(const byte *encodedPolynomialOver, unsigned int byteCount);
+
+ //! convert from Basic Encoding Rules encoded byte array
+ explicit PolynomialOver(const byte *BEREncodedPolynomialOver);
+
+ //! convert from BER encoded byte array stored in a BufferedTransformation object
+ explicit PolynomialOver(BufferedTransformation &bt);
+
+ //! create a random PolynomialOver<T>
+ PolynomialOver(RandomNumberGenerator &rng, const RandomizationParameter &parameter, const Ring &ring)
+ {Randomize(rng, parameter, ring);}
+ //@}
+
+ //! \name ACCESSORS
+ //@{
+ //! the zero polynomial will return a degree of -1
+ int Degree(const Ring &ring) const {return int(CoefficientCount(ring))-1;}
+ //!
+ unsigned int CoefficientCount(const Ring &ring) const;
+ //! return coefficient for x^i
+ CoefficientType GetCoefficient(unsigned int i, const Ring &ring) const;
+ //@}
+
+ //! \name MANIPULATORS
+ //@{
+ //!
+ PolynomialOver<Ring>& operator=(const PolynomialOver<Ring>& t);
+
+ //!
+ void Randomize(RandomNumberGenerator &rng, const RandomizationParameter &parameter, const Ring &ring);
+
+ //! set the coefficient for x^i to value
+ void SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring);
+
+ //!
+ void Negate(const Ring &ring);
+
+ //!
+ void swap(PolynomialOver<Ring> &t);
+ //@}
+
+
+ //! \name BASIC ARITHMETIC ON POLYNOMIALS
+ //@{
+ bool Equals(const PolynomialOver<Ring> &t, const Ring &ring) const;
+ bool IsZero(const Ring &ring) const {return CoefficientCount(ring)==0;}
+
+ PolynomialOver<Ring> Plus(const PolynomialOver<Ring>& t, const Ring &ring) const;
+ PolynomialOver<Ring> Minus(const PolynomialOver<Ring>& t, const Ring &ring) const;
+ PolynomialOver<Ring> Inverse(const Ring &ring) const;
+
+ PolynomialOver<Ring> Times(const PolynomialOver<Ring>& t, const Ring &ring) const;
+ PolynomialOver<Ring> DividedBy(const PolynomialOver<Ring>& t, const Ring &ring) const;
+ PolynomialOver<Ring> Modulo(const PolynomialOver<Ring>& t, const Ring &ring) const;
+ PolynomialOver<Ring> MultiplicativeInverse(const Ring &ring) const;
+ bool IsUnit(const Ring &ring) const;
+
+ PolynomialOver<Ring>& Accumulate(const PolynomialOver<Ring>& t, const Ring &ring);
+ PolynomialOver<Ring>& Reduce(const PolynomialOver<Ring>& t, const Ring &ring);
+
+ //!
+ PolynomialOver<Ring> Doubled(const Ring &ring) const {return Plus(*this, ring);}
+ //!
+ PolynomialOver<Ring> Squared(const Ring &ring) const {return Times(*this, ring);}
+
+ CoefficientType EvaluateAt(const CoefficientType &x, const Ring &ring) const;
+
+ PolynomialOver<Ring>& ShiftLeft(unsigned int n, const Ring &ring);
+ PolynomialOver<Ring>& ShiftRight(unsigned int n, const Ring &ring);
+
+ //! calculate r and q such that (a == d*q + r) && (0 <= degree of r < degree of d)
+ static void Divide(PolynomialOver<Ring> &r, PolynomialOver<Ring> &q, const PolynomialOver<Ring> &a, const PolynomialOver<Ring> &d, const Ring &ring);
+ //@}
+
+ //! \name INPUT/OUTPUT
+ //@{
+ std::istream& Input(std::istream &in, const Ring &ring);
+ std::ostream& Output(std::ostream &out, const Ring &ring) const;
+ //@}
+
+private:
+ void FromStr(const char *str, const Ring &ring);
+
+ std::vector<CoefficientType> m_coefficients;
+};
+
+//! Polynomials over a fixed ring
+/*! Having a fixed ring allows overloaded operators */
+template <class T, int instance> class PolynomialOverFixedRing : private PolynomialOver<T>
+{
+ typedef PolynomialOver<T> B;
+ typedef PolynomialOverFixedRing<T, instance> ThisType;
+
+public:
+ typedef T Ring;
+ typedef typename T::Element CoefficientType;
+ typedef typename B::DivideByZero DivideByZero;
+ typedef typename B::RandomizationParameter RandomizationParameter;
+
+ //! \name CREATORS
+ //@{
+ //! creates the zero polynomial
+ PolynomialOverFixedRing(unsigned int count = 0) : B(ms_fixedRing, count) {}
+
+ //! copy constructor
+ PolynomialOverFixedRing(const ThisType &t) : B(t) {}
+
+ explicit PolynomialOverFixedRing(const B &t) : B(t) {}
+
+ //! construct constant polynomial
+ PolynomialOverFixedRing(const CoefficientType &element) : B(element) {}
+
+ //! construct polynomial with specified coefficients, starting from coefficient of x^0
+ template <typename Iterator> PolynomialOverFixedRing(Iterator first, Iterator last)
+ : B(first, last) {}
+
+ //! convert from string
+ explicit PolynomialOverFixedRing(const char *str) : B(str, ms_fixedRing) {}
+
+ //! convert from big-endian byte array
+ PolynomialOverFixedRing(const byte *encodedPoly, unsigned int byteCount) : B(encodedPoly, byteCount) {}
+
+ //! convert from Basic Encoding Rules encoded byte array
+ explicit PolynomialOverFixedRing(const byte *BEREncodedPoly) : B(BEREncodedPoly) {}
+
+ //! convert from BER encoded byte array stored in a BufferedTransformation object
+ explicit PolynomialOverFixedRing(BufferedTransformation &bt) : B(bt) {}
+
+ //! create a random PolynomialOverFixedRing
+ PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter &parameter) : B(rng, parameter, ms_fixedRing) {}
+
+ static const ThisType &Zero();
+ static const ThisType &One();
+ //@}
+
+ //! \name ACCESSORS
+ //@{
+ //! the zero polynomial will return a degree of -1
+ int Degree() const {return B::Degree(ms_fixedRing);}
+ //! degree + 1
+ unsigned int CoefficientCount() const {return B::CoefficientCount(ms_fixedRing);}
+ //! return coefficient for x^i
+ CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);}
+ //! return coefficient for x^i
+ CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);}
+ //@}
+
+ //! \name MANIPULATORS
+ //@{
+ //!
+ ThisType& operator=(const ThisType& t) {B::operator=(t); return *this;}
+ //!
+ ThisType& operator+=(const ThisType& t) {Accumulate(t, ms_fixedRing); return *this;}
+ //!
+ ThisType& operator-=(const ThisType& t) {Reduce(t, ms_fixedRing); return *this;}
+ //!
+ ThisType& operator*=(const ThisType& t) {return *this = *this*t;}
+ //!
+ ThisType& operator/=(const ThisType& t) {return *this = *this/t;}
+ //!
+ ThisType& operator%=(const ThisType& t) {return *this = *this%t;}
+
+ //!
+ ThisType& operator<<=(unsigned int n) {ShiftLeft(n, ms_fixedRing); return *this;}
+ //!
+ ThisType& operator>>=(unsigned int n) {ShiftRight(n, ms_fixedRing); return *this;}
+
+ //! set the coefficient for x^i to value
+ void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, ms_fixedRing);}
+
+ //!
+ void Randomize(RandomNumberGenerator &rng, const RandomizationParameter &parameter) {B::Randomize(rng, parameter, ms_fixedRing);}
+
+ //!
+ void Negate() {B::Negate(ms_fixedRing);}
+
+ void swap(ThisType &t) {B::swap(t);}
+ //@}
+
+ //! \name UNARY OPERATORS
+ //@{
+ //!
+ bool operator!() const {return CoefficientCount()==0;}
+ //!
+ ThisType operator+() const {return *this;}
+ //!
+ ThisType operator-() const {return ThisType(Inverse(ms_fixedRing));}
+ //@}
+
+ //! \name BINARY OPERATORS
+ //@{
+ //!
+ friend ThisType operator>>(ThisType a, unsigned int n) {return ThisType(a>>=n);}
+ //!
+ friend ThisType operator<<(ThisType a, unsigned int n) {return ThisType(a<<=n);}
+ //@}
+
+ //! \name OTHER ARITHMETIC FUNCTIONS
+ //@{
+ //!
+ ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(ms_fixedRing));}
+ //!
+ bool IsUnit() const {return B::IsUnit(ms_fixedRing);}
+
+ //!
+ ThisType Doubled() const {return ThisType(B::Doubled(ms_fixedRing));}
+ //!
+ ThisType Squared() const {return ThisType(B::Squared(ms_fixedRing));}
+
+ CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, ms_fixedRing);}
+
+ //! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
+ static void Divide(ThisType &r, ThisType &q, const ThisType &a, const ThisType &d)
+ {B::Divide(r, q, a, d, ms_fixedRing);}
+ //@}
+
+ //! \name INPUT/OUTPUT
+ //@{
+ //!
+ friend std::istream& operator>>(std::istream& in, ThisType &a)
+ {return a.Input(in, ms_fixedRing);}
+ //!
+ friend std::ostream& operator<<(std::ostream& out, const ThisType &a)
+ {return a.Output(out, ms_fixedRing);}
+ //@}
+
+private:
+ struct NewOnePolynomial
+ {
+ ThisType * operator()() const
+ {
+ return new ThisType(ms_fixedRing.MultiplicativeIdentity());
+ }
+ };
+
+ static const Ring ms_fixedRing;
+};
+
+//! Ring of polynomials over another ring
+template <class T> class RingOfPolynomialsOver : public AbstractEuclideanDomain<PolynomialOver<T> >
+{
+public:
+ typedef T CoefficientRing;
+ typedef PolynomialOver<T> Element;
+ typedef typename Element::CoefficientType CoefficientType;
+ typedef typename Element::RandomizationParameter RandomizationParameter;
+
+ RingOfPolynomialsOver(const CoefficientRing &ring) : m_ring(ring) {}
+
+ Element RandomElement(RandomNumberGenerator &rng, const RandomizationParameter &parameter)
+ {return Element(rng, parameter, m_ring);}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return a.Equals(b, m_ring);}
+
+ const Element& Identity() const
+ {return this->result = m_ring.Identity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return this->result = a.Plus(b, m_ring);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {a.Accumulate(b, m_ring); return a;}
+
+ const Element& Inverse(const Element &a) const
+ {return this->result = a.Inverse(m_ring);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return this->result = a.Minus(b, m_ring);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a.Reduce(b, m_ring);}
+
+ const Element& Double(const Element &a) const
+ {return this->result = a.Doubled(m_ring);}
+
+ const Element& MultiplicativeIdentity() const
+ {return this->result = m_ring.MultiplicativeIdentity();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return this->result = a.Times(b, m_ring);}
+
+ const Element& Square(const Element &a) const
+ {return this->result = a.Squared(m_ring);}
+
+ bool IsUnit(const Element &a) const
+ {return a.IsUnit(m_ring);}
+
+ const Element& MultiplicativeInverse(const Element &a) const
+ {return this->result = a.MultiplicativeInverse(m_ring);}
+
+ const Element& Divide(const Element &a, const Element &b) const
+ {return this->result = a.DividedBy(b, m_ring);}
+
+ const Element& Mod(const Element &a, const Element &b) const
+ {return this->result = a.Modulo(b, m_ring);}
+
+ void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
+ {Element::Divide(r, q, a, d, m_ring);}
+
+ class InterpolationFailed : public Exception
+ {
+ public:
+ InterpolationFailed() : Exception(OTHER_ERROR, "RingOfPolynomialsOver<T>: interpolation failed") {}
+ };
+
+ Element Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
+
+ // a faster version of Interpolate(x, y, n).EvaluateAt(position)
+ CoefficientType InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
+/*
+ void PrepareBulkInterpolation(CoefficientType *w, const CoefficientType x[], unsigned int n) const;
+ void PrepareBulkInterpolationAt(CoefficientType *v, const CoefficientType &position, const CoefficientType x[], const CoefficientType w[], unsigned int n) const;
+ CoefficientType BulkInterpolateAt(const CoefficientType y[], const CoefficientType v[], unsigned int n) const;
+*/
+protected:
+ void CalculateAlpha(std::vector<CoefficientType> &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
+
+ CoefficientRing m_ring;
+};
+
+template <class Ring, class Element>
+void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n);
+template <class Ring, class Element>
+void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n);
+template <class Ring, class Element>
+Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n);
+
+//!
+template <class T, int instance>
+inline bool operator==(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return a.Equals(b, a.ms_fixedRing);}
+//!
+template <class T, int instance>
+inline bool operator!=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return !(a==b);}
+
+//!
+template <class T, int instance>
+inline bool operator> (const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return a.Degree() > b.Degree();}
+//!
+template <class T, int instance>
+inline bool operator>=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return a.Degree() >= b.Degree();}
+//!
+template <class T, int instance>
+inline bool operator< (const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return a.Degree() < b.Degree();}
+//!
+template <class T, int instance>
+inline bool operator<=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return a.Degree() <= b.Degree();}
+
+//!
+template <class T, int instance>
+inline CryptoPP::PolynomialOverFixedRing<T, instance> operator+(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Plus(b, a.ms_fixedRing));}
+//!
+template <class T, int instance>
+inline CryptoPP::PolynomialOverFixedRing<T, instance> operator-(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Minus(b, a.ms_fixedRing));}
+//!
+template <class T, int instance>
+inline CryptoPP::PolynomialOverFixedRing<T, instance> operator*(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Times(b, a.ms_fixedRing));}
+//!
+template <class T, int instance>
+inline CryptoPP::PolynomialOverFixedRing<T, instance> operator/(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.DividedBy(b, a.ms_fixedRing));}
+//!
+template <class T, int instance>
+inline CryptoPP::PolynomialOverFixedRing<T, instance> operator%(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
+ {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Modulo(b, a.ms_fixedRing));}
+
+NAMESPACE_END
+
+NAMESPACE_BEGIN(std)
+template<class T> inline void swap(CryptoPP::PolynomialOver<T> &a, CryptoPP::PolynomialOver<T> &b)
+{
+ a.swap(b);
+}
+template<class T, int i> inline void swap(CryptoPP::PolynomialOverFixedRing<T,i> &a, CryptoPP::PolynomialOverFixedRing<T,i> &b)
+{
+ a.swap(b);
+}
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/pssr.cpp b/lib/cryptopp/pssr.cpp
new file mode 100644
index 000000000..ccbe4ee27
--- /dev/null
+++ b/lib/cryptopp/pssr.cpp
@@ -0,0 +1,145 @@
+// pssr.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "pssr.h"
+#include <functional>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// more in dll.cpp
+template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
+template<> const byte EMSA2HashId<RIPEMD128>::id = 0x32;
+template<> const byte EMSA2HashId<Whirlpool>::id = 0x37;
+
+#ifndef CRYPTOPP_IMPORTS
+
+size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
+{
+ size_t saltLen = SaltLen(digestLength);
+ size_t minPadLen = MinPadLen(digestLength);
+ return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength);
+}
+
+size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
+{
+ if (AllowRecovery())
+ return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8;
+ return 0;
+}
+
+bool PSSR_MEM_Base::IsProbabilistic() const
+{
+ return SaltLen(1) > 0;
+}
+
+bool PSSR_MEM_Base::AllowNonrecoverablePart() const
+{
+ return true;
+}
+
+bool PSSR_MEM_Base::RecoverablePartFirst() const
+{
+ return false;
+}
+
+void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
+
+ const size_t u = hashIdentifier.second + 1;
+ const size_t representativeByteLength = BitsToBytes(representativeBitLength);
+ const size_t digestSize = hash.DigestSize();
+ const size_t saltSize = SaltLen(digestSize);
+ byte *const h = representative + representativeByteLength - u - digestSize;
+
+ SecByteBlock digest(digestSize), salt(saltSize);
+ hash.Final(digest);
+ rng.GenerateBlock(salt, saltSize);
+
+ // compute H = hash of M'
+ byte c[8];
+ PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
+ PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
+ hash.Update(c, 8);
+ hash.Update(recoverableMessage, recoverableMessageLength);
+ hash.Update(digest, digestSize);
+ hash.Update(salt, saltSize);
+ hash.Final(h);
+
+ // compute representative
+ GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
+ byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
+ xorStart[0] ^= 1;
+ xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
+ xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
+ memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
+ representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc;
+ if (representativeBitLength % 8 != 0)
+ representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
+}
+
+DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength,
+ byte *recoverableMessage) const
+{
+ assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
+
+ const size_t u = hashIdentifier.second + 1;
+ const size_t representativeByteLength = BitsToBytes(representativeBitLength);
+ const size_t digestSize = hash.DigestSize();
+ const size_t saltSize = SaltLen(digestSize);
+ const byte *const h = representative + representativeByteLength - u - digestSize;
+
+ SecByteBlock digest(digestSize);
+ hash.Final(digest);
+
+ DecodingResult result(0);
+ bool &valid = result.isValidCoding;
+ size_t &recoverableMessageLength = result.messageLength;
+
+ valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
+ valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid;
+
+ GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
+ if (representativeBitLength % 8 != 0)
+ representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
+
+ // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
+ byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
+ byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0));
+ recoverableMessageLength = salt-M-1;
+ if (*M == 0x01
+ && (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize)
+ && recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize))
+ {
+ memcpy(recoverableMessage, M+1, recoverableMessageLength);
+ }
+ else
+ {
+ recoverableMessageLength = 0;
+ valid = false;
+ }
+
+ // verify H = hash of M'
+ byte c[8];
+ PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
+ PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
+ hash.Update(c, 8);
+ hash.Update(recoverableMessage, recoverableMessageLength);
+ hash.Update(digest, digestSize);
+ hash.Update(salt, saltSize);
+ valid = hash.Verify(h) && valid;
+
+ if (!AllowRecovery() && valid && recoverableMessageLength != 0)
+ {throw NotImplemented("PSSR_MEM: message recovery disabled");}
+
+ return result;
+}
+
+#endif
+
+NAMESPACE_END
diff --git a/lib/cryptopp/pssr.h b/lib/cryptopp/pssr.h
new file mode 100644
index 000000000..6ec6936e5
--- /dev/null
+++ b/lib/cryptopp/pssr.h
@@ -0,0 +1,66 @@
+#ifndef CRYPTOPP_PSSR_H
+#define CRYPTOPP_PSSR_H
+
+#include "pubkey.h"
+#include "emsa2.h"
+
+#ifdef CRYPTOPP_IS_DLL
+#include "sha.h"
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+class CRYPTOPP_DLL PSSR_MEM_Base : public PK_RecoverableSignatureMessageEncodingMethod
+{
+ virtual bool AllowRecovery() const =0;
+ virtual size_t SaltLen(size_t hashLen) const =0;
+ virtual size_t MinPadLen(size_t hashLen) const =0;
+ virtual const MaskGeneratingFunction & GetMGF() const =0;
+
+public:
+ size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const;
+ size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const;
+ bool IsProbabilistic() const;
+ bool AllowNonrecoverablePart() const;
+ bool RecoverablePartFirst() const;
+ void ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const;
+ DecodingResult RecoverMessageFromRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength,
+ byte *recoverableMessage) const;
+};
+
+template <bool USE_HASH_ID> class PSSR_MEM_BaseWithHashId;
+template<> class PSSR_MEM_BaseWithHashId<true> : public EMSA2HashIdLookup<PSSR_MEM_Base> {};
+template<> class PSSR_MEM_BaseWithHashId<false> : public PSSR_MEM_Base {};
+
+template <bool ALLOW_RECOVERY, class MGF=P1363_MGF1, int SALT_LEN=-1, int MIN_PAD_LEN=0, bool USE_HASH_ID=false>
+class PSSR_MEM : public PSSR_MEM_BaseWithHashId<USE_HASH_ID>
+{
+ virtual bool AllowRecovery() const {return ALLOW_RECOVERY;}
+ virtual size_t SaltLen(size_t hashLen) const {return SALT_LEN < 0 ? hashLen : SALT_LEN;}
+ virtual size_t MinPadLen(size_t hashLen) const {return MIN_PAD_LEN < 0 ? hashLen : MIN_PAD_LEN;}
+ virtual const MaskGeneratingFunction & GetMGF() const {static MGF mgf; return mgf;}
+
+public:
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(ALLOW_RECOVERY ? "PSSR-" : "PSS-") + MGF::StaticAlgorithmName();}
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/sig.html#sem_PSSR-MGF1">PSSR-MGF1</a>
+struct PSSR : public SignatureStandard
+{
+ typedef PSSR_MEM<true> SignatureMessageEncodingMethod;
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/sig.html#sem_PSS-MGF1">PSS-MGF1</a>
+struct PSS : public SignatureStandard
+{
+ typedef PSSR_MEM<false> SignatureMessageEncodingMethod;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/pubkey.cpp b/lib/cryptopp/pubkey.cpp
new file mode 100644
index 000000000..1159e5343
--- /dev/null
+++ b/lib/cryptopp/pubkey.cpp
@@ -0,0 +1,165 @@
+// pubkey.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "pubkey.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart)
+{
+ ArraySink *sink;
+ HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength));
+ word32 counter = counterStart;
+ while (sink->AvailableSize() > 0)
+ {
+ filter.Put(input, inputLength);
+ filter.PutWord32(counter++);
+ filter.Put(derivationParams, derivationParamsLength);
+ filter.MessageEnd();
+ }
+}
+
+bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
+ ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
+ return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
+}
+
+bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const
+{
+ SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize()));
+ DecodingResult result = RecoverMessageFromRepresentative(
+ hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage);
+ return result.isValidCoding && result.messageLength == 0;
+}
+
+void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
+{
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ HashIdentifier id = GetHashIdentifier();
+ const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
+
+ if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
+ throw PK_SignatureScheme::KeyTooShort();
+
+ size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize());
+
+ if (maxRecoverableLength == 0)
+ {throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");}
+ if (recoverableMessageLength > maxRecoverableLength)
+ throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm");
+
+ ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
+ encoding.ProcessRecoverableMessage(
+ ma.AccessHash(),
+ recoverableMessage, recoverableMessageLength,
+ NULL, 0, ma.m_semisignature);
+}
+
+size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
+{
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ HashIdentifier id = GetHashIdentifier();
+ const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
+
+ if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
+ throw PK_SignatureScheme::KeyTooShort();
+
+ SecByteBlock representative(MessageRepresentativeLength());
+ encoding.ComputeMessageRepresentative(rng,
+ ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
+ ma.AccessHash(), id, ma.m_empty,
+ representative, MessageRepresentativeBitLength());
+ ma.m_empty = true;
+
+ Integer r(representative, representative.size());
+ size_t signatureLength = SignatureLength();
+ GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength);
+ return signatureLength;
+}
+
+void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
+{
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ HashIdentifier id = GetHashIdentifier();
+ const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
+
+ if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
+ throw PK_SignatureScheme::KeyTooShort();
+
+ ma.m_representative.New(MessageRepresentativeLength());
+ Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength));
+ if (x.BitCount() > MessageRepresentativeBitLength())
+ x = Integer::Zero(); // don't return false here to prevent timing attack
+ x.Encode(ma.m_representative, ma.m_representative.size());
+}
+
+bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
+{
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ HashIdentifier id = GetHashIdentifier();
+ const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
+
+ if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
+ throw PK_SignatureScheme::KeyTooShort();
+
+ bool result = encoding.VerifyMessageRepresentative(
+ ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength());
+ ma.m_empty = true;
+ return result;
+}
+
+DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
+{
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ HashIdentifier id = GetHashIdentifier();
+ const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
+
+ if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
+ throw PK_SignatureScheme::KeyTooShort();
+
+ DecodingResult result = encoding.RecoverMessageFromRepresentative(
+ ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage);
+ ma.m_empty = true;
+ return result;
+}
+
+DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
+{
+ if (ciphertextLength != FixedCiphertextLength())
+ throw InvalidArgument(AlgorithmName() + ": ciphertext length of " + IntToString(ciphertextLength) + " doesn't match the required length of " + IntToString(FixedCiphertextLength()) + " for this key");
+
+ SecByteBlock paddedBlock(PaddedBlockByteLength());
+ Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, ciphertextLength));
+ if (x.ByteCount() > paddedBlock.size())
+ x = Integer::Zero(); // don't return false here to prevent timing attack
+ x.Encode(paddedBlock, paddedBlock.size());
+ return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters);
+}
+
+void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
+{
+ if (plaintextLength > FixedMaxPlaintextLength())
+ {
+ if (FixedMaxPlaintextLength() < 1)
+ throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages");
+ else
+ throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key");
+ }
+
+ SecByteBlock paddedBlock(PaddedBlockByteLength());
+ GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters);
+ GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength());
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/pubkey.h b/lib/cryptopp/pubkey.h
new file mode 100644
index 000000000..3a3f3bcde
--- /dev/null
+++ b/lib/cryptopp/pubkey.h
@@ -0,0 +1,1678 @@
+// pubkey.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_PUBKEY_H
+#define CRYPTOPP_PUBKEY_H
+
+/** \file
+
+ This file contains helper classes/functions for implementing public key algorithms.
+
+ The class hierachies in this .h file tend to look like this:
+<pre>
+ x1
+ / \
+ y1 z1
+ | |
+ x2<y1> x2<z1>
+ | |
+ y2 z2
+ | |
+ x3<y2> x3<z2>
+ | |
+ y3 z3
+</pre>
+ - x1, y1, z1 are abstract interface classes defined in cryptlib.h
+ - x2, y2, z2 are implementations of the interfaces using "abstract policies", which
+ are pure virtual functions that should return interfaces to interchangeable algorithms.
+ These classes have "Base" suffixes.
+ - x3, y3, z3 hold actual algorithms and implement those virtual functions.
+ These classes have "Impl" suffixes.
+
+ The "TF_" prefix means an implementation using trapdoor functions on integers.
+ The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard).
+*/
+
+#include "modarith.h"
+#include "filters.h"
+#include "eprecomp.h"
+#include "fips140.h"
+#include "argnames.h"
+#include <memory>
+
+// VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file
+#undef INTERFACE
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds
+{
+public:
+ virtual ~TrapdoorFunctionBounds() {}
+
+ virtual Integer PreimageBound() const =0;
+ virtual Integer ImageBound() const =0;
+ virtual Integer MaxPreimage() const {return --PreimageBound();}
+ virtual Integer MaxImage() const {return --ImageBound();}
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds
+{
+public:
+ virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0;
+ virtual bool IsRandomized() const {return true;}
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction
+{
+public:
+ Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const
+ {return ApplyFunction(x);}
+ bool IsRandomized() const {return false;}
+
+ virtual Integer ApplyFunction(const Integer &x) const =0;
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse
+{
+public:
+ virtual ~RandomizedTrapdoorFunctionInverse() {}
+
+ virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
+ virtual bool IsRandomized() const {return true;}
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
+{
+public:
+ virtual ~TrapdoorFunctionInverse() {}
+
+ Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
+ {return CalculateInverse(rng, x);}
+ bool IsRandomized() const {return false;}
+
+ virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
+};
+
+// ********************************************************
+
+//! message encoding method for public key encryption
+class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod
+{
+public:
+ virtual ~PK_EncryptionMessageEncodingMethod() {}
+
+ virtual bool ParameterSupported(const char *name) const {return false;}
+
+ //! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus)
+ virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0;
+
+ virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs &parameters) const =0;
+
+ virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs &parameters) const =0;
+};
+
+// ********************************************************
+
+//! _
+template <class TFI, class MEI>
+class CRYPTOPP_NO_VTABLE TF_Base
+{
+protected:
+ virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0;
+
+ typedef TFI TrapdoorFunctionInterface;
+ virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0;
+
+ typedef MEI MessageEncodingInterface;
+ virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0;
+};
+
+// ********************************************************
+
+//! _
+template <class BASE>
+class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE
+{
+public:
+ size_t MaxPlaintextLength(size_t ciphertextLength) const
+ {return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;}
+ size_t CiphertextLength(size_t plaintextLength) const
+ {return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;}
+
+ virtual size_t FixedMaxPlaintextLength() const =0;
+ virtual size_t FixedCiphertextLength() const =0;
+};
+
+//! _
+template <class INTERFACE, class BASE>
+class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl<INTERFACE>, protected BASE
+{
+public:
+ bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);}
+ size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());}
+ size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();}
+
+protected:
+ size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());}
+ size_t PaddedBlockBitLength() const {return this->GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;}
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase<PK_Decryptor, TF_Base<TrapdoorFunctionInverse, PK_EncryptionMessageEncodingMethod> >
+{
+public:
+ DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase<PK_Encryptor, TF_Base<RandomizedTrapdoorFunction, PK_EncryptionMessageEncodingMethod> >
+{
+public:
+ void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+};
+
+// ********************************************************
+
+typedef std::pair<const byte *, size_t> HashIdentifier;
+
+//! interface for message encoding method for public key signature schemes
+class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod
+{
+public:
+ virtual ~PK_SignatureMessageEncodingMethod() {}
+
+ virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
+ {return 0;}
+ virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
+ {return 0;}
+
+ bool IsProbabilistic() const
+ {return true;}
+ bool AllowNonrecoverablePart() const
+ {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
+ virtual bool RecoverablePartFirst() const
+ {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
+
+ // for verification, DL
+ virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const {}
+
+ // for signature
+ virtual void ProcessRecoverableMessage(HashTransformation &hash,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ const byte *presignature, size_t presignatureLength,
+ SecByteBlock &semisignature) const
+ {
+ if (RecoverablePartFirst())
+ assert(!"ProcessRecoverableMessage() not implemented");
+ }
+
+ virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const =0;
+
+ virtual bool VerifyMessageRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const =0;
+
+ virtual DecodingResult RecoverMessageFromRepresentative( // for TF
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength,
+ byte *recoveredMessage) const
+ {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
+
+ virtual DecodingResult RecoverMessageFromSemisignature( // for DL
+ HashTransformation &hash, HashIdentifier hashIdentifier,
+ const byte *presignature, size_t presignatureLength,
+ const byte *semisignature, size_t semisignatureLength,
+ byte *recoveredMessage) const
+ {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
+
+ // VC60 workaround
+ struct HashIdentifierLookup
+ {
+ template <class H> struct HashIdentifierLookup2
+ {
+ static HashIdentifier CRYPTOPP_API Lookup()
+ {
+ return HashIdentifier((const byte *)NULL, 0);
+ }
+ };
+ };
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
+{
+public:
+ bool VerifyMessageRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const;
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
+{
+public:
+ bool VerifyMessageRepresentative(
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const;
+};
+
+class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod
+{
+public:
+ void ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const;
+};
+
+class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod
+{
+public:
+ void ComputeMessageRepresentative(RandomNumberGenerator &rng,
+ const byte *recoverableMessage, size_t recoverableMessageLength,
+ HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
+ byte *representative, size_t representativeBitLength) const;
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator
+{
+public:
+ PK_MessageAccumulatorBase() : m_empty(true) {}
+
+ virtual HashTransformation & AccessHash() =0;
+
+ void Update(const byte *input, size_t length)
+ {
+ AccessHash().Update(input, length);
+ m_empty = m_empty && length == 0;
+ }
+
+ SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature;
+ Integer m_k, m_s;
+ bool m_empty;
+};
+
+template <class HASH_ALGORITHM>
+class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM>
+{
+public:
+ HashTransformation & AccessHash() {return this->m_object;}
+};
+
+//! _
+template <class INTERFACE, class BASE>
+class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE
+{
+public:
+ size_t SignatureLength() const
+ {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();}
+ size_t MaxRecoverableLength() const
+ {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());}
+ size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
+ {return this->MaxRecoverableLength();}
+
+ bool IsProbabilistic() const
+ {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();}
+ bool AllowNonrecoverablePart() const
+ {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();}
+ bool RecoverablePartFirst() const
+ {return this->GetMessageEncodingInterface().RecoverablePartFirst();}
+
+protected:
+ size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
+ size_t MessageRepresentativeBitLength() const {return this->GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;}
+ virtual HashIdentifier GetHashIdentifier() const =0;
+ virtual size_t GetDigestSize() const =0;
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase<PK_Signer, TF_Base<RandomizedTrapdoorFunctionInverse, PK_SignatureMessageEncodingMethod> >
+{
+public:
+ void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const;
+ size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const;
+};
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase<PK_Verifier, TF_Base<TrapdoorFunction, PK_SignatureMessageEncodingMethod> >
+{
+public:
+ void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const;
+ bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const;
+ DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const;
+};
+
+// ********************************************************
+
+//! _
+template <class T1, class T2, class T3>
+struct TF_CryptoSchemeOptions
+{
+ typedef T1 AlgorithmInfo;
+ typedef T2 Keys;
+ typedef typename Keys::PrivateKey PrivateKey;
+ typedef typename Keys::PublicKey PublicKey;
+ typedef T3 MessageEncodingMethod;
+};
+
+//! _
+template <class T1, class T2, class T3, class T4>
+struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions<T1, T2, T3>
+{
+ typedef T4 HashFunction;
+};
+
+//! _
+template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
+class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
+{
+public:
+ typedef SCHEME_OPTIONS SchemeOptions;
+ typedef KEY_CLASS KeyClass;
+
+ PublicKey & AccessPublicKey() {return AccessKey();}
+ const PublicKey & GetPublicKey() const {return GetKey();}
+
+ PrivateKey & AccessPrivateKey() {return AccessKey();}
+ const PrivateKey & GetPrivateKey() const {return GetKey();}
+
+ virtual const KeyClass & GetKey() const =0;
+ virtual KeyClass & AccessKey() =0;
+
+ const KeyClass & GetTrapdoorFunction() const {return GetKey();}
+
+ PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
+ {
+ return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
+ }
+ PK_MessageAccumulator * NewVerificationAccumulator() const
+ {
+ return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
+ }
+
+protected:
+ const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const
+ {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
+ const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const
+ {return GetKey();}
+ const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const
+ {return GetKey();}
+
+ // for signature scheme
+ HashIdentifier GetHashIdentifier() const
+ {
+ typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction> L;
+ return L::Lookup();
+ }
+ size_t GetDigestSize() const
+ {
+ typedef CPP_TYPENAME SchemeOptions::HashFunction H;
+ return H::DIGESTSIZE;
+ }
+};
+
+//! _
+template <class BASE, class SCHEME_OPTIONS, class KEY>
+class TF_ObjectImplExtRef : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
+{
+public:
+ TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {}
+ void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;}
+
+ const KEY & GetKey() const {return *m_pKey;}
+ KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");}
+
+private:
+ const KEY * m_pKey;
+};
+
+//! _
+template <class BASE, class SCHEME_OPTIONS, class KEY_CLASS>
+class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY_CLASS>
+{
+public:
+ typedef KEY_CLASS KeyClass;
+
+ const KeyClass & GetKey() const {return m_trapdoorFunction;}
+ KeyClass & AccessKey() {return m_trapdoorFunction;}
+
+private:
+ KeyClass m_trapdoorFunction;
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class TF_DecryptorImpl : public TF_ObjectImpl<TF_DecryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
+{
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class TF_EncryptorImpl : public TF_ObjectImpl<TF_EncryptorBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
+{
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class TF_SignerImpl : public TF_ObjectImpl<TF_SignerBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
+{
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class TF_VerifierImpl : public TF_ObjectImpl<TF_VerifierBase, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
+{
+};
+
+// ********************************************************
+
+//! _
+class CRYPTOPP_NO_VTABLE MaskGeneratingFunction
+{
+public:
+ virtual ~MaskGeneratingFunction() {}
+ virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0;
+};
+
+CRYPTOPP_DLL void CRYPTOPP_API P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart);
+
+//! _
+class P1363_MGF1 : public MaskGeneratingFunction
+{
+public:
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "MGF1";}
+ void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const
+ {
+ P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULL, 0, mask, 0);
+ }
+};
+
+// ********************************************************
+
+//! _
+template <class H>
+class P1363_KDF2
+{
+public:
+ static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength)
+ {
+ H h;
+ P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1);
+ }
+};
+
+// ********************************************************
+
+//! to be thrown by DecodeElement and AgreeWithStaticPrivateKey
+class DL_BadElement : public InvalidDataFormat
+{
+public:
+ DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {}
+};
+
+//! interface for DL group parameters
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters
+{
+ typedef DL_GroupParameters<T> ThisClass;
+
+public:
+ typedef T Element;
+
+ DL_GroupParameters() : m_validationLevel(0) {}
+
+ // CryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const
+ {
+ if (!GetBasePrecomputation().IsInitialized())
+ return false;
+
+ if (m_validationLevel > level)
+ return true;
+
+ bool pass = ValidateGroup(rng, level);
+ pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation());
+
+ m_validationLevel = pass ? level+1 : 0;
+
+ return pass;
+ }
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ return GetValueHelper(this, name, valueType, pValue)
+ CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder)
+ CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator)
+ ;
+ }
+
+ bool SupportsPrecomputation() const {return true;}
+
+ void Precompute(unsigned int precomputationStorage=16)
+ {
+ AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage);
+ }
+
+ void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
+ {
+ AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation);
+ m_validationLevel = 0;
+ }
+
+ void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
+ {
+ GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation);
+ }
+
+ // non-inherited
+ virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());}
+ virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);}
+ virtual Element ExponentiateBase(const Integer &exponent) const
+ {
+ return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent);
+ }
+ virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const
+ {
+ Element result;
+ SimultaneousExponentiate(&result, base, &exponent, 1);
+ return result;
+ }
+
+ virtual const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const =0;
+ virtual const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const =0;
+ virtual DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() =0;
+ virtual const Integer & GetSubgroupOrder() const =0; // order of subgroup generated by base element
+ virtual Integer GetMaxExponent() const =0;
+ virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();} // one of these two needs to be overriden
+ virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();}
+ virtual unsigned int GetEncodedElementSize(bool reversible) const =0;
+ virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0;
+ virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0;
+ virtual Integer ConvertElementToInteger(const Element &element) const =0;
+ virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0;
+ virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const =0;
+ virtual bool FastSubgroupCheckAvailable() const =0;
+ virtual bool IsIdentity(const Element &element) const =0;
+ virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0;
+
+protected:
+ void ParametersChanged() {m_validationLevel = 0;}
+
+private:
+ mutable unsigned int m_validationLevel;
+};
+
+//! _
+template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element>, class BASE = DL_GroupParameters<CPP_TYPENAME GROUP_PRECOMP::Element> >
+class DL_GroupParametersImpl : public BASE
+{
+public:
+ typedef GROUP_PRECOMP GroupPrecomputation;
+ typedef typename GROUP_PRECOMP::Element Element;
+ typedef BASE_PRECOMP BasePrecomputation;
+
+ const DL_GroupPrecomputation<Element> & GetGroupPrecomputation() const {return m_groupPrecomputation;}
+ const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return m_gpc;}
+ DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return m_gpc;}
+
+protected:
+ GROUP_PRECOMP m_groupPrecomputation;
+ BASE_PRECOMP m_gpc;
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_Key
+{
+public:
+ virtual const DL_GroupParameters<T> & GetAbstractGroupParameters() const =0;
+ virtual DL_GroupParameters<T> & AccessAbstractGroupParameters() =0;
+};
+
+//! interface for DL public keys
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key<T>
+{
+ typedef DL_PublicKey<T> ThisClass;
+
+public:
+ typedef T Element;
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
+ CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement);
+ }
+
+ void AssignFrom(const NameValuePairs &source);
+
+ // non-inherited
+ virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());}
+ virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);}
+ virtual Element ExponentiatePublicElement(const Integer &exponent) const
+ {
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent);
+ }
+ virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const
+ {
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp);
+ }
+
+ virtual const DL_FixedBasePrecomputation<T> & GetPublicPrecomputation() const =0;
+ virtual DL_FixedBasePrecomputation<T> & AccessPublicPrecomputation() =0;
+};
+
+//! interface for DL private keys
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key<T>
+{
+ typedef DL_PrivateKey<T> ThisClass;
+
+public:
+ typedef T Element;
+
+ void MakePublicKey(DL_PublicKey<T> &pub) const
+ {
+ pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters());
+ pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent()));
+ }
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters())
+ CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent);
+ }
+
+ void AssignFrom(const NameValuePairs &source)
+ {
+ this->AccessAbstractGroupParameters().AssignFrom(source);
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent);
+ }
+
+ virtual const Integer & GetPrivateExponent() const =0;
+ virtual void SetPrivateExponent(const Integer &x) =0;
+};
+
+template <class T>
+void DL_PublicKey<T>::AssignFrom(const NameValuePairs &source)
+{
+ DL_PrivateKey<T> *pPrivateKey = NULL;
+ if (source.GetThisPointer(pPrivateKey))
+ pPrivateKey->MakePublicKey(*this);
+ else
+ {
+ this->AccessAbstractGroupParameters().AssignFrom(source);
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement);
+ }
+}
+
+class OID;
+
+//! _
+template <class PK, class GP, class O = OID>
+class DL_KeyImpl : public PK
+{
+public:
+ typedef GP GroupParameters;
+
+ O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();}
+// void BERDecode(BufferedTransformation &bt)
+// {PK::BERDecode(bt);}
+// void DEREncode(BufferedTransformation &bt) const
+// {PK::DEREncode(bt);}
+ bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
+ {AccessGroupParameters().BERDecode(bt); return true;}
+ bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
+ {GetGroupParameters().DEREncode(bt); return true;}
+
+ const GP & GetGroupParameters() const {return m_groupParameters;}
+ GP & AccessGroupParameters() {return m_groupParameters;}
+
+private:
+ GP m_groupParameters;
+};
+
+class X509PublicKey;
+class PKCS8PrivateKey;
+
+//! _
+template <class GP>
+class DL_PrivateKeyImpl : public DL_PrivateKey<CPP_TYPENAME GP::Element>, public DL_KeyImpl<PKCS8PrivateKey, GP>
+{
+public:
+ typedef typename GP::Element Element;
+
+ // GeneratableCryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const
+ {
+ bool pass = GetAbstractGroupParameters().Validate(rng, level);
+
+ const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder();
+ const Integer &x = GetPrivateExponent();
+
+ pass = pass && x.IsPositive() && x < q;
+ if (level >= 1)
+ pass = pass && Integer::Gcd(x, q) == Integer::One();
+ return pass;
+ }
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ return GetValueHelper<DL_PrivateKey<Element> >(this, name, valueType, pValue).Assignable();
+ }
+
+ void AssignFrom(const NameValuePairs &source)
+ {
+ AssignFromHelper<DL_PrivateKey<Element> >(this, source);
+ }
+
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
+ {
+ if (!params.GetThisObject(this->AccessGroupParameters()))
+ this->AccessGroupParameters().GenerateRandom(rng, params);
+// std::pair<const byte *, int> seed;
+ Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
+// Integer::ANY, Integer::Zero(), Integer::One(),
+// params.GetValue("DeterministicKeyGenerationSeed", seed) ? &seed : NULL);
+ SetPrivateExponent(x);
+ }
+
+ bool SupportsPrecomputation() const {return true;}
+
+ void Precompute(unsigned int precomputationStorage=16)
+ {AccessAbstractGroupParameters().Precompute(precomputationStorage);}
+
+ void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
+ {AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);}
+
+ void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
+ {GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);}
+
+ // DL_Key
+ const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
+ DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
+
+ // DL_PrivateKey
+ const Integer & GetPrivateExponent() const {return m_x;}
+ void SetPrivateExponent(const Integer &x) {m_x = x;}
+
+ // PKCS8PrivateKey
+ void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t)
+ {m_x.BERDecode(bt);}
+ void DEREncodePrivateKey(BufferedTransformation &bt) const
+ {m_x.DEREncode(bt);}
+
+private:
+ Integer m_x;
+};
+
+//! _
+template <class BASE, class SIGNATURE_SCHEME>
+class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE
+{
+public:
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
+ {
+ BASE::GenerateRandom(rng, params);
+
+ if (FIPS_140_2_ComplianceEnabled())
+ {
+ typename SIGNATURE_SCHEME::Signer signer(*this);
+ typename SIGNATURE_SCHEME::Verifier verifier(signer);
+ SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);
+ }
+ }
+};
+
+//! _
+template <class GP>
+class DL_PublicKeyImpl : public DL_PublicKey<typename GP::Element>, public DL_KeyImpl<X509PublicKey, GP>
+{
+public:
+ typedef typename GP::Element Element;
+
+ // CryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const
+ {
+ bool pass = GetAbstractGroupParameters().Validate(rng, level);
+ pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation());
+ return pass;
+ }
+
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+ {
+ return GetValueHelper<DL_PublicKey<Element> >(this, name, valueType, pValue).Assignable();
+ }
+
+ void AssignFrom(const NameValuePairs &source)
+ {
+ AssignFromHelper<DL_PublicKey<Element> >(this, source);
+ }
+
+ bool SupportsPrecomputation() const {return true;}
+
+ void Precompute(unsigned int precomputationStorage=16)
+ {
+ AccessAbstractGroupParameters().Precompute(precomputationStorage);
+ AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage);
+ }
+
+ void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
+ {
+ AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);
+ AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
+ }
+
+ void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
+ {
+ GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);
+ GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation);
+ }
+
+ // DL_Key
+ const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return this->GetGroupParameters();}
+ DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return this->AccessGroupParameters();}
+
+ // DL_PublicKey
+ const DL_FixedBasePrecomputation<Element> & GetPublicPrecomputation() const {return m_ypc;}
+ DL_FixedBasePrecomputation<Element> & AccessPublicPrecomputation() {return m_ypc;}
+
+ // non-inherited
+ bool operator==(const DL_PublicKeyImpl<GP> &rhs) const
+ {return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();}
+
+private:
+ typename GP::BasePrecomputation m_ypc;
+};
+
+//! interface for Elgamal-like signature algorithms
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm
+{
+public:
+ virtual void Sign(const DL_GroupParameters<T> &params, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0;
+ virtual bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0;
+ virtual Integer RecoverPresignature(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &r, const Integer &s) const
+ {throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery");}
+ virtual size_t RLen(const DL_GroupParameters<T> &params) const
+ {return params.GetSubgroupOrder().ByteCount();}
+ virtual size_t SLen(const DL_GroupParameters<T> &params) const
+ {return params.GetSubgroupOrder().ByteCount();}
+};
+
+//! interface for DL key agreement algorithms
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm
+{
+public:
+ typedef T Element;
+
+ virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const =0;
+ virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0;
+};
+
+//! interface for key derivation algorithms used in DL cryptosystems
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm
+{
+public:
+ virtual bool ParameterSupported(const char *name) const {return false;}
+ virtual void Derive(const DL_GroupParameters<T> &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0;
+};
+
+//! interface for symmetric encryption algorithms used in DL cryptosystems
+class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm
+{
+public:
+ virtual bool ParameterSupported(const char *name) const {return false;}
+ virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0;
+ virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0;
+ virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0;
+ virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const =0;
+ virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const =0;
+};
+
+//! _
+template <class KI>
+class CRYPTOPP_NO_VTABLE DL_Base
+{
+protected:
+ typedef KI KeyInterface;
+ typedef typename KI::Element Element;
+
+ const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();}
+ DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();}
+
+ virtual KeyInterface & AccessKeyInterface() =0;
+ virtual const KeyInterface & GetKeyInterface() const =0;
+};
+
+//! _
+template <class INTERFACE, class KEY_INTERFACE>
+class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base<KEY_INTERFACE>
+{
+public:
+ size_t SignatureLength() const
+ {
+ return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters())
+ + GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters());
+ }
+ size_t MaxRecoverableLength() const
+ {return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());}
+ size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const
+ {assert(false); return 0;} // TODO
+
+ bool IsProbabilistic() const
+ {return true;}
+ bool AllowNonrecoverablePart() const
+ {return GetMessageEncodingInterface().AllowNonrecoverablePart();}
+ bool RecoverablePartFirst() const
+ {return GetMessageEncodingInterface().RecoverablePartFirst();}
+
+protected:
+ size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
+ size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();}
+
+ virtual const DL_ElgamalLikeSignatureAlgorithm<CPP_TYPENAME KEY_INTERFACE::Element> & GetSignatureAlgorithm() const =0;
+ virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0;
+ virtual HashIdentifier GetHashIdentifier() const =0;
+ virtual size_t GetDigestSize() const =0;
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase<PK_Signer, DL_PrivateKey<T> >
+{
+public:
+ // for validation testing
+ void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const
+ {
+ const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ const DL_PrivateKey<T> &key = this->GetKeyInterface();
+
+ r = params.ConvertElementToInteger(params.ExponentiateBase(k));
+ alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
+ }
+
+ void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
+ {
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
+ this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(),
+ recoverableMessage, recoverableMessageLength,
+ ma.m_presignature, ma.m_presignature.size(),
+ ma.m_semisignature);
+ }
+
+ size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
+ {
+ this->GetMaterial().DoQuickSanityCheck();
+
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ const DL_PrivateKey<T> &key = this->GetKeyInterface();
+
+ SecByteBlock representative(this->MessageRepresentativeLength());
+ this->GetMessageEncodingInterface().ComputeMessageRepresentative(
+ rng,
+ ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
+ ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
+ representative, this->MessageRepresentativeBitLength());
+ ma.m_empty = true;
+ Integer e(representative, representative.size());
+
+ // hash message digest into random number k to prevent reusing the same k on a different messages
+ // after virtual machine rollback
+ if (rng.CanIncorporateEntropy())
+ rng.IncorporateEntropy(representative, representative.size());
+ Integer k(rng, 1, params.GetSubgroupOrder()-1);
+ Integer r, s;
+ r = params.ConvertElementToInteger(params.ExponentiateBase(k));
+ alg.Sign(params, key.GetPrivateExponent(), k, e, r, s);
+
+ /*
+ Integer r, s;
+ if (this->MaxRecoverableLength() > 0)
+ r.Decode(ma.m_semisignature, ma.m_semisignature.size());
+ else
+ r.Decode(ma.m_presignature, ma.m_presignature.size());
+ alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s);
+ */
+
+ size_t rLen = alg.RLen(params);
+ r.Encode(signature, rLen);
+ s.Encode(signature+rLen, alg.SLen(params));
+
+ if (restart)
+ RestartMessageAccumulator(rng, ma);
+
+ return this->SignatureLength();
+ }
+
+protected:
+ void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const
+ {
+ // k needs to be generated before hashing for signature schemes with recovery
+ // but to defend against VM rollbacks we need to generate k after hashing.
+ // so this code is commented out, since no DL-based signature scheme with recovery
+ // has been implemented in Crypto++ anyway
+ /*
+ const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1);
+ ma.m_presignature.New(params.GetEncodedElementSize(false));
+ params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size());
+ */
+ }
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase<PK_Verifier, DL_PublicKey<T> >
+{
+public:
+ void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
+ {
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+
+ size_t rLen = alg.RLen(params);
+ ma.m_semisignature.Assign(signature, rLen);
+ ma.m_s.Decode(signature+rLen, alg.SLen(params));
+
+ this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size());
+ }
+
+ bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
+ {
+ this->GetMaterial().DoQuickSanityCheck();
+
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ const DL_PublicKey<T> &key = this->GetKeyInterface();
+
+ SecByteBlock representative(this->MessageRepresentativeLength());
+ this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
+ ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
+ representative, this->MessageRepresentativeBitLength());
+ ma.m_empty = true;
+ Integer e(representative, representative.size());
+
+ Integer r(ma.m_semisignature, ma.m_semisignature.size());
+ return alg.Verify(params, key, e, r, ma.m_s);
+ }
+
+ DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
+ {
+ this->GetMaterial().DoQuickSanityCheck();
+
+ PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
+ const DL_ElgamalLikeSignatureAlgorithm<T> &alg = this->GetSignatureAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ const DL_PublicKey<T> &key = this->GetKeyInterface();
+
+ SecByteBlock representative(this->MessageRepresentativeLength());
+ this->GetMessageEncodingInterface().ComputeMessageRepresentative(
+ NullRNG(),
+ ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
+ ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty,
+ representative, this->MessageRepresentativeBitLength());
+ ma.m_empty = true;
+ Integer e(representative, representative.size());
+
+ ma.m_presignature.New(params.GetEncodedElementSize(false));
+ Integer r(ma.m_semisignature, ma.m_semisignature.size());
+ alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size());
+
+ return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature(
+ ma.AccessHash(), this->GetHashIdentifier(),
+ ma.m_presignature, ma.m_presignature.size(),
+ ma.m_semisignature, ma.m_semisignature.size(),
+ recoveredMessage);
+ }
+};
+
+//! _
+template <class PK, class KI>
+class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base<KI>
+{
+public:
+ typedef typename DL_Base<KI>::Element Element;
+
+ size_t MaxPlaintextLength(size_t ciphertextLength) const
+ {
+ unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true);
+ return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen);
+ }
+
+ size_t CiphertextLength(size_t plaintextLength) const
+ {
+ size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength);
+ return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len;
+ }
+
+ bool ParameterSupported(const char *name) const
+ {return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);}
+
+protected:
+ virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
+ virtual const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const =0;
+ virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0;
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase<PK_Decryptor, DL_PrivateKey<T> >
+{
+public:
+ typedef T Element;
+
+ DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const
+ {
+ try
+ {
+ const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
+ const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
+ const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ const DL_PrivateKey<T> &key = this->GetKeyInterface();
+
+ Element q = params.DecodeElement(ciphertext, true);
+ size_t elementSize = params.GetEncodedElementSize(true);
+ ciphertext += elementSize;
+ ciphertextLength -= elementSize;
+
+ Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent());
+
+ SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength)));
+ derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
+
+ return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters);
+ }
+ catch (DL_BadElement &)
+ {
+ return DecodingResult();
+ }
+ }
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase<PK_Encryptor, DL_PublicKey<T> >
+{
+public:
+ typedef T Element;
+
+ void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const
+ {
+ const DL_KeyAgreementAlgorithm<T> &agreeAlg = this->GetKeyAgreementAlgorithm();
+ const DL_KeyDerivationAlgorithm<T> &derivAlg = this->GetKeyDerivationAlgorithm();
+ const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm();
+ const DL_GroupParameters<T> &params = this->GetAbstractGroupParameters();
+ const DL_PublicKey<T> &key = this->GetKeyInterface();
+
+ Integer x(rng, Integer::One(), params.GetMaxExponent());
+ Element q = params.ExponentiateBase(x);
+ params.EncodeElement(true, q, ciphertext);
+ unsigned int elementSize = params.GetEncodedElementSize(true);
+ ciphertext += elementSize;
+
+ Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x);
+
+ SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength));
+ derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters);
+
+ encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters);
+ }
+};
+
+//! _
+template <class T1, class T2>
+struct DL_SchemeOptionsBase
+{
+ typedef T1 AlgorithmInfo;
+ typedef T2 GroupParameters;
+ typedef typename GroupParameters::Element Element;
+};
+
+//! _
+template <class T1, class T2>
+struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase<T1, typename T2::PublicKey::GroupParameters>
+{
+ typedef T2 Keys;
+ typedef typename Keys::PrivateKey PrivateKey;
+ typedef typename Keys::PublicKey PublicKey;
+};
+
+//! _
+template <class T1, class T2, class T3, class T4, class T5>
+struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
+{
+ typedef T3 SignatureAlgorithm;
+ typedef T4 MessageEncodingMethod;
+ typedef T5 HashFunction;
+};
+
+//! _
+template <class T1, class T2, class T3, class T4, class T5>
+struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions<T1, T2>
+{
+ typedef T3 KeyAgreementAlgorithm;
+ typedef T4 KeyDerivationAlgorithm;
+ typedef T5 SymmetricEncryptionAlgorithm;
+};
+
+//! _
+template <class BASE, class SCHEME_OPTIONS, class KEY>
+class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
+{
+public:
+ typedef SCHEME_OPTIONS SchemeOptions;
+ typedef typename KEY::Element Element;
+
+ PrivateKey & AccessPrivateKey() {return m_key;}
+ PublicKey & AccessPublicKey() {return m_key;}
+
+ // KeyAccessor
+ const KEY & GetKey() const {return m_key;}
+ KEY & AccessKey() {return m_key;}
+
+protected:
+ typename BASE::KeyInterface & AccessKeyInterface() {return m_key;}
+ const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;}
+
+ // for signature scheme
+ HashIdentifier GetHashIdentifier() const
+ {
+ typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup;
+ return HashLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction>::Lookup();
+ }
+ size_t GetDigestSize() const
+ {
+ typedef CPP_TYPENAME SchemeOptions::HashFunction H;
+ return H::DIGESTSIZE;
+ }
+
+private:
+ KEY m_key;
+};
+
+//! _
+template <class BASE, class SCHEME_OPTIONS, class KEY>
+class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
+{
+public:
+ typedef typename KEY::Element Element;
+
+protected:
+ const DL_ElgamalLikeSignatureAlgorithm<Element> & GetSignatureAlgorithm() const
+ {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SignatureAlgorithm>().Ref();}
+ const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
+ {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyAgreementAlgorithm>().Ref();}
+ const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const
+ {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyDerivationAlgorithm>().Ref();}
+ const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const
+ {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SymmetricEncryptionAlgorithm>().Ref();}
+ HashIdentifier GetHashIdentifier() const
+ {return HashIdentifier();}
+ const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const
+ {return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class DL_SignerImpl : public DL_ObjectImpl<DL_SignerBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
+{
+public:
+ PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const
+ {
+ std::auto_ptr<PK_MessageAccumulatorBase> p(new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>);
+ this->RestartMessageAccumulator(rng, *p);
+ return p.release();
+ }
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class DL_VerifierImpl : public DL_ObjectImpl<DL_VerifierBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
+{
+public:
+ PK_MessageAccumulator * NewVerificationAccumulator() const
+ {
+ return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
+ }
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class DL_EncryptorImpl : public DL_ObjectImpl<DL_EncryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>
+{
+};
+
+//! _
+template <class SCHEME_OPTIONS>
+class DL_DecryptorImpl : public DL_ObjectImpl<DL_DecryptorBase<typename SCHEME_OPTIONS::Element>, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>
+{
+};
+
+// ********************************************************
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain
+{
+public:
+ typedef T Element;
+
+ CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
+ unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
+ unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
+ unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
+
+ void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
+ {
+ Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
+ x.Encode(privateKey, PrivateKeyLength());
+ }
+
+ void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
+ {
+ const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
+ Integer x(privateKey, PrivateKeyLength());
+ Element y = params.ExponentiateBase(x);
+ params.EncodeElement(true, y, publicKey);
+ }
+
+ bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const
+ {
+ try
+ {
+ const DL_GroupParameters<T> &params = GetAbstractGroupParameters();
+ Integer x(privateKey, PrivateKeyLength());
+ Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey);
+
+ Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey(
+ GetAbstractGroupParameters(), w, validateOtherPublicKey, x);
+ params.EncodeElement(false, z, agreedValue);
+ }
+ catch (DL_BadElement &)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();}
+
+protected:
+ virtual const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const =0;
+ virtual DL_GroupParameters<Element> & AccessAbstractGroupParameters() =0;
+ const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return const_cast<DL_SimpleKeyAgreementDomainBase<Element> *>(this)->AccessAbstractGroupParameters();}
+};
+
+enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION};
+typedef EnumToType<CofactorMultiplicationOption, NO_COFACTOR_MULTIPLICTION> NoCofactorMultiplication;
+typedef EnumToType<CofactorMultiplicationOption, COMPATIBLE_COFACTOR_MULTIPLICTION> CompatibleCofactorMultiplication;
+typedef EnumToType<CofactorMultiplicationOption, INCOMPATIBLE_COFACTOR_MULTIPLICTION> IncompatibleCofactorMultiplication;
+
+//! DH key agreement algorithm
+template <class ELEMENT, class COFACTOR_OPTION>
+class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm<ELEMENT>
+{
+public:
+ typedef ELEMENT Element;
+
+ static const char * CRYPTOPP_API StaticAlgorithmName()
+ {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";}
+
+ Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters<Element> &params, const DL_FixedBasePrecomputation<Element> &publicPrecomputation, const Integer &privateExponent) const
+ {
+ return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(),
+ COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent);
+ }
+
+ Element AgreeWithStaticPrivateKey(const DL_GroupParameters<Element> &params, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const
+ {
+ if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
+ {
+ const Integer &k = params.GetCofactor();
+ return params.ExponentiateElement(publicElement,
+ ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k);
+ }
+ else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION)
+ return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor());
+ else
+ {
+ assert(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION);
+
+ if (!validateOtherPublicKey)
+ return params.ExponentiateElement(publicElement, privateExponent);
+
+ if (params.FastSubgroupCheckAvailable())
+ {
+ if (!params.ValidateElement(2, publicElement, NULL))
+ throw DL_BadElement();
+ return params.ExponentiateElement(publicElement, privateExponent);
+ }
+ else
+ {
+ const Integer e[2] = {params.GetSubgroupOrder(), privateExponent};
+ Element r[2];
+ params.SimultaneousExponentiate(r, publicElement, e, 2);
+ if (!params.IsIdentity(r[0]))
+ throw DL_BadElement();
+ return r[1];
+ }
+ }
+ }
+};
+
+// ********************************************************
+
+//! A template implementing constructors for public key algorithm classes
+template <class BASE>
+class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE
+{
+public:
+ PK_FinalTemplate() {}
+
+ PK_FinalTemplate(const CryptoMaterial &key)
+ {this->AccessKey().AssignFrom(key);}
+
+ PK_FinalTemplate(BufferedTransformation &bt)
+ {this->AccessKey().BERDecode(bt);}
+
+ PK_FinalTemplate(const AsymmetricAlgorithm &algorithm)
+ {this->AccessKey().AssignFrom(algorithm.GetMaterial());}
+
+ PK_FinalTemplate(const Integer &v1)
+ {this->AccessKey().Initialize(v1);}
+
+#if (defined(_MSC_VER) && _MSC_VER < 1300)
+
+ template <class T1, class T2>
+ PK_FinalTemplate(T1 &v1, T2 &v2)
+ {this->AccessKey().Initialize(v1, v2);}
+
+ template <class T1, class T2, class T3>
+ PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3)
+ {this->AccessKey().Initialize(v1, v2, v3);}
+
+ template <class T1, class T2, class T3, class T4>
+ PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4)
+ {this->AccessKey().Initialize(v1, v2, v3, v4);}
+
+ template <class T1, class T2, class T3, class T4, class T5>
+ PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6>
+ PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
+ PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
+ PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
+
+#else
+
+ template <class T1, class T2>
+ PK_FinalTemplate(const T1 &v1, const T2 &v2)
+ {this->AccessKey().Initialize(v1, v2);}
+
+ template <class T1, class T2, class T3>
+ PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3)
+ {this->AccessKey().Initialize(v1, v2, v3);}
+
+ template <class T1, class T2, class T3, class T4>
+ PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
+ {this->AccessKey().Initialize(v1, v2, v3, v4);}
+
+ template <class T1, class T2, class T3, class T4, class T5>
+ PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6>
+ PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
+ PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
+ PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
+
+ template <class T1, class T2>
+ PK_FinalTemplate(T1 &v1, const T2 &v2)
+ {this->AccessKey().Initialize(v1, v2);}
+
+ template <class T1, class T2, class T3>
+ PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3)
+ {this->AccessKey().Initialize(v1, v2, v3);}
+
+ template <class T1, class T2, class T3, class T4>
+ PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
+ {this->AccessKey().Initialize(v1, v2, v3, v4);}
+
+ template <class T1, class T2, class T3, class T4, class T5>
+ PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6>
+ PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
+ PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
+
+ template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
+ PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8)
+ {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
+
+#endif
+};
+
+//! Base class for public key encryption standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms.
+struct EncryptionStandard {};
+
+//! Base class for public key signature standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms.
+struct SignatureStandard {};
+
+template <class STANDARD, class KEYS, class ALG_INFO>
+class TF_ES;
+
+//! Trapdoor Function Based Encryption Scheme
+template <class STANDARD, class KEYS, class ALG_INFO = TF_ES<STANDARD, KEYS, int> >
+class TF_ES : public KEYS
+{
+ typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod;
+
+public:
+ //! see EncryptionStandard for a list of standards
+ typedef STANDARD Standard;
+ typedef TF_CryptoSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod> SchemeOptions;
+
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();}
+
+ //! implements PK_Decryptor interface
+ typedef PK_FinalTemplate<TF_DecryptorImpl<SchemeOptions> > Decryptor;
+ //! implements PK_Encryptor interface
+ typedef PK_FinalTemplate<TF_EncryptorImpl<SchemeOptions> > Encryptor;
+};
+
+template <class STANDARD, class H, class KEYS, class ALG_INFO> // VC60 workaround: doesn't work if KEYS is first parameter
+class TF_SS;
+
+//! Trapdoor Function Based Signature Scheme
+template <class STANDARD, class H, class KEYS, class ALG_INFO = TF_SS<STANDARD, H, KEYS, int> > // VC60 workaround: doesn't work if KEYS is first parameter
+class TF_SS : public KEYS
+{
+public:
+ //! see SignatureStandard for a list of standards
+ typedef STANDARD Standard;
+ typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod;
+ typedef TF_SignatureSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod, H> SchemeOptions;
+
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
+
+ //! implements PK_Signer interface
+ typedef PK_FinalTemplate<TF_SignerImpl<SchemeOptions> > Signer;
+ //! implements PK_Verifier interface
+ typedef PK_FinalTemplate<TF_VerifierImpl<SchemeOptions> > Verifier;
+};
+
+template <class KEYS, class SA, class MEM, class H, class ALG_INFO>
+class DL_SS;
+
+//! Discrete Log Based Signature Scheme
+template <class KEYS, class SA, class MEM, class H, class ALG_INFO = DL_SS<KEYS, SA, MEM, H, int> >
+class DL_SS : public KEYS
+{
+ typedef DL_SignatureSchemeOptions<ALG_INFO, KEYS, SA, MEM, H> SchemeOptions;
+
+public:
+ static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";}
+
+ //! implements PK_Signer interface
+ typedef PK_FinalTemplate<DL_SignerImpl<SchemeOptions> > Signer;
+ //! implements PK_Verifier interface
+ typedef PK_FinalTemplate<DL_VerifierImpl<SchemeOptions> > Verifier;
+};
+
+//! Discrete Log Based Encryption Scheme
+template <class KEYS, class AA, class DA, class EA, class ALG_INFO>
+class DL_ES : public KEYS
+{
+ typedef DL_CryptoSchemeOptions<ALG_INFO, KEYS, AA, DA, EA> SchemeOptions;
+
+public:
+ //! implements PK_Decryptor interface
+ typedef PK_FinalTemplate<DL_DecryptorImpl<SchemeOptions> > Decryptor;
+ //! implements PK_Encryptor interface
+ typedef PK_FinalTemplate<DL_EncryptorImpl<SchemeOptions> > Encryptor;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/pwdbased.h b/lib/cryptopp/pwdbased.h
new file mode 100644
index 000000000..f755724b1
--- /dev/null
+++ b/lib/cryptopp/pwdbased.h
@@ -0,0 +1,214 @@
+// pwdbased.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_PWDBASED_H
+#define CRYPTOPP_PWDBASED_H
+
+#include "cryptlib.h"
+#include "hmac.h"
+#include "hrtimer.h"
+#include "integer.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! abstract base class for password based key derivation function
+class PasswordBasedKeyDerivationFunction
+{
+public:
+ virtual size_t MaxDerivedKeyLength() const =0;
+ virtual bool UsesPurposeByte() const =0;
+ //! derive key from password
+ /*! If timeInSeconds != 0, will iterate until time elapsed, as measured by ThreadUserTimer
+ Returns actual iteration count, which is equal to iterations if timeInSeconds == 0, and not less than iterations otherwise. */
+ virtual unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const =0;
+};
+
+//! PBKDF1 from PKCS #5, T should be a HashTransformation class
+template <class T>
+class PKCS5_PBKDF1 : public PasswordBasedKeyDerivationFunction
+{
+public:
+ size_t MaxDerivedKeyLength() const {return T::DIGESTSIZE;}
+ bool UsesPurposeByte() const {return false;}
+ // PKCS #5 says PBKDF1 should only take 8-byte salts. This implementation allows salts of any length.
+ unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const;
+};
+
+//! PBKDF2 from PKCS #5, T should be a HashTransformation class
+template <class T>
+class PKCS5_PBKDF2_HMAC : public PasswordBasedKeyDerivationFunction
+{
+public:
+ size_t MaxDerivedKeyLength() const {return 0xffffffffU;} // should multiply by T::DIGESTSIZE, but gets overflow that way
+ bool UsesPurposeByte() const {return false;}
+ unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const;
+};
+
+/*
+class PBKDF2Params
+{
+public:
+ SecByteBlock m_salt;
+ unsigned int m_interationCount;
+ ASNOptional<ASNUnsignedWrapper<word32> > m_keyLength;
+};
+*/
+
+template <class T>
+unsigned int PKCS5_PBKDF1<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
+{
+ assert(derivedLen <= MaxDerivedKeyLength());
+ assert(iterations > 0 || timeInSeconds > 0);
+
+ if (!iterations)
+ iterations = 1;
+
+ T hash;
+ hash.Update(password, passwordLen);
+ hash.Update(salt, saltLen);
+
+ SecByteBlock buffer(hash.DigestSize());
+ hash.Final(buffer);
+
+ unsigned int i;
+ ThreadUserTimer timer;
+
+ if (timeInSeconds)
+ timer.StartTimer();
+
+ for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
+ hash.CalculateDigest(buffer, buffer, buffer.size());
+
+ memcpy(derived, buffer, derivedLen);
+ return i;
+}
+
+template <class T>
+unsigned int PKCS5_PBKDF2_HMAC<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
+{
+ assert(derivedLen <= MaxDerivedKeyLength());
+ assert(iterations > 0 || timeInSeconds > 0);
+
+ if (!iterations)
+ iterations = 1;
+
+ HMAC<T> hmac(password, passwordLen);
+ SecByteBlock buffer(hmac.DigestSize());
+ ThreadUserTimer timer;
+
+ unsigned int i=1;
+ while (derivedLen > 0)
+ {
+ hmac.Update(salt, saltLen);
+ unsigned int j;
+ for (j=0; j<4; j++)
+ {
+ byte b = byte(i >> ((3-j)*8));
+ hmac.Update(&b, 1);
+ }
+ hmac.Final(buffer);
+
+ size_t segmentLen = STDMIN(derivedLen, buffer.size());
+ memcpy(derived, buffer, segmentLen);
+
+ if (timeInSeconds)
+ {
+ timeInSeconds = timeInSeconds / ((derivedLen + buffer.size() - 1) / buffer.size());
+ timer.StartTimer();
+ }
+
+ for (j=1; j<iterations || (timeInSeconds && (j%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); j++)
+ {
+ hmac.CalculateDigest(buffer, buffer, buffer.size());
+ xorbuf(derived, buffer, segmentLen);
+ }
+
+ if (timeInSeconds)
+ {
+ iterations = j;
+ timeInSeconds = 0;
+ }
+
+ derived += segmentLen;
+ derivedLen -= segmentLen;
+ i++;
+ }
+
+ return iterations;
+}
+
+//! PBKDF from PKCS #12, appendix B, T should be a HashTransformation class
+template <class T>
+class PKCS12_PBKDF : public PasswordBasedKeyDerivationFunction
+{
+public:
+ size_t MaxDerivedKeyLength() const {return size_t(0)-1;}
+ bool UsesPurposeByte() const {return true;}
+ unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const;
+};
+
+template <class T>
+unsigned int PKCS12_PBKDF<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
+{
+ assert(derivedLen <= MaxDerivedKeyLength());
+ assert(iterations > 0 || timeInSeconds > 0);
+
+ if (!iterations)
+ iterations = 1;
+
+ const size_t v = T::BLOCKSIZE; // v is in bytes rather than bits as in PKCS #12
+ const size_t DLen = v, SLen = RoundUpToMultipleOf(saltLen, v);
+ const size_t PLen = RoundUpToMultipleOf(passwordLen, v), ILen = SLen + PLen;
+ SecByteBlock buffer(DLen + SLen + PLen);
+ byte *D = buffer, *S = buffer+DLen, *P = buffer+DLen+SLen, *I = S;
+
+ memset(D, purpose, DLen);
+ size_t i;
+ for (i=0; i<SLen; i++)
+ S[i] = salt[i % saltLen];
+ for (i=0; i<PLen; i++)
+ P[i] = password[i % passwordLen];
+
+
+ T hash;
+ SecByteBlock Ai(T::DIGESTSIZE), B(v);
+ ThreadUserTimer timer;
+
+ while (derivedLen > 0)
+ {
+ hash.CalculateDigest(Ai, buffer, buffer.size());
+
+ if (timeInSeconds)
+ {
+ timeInSeconds = timeInSeconds / ((derivedLen + Ai.size() - 1) / Ai.size());
+ timer.StartTimer();
+ }
+
+ for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
+ hash.CalculateDigest(Ai, Ai, Ai.size());
+
+ if (timeInSeconds)
+ {
+ iterations = (unsigned int)i;
+ timeInSeconds = 0;
+ }
+
+ for (i=0; i<B.size(); i++)
+ B[i] = Ai[i % Ai.size()];
+
+ Integer B1(B, B.size());
+ ++B1;
+ for (i=0; i<ILen; i+=v)
+ (Integer(I+i, v) + B1).Encode(I+i, v);
+
+ size_t segmentLen = STDMIN(derivedLen, Ai.size());
+ memcpy(derived, Ai, segmentLen);
+ derived += segmentLen;
+ derivedLen -= segmentLen;
+ }
+
+ return iterations;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/queue.cpp b/lib/cryptopp/queue.cpp
new file mode 100644
index 000000000..ff2f0d316
--- /dev/null
+++ b/lib/cryptopp/queue.cpp
@@ -0,0 +1,565 @@
+// queue.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "queue.h"
+#include "filters.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const unsigned int s_maxAutoNodeSize = 16*1024;
+
+// this class for use by ByteQueue only
+class ByteQueueNode
+{
+public:
+ ByteQueueNode(size_t maxSize)
+ : buf(maxSize)
+ {
+ m_head = m_tail = 0;
+ next = 0;
+ }
+
+ inline size_t MaxSize() const {return buf.size();}
+
+ inline size_t CurrentSize() const
+ {
+ return m_tail-m_head;
+ }
+
+ inline bool UsedUp() const
+ {
+ return (m_head==MaxSize());
+ }
+
+ inline void Clear()
+ {
+ m_head = m_tail = 0;
+ }
+
+ inline size_t Put(const byte *begin, size_t length)
+ {
+ size_t l = STDMIN(length, MaxSize()-m_tail);
+ if (buf+m_tail != begin)
+ memcpy(buf+m_tail, begin, l);
+ m_tail += l;
+ return l;
+ }
+
+ inline size_t Peek(byte &outByte) const
+ {
+ if (m_tail==m_head)
+ return 0;
+
+ outByte=buf[m_head];
+ return 1;
+ }
+
+ inline size_t Peek(byte *target, size_t copyMax) const
+ {
+ size_t len = STDMIN(copyMax, m_tail-m_head);
+ memcpy(target, buf+m_head, len);
+ return len;
+ }
+
+ inline size_t CopyTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const
+ {
+ size_t len = m_tail-m_head;
+ target.ChannelPut(channel, buf+m_head, len);
+ return len;
+ }
+
+ inline size_t CopyTo(BufferedTransformation &target, size_t copyMax, const std::string &channel=DEFAULT_CHANNEL) const
+ {
+ size_t len = STDMIN(copyMax, m_tail-m_head);
+ target.ChannelPut(channel, buf+m_head, len);
+ return len;
+ }
+
+ inline size_t Get(byte &outByte)
+ {
+ size_t len = Peek(outByte);
+ m_head += len;
+ return len;
+ }
+
+ inline size_t Get(byte *outString, size_t getMax)
+ {
+ size_t len = Peek(outString, getMax);
+ m_head += len;
+ return len;
+ }
+
+ inline size_t TransferTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
+ {
+ size_t len = m_tail-m_head;
+ target.ChannelPutModifiable(channel, buf+m_head, len);
+ m_head = m_tail;
+ return len;
+ }
+
+ inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL)
+ {
+ size_t len = UnsignedMin(m_tail-m_head, transferMax);
+ target.ChannelPutModifiable(channel, buf+m_head, len);
+ m_head += len;
+ return len;
+ }
+
+ inline size_t Skip(size_t skipMax)
+ {
+ size_t len = STDMIN(skipMax, m_tail-m_head);
+ m_head += len;
+ return len;
+ }
+
+ inline byte operator[](size_t i) const
+ {
+ return buf[m_head+i];
+ }
+
+ ByteQueueNode *next;
+
+ SecByteBlock buf;
+ size_t m_head, m_tail;
+};
+
+// ********************************************************
+
+ByteQueue::ByteQueue(size_t nodeSize)
+ : m_lazyString(NULL), m_lazyLength(0)
+{
+ SetNodeSize(nodeSize);
+ m_head = m_tail = new ByteQueueNode(m_nodeSize);
+}
+
+void ByteQueue::SetNodeSize(size_t nodeSize)
+{
+ m_autoNodeSize = !nodeSize;
+ m_nodeSize = m_autoNodeSize ? 256 : nodeSize;
+}
+
+ByteQueue::ByteQueue(const ByteQueue &copy)
+ : m_lazyString(NULL)
+{
+ CopyFrom(copy);
+}
+
+void ByteQueue::CopyFrom(const ByteQueue &copy)
+{
+ m_lazyLength = 0;
+ m_autoNodeSize = copy.m_autoNodeSize;
+ m_nodeSize = copy.m_nodeSize;
+ m_head = m_tail = new ByteQueueNode(*copy.m_head);
+
+ for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
+ {
+ m_tail->next = new ByteQueueNode(*current);
+ m_tail = m_tail->next;
+ }
+
+ m_tail->next = NULL;
+
+ Put(copy.m_lazyString, copy.m_lazyLength);
+}
+
+ByteQueue::~ByteQueue()
+{
+ Destroy();
+}
+
+void ByteQueue::Destroy()
+{
+ for (ByteQueueNode *next, *current=m_head; current; current=next)
+ {
+ next=current->next;
+ delete current;
+ }
+}
+
+void ByteQueue::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256);
+ Clear();
+}
+
+lword ByteQueue::CurrentSize() const
+{
+ lword size=0;
+
+ for (ByteQueueNode *current=m_head; current; current=current->next)
+ size += current->CurrentSize();
+
+ return size + m_lazyLength;
+}
+
+bool ByteQueue::IsEmpty() const
+{
+ return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
+}
+
+void ByteQueue::Clear()
+{
+ for (ByteQueueNode *next, *current=m_head->next; current; current=next)
+ {
+ next=current->next;
+ delete current;
+ }
+
+ m_tail = m_head;
+ m_head->Clear();
+ m_head->next = NULL;
+ m_lazyLength = 0;
+}
+
+size_t ByteQueue::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ if (m_lazyLength > 0)
+ FinalizeLazyPut();
+
+ size_t len;
+ while ((len=m_tail->Put(inString, length)) < length)
+ {
+ inString += len;
+ length -= len;
+ if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize)
+ do
+ {
+ m_nodeSize *= 2;
+ }
+ while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize);
+ m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, length));
+ m_tail = m_tail->next;
+ }
+
+ return 0;
+}
+
+void ByteQueue::CleanupUsedNodes()
+{
+ while (m_head != m_tail && m_head->UsedUp())
+ {
+ ByteQueueNode *temp=m_head;
+ m_head=m_head->next;
+ delete temp;
+ }
+
+ if (m_head->CurrentSize() == 0)
+ m_head->Clear();
+}
+
+void ByteQueue::LazyPut(const byte *inString, size_t size)
+{
+ if (m_lazyLength > 0)
+ FinalizeLazyPut();
+
+ if (inString == m_tail->buf+m_tail->m_tail)
+ Put(inString, size);
+ else
+ {
+ m_lazyString = const_cast<byte *>(inString);
+ m_lazyLength = size;
+ m_lazyStringModifiable = false;
+ }
+}
+
+void ByteQueue::LazyPutModifiable(byte *inString, size_t size)
+{
+ if (m_lazyLength > 0)
+ FinalizeLazyPut();
+ m_lazyString = inString;
+ m_lazyLength = size;
+ m_lazyStringModifiable = true;
+}
+
+void ByteQueue::UndoLazyPut(size_t size)
+{
+ if (m_lazyLength < size)
+ throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large");
+
+ m_lazyLength -= size;
+}
+
+void ByteQueue::FinalizeLazyPut()
+{
+ size_t len = m_lazyLength;
+ m_lazyLength = 0;
+ if (len)
+ Put(m_lazyString, len);
+}
+
+size_t ByteQueue::Get(byte &outByte)
+{
+ if (m_head->Get(outByte))
+ {
+ if (m_head->UsedUp())
+ CleanupUsedNodes();
+ return 1;
+ }
+ else if (m_lazyLength > 0)
+ {
+ outByte = *m_lazyString++;
+ m_lazyLength--;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+size_t ByteQueue::Get(byte *outString, size_t getMax)
+{
+ ArraySink sink(outString, getMax);
+ return (size_t)TransferTo(sink, getMax);
+}
+
+size_t ByteQueue::Peek(byte &outByte) const
+{
+ if (m_head->Peek(outByte))
+ return 1;
+ else if (m_lazyLength > 0)
+ {
+ outByte = *m_lazyString;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+size_t ByteQueue::Peek(byte *outString, size_t peekMax) const
+{
+ ArraySink sink(outString, peekMax);
+ return (size_t)CopyTo(sink, peekMax);
+}
+
+size_t ByteQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ if (blocking)
+ {
+ lword bytesLeft = transferBytes;
+ for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
+ bytesLeft -= current->TransferTo(target, bytesLeft, channel);
+ CleanupUsedNodes();
+
+ size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
+ if (len)
+ {
+ if (m_lazyStringModifiable)
+ target.ChannelPutModifiable(channel, m_lazyString, len);
+ else
+ target.ChannelPut(channel, m_lazyString, len);
+ m_lazyString += len;
+ m_lazyLength -= len;
+ bytesLeft -= len;
+ }
+ transferBytes -= bytesLeft;
+ return 0;
+ }
+ else
+ {
+ Walker walker(*this);
+ size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
+ Skip(transferBytes);
+ return blockedBytes;
+ }
+}
+
+size_t ByteQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ Walker walker(*this);
+ walker.Skip(begin);
+ lword transferBytes = end-begin;
+ size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
+ begin += transferBytes;
+ return blockedBytes;
+}
+
+void ByteQueue::Unget(byte inByte)
+{
+ Unget(&inByte, 1);
+}
+
+void ByteQueue::Unget(const byte *inString, size_t length)
+{
+ size_t len = STDMIN(length, m_head->m_head);
+ length -= len;
+ m_head->m_head -= len;
+ memcpy(m_head->buf + m_head->m_head, inString + length, len);
+
+ if (length > 0)
+ {
+ ByteQueueNode *newHead = new ByteQueueNode(length);
+ newHead->next = m_head;
+ m_head = newHead;
+ m_head->Put(inString, length);
+ }
+}
+
+const byte * ByteQueue::Spy(size_t &contiguousSize) const
+{
+ contiguousSize = m_head->m_tail - m_head->m_head;
+ if (contiguousSize == 0 && m_lazyLength > 0)
+ {
+ contiguousSize = m_lazyLength;
+ return m_lazyString;
+ }
+ else
+ return m_head->buf + m_head->m_head;
+}
+
+byte * ByteQueue::CreatePutSpace(size_t &size)
+{
+ if (m_lazyLength > 0)
+ FinalizeLazyPut();
+
+ if (m_tail->m_tail == m_tail->MaxSize())
+ {
+ m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, size));
+ m_tail = m_tail->next;
+ }
+
+ size = m_tail->MaxSize() - m_tail->m_tail;
+ return m_tail->buf + m_tail->m_tail;
+}
+
+ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
+{
+ Destroy();
+ CopyFrom(rhs);
+ return *this;
+}
+
+bool ByteQueue::operator==(const ByteQueue &rhs) const
+{
+ const lword currentSize = CurrentSize();
+
+ if (currentSize != rhs.CurrentSize())
+ return false;
+
+ Walker walker1(*this), walker2(rhs);
+ byte b1, b2;
+
+ while (walker1.Get(b1) && walker2.Get(b2))
+ if (b1 != b2)
+ return false;
+
+ return true;
+}
+
+byte ByteQueue::operator[](lword i) const
+{
+ for (ByteQueueNode *current=m_head; current; current=current->next)
+ {
+ if (i < current->CurrentSize())
+ return (*current)[(size_t)i];
+
+ i -= current->CurrentSize();
+ }
+
+ assert(i < m_lazyLength);
+ return m_lazyString[i];
+}
+
+void ByteQueue::swap(ByteQueue &rhs)
+{
+ std::swap(m_autoNodeSize, rhs.m_autoNodeSize);
+ std::swap(m_nodeSize, rhs.m_nodeSize);
+ std::swap(m_head, rhs.m_head);
+ std::swap(m_tail, rhs.m_tail);
+ std::swap(m_lazyString, rhs.m_lazyString);
+ std::swap(m_lazyLength, rhs.m_lazyLength);
+ std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable);
+}
+
+// ********************************************************
+
+void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_node = m_queue.m_head;
+ m_position = 0;
+ m_offset = 0;
+ m_lazyString = m_queue.m_lazyString;
+ m_lazyLength = m_queue.m_lazyLength;
+}
+
+size_t ByteQueue::Walker::Get(byte &outByte)
+{
+ ArraySink sink(&outByte, 1);
+ return (size_t)TransferTo(sink, 1);
+}
+
+size_t ByteQueue::Walker::Get(byte *outString, size_t getMax)
+{
+ ArraySink sink(outString, getMax);
+ return (size_t)TransferTo(sink, getMax);
+}
+
+size_t ByteQueue::Walker::Peek(byte &outByte) const
+{
+ ArraySink sink(&outByte, 1);
+ return (size_t)CopyTo(sink, 1);
+}
+
+size_t ByteQueue::Walker::Peek(byte *outString, size_t peekMax) const
+{
+ ArraySink sink(outString, peekMax);
+ return (size_t)CopyTo(sink, peekMax);
+}
+
+size_t ByteQueue::Walker::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
+{
+ lword bytesLeft = transferBytes;
+ size_t blockedBytes = 0;
+
+ while (m_node)
+ {
+ size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset);
+ blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
+
+ if (blockedBytes)
+ goto done;
+
+ m_position += len;
+ bytesLeft -= len;
+
+ if (!bytesLeft)
+ {
+ m_offset += len;
+ goto done;
+ }
+
+ m_node = m_node->next;
+ m_offset = 0;
+ }
+
+ if (bytesLeft && m_lazyLength)
+ {
+ size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
+ blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking);
+ if (blockedBytes)
+ goto done;
+
+ m_lazyString += len;
+ m_lazyLength -= len;
+ bytesLeft -= len;
+ }
+
+done:
+ transferBytes -= bytesLeft;
+ return blockedBytes;
+}
+
+size_t ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
+{
+ Walker walker(*this);
+ walker.Skip(begin);
+ lword transferBytes = end-begin;
+ size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
+ begin += transferBytes;
+ return blockedBytes;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/queue.h b/lib/cryptopp/queue.h
new file mode 100644
index 000000000..ab89dbdf1
--- /dev/null
+++ b/lib/cryptopp/queue.h
@@ -0,0 +1,144 @@
+// specification file for an unlimited queue for storing bytes
+
+#ifndef CRYPTOPP_QUEUE_H
+#define CRYPTOPP_QUEUE_H
+
+#include "simple.h"
+//#include <algorithm>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/** The queue is implemented as a linked list of byte arrays, but you don't need to
+ know about that. So just ignore this next line. :) */
+class ByteQueueNode;
+
+//! Byte Queue
+class CRYPTOPP_DLL ByteQueue : public Bufferless<BufferedTransformation>
+{
+public:
+ ByteQueue(size_t nodeSize=0);
+ ByteQueue(const ByteQueue &copy);
+ ~ByteQueue();
+
+ lword MaxRetrievable() const
+ {return CurrentSize();}
+ bool AnyRetrievable() const
+ {return !IsEmpty();}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ byte * CreatePutSpace(size_t &size);
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
+
+ size_t Get(byte &outByte);
+ size_t Get(byte *outString, size_t getMax);
+
+ size_t Peek(byte &outByte) const;
+ size_t Peek(byte *outString, size_t peekMax) const;
+
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+
+ // these member functions are not inherited
+ void SetNodeSize(size_t nodeSize);
+
+ lword CurrentSize() const;
+ bool IsEmpty() const;
+
+ void Clear();
+
+ void Unget(byte inByte);
+ void Unget(const byte *inString, size_t length);
+
+ const byte * Spy(size_t &contiguousSize) const;
+
+ void LazyPut(const byte *inString, size_t size);
+ void LazyPutModifiable(byte *inString, size_t size);
+ void UndoLazyPut(size_t size);
+ void FinalizeLazyPut();
+
+ ByteQueue & operator=(const ByteQueue &rhs);
+ bool operator==(const ByteQueue &rhs) const;
+ bool operator!=(const ByteQueue &rhs) const {return !operator==(rhs);}
+ byte operator[](lword i) const;
+ void swap(ByteQueue &rhs);
+
+ class Walker : public InputRejecting<BufferedTransformation>
+ {
+ public:
+ Walker(const ByteQueue &queue)
+ : m_queue(queue) {Initialize();}
+
+ lword GetCurrentPosition() {return m_position;}
+
+ lword MaxRetrievable() const
+ {return m_queue.CurrentSize() - m_position;}
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+
+ size_t Get(byte &outByte);
+ size_t Get(byte *outString, size_t getMax);
+
+ size_t Peek(byte &outByte) const;
+ size_t Peek(byte *outString, size_t peekMax) const;
+
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
+
+ private:
+ const ByteQueue &m_queue;
+ const ByteQueueNode *m_node;
+ lword m_position;
+ size_t m_offset;
+ const byte *m_lazyString;
+ size_t m_lazyLength;
+ };
+
+ friend class Walker;
+
+private:
+ void CleanupUsedNodes();
+ void CopyFrom(const ByteQueue &copy);
+ void Destroy();
+
+ bool m_autoNodeSize;
+ size_t m_nodeSize;
+ ByteQueueNode *m_head, *m_tail;
+ byte *m_lazyString;
+ size_t m_lazyLength;
+ bool m_lazyStringModifiable;
+};
+
+//! use this to make sure LazyPut is finalized in event of exception
+class CRYPTOPP_DLL LazyPutter
+{
+public:
+ LazyPutter(ByteQueue &bq, const byte *inString, size_t size)
+ : m_bq(bq) {bq.LazyPut(inString, size);}
+ ~LazyPutter()
+ {try {m_bq.FinalizeLazyPut();} catch(...) {}}
+protected:
+ LazyPutter(ByteQueue &bq) : m_bq(bq) {}
+private:
+ ByteQueue &m_bq;
+};
+
+//! like LazyPutter, but does a LazyPutModifiable instead
+class LazyPutterModifiable : public LazyPutter
+{
+public:
+ LazyPutterModifiable(ByteQueue &bq, byte *inString, size_t size)
+ : LazyPutter(bq) {bq.LazyPutModifiable(inString, size);}
+};
+
+NAMESPACE_END
+
+#ifndef __BORLANDC__
+NAMESPACE_BEGIN(std)
+template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
+{
+ a.swap(b);
+}
+NAMESPACE_END
+#endif
+
+#endif
diff --git a/lib/cryptopp/rabin.cpp b/lib/cryptopp/rabin.cpp
new file mode 100644
index 000000000..d496333b5
--- /dev/null
+++ b/lib/cryptopp/rabin.cpp
@@ -0,0 +1,221 @@
+// rabin.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "rabin.h"
+#include "nbtheory.h"
+#include "asn.h"
+#include "sha.h"
+#include "modarith.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void RabinFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ m_n.BERDecode(seq);
+ m_r.BERDecode(seq);
+ m_s.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void RabinFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ m_n.DEREncode(seq);
+ m_r.DEREncode(seq);
+ m_s.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer RabinFunction::ApplyFunction(const Integer &in) const
+{
+ DoQuickSanityCheck();
+
+ Integer out = in.Squared()%m_n;
+ if (in.IsOdd())
+ out = out*m_r%m_n;
+ if (Jacobi(in, m_n)==-1)
+ out = out*m_s%m_n;
+ return out;
+}
+
+bool RabinFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = true;
+ pass = pass && m_n > Integer::One() && m_n%4 == 1;
+ pass = pass && m_r > Integer::One() && m_r < m_n;
+ pass = pass && m_s > Integer::One() && m_s < m_n;
+ if (level >= 1)
+ pass = pass && Jacobi(m_r, m_n) == -1 && Jacobi(m_s, m_n) == -1;
+ return pass;
+}
+
+bool RabinFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_GET_FUNCTION_ENTRY(QuadraticResidueModPrime1)
+ CRYPTOPP_GET_FUNCTION_ENTRY(QuadraticResidueModPrime2)
+ ;
+}
+
+void RabinFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_SET_FUNCTION_ENTRY(QuadraticResidueModPrime1)
+ CRYPTOPP_SET_FUNCTION_ENTRY(QuadraticResidueModPrime2)
+ ;
+}
+
+// *****************************************************************************
+// private key operations:
+
+// generate a random private key
+void InvertibleRabinFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ int modulusSize = 2048;
+ alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
+
+ if (modulusSize < 16)
+ throw InvalidArgument("InvertibleRabinFunction: specified modulus size is too small");
+
+ // VC70 workaround: putting these after primeParam causes overlapped stack allocation
+ bool rFound=false, sFound=false;
+ Integer t=2;
+
+ AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize)
+ ("EquivalentTo", 3)("Mod", 4);
+ m_p.GenerateRandom(rng, primeParam);
+ m_q.GenerateRandom(rng, primeParam);
+
+ while (!(rFound && sFound))
+ {
+ int jp = Jacobi(t, m_p);
+ int jq = Jacobi(t, m_q);
+
+ if (!rFound && jp==1 && jq==-1)
+ {
+ m_r = t;
+ rFound = true;
+ }
+
+ if (!sFound && jp==-1 && jq==1)
+ {
+ m_s = t;
+ sFound = true;
+ }
+
+ ++t;
+ }
+
+ m_n = m_p * m_q;
+ m_u = m_q.InverseMod(m_p);
+}
+
+void InvertibleRabinFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ m_n.BERDecode(seq);
+ m_r.BERDecode(seq);
+ m_s.BERDecode(seq);
+ m_p.BERDecode(seq);
+ m_q.BERDecode(seq);
+ m_u.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void InvertibleRabinFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ m_n.DEREncode(seq);
+ m_r.DEREncode(seq);
+ m_s.DEREncode(seq);
+ m_p.DEREncode(seq);
+ m_q.DEREncode(seq);
+ m_u.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer InvertibleRabinFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &in) const
+{
+ DoQuickSanityCheck();
+
+ ModularArithmetic modn(m_n);
+ Integer r(rng, Integer::One(), m_n - Integer::One());
+ r = modn.Square(r);
+ Integer r2 = modn.Square(r);
+ Integer c = modn.Multiply(in, r2); // blind
+
+ Integer cp=c%m_p, cq=c%m_q;
+
+ int jp = Jacobi(cp, m_p);
+ int jq = Jacobi(cq, m_q);
+
+ if (jq==-1)
+ {
+ cp = cp*EuclideanMultiplicativeInverse(m_r, m_p)%m_p;
+ cq = cq*EuclideanMultiplicativeInverse(m_r, m_q)%m_q;
+ }
+
+ if (jp==-1)
+ {
+ cp = cp*EuclideanMultiplicativeInverse(m_s, m_p)%m_p;
+ cq = cq*EuclideanMultiplicativeInverse(m_s, m_q)%m_q;
+ }
+
+ cp = ModularSquareRoot(cp, m_p);
+ cq = ModularSquareRoot(cq, m_q);
+
+ if (jp==-1)
+ cp = m_p-cp;
+
+ Integer out = CRT(cq, m_q, cp, m_p, m_u);
+
+ out = modn.Divide(out, r); // unblind
+
+ if ((jq==-1 && out.IsEven()) || (jq==1 && out.IsOdd()))
+ out = m_n-out;
+
+ return out;
+}
+
+bool InvertibleRabinFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = RabinFunction::Validate(rng, level);
+ pass = pass && m_p > Integer::One() && m_p%4 == 3 && m_p < m_n;
+ pass = pass && m_q > Integer::One() && m_q%4 == 3 && m_q < m_n;
+ pass = pass && m_u.IsPositive() && m_u < m_p;
+ if (level >= 1)
+ {
+ pass = pass && m_p * m_q == m_n;
+ pass = pass && m_u * m_q % m_p == 1;
+ pass = pass && Jacobi(m_r, m_p) == 1;
+ pass = pass && Jacobi(m_r, m_q) == -1;
+ pass = pass && Jacobi(m_s, m_p) == -1;
+ pass = pass && Jacobi(m_s, m_q) == 1;
+ }
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
+ return pass;
+}
+
+bool InvertibleRabinFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper<RabinFunction>(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+void InvertibleRabinFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper<RabinFunction>(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/rabin.h b/lib/cryptopp/rabin.h
new file mode 100644
index 000000000..1c9bcbb49
--- /dev/null
+++ b/lib/cryptopp/rabin.h
@@ -0,0 +1,107 @@
+#ifndef CRYPTOPP_RABIN_H
+#define CRYPTOPP_RABIN_H
+
+/** \file
+*/
+
+#include "oaep.h"
+#include "pssr.h"
+#include "integer.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class RabinFunction : public TrapdoorFunction, public PublicKey
+{
+ typedef RabinFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n, const Integer &r, const Integer &s)
+ {m_n = n; m_r = r; m_s = s;}
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ Integer ApplyFunction(const Integer &x) const;
+ Integer PreimageBound() const {return m_n;}
+ Integer ImageBound() const {return m_n;}
+
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ const Integer& GetModulus() const {return m_n;}
+ const Integer& GetQuadraticResidueModPrime1() const {return m_r;}
+ const Integer& GetQuadraticResidueModPrime2() const {return m_s;}
+
+ void SetModulus(const Integer &n) {m_n = n;}
+ void SetQuadraticResidueModPrime1(const Integer &r) {m_r = r;}
+ void SetQuadraticResidueModPrime2(const Integer &s) {m_s = s;}
+
+protected:
+ Integer m_n, m_r, m_s;
+};
+
+//! _
+class InvertibleRabinFunction : public RabinFunction, public TrapdoorFunctionInverse, public PrivateKey
+{
+ typedef InvertibleRabinFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n, const Integer &r, const Integer &s,
+ const Integer &p, const Integer &q, const Integer &u)
+ {m_n = n; m_r = r; m_s = s; m_p = p; m_q = q; m_u = u;}
+ void Initialize(RandomNumberGenerator &rng, unsigned int keybits)
+ {GenerateRandomWithKeySize(rng, keybits);}
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const;
+
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+ /*! parameters: (ModulusSize) */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+
+ const Integer& GetPrime1() const {return m_p;}
+ const Integer& GetPrime2() const {return m_q;}
+ const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;}
+
+ void SetPrime1(const Integer &p) {m_p = p;}
+ void SetPrime2(const Integer &q) {m_q = q;}
+ void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;}
+
+protected:
+ Integer m_p, m_q, m_u;
+};
+
+//! Rabin
+struct Rabin
+{
+ static std::string StaticAlgorithmName() {return "Rabin-Crypto++Variant";}
+ typedef RabinFunction PublicKey;
+ typedef InvertibleRabinFunction PrivateKey;
+};
+
+//! Rabin encryption
+template <class STANDARD>
+struct RabinES : public TF_ES<STANDARD, Rabin>
+{
+};
+
+//! Rabin signature
+template <class STANDARD, class H>
+struct RabinSS : public TF_SS<STANDARD, H, Rabin>
+{
+};
+
+// More typedefs for backwards compatibility
+class SHA1;
+typedef RabinES<OAEP<SHA1> >::Decryptor RabinDecryptor;
+typedef RabinES<OAEP<SHA1> >::Encryptor RabinEncryptor;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/randpool.cpp b/lib/cryptopp/randpool.cpp
new file mode 100644
index 000000000..a063c8996
--- /dev/null
+++ b/lib/cryptopp/randpool.cpp
@@ -0,0 +1,63 @@
+// randpool.cpp - written and placed in the public domain by Wei Dai
+// RandomPool used to follow the design of randpool in PGP 2.6.x,
+// but as of version 5.5 it has been redesigned to reduce the risk
+// of reusing random numbers after state rollback (which may occur
+// when running in a virtual machine like VMware).
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "randpool.h"
+#include "aes.h"
+#include "sha.h"
+#include "hrtimer.h"
+#include <time.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+RandomPool::RandomPool()
+ : m_pCipher(new AES::Encryption), m_keySet(false)
+{
+ memset(m_key, 0, m_key.SizeInBytes());
+ memset(m_seed, 0, m_seed.SizeInBytes());
+}
+
+void RandomPool::IncorporateEntropy(const byte *input, size_t length)
+{
+ SHA256 hash;
+ hash.Update(m_key, 32);
+ hash.Update(input, length);
+ hash.Final(m_key);
+ m_keySet = false;
+}
+
+void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
+{
+ if (size > 0)
+ {
+ if (!m_keySet)
+ m_pCipher->SetKey(m_key, 32);
+
+ Timer timer;
+ TimerWord tw = timer.GetCurrentTimerValue();
+ CRYPTOPP_COMPILE_ASSERT(sizeof(tw) <= 16);
+ *(TimerWord *)m_seed.data() += tw;
+
+ time_t t = time(NULL);
+ CRYPTOPP_COMPILE_ASSERT(sizeof(t) <= 8);
+ *(time_t *)(m_seed.data()+8) += t;
+
+ do
+ {
+ m_pCipher->ProcessBlock(m_seed);
+ size_t len = UnsignedMin(16, size);
+ target.ChannelPut(channel, m_seed, len);
+ size -= len;
+ } while (size > 0);
+ }
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/randpool.h b/lib/cryptopp/randpool.h
new file mode 100644
index 000000000..c25bc9bb1
--- /dev/null
+++ b/lib/cryptopp/randpool.h
@@ -0,0 +1,33 @@
+#ifndef CRYPTOPP_RANDPOOL_H
+#define CRYPTOPP_RANDPOOL_H
+
+#include "cryptlib.h"
+#include "filters.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Randomness Pool
+/*! This class can be used to generate cryptographic quality
+ pseudorandom bytes after seeding the pool with IncorporateEntropy() */
+class CRYPTOPP_DLL RandomPool : public RandomNumberGenerator, public NotCopyable
+{
+public:
+ RandomPool();
+
+ bool CanIncorporateEntropy() const {return true;}
+ void IncorporateEntropy(const byte *input, size_t length);
+ void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size);
+
+ // for backwards compatibility. use RandomNumberSource, RandomNumberStore, and RandomNumberSink for other BufferTransformation functionality
+ void Put(const byte *input, size_t length) {IncorporateEntropy(input, length);}
+
+private:
+ FixedSizeSecBlock<byte, 32> m_key;
+ FixedSizeSecBlock<byte, 16> m_seed;
+ member_ptr<BlockCipher> m_pCipher;
+ bool m_keySet;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/rdtables.cpp b/lib/cryptopp/rdtables.cpp
new file mode 100644
index 000000000..493793252
--- /dev/null
+++ b/lib/cryptopp/rdtables.cpp
@@ -0,0 +1,172 @@
+// Rijndael tables
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "rijndael.h"
+
+// VC60 workaround: gives a C4786 warning without this function
+// when runtime lib is set to multithread debug DLL
+// even though warning 4786 is disabled!
+void Rijndael_VC60Workaround()
+{
+}
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+*/
+
+const byte Rijndael::Base::Se[256] = {
+ 0x63, 0x7c, 0x77, 0x7b,
+ 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b,
+ 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d,
+ 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf,
+ 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26,
+ 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1,
+ 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3,
+ 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2,
+ 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a,
+ 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3,
+ 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed,
+ 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39,
+ 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb,
+ 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f,
+ 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f,
+ 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21,
+ 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec,
+ 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d,
+ 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc,
+ 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14,
+ 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a,
+ 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62,
+ 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d,
+ 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea,
+ 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e,
+ 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f,
+ 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66,
+ 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9,
+ 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11,
+ 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9,
+ 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d,
+ 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f,
+ 0xb0, 0x54, 0xbb, 0x16,
+};
+
+const byte Rijndael::Base::Sd[256] = {
+ 0x52, 0x09, 0x6a, 0xd5,
+ 0x30, 0x36, 0xa5, 0x38,
+ 0xbf, 0x40, 0xa3, 0x9e,
+ 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82,
+ 0x9b, 0x2f, 0xff, 0x87,
+ 0x34, 0x8e, 0x43, 0x44,
+ 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32,
+ 0xa6, 0xc2, 0x23, 0x3d,
+ 0xee, 0x4c, 0x95, 0x0b,
+ 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66,
+ 0x28, 0xd9, 0x24, 0xb2,
+ 0x76, 0x5b, 0xa2, 0x49,
+ 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64,
+ 0x86, 0x68, 0x98, 0x16,
+ 0xd4, 0xa4, 0x5c, 0xcc,
+ 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50,
+ 0xfd, 0xed, 0xb9, 0xda,
+ 0x5e, 0x15, 0x46, 0x57,
+ 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00,
+ 0x8c, 0xbc, 0xd3, 0x0a,
+ 0xf7, 0xe4, 0x58, 0x05,
+ 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f,
+ 0xca, 0x3f, 0x0f, 0x02,
+ 0xc1, 0xaf, 0xbd, 0x03,
+ 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41,
+ 0x4f, 0x67, 0xdc, 0xea,
+ 0x97, 0xf2, 0xcf, 0xce,
+ 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22,
+ 0xe7, 0xad, 0x35, 0x85,
+ 0xe2, 0xf9, 0x37, 0xe8,
+ 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71,
+ 0x1d, 0x29, 0xc5, 0x89,
+ 0x6f, 0xb7, 0x62, 0x0e,
+ 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b,
+ 0xc6, 0xd2, 0x79, 0x20,
+ 0x9a, 0xdb, 0xc0, 0xfe,
+ 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33,
+ 0x88, 0x07, 0xc7, 0x31,
+ 0xb1, 0x12, 0x10, 0x59,
+ 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9,
+ 0x19, 0xb5, 0x4a, 0x0d,
+ 0x2d, 0xe5, 0x7a, 0x9f,
+ 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d,
+ 0xae, 0x2a, 0xf5, 0xb0,
+ 0xc8, 0xeb, 0xbb, 0x3c,
+ 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e,
+ 0xba, 0x77, 0xd6, 0x26,
+ 0xe1, 0x69, 0x14, 0x63,
+ 0x55, 0x21, 0x0c, 0x7d,
+};
+
+const word32 Rijndael::Base::rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/resource.h b/lib/cryptopp/resource.h
new file mode 100644
index 000000000..861e22ba3
--- /dev/null
+++ b/lib/cryptopp/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by cryptopp.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/lib/cryptopp/rijndael.cpp b/lib/cryptopp/rijndael.cpp
new file mode 100644
index 000000000..c185032cf
--- /dev/null
+++ b/lib/cryptopp/rijndael.cpp
@@ -0,0 +1,1261 @@
+// rijndael.cpp - modified by Chris Morgan <cmorgan@wpi.edu>
+// and Wei Dai from Paulo Baretto's Rijndael implementation
+// The original code and all modifications are in the public domain.
+
+// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM rijndael.cpp" to generate MASM code
+
+/*
+July 2010: Added support for AES-NI instructions via compiler intrinsics.
+*/
+
+/*
+Feb 2009: The x86/x64 assembly code was rewritten in by Wei Dai to do counter mode
+caching, which was invented by Hongjun Wu and popularized by Daniel J. Bernstein
+and Peter Schwabe in their paper "New AES software speed records". The round
+function was also modified to include a trick similar to one in Brian Gladman's
+x86 assembly code, doing an 8-bit register move to minimize the number of
+register spills. Also switched to compressed tables and copying round keys to
+the stack.
+
+The C++ implementation now uses compressed tables if
+CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is defined.
+*/
+
+/*
+July 2006: Defense against timing attacks was added in by Wei Dai.
+
+The code now uses smaller tables in the first and last rounds,
+and preloads them into L1 cache before usage (by loading at least
+one element in each cache line).
+
+We try to delay subsequent accesses to each table (used in the first
+and last rounds) until all of the table has been preloaded. Hopefully
+the compiler isn't smart enough to optimize that code away.
+
+After preloading the table, we also try not to access any memory location
+other than the table and the stack, in order to prevent table entries from
+being unloaded from L1 cache, until that round is finished.
+(Some popular CPUs have 2-way associative caches.)
+*/
+
+// This is the original introductory comment:
+
+/**
+ * version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
+ */
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#include "rijndael.h"
+#include "misc.h"
+#include "cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+namespace rdtable {CRYPTOPP_ALIGN_DATA(16) word64 Te[256+2];}
+using namespace rdtable;
+#else
+static word64 Te[256];
+#endif
+static word64 Td[256];
+#else
+static word32 Te[256*4], Td[256*4];
+#endif
+static volatile bool s_TeFilled = false, s_TdFilled = false;
+
+// ************************* Portable Code ************************************
+
+#define QUARTER_ROUND(L, T, t, a, b, c, d) \
+ a ^= L(T, 3, byte(t)); t >>= 8;\
+ b ^= L(T, 2, byte(t)); t >>= 8;\
+ c ^= L(T, 1, byte(t)); t >>= 8;\
+ d ^= L(T, 0, t);
+
+#define QUARTER_ROUND_LE(t, a, b, c, d) \
+ tempBlock[a] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\
+ tempBlock[b] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\
+ tempBlock[c] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\
+ tempBlock[d] = ((byte *)(Te+t))[1];
+
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ #define QUARTER_ROUND_LD(t, a, b, c, d) \
+ tempBlock[a] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\
+ tempBlock[b] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\
+ tempBlock[c] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\
+ tempBlock[d] = ((byte *)(Td+t))[GetNativeByteOrder()*7];
+#else
+ #define QUARTER_ROUND_LD(t, a, b, c, d) \
+ tempBlock[a] = Sd[byte(t)]; t >>= 8;\
+ tempBlock[b] = Sd[byte(t)]; t >>= 8;\
+ tempBlock[c] = Sd[byte(t)]; t >>= 8;\
+ tempBlock[d] = Sd[t];
+#endif
+
+#define QUARTER_ROUND_E(t, a, b, c, d) QUARTER_ROUND(TL_M, Te, t, a, b, c, d)
+#define QUARTER_ROUND_D(t, a, b, c, d) QUARTER_ROUND(TL_M, Td, t, a, b, c, d)
+
+#ifdef IS_LITTLE_ENDIAN
+ #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, d, c, b, a)
+ #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, d, c, b, a)
+ #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ #define TL_F(T, i, x) (*(word32 *)((byte *)T + x*8 + (6-i)%4+1))
+ #define TL_M(T, i, x) (*(word32 *)((byte *)T + x*8 + (i+3)%4+1))
+ #else
+ #define TL_F(T, i, x) rotrFixed(T[x], (3-i)*8)
+ #define TL_M(T, i, x) T[i*256 + x]
+ #endif
+#else
+ #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, a, b, c, d)
+ #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, a, b, c, d)
+ #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ #define TL_F(T, i, x) (*(word32 *)((byte *)T + x*8 + (4-i)%4))
+ #define TL_M TL_F
+ #else
+ #define TL_F(T, i, x) rotrFixed(T[x], i*8)
+ #define TL_M(T, i, x) T[i*256 + x]
+ #endif
+#endif
+
+
+#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b))
+#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))
+#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))
+
+#define f3(x) (f2(x) ^ x)
+#define f9(x) (f8(x) ^ x)
+#define fb(x) (f8(x) ^ f2(x) ^ x)
+#define fd(x) (f8(x) ^ f4(x) ^ x)
+#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
+
+void Rijndael::Base::FillEncTable()
+{
+ for (int i=0; i<256; i++)
+ {
+ byte x = Se[i];
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ word32 y = word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24;
+ Te[i] = word64(y | f3(x))<<32 | y;
+#else
+ word32 y = f3(x) | word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24;
+ for (int j=0; j<4; j++)
+ {
+ Te[i+j*256] = y;
+ y = rotrFixed(y, 8);
+ }
+#endif
+ }
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ Te[256] = Te[257] = 0;
+#endif
+ s_TeFilled = true;
+}
+
+void Rijndael::Base::FillDecTable()
+{
+ for (int i=0; i<256; i++)
+ {
+ byte x = Sd[i];
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ word32 y = word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24;
+ Td[i] = word64(y | fb(x))<<32 | y | x;
+#else
+ word32 y = fb(x) | word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24;;
+ for (int j=0; j<4; j++)
+ {
+ Td[i+j*256] = y;
+ y = rotrFixed(y, 8);
+ }
+#endif
+ }
+ s_TdFilled = true;
+}
+
+void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &)
+{
+ AssertValidKeyLength(keylen);
+
+ m_rounds = keylen/4 + 6;
+ m_key.New(4*(m_rounds+1));
+
+ word32 *rk = m_key;
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE && (!defined(_MSC_VER) || _MSC_VER >= 1600 || CRYPTOPP_BOOL_X86)
+ // MSVC 2008 SP1 generates bad code for _mm_extract_epi32() when compiling for X64
+ if (HasAESNI())
+ {
+ static const word32 rcLE[] = {
+ 0x01, 0x02, 0x04, 0x08,
+ 0x10, 0x20, 0x40, 0x80,
+ 0x1B, 0x36, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+ };
+ const word32 *rc = rcLE;
+
+ __m128i temp = _mm_loadu_si128((__m128i *)(userKey+keylen-16));
+ memcpy(rk, userKey, keylen);
+
+ while (true)
+ {
+ rk[keylen/4] = rk[0] ^ _mm_extract_epi32(_mm_aeskeygenassist_si128(temp, 0), 3) ^ *(rc++);
+ rk[keylen/4+1] = rk[1] ^ rk[keylen/4];
+ rk[keylen/4+2] = rk[2] ^ rk[keylen/4+1];
+ rk[keylen/4+3] = rk[3] ^ rk[keylen/4+2];
+
+ if (rk + keylen/4 + 4 == m_key.end())
+ break;
+
+ if (keylen == 24)
+ {
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ temp = _mm_insert_epi32(temp, rk[11], 3);
+ }
+ else if (keylen == 32)
+ {
+ temp = _mm_insert_epi32(temp, rk[11], 3);
+ rk[12] = rk[ 4] ^ _mm_extract_epi32(_mm_aeskeygenassist_si128(temp, 0), 2);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+ temp = _mm_insert_epi32(temp, rk[15], 3);
+ }
+ else
+ temp = _mm_insert_epi32(temp, rk[7], 3);
+
+ rk += keylen/4;
+ }
+
+ if (!IsForwardTransformation())
+ {
+ rk = m_key;
+ unsigned int i, j;
+
+ std::swap(*(__m128i *)(rk), *(__m128i *)(rk+4*m_rounds));
+
+ for (i = 4, j = 4*m_rounds-4; i < j; i += 4, j -= 4)
+ {
+ temp = _mm_aesimc_si128(*(__m128i *)(rk+i));
+ *(__m128i *)(rk+i) = _mm_aesimc_si128(*(__m128i *)(rk+j));
+ *(__m128i *)(rk+j) = temp;
+ }
+
+ *(__m128i *)(rk+i) = _mm_aesimc_si128(*(__m128i *)(rk+i));
+ }
+
+ return;
+ }
+#endif
+
+ GetUserKey(BIG_ENDIAN_ORDER, rk, keylen/4, userKey, keylen);
+ const word32 *rc = rcon;
+ word32 temp;
+
+ while (true)
+ {
+ temp = rk[keylen/4-1];
+ word32 x = (word32(Se[GETBYTE(temp, 2)]) << 24) ^ (word32(Se[GETBYTE(temp, 1)]) << 16) ^ (word32(Se[GETBYTE(temp, 0)]) << 8) ^ Se[GETBYTE(temp, 3)];
+ rk[keylen/4] = rk[0] ^ x ^ *(rc++);
+ rk[keylen/4+1] = rk[1] ^ rk[keylen/4];
+ rk[keylen/4+2] = rk[2] ^ rk[keylen/4+1];
+ rk[keylen/4+3] = rk[3] ^ rk[keylen/4+2];
+
+ if (rk + keylen/4 + 4 == m_key.end())
+ break;
+
+ if (keylen == 24)
+ {
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ }
+ else if (keylen == 32)
+ {
+ temp = rk[11];
+ rk[12] = rk[ 4] ^ (word32(Se[GETBYTE(temp, 3)]) << 24) ^ (word32(Se[GETBYTE(temp, 2)]) << 16) ^ (word32(Se[GETBYTE(temp, 1)]) << 8) ^ Se[GETBYTE(temp, 0)];
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+ }
+ rk += keylen/4;
+ }
+
+ rk = m_key;
+
+ if (IsForwardTransformation())
+ {
+ if (!s_TeFilled)
+ FillEncTable();
+
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, rk, rk, 16);
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, rk + m_rounds*4, rk + m_rounds*4, 16);
+ }
+ else
+ {
+ if (!s_TdFilled)
+ FillDecTable();
+
+ unsigned int i, j;
+
+#define InverseMixColumn(x) TL_M(Td, 0, Se[GETBYTE(x, 3)]) ^ TL_M(Td, 1, Se[GETBYTE(x, 2)]) ^ TL_M(Td, 2, Se[GETBYTE(x, 1)]) ^ TL_M(Td, 3, Se[GETBYTE(x, 0)])
+
+ for (i = 4, j = 4*m_rounds-4; i < j; i += 4, j -= 4)
+ {
+ temp = InverseMixColumn(rk[i ]); rk[i ] = InverseMixColumn(rk[j ]); rk[j ] = temp;
+ temp = InverseMixColumn(rk[i + 1]); rk[i + 1] = InverseMixColumn(rk[j + 1]); rk[j + 1] = temp;
+ temp = InverseMixColumn(rk[i + 2]); rk[i + 2] = InverseMixColumn(rk[j + 2]); rk[j + 2] = temp;
+ temp = InverseMixColumn(rk[i + 3]); rk[i + 3] = InverseMixColumn(rk[j + 3]); rk[j + 3] = temp;
+ }
+
+ rk[i+0] = InverseMixColumn(rk[i+0]);
+ rk[i+1] = InverseMixColumn(rk[i+1]);
+ rk[i+2] = InverseMixColumn(rk[i+2]);
+ rk[i+3] = InverseMixColumn(rk[i+3]);
+
+ temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[0]); rk[0] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+0]); rk[4*m_rounds+0] = temp;
+ temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[1]); rk[1] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+1]); rk[4*m_rounds+1] = temp;
+ temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[2]); rk[2] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+2]); rk[4*m_rounds+2] = temp;
+ temp = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[3]); rk[3] = ConditionalByteReverse(BIG_ENDIAN_ORDER, rk[4*m_rounds+3]); rk[4*m_rounds+3] = temp;
+ }
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ if (HasAESNI())
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, rk+4, rk+4, (m_rounds-1)*16);
+#endif
+}
+
+void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) || CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ if (HasSSE2())
+#else
+ if (HasAESNI())
+#endif
+ {
+ Rijndael::Enc::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0);
+ return;
+ }
+#endif
+
+ typedef BlockGetAndPut<word32, NativeByteOrder> Block;
+
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ Block::Get(inBlock)(s0)(s1)(s2)(s3);
+
+ const word32 *rk = m_key;
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ t0 = rk[4];
+ t1 = rk[5];
+ t2 = rk[6];
+ t3 = rk[7];
+ rk += 8;
+
+ // timing attack countermeasure. see comments at top for more details
+ const int cacheLineSize = GetCacheLineSize();
+ unsigned int i;
+ word32 u = 0;
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ for (i=0; i<2048; i+=cacheLineSize)
+#else
+ for (i=0; i<1024; i+=cacheLineSize)
+#endif
+ u &= *(const word32 *)(((const byte *)Te)+i);
+ u &= Te[255];
+ s0 |= u; s1 |= u; s2 |= u; s3 |= u;
+
+ QUARTER_ROUND_FE(s3, t0, t1, t2, t3)
+ QUARTER_ROUND_FE(s2, t3, t0, t1, t2)
+ QUARTER_ROUND_FE(s1, t2, t3, t0, t1)
+ QUARTER_ROUND_FE(s0, t1, t2, t3, t0)
+
+ // Nr - 2 full rounds:
+ unsigned int r = m_rounds/2 - 1;
+ do
+ {
+ s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3];
+
+ QUARTER_ROUND_E(t3, s0, s1, s2, s3)
+ QUARTER_ROUND_E(t2, s3, s0, s1, s2)
+ QUARTER_ROUND_E(t1, s2, s3, s0, s1)
+ QUARTER_ROUND_E(t0, s1, s2, s3, s0)
+
+ t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7];
+
+ QUARTER_ROUND_E(s3, t0, t1, t2, t3)
+ QUARTER_ROUND_E(s2, t3, t0, t1, t2)
+ QUARTER_ROUND_E(s1, t2, t3, t0, t1)
+ QUARTER_ROUND_E(s0, t1, t2, t3, t0)
+
+ rk += 8;
+ } while (--r);
+
+ word32 tbw[4];
+ byte *const tempBlock = (byte *)tbw;
+
+ QUARTER_ROUND_LE(t2, 15, 2, 5, 8)
+ QUARTER_ROUND_LE(t1, 11, 14, 1, 4)
+ QUARTER_ROUND_LE(t0, 7, 10, 13, 0)
+ QUARTER_ROUND_LE(t3, 3, 6, 9, 12)
+
+ Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]);
+}
+
+void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ if (HasAESNI())
+ {
+ Rijndael::Dec::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0);
+ return;
+ }
+#endif
+
+ typedef BlockGetAndPut<word32, NativeByteOrder> Block;
+
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ Block::Get(inBlock)(s0)(s1)(s2)(s3);
+
+ const word32 *rk = m_key;
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ t0 = rk[4];
+ t1 = rk[5];
+ t2 = rk[6];
+ t3 = rk[7];
+ rk += 8;
+
+ // timing attack countermeasure. see comments at top for more details
+ const int cacheLineSize = GetCacheLineSize();
+ unsigned int i;
+ word32 u = 0;
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ for (i=0; i<2048; i+=cacheLineSize)
+#else
+ for (i=0; i<1024; i+=cacheLineSize)
+#endif
+ u &= *(const word32 *)(((const byte *)Td)+i);
+ u &= Td[255];
+ s0 |= u; s1 |= u; s2 |= u; s3 |= u;
+
+ QUARTER_ROUND_FD(s3, t2, t1, t0, t3)
+ QUARTER_ROUND_FD(s2, t1, t0, t3, t2)
+ QUARTER_ROUND_FD(s1, t0, t3, t2, t1)
+ QUARTER_ROUND_FD(s0, t3, t2, t1, t0)
+
+ // Nr - 2 full rounds:
+ unsigned int r = m_rounds/2 - 1;
+ do
+ {
+ s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3];
+
+ QUARTER_ROUND_D(t3, s2, s1, s0, s3)
+ QUARTER_ROUND_D(t2, s1, s0, s3, s2)
+ QUARTER_ROUND_D(t1, s0, s3, s2, s1)
+ QUARTER_ROUND_D(t0, s3, s2, s1, s0)
+
+ t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7];
+
+ QUARTER_ROUND_D(s3, t2, t1, t0, t3)
+ QUARTER_ROUND_D(s2, t1, t0, t3, t2)
+ QUARTER_ROUND_D(s1, t0, t3, t2, t1)
+ QUARTER_ROUND_D(s0, t3, t2, t1, t0)
+
+ rk += 8;
+ } while (--r);
+
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ // timing attack countermeasure. see comments at top for more details
+ // If CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is defined,
+ // QUARTER_ROUND_LD will use Td, which is already preloaded.
+ u = 0;
+ for (i=0; i<256; i+=cacheLineSize)
+ u &= *(const word32 *)(Sd+i);
+ u &= *(const word32 *)(Sd+252);
+ t0 |= u; t1 |= u; t2 |= u; t3 |= u;
+#endif
+
+ word32 tbw[4];
+ byte *const tempBlock = (byte *)tbw;
+
+ QUARTER_ROUND_LD(t2, 7, 2, 13, 8)
+ QUARTER_ROUND_LD(t1, 3, 14, 9, 4)
+ QUARTER_ROUND_LD(t0, 15, 10, 5, 0)
+ QUARTER_ROUND_LD(t3, 11, 6, 1, 12)
+
+ Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]);
+}
+
+// ************************* Assembly Code ************************************
+
+#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+
+CRYPTOPP_NAKED void CRYPTOPP_FASTCALL Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k)
+{
+#if CRYPTOPP_BOOL_X86
+
+#define L_REG esp
+#define L_INDEX(i) (L_REG+768+i)
+#define L_INXORBLOCKS L_INBLOCKS+4
+#define L_OUTXORBLOCKS L_INBLOCKS+8
+#define L_OUTBLOCKS L_INBLOCKS+12
+#define L_INCREMENTS L_INDEX(16*15)
+#define L_SP L_INDEX(16*16)
+#define L_LENGTH L_INDEX(16*16+4)
+#define L_KEYS_BEGIN L_INDEX(16*16+8)
+
+#define MOVD movd
+#define MM(i) mm##i
+
+#define MXOR(a,b,c) \
+ AS2( movzx esi, b)\
+ AS2( movd mm7, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\
+ AS2( pxor MM(a), mm7)\
+
+#define MMOV(a,b,c) \
+ AS2( movzx esi, b)\
+ AS2( movd MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\
+
+#else
+
+#define L_REG r8
+#define L_INDEX(i) (L_REG+i)
+#define L_INXORBLOCKS L_INBLOCKS+8
+#define L_OUTXORBLOCKS L_INBLOCKS+16
+#define L_OUTBLOCKS L_INBLOCKS+24
+#define L_INCREMENTS L_INDEX(16*16)
+#define L_LENGTH L_INDEX(16*18+8)
+#define L_KEYS_BEGIN L_INDEX(16*19)
+
+#define MOVD mov
+#define MM_0 r9d
+#define MM_1 r12d
+#ifdef __GNUC__
+#define MM_2 r11d
+#else
+#define MM_2 r10d
+#endif
+#define MM(i) MM_##i
+
+#define MXOR(a,b,c) \
+ AS2( movzx esi, b)\
+ AS2( xor MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\
+
+#define MMOV(a,b,c) \
+ AS2( movzx esi, b)\
+ AS2( mov MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\
+
+#endif
+
+#define L_SUBKEYS L_INDEX(0)
+#define L_SAVED_X L_SUBKEYS
+#define L_KEY12 L_INDEX(16*12)
+#define L_LASTROUND L_INDEX(16*13)
+#define L_INBLOCKS L_INDEX(16*14)
+#define MAP0TO4(i) (ASM_MOD(i+3,4)+1)
+
+#define XOR(a,b,c) \
+ AS2( movzx esi, b)\
+ AS2( xor a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\
+
+#define MOV(a,b,c) \
+ AS2( movzx esi, b)\
+ AS2( mov a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+ ALIGN 8
+ Rijndael_Enc_AdvancedProcessBlocks PROC FRAME
+ rex_push_reg rsi
+ push_reg rdi
+ push_reg rbx
+ push_reg r12
+ .endprolog
+ mov L_REG, rcx
+ mov AS_REG_7, ?Te@rdtable@CryptoPP@@3PA_KA
+ mov edi, DWORD PTR [?g_cacheLineSize@CryptoPP@@3IA]
+#elif defined(__GNUC__)
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ #if CRYPTOPP_BOOL_X64
+ AS2( mov L_REG, rcx)
+ #endif
+ AS_PUSH_IF86(bx)
+ AS_PUSH_IF86(bp)
+ AS2( mov AS_REG_7, WORD_REG(si))
+#else
+ AS_PUSH_IF86(si)
+ AS_PUSH_IF86(di)
+ AS_PUSH_IF86(bx)
+ AS_PUSH_IF86(bp)
+ AS2( lea AS_REG_7, [Te])
+ AS2( mov edi, [g_cacheLineSize])
+#endif
+
+#if CRYPTOPP_BOOL_X86
+ AS2( mov [ecx+16*12+16*4], esp) // save esp to L_SP
+ AS2( lea esp, [ecx-768])
+#endif
+
+ // copy subkeys to stack
+ AS2( mov WORD_REG(si), [L_KEYS_BEGIN])
+ AS2( mov WORD_REG(ax), 16)
+ AS2( and WORD_REG(ax), WORD_REG(si))
+ AS2( movdqa xmm3, XMMWORD_PTR [WORD_REG(dx)+16+WORD_REG(ax)]) // subkey 1 (non-counter) or 2 (counter)
+ AS2( movdqa [L_KEY12], xmm3)
+ AS2( lea WORD_REG(ax), [WORD_REG(dx)+WORD_REG(ax)+2*16])
+ AS2( sub WORD_REG(ax), WORD_REG(si))
+ ASL(0)
+ AS2( movdqa xmm0, [WORD_REG(ax)+WORD_REG(si)])
+ AS2( movdqa XMMWORD_PTR [L_SUBKEYS+WORD_REG(si)], xmm0)
+ AS2( add WORD_REG(si), 16)
+ AS2( cmp WORD_REG(si), 16*12)
+ ASJ( jl, 0, b)
+
+ // read subkeys 0, 1 and last
+ AS2( movdqa xmm4, [WORD_REG(ax)+WORD_REG(si)]) // last subkey
+ AS2( movdqa xmm1, [WORD_REG(dx)]) // subkey 0
+ AS2( MOVD MM(1), [WORD_REG(dx)+4*4]) // 0,1,2,3
+ AS2( mov ebx, [WORD_REG(dx)+5*4]) // 4,5,6,7
+ AS2( mov ecx, [WORD_REG(dx)+6*4]) // 8,9,10,11
+ AS2( mov edx, [WORD_REG(dx)+7*4]) // 12,13,14,15
+
+ // load table into cache
+ AS2( xor WORD_REG(ax), WORD_REG(ax))
+ ASL(9)
+ AS2( mov esi, [AS_REG_7+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( mov esi, [AS_REG_7+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( mov esi, [AS_REG_7+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( mov esi, [AS_REG_7+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( cmp WORD_REG(ax), 2048)
+ ASJ( jl, 9, b)
+ AS1( lfence)
+
+ AS2( test DWORD PTR [L_LENGTH], 1)
+ ASJ( jz, 8, f)
+
+ // counter mode one-time setup
+ AS2( mov WORD_REG(si), [L_INBLOCKS])
+ AS2( movdqu xmm2, [WORD_REG(si)]) // counter
+ AS2( pxor xmm2, xmm1)
+ AS2( psrldq xmm1, 14)
+ AS2( movd eax, xmm1)
+ AS2( mov al, BYTE PTR [WORD_REG(si)+15])
+ AS2( MOVD MM(2), eax)
+#if CRYPTOPP_BOOL_X86
+ AS2( mov eax, 1)
+ AS2( movd mm3, eax)
+#endif
+
+ // partial first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: mm1, ebx, ecx, edx
+ AS2( movd eax, xmm2)
+ AS2( psrldq xmm2, 4)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ MXOR( 1, al, 0) // 0
+ XOR( edx, ah, 1) // 1
+ AS2( shr eax, 16)
+ XOR( ecx, al, 2) // 2
+ XOR( ebx, ah, 3) // 3
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ XOR( ebx, al, 0) // 4
+ MXOR( 1, ah, 1) // 5
+ AS2( shr eax, 16)
+ XOR( edx, al, 2) // 6
+ XOR( ecx, ah, 3) // 7
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ XOR( ecx, al, 0) // 8
+ XOR( ebx, ah, 1) // 9
+ AS2( shr eax, 16)
+ MXOR( 1, al, 2) // 10
+ XOR( edx, ah, 3) // 11
+ AS2( mov eax, edi)
+ XOR( edx, al, 0) // 12
+ XOR( ecx, ah, 1) // 13
+ AS2( shr eax, 16)
+ XOR( ebx, al, 2) // 14
+ AS2( psrldq xmm2, 3)
+
+ // partial second round, in: ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15), out: eax, ebx, edi, mm0
+ AS2( mov eax, [L_KEY12+0*4])
+ AS2( mov edi, [L_KEY12+2*4])
+ AS2( MOVD MM(0), [L_KEY12+3*4])
+ MXOR( 0, cl, 3) /* 11 */
+ XOR( edi, bl, 3) /* 7 */
+ MXOR( 0, bh, 2) /* 6 */
+ AS2( shr ebx, 16) /* 4,5 */
+ XOR( eax, bl, 1) /* 5 */
+ MOV( ebx, bh, 0) /* 4 */
+ AS2( xor ebx, [L_KEY12+1*4])
+ XOR( eax, ch, 2) /* 10 */
+ AS2( shr ecx, 16) /* 8,9 */
+ XOR( eax, dl, 3) /* 15 */
+ XOR( ebx, dh, 2) /* 14 */
+ AS2( shr edx, 16) /* 12,13 */
+ XOR( edi, ch, 0) /* 8 */
+ XOR( ebx, cl, 1) /* 9 */
+ XOR( edi, dl, 1) /* 13 */
+ MXOR( 0, dh, 0) /* 12 */
+
+ AS2( movd ecx, xmm2)
+ AS2( MOVD edx, MM(1))
+ AS2( MOVD [L_SAVED_X+3*4], MM(0))
+ AS2( mov [L_SAVED_X+0*4], eax)
+ AS2( mov [L_SAVED_X+1*4], ebx)
+ AS2( mov [L_SAVED_X+2*4], edi)
+ ASJ( jmp, 5, f)
+
+ ASL(3)
+ // non-counter mode per-block setup
+ AS2( MOVD MM(1), [L_KEY12+0*4]) // 0,1,2,3
+ AS2( mov ebx, [L_KEY12+1*4]) // 4,5,6,7
+ AS2( mov ecx, [L_KEY12+2*4]) // 8,9,10,11
+ AS2( mov edx, [L_KEY12+3*4]) // 12,13,14,15
+ ASL(8)
+ AS2( mov WORD_REG(ax), [L_INBLOCKS])
+ AS2( movdqu xmm2, [WORD_REG(ax)])
+ AS2( mov WORD_REG(si), [L_INXORBLOCKS])
+ AS2( movdqu xmm5, [WORD_REG(si)])
+ AS2( pxor xmm2, xmm1)
+ AS2( pxor xmm2, xmm5)
+
+ // first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: eax, ebx, ecx, edx
+ AS2( movd eax, xmm2)
+ AS2( psrldq xmm2, 4)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ MXOR( 1, al, 0) // 0
+ XOR( edx, ah, 1) // 1
+ AS2( shr eax, 16)
+ XOR( ecx, al, 2) // 2
+ XOR( ebx, ah, 3) // 3
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ XOR( ebx, al, 0) // 4
+ MXOR( 1, ah, 1) // 5
+ AS2( shr eax, 16)
+ XOR( edx, al, 2) // 6
+ XOR( ecx, ah, 3) // 7
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ XOR( ecx, al, 0) // 8
+ XOR( ebx, ah, 1) // 9
+ AS2( shr eax, 16)
+ MXOR( 1, al, 2) // 10
+ XOR( edx, ah, 3) // 11
+ AS2( mov eax, edi)
+ XOR( edx, al, 0) // 12
+ XOR( ecx, ah, 1) // 13
+ AS2( shr eax, 16)
+ XOR( ebx, al, 2) // 14
+ MXOR( 1, ah, 3) // 15
+ AS2( MOVD eax, MM(1))
+
+ AS2( add L_REG, [L_KEYS_BEGIN])
+ AS2( add L_REG, 4*16)
+ ASJ( jmp, 2, f)
+
+ ASL(1)
+ // counter-mode per-block setup
+ AS2( MOVD ecx, MM(2))
+ AS2( MOVD edx, MM(1))
+ AS2( mov eax, [L_SAVED_X+0*4])
+ AS2( mov ebx, [L_SAVED_X+1*4])
+ AS2( xor cl, ch)
+ AS2( and WORD_REG(cx), 255)
+ ASL(5)
+#if CRYPTOPP_BOOL_X86
+ AS2( paddb MM(2), mm3)
+#else
+ AS2( add MM(2), 1)
+#endif
+ // remaining part of second round, in: edx(previous round),esi(keyed counter byte) eax,ebx,[L_SAVED_X+2*4],[L_SAVED_X+3*4], out: eax,ebx,ecx,edx
+ AS2( xor edx, DWORD PTR [AS_REG_7+WORD_REG(cx)*8+3])
+ XOR( ebx, dl, 3)
+ MOV( ecx, dh, 2)
+ AS2( shr edx, 16)
+ AS2( xor ecx, [L_SAVED_X+2*4])
+ XOR( eax, dh, 0)
+ MOV( edx, dl, 1)
+ AS2( xor edx, [L_SAVED_X+3*4])
+
+ AS2( add L_REG, [L_KEYS_BEGIN])
+ AS2( add L_REG, 3*16)
+ ASJ( jmp, 4, f)
+
+// in: eax(0,1,2,3), ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15)
+// out: eax, ebx, edi, mm0
+#define ROUND() \
+ MXOR( 0, cl, 3) /* 11 */\
+ AS2( mov cl, al) /* 8,9,10,3 */\
+ XOR( edi, ah, 2) /* 2 */\
+ AS2( shr eax, 16) /* 0,1 */\
+ XOR( edi, bl, 3) /* 7 */\
+ MXOR( 0, bh, 2) /* 6 */\
+ AS2( shr ebx, 16) /* 4,5 */\
+ MXOR( 0, al, 1) /* 1 */\
+ MOV( eax, ah, 0) /* 0 */\
+ XOR( eax, bl, 1) /* 5 */\
+ MOV( ebx, bh, 0) /* 4 */\
+ XOR( eax, ch, 2) /* 10 */\
+ XOR( ebx, cl, 3) /* 3 */\
+ AS2( shr ecx, 16) /* 8,9 */\
+ XOR( eax, dl, 3) /* 15 */\
+ XOR( ebx, dh, 2) /* 14 */\
+ AS2( shr edx, 16) /* 12,13 */\
+ XOR( edi, ch, 0) /* 8 */\
+ XOR( ebx, cl, 1) /* 9 */\
+ XOR( edi, dl, 1) /* 13 */\
+ MXOR( 0, dh, 0) /* 12 */\
+
+ ASL(2) // 2-round loop
+ AS2( MOVD MM(0), [L_SUBKEYS-4*16+3*4])
+ AS2( mov edi, [L_SUBKEYS-4*16+2*4])
+ ROUND()
+ AS2( mov ecx, edi)
+ AS2( xor eax, [L_SUBKEYS-4*16+0*4])
+ AS2( xor ebx, [L_SUBKEYS-4*16+1*4])
+ AS2( MOVD edx, MM(0))
+
+ ASL(4)
+ AS2( MOVD MM(0), [L_SUBKEYS-4*16+7*4])
+ AS2( mov edi, [L_SUBKEYS-4*16+6*4])
+ ROUND()
+ AS2( mov ecx, edi)
+ AS2( xor eax, [L_SUBKEYS-4*16+4*4])
+ AS2( xor ebx, [L_SUBKEYS-4*16+5*4])
+ AS2( MOVD edx, MM(0))
+
+ AS2( add L_REG, 32)
+ AS2( test L_REG, 255)
+ ASJ( jnz, 2, b)
+ AS2( sub L_REG, 16*16)
+
+#define LAST(a, b, c) \
+ AS2( movzx esi, a )\
+ AS2( movzx edi, BYTE PTR [AS_REG_7+WORD_REG(si)*8+1] )\
+ AS2( movzx esi, b )\
+ AS2( xor edi, DWORD PTR [AS_REG_7+WORD_REG(si)*8+0] )\
+ AS2( mov WORD PTR [L_LASTROUND+c], di )\
+
+ // last round
+ LAST(ch, dl, 2)
+ LAST(dh, al, 6)
+ AS2( shr edx, 16)
+ LAST(ah, bl, 10)
+ AS2( shr eax, 16)
+ LAST(bh, cl, 14)
+ AS2( shr ebx, 16)
+ LAST(dh, al, 12)
+ AS2( shr ecx, 16)
+ LAST(ah, bl, 0)
+ LAST(bh, cl, 4)
+ LAST(ch, dl, 8)
+
+ AS2( mov WORD_REG(ax), [L_OUTXORBLOCKS])
+ AS2( mov WORD_REG(bx), [L_OUTBLOCKS])
+
+ AS2( mov WORD_REG(cx), [L_LENGTH])
+ AS2( sub WORD_REG(cx), 16)
+
+ AS2( movdqu xmm2, [WORD_REG(ax)])
+ AS2( pxor xmm2, xmm4)
+
+#if CRYPTOPP_BOOL_X86
+ AS2( movdqa xmm0, [L_INCREMENTS])
+ AS2( paddd xmm0, [L_INBLOCKS])
+ AS2( movdqa [L_INBLOCKS], xmm0)
+#else
+ AS2( movdqa xmm0, [L_INCREMENTS+16])
+ AS2( paddq xmm0, [L_INBLOCKS+16])
+ AS2( movdqa [L_INBLOCKS+16], xmm0)
+#endif
+
+ AS2( pxor xmm2, [L_LASTROUND])
+ AS2( movdqu [WORD_REG(bx)], xmm2)
+
+ ASJ( jle, 7, f)
+ AS2( mov [L_LENGTH], WORD_REG(cx))
+ AS2( test WORD_REG(cx), 1)
+ ASJ( jnz, 1, b)
+#if CRYPTOPP_BOOL_X64
+ AS2( movdqa xmm0, [L_INCREMENTS])
+ AS2( paddq xmm0, [L_INBLOCKS])
+ AS2( movdqa [L_INBLOCKS], xmm0)
+#endif
+ ASJ( jmp, 3, b)
+
+ ASL(7)
+ // erase keys on stack
+ AS2( xorps xmm0, xmm0)
+ AS2( lea WORD_REG(ax), [L_SUBKEYS+7*16])
+ AS2( movaps [WORD_REG(ax)-7*16], xmm0)
+ AS2( movaps [WORD_REG(ax)-6*16], xmm0)
+ AS2( movaps [WORD_REG(ax)-5*16], xmm0)
+ AS2( movaps [WORD_REG(ax)-4*16], xmm0)
+ AS2( movaps [WORD_REG(ax)-3*16], xmm0)
+ AS2( movaps [WORD_REG(ax)-2*16], xmm0)
+ AS2( movaps [WORD_REG(ax)-1*16], xmm0)
+ AS2( movaps [WORD_REG(ax)+0*16], xmm0)
+ AS2( movaps [WORD_REG(ax)+1*16], xmm0)
+ AS2( movaps [WORD_REG(ax)+2*16], xmm0)
+ AS2( movaps [WORD_REG(ax)+3*16], xmm0)
+ AS2( movaps [WORD_REG(ax)+4*16], xmm0)
+ AS2( movaps [WORD_REG(ax)+5*16], xmm0)
+ AS2( movaps [WORD_REG(ax)+6*16], xmm0)
+#if CRYPTOPP_BOOL_X86
+ AS2( mov esp, [L_SP])
+ AS1( emms)
+#endif
+ AS_POP_IF86(bp)
+ AS_POP_IF86(bx)
+#if defined(_MSC_VER) && CRYPTOPP_BOOL_X86
+ AS_POP_IF86(di)
+ AS_POP_IF86(si)
+ AS1(ret)
+#endif
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+ pop r12
+ pop rbx
+ pop rdi
+ pop rsi
+ ret
+ Rijndael_Enc_AdvancedProcessBlocks ENDP
+#endif
+#ifdef __GNUC__
+ ".att_syntax prefix;"
+ :
+ : "c" (locals), "d" (k), "S" (Te), "D" (g_cacheLineSize)
+ : "memory", "cc", "%eax"
+ #if CRYPTOPP_BOOL_X64
+ , "%rbx", "%r8", "%r9", "%r10", "%r11", "%r12"
+ #endif
+ );
+#endif
+}
+
+#endif
+
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+void Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k);
+}
+#endif
+
+#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86
+
+static inline bool AliasedWithTable(const byte *begin, const byte *end)
+{
+ size_t s0 = size_t(begin)%4096, s1 = size_t(end)%4096;
+ size_t t0 = size_t(Te)%4096, t1 = (size_t(Te)+sizeof(Te))%4096;
+ if (t1 > t0)
+ return (s0 >= t0 && s0 < t1) || (s1 > t0 && s1 <= t1);
+ else
+ return (s0 < t1 || s1 <= t1) || (s0 >= t0 || s1 > t0);
+}
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+
+inline void AESNI_Enc_Block(__m128i &block, const __m128i *subkeys, unsigned int rounds)
+{
+ block = _mm_xor_si128(block, subkeys[0]);
+ for (unsigned int i=1; i<rounds-1; i+=2)
+ {
+ block = _mm_aesenc_si128(block, subkeys[i]);
+ block = _mm_aesenc_si128(block, subkeys[i+1]);
+ }
+ block = _mm_aesenc_si128(block, subkeys[rounds-1]);
+ block = _mm_aesenclast_si128(block, subkeys[rounds]);
+}
+
+inline void AESNI_Enc_4_Blocks(__m128i &block0, __m128i &block1, __m128i &block2, __m128i &block3, const __m128i *subkeys, unsigned int rounds)
+{
+ __m128i rk = subkeys[0];
+ block0 = _mm_xor_si128(block0, rk);
+ block1 = _mm_xor_si128(block1, rk);
+ block2 = _mm_xor_si128(block2, rk);
+ block3 = _mm_xor_si128(block3, rk);
+ for (unsigned int i=1; i<rounds; i++)
+ {
+ rk = subkeys[i];
+ block0 = _mm_aesenc_si128(block0, rk);
+ block1 = _mm_aesenc_si128(block1, rk);
+ block2 = _mm_aesenc_si128(block2, rk);
+ block3 = _mm_aesenc_si128(block3, rk);
+ }
+ rk = subkeys[rounds];
+ block0 = _mm_aesenclast_si128(block0, rk);
+ block1 = _mm_aesenclast_si128(block1, rk);
+ block2 = _mm_aesenclast_si128(block2, rk);
+ block3 = _mm_aesenclast_si128(block3, rk);
+}
+
+inline void AESNI_Dec_Block(__m128i &block, const __m128i *subkeys, unsigned int rounds)
+{
+ block = _mm_xor_si128(block, subkeys[0]);
+ for (unsigned int i=1; i<rounds-1; i+=2)
+ {
+ block = _mm_aesdec_si128(block, subkeys[i]);
+ block = _mm_aesdec_si128(block, subkeys[i+1]);
+ }
+ block = _mm_aesdec_si128(block, subkeys[rounds-1]);
+ block = _mm_aesdeclast_si128(block, subkeys[rounds]);
+}
+
+inline void AESNI_Dec_4_Blocks(__m128i &block0, __m128i &block1, __m128i &block2, __m128i &block3, const __m128i *subkeys, unsigned int rounds)
+{
+ __m128i rk = subkeys[0];
+ block0 = _mm_xor_si128(block0, rk);
+ block1 = _mm_xor_si128(block1, rk);
+ block2 = _mm_xor_si128(block2, rk);
+ block3 = _mm_xor_si128(block3, rk);
+ for (unsigned int i=1; i<rounds; i++)
+ {
+ rk = subkeys[i];
+ block0 = _mm_aesdec_si128(block0, rk);
+ block1 = _mm_aesdec_si128(block1, rk);
+ block2 = _mm_aesdec_si128(block2, rk);
+ block3 = _mm_aesdec_si128(block3, rk);
+ }
+ rk = subkeys[rounds];
+ block0 = _mm_aesdeclast_si128(block0, rk);
+ block1 = _mm_aesdeclast_si128(block1, rk);
+ block2 = _mm_aesdeclast_si128(block2, rk);
+ block3 = _mm_aesdeclast_si128(block3, rk);
+}
+
+static CRYPTOPP_ALIGN_DATA(16) const word32 s_one[] = {0, 0, 0, 1<<24};
+
+template <typename F1, typename F4>
+inline size_t AESNI_AdvancedProcessBlocks(F1 func1, F4 func4, const __m128i *subkeys, unsigned int rounds, const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+ size_t blockSize = 16;
+ size_t inIncrement = (flags & (BlockTransformation::BT_InBlockIsCounter|BlockTransformation::BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+ size_t xorIncrement = xorBlocks ? blockSize : 0;
+ size_t outIncrement = (flags & BlockTransformation::BT_DontIncrementInOutPointers) ? 0 : blockSize;
+
+ if (flags & BlockTransformation::BT_ReverseDirection)
+ {
+ assert(length % blockSize == 0);
+ inBlocks += length - blockSize;
+ xorBlocks += length - blockSize;
+ outBlocks += length - blockSize;
+ inIncrement = 0-inIncrement;
+ xorIncrement = 0-xorIncrement;
+ outIncrement = 0-outIncrement;
+ }
+
+ if (flags & BlockTransformation::BT_AllowParallel)
+ {
+ while (length >= 4*blockSize)
+ {
+ __m128i block0 = _mm_loadu_si128((const __m128i *)inBlocks), block1, block2, block3;
+ if (flags & BlockTransformation::BT_InBlockIsCounter)
+ {
+ const __m128i be1 = *(const __m128i *)s_one;
+ block1 = _mm_add_epi32(block0, be1);
+ block2 = _mm_add_epi32(block1, be1);
+ block3 = _mm_add_epi32(block2, be1);
+ _mm_storeu_si128((__m128i *)inBlocks, _mm_add_epi32(block3, be1));
+ }
+ else
+ {
+ inBlocks += inIncrement;
+ block1 = _mm_loadu_si128((const __m128i *)inBlocks);
+ inBlocks += inIncrement;
+ block2 = _mm_loadu_si128((const __m128i *)inBlocks);
+ inBlocks += inIncrement;
+ block3 = _mm_loadu_si128((const __m128i *)inBlocks);
+ inBlocks += inIncrement;
+ }
+
+ if (flags & BlockTransformation::BT_XorInput)
+ {
+ block0 = _mm_xor_si128(block0, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ block1 = _mm_xor_si128(block1, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ block2 = _mm_xor_si128(block2, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ block3 = _mm_xor_si128(block3, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ }
+
+ func4(block0, block1, block2, block3, subkeys, rounds);
+
+ if (xorBlocks && !(flags & BlockTransformation::BT_XorInput))
+ {
+ block0 = _mm_xor_si128(block0, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ block1 = _mm_xor_si128(block1, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ block2 = _mm_xor_si128(block2, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ block3 = _mm_xor_si128(block3, _mm_loadu_si128((const __m128i *)xorBlocks));
+ xorBlocks += xorIncrement;
+ }
+
+ _mm_storeu_si128((__m128i *)outBlocks, block0);
+ outBlocks += outIncrement;
+ _mm_storeu_si128((__m128i *)outBlocks, block1);
+ outBlocks += outIncrement;
+ _mm_storeu_si128((__m128i *)outBlocks, block2);
+ outBlocks += outIncrement;
+ _mm_storeu_si128((__m128i *)outBlocks, block3);
+ outBlocks += outIncrement;
+
+ length -= 4*blockSize;
+ }
+ }
+
+ while (length >= blockSize)
+ {
+ __m128i block = _mm_loadu_si128((const __m128i *)inBlocks);
+
+ if (flags & BlockTransformation::BT_XorInput)
+ block = _mm_xor_si128(block, _mm_loadu_si128((const __m128i *)xorBlocks));
+
+ if (flags & BlockTransformation::BT_InBlockIsCounter)
+ const_cast<byte *>(inBlocks)[15]++;
+
+ func1(block, subkeys, rounds);
+
+ if (xorBlocks && !(flags & BlockTransformation::BT_XorInput))
+ block = _mm_xor_si128(block, _mm_loadu_si128((const __m128i *)xorBlocks));
+
+ _mm_storeu_si128((__m128i *)outBlocks, block);
+
+ inBlocks += inIncrement;
+ outBlocks += outIncrement;
+ xorBlocks += xorIncrement;
+ length -= blockSize;
+ }
+
+ return length;
+}
+#endif
+
+size_t Rijndael::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
+{
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ if (HasAESNI())
+ return AESNI_AdvancedProcessBlocks(AESNI_Enc_Block, AESNI_Enc_4_Blocks, (const __m128i *)m_key.begin(), m_rounds, inBlocks, xorBlocks, outBlocks, length, flags);
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ if (HasSSE2())
+ {
+ if (length < BLOCKSIZE)
+ return length;
+
+ struct Locals
+ {
+ word32 subkeys[4*12], workspace[8];
+ const byte *inBlocks, *inXorBlocks, *outXorBlocks;
+ byte *outBlocks;
+ size_t inIncrement, inXorIncrement, outXorIncrement, outIncrement;
+ size_t regSpill, lengthAndCounterFlag, keysBegin;
+ };
+
+ size_t increment = BLOCKSIZE;
+ const byte* zeros = (byte *)(Te+256);
+ byte *space;
+
+ do {
+ space = (byte *)alloca(255+sizeof(Locals));
+ space += (256-(size_t)space%256)%256;
+ }
+ while (AliasedWithTable(space, space+sizeof(Locals)));
+
+ if (flags & BT_ReverseDirection)
+ {
+ assert(length % BLOCKSIZE == 0);
+ inBlocks += length - BLOCKSIZE;
+ xorBlocks += length - BLOCKSIZE;
+ outBlocks += length - BLOCKSIZE;
+ increment = 0-increment;
+ }
+
+ Locals &locals = *(Locals *)space;
+
+ locals.inBlocks = inBlocks;
+ locals.inXorBlocks = (flags & BT_XorInput) && xorBlocks ? xorBlocks : zeros;
+ locals.outXorBlocks = (flags & BT_XorInput) || !xorBlocks ? zeros : xorBlocks;
+ locals.outBlocks = outBlocks;
+
+ locals.inIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment;
+ locals.inXorIncrement = (flags & BT_XorInput) && xorBlocks ? increment : 0;
+ locals.outXorIncrement = (flags & BT_XorInput) || !xorBlocks ? 0 : increment;
+ locals.outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment;
+
+ locals.lengthAndCounterFlag = length - (length%16) - bool(flags & BT_InBlockIsCounter);
+ int keysToCopy = m_rounds - (flags & BT_InBlockIsCounter ? 3 : 2);
+ locals.keysBegin = (12-keysToCopy)*16;
+
+ Rijndael_Enc_AdvancedProcessBlocks(&locals, m_key);
+ return length % BLOCKSIZE;
+ }
+#endif
+
+ return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
+}
+
+#endif
+
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+
+size_t Rijndael::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
+{
+ if (HasAESNI())
+ return AESNI_AdvancedProcessBlocks(AESNI_Dec_Block, AESNI_Dec_4_Blocks, (const __m128i *)m_key.begin(), m_rounds, inBlocks, xorBlocks, outBlocks, length, flags);
+
+ return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
+}
+
+#endif // #if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+
+NAMESPACE_END
+
+#endif
+#endif
diff --git a/lib/cryptopp/rijndael.h b/lib/cryptopp/rijndael.h
new file mode 100644
index 000000000..64c784b07
--- /dev/null
+++ b/lib/cryptopp/rijndael.h
@@ -0,0 +1,68 @@
+#ifndef CRYPTOPP_RIJNDAEL_H
+#define CRYPTOPP_RIJNDAEL_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+struct Rijndael_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8>
+{
+ CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return CRYPTOPP_RIJNDAEL_NAME;}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#Rijndael">Rijndael</a>
+class CRYPTOPP_DLL Rijndael : public Rijndael_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<Rijndael_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+
+ protected:
+ static void FillEncTable();
+ static void FillDecTable();
+
+ // VS2005 workaround: have to put these on seperate lines, or error C2487 is triggered in DLL build
+ static const byte Se[256];
+ static const byte Sd[256];
+
+ static const word32 rcon[];
+
+ unsigned int m_rounds;
+ FixedSizeAlignedSecBlock<word32, 4*15> m_key;
+ };
+
+ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86
+ size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
+ };
+
+ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
+ size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+typedef Rijndael::Encryption RijndaelEncryption;
+typedef Rijndael::Decryption RijndaelDecryption;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/rng.cpp b/lib/cryptopp/rng.cpp
new file mode 100644
index 000000000..9866cd831
--- /dev/null
+++ b/lib/cryptopp/rng.cpp
@@ -0,0 +1,155 @@
+// rng.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#include "rng.h"
+#include "fips140.h"
+
+#include <time.h>
+#include <math.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// linear congruential generator
+// originally by William S. England
+
+// do not use for cryptographic purposes
+
+/*
+** Original_numbers are the original published m and q in the
+** ACM article above. John Burton has furnished numbers for
+** a reportedly better generator. The new numbers are now
+** used in this program by default.
+*/
+
+#ifndef LCRNG_ORIGINAL_NUMBERS
+const word32 LC_RNG::m=2147483647L;
+const word32 LC_RNG::q=44488L;
+
+const word16 LC_RNG::a=(unsigned int)48271L;
+const word16 LC_RNG::r=3399;
+#else
+const word32 LC_RNG::m=2147483647L;
+const word32 LC_RNG::q=127773L;
+
+const word16 LC_RNG::a=16807;
+const word16 LC_RNG::r=2836;
+#endif
+
+void LC_RNG::GenerateBlock(byte *output, size_t size)
+{
+ while (size--)
+ {
+ word32 hi = seed/q;
+ word32 lo = seed%q;
+
+ long test = a*lo - r*hi;
+
+ if (test > 0)
+ seed = test;
+ else
+ seed = test+ m;
+
+ *output++ = (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3));
+ }
+}
+
+// ********************************************************
+
+#ifndef CRYPTOPP_IMPORTS
+
+X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector)
+ : cipher(c),
+ S(cipher->BlockSize()),
+ dtbuf(S),
+ randseed(seed, S),
+ m_lastBlock(S),
+ m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0)
+{
+ if (!deterministicTimeVector)
+ {
+ time_t tstamp1 = time(0);
+ xorbuf(dtbuf, (byte *)&tstamp1, UnsignedMin(sizeof(tstamp1), S));
+ cipher->ProcessBlock(dtbuf);
+ clock_t tstamp2 = clock();
+ xorbuf(dtbuf, (byte *)&tstamp2, UnsignedMin(sizeof(tstamp2), S));
+ cipher->ProcessBlock(dtbuf);
+ }
+
+ // for FIPS 140-2
+ GenerateBlock(m_lastBlock, S);
+}
+
+void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
+{
+ while (size > 0)
+ {
+ // calculate new enciphered timestamp
+ if (m_deterministicTimeVector.size())
+ {
+ cipher->ProcessBlock(m_deterministicTimeVector, dtbuf);
+ IncrementCounterByOne(m_deterministicTimeVector, S);
+ }
+ else
+ {
+ clock_t c = clock();
+ xorbuf(dtbuf, (byte *)&c, UnsignedMin(sizeof(c), S));
+ time_t t = time(NULL);
+ xorbuf(dtbuf+S-UnsignedMin(sizeof(t), S), (byte *)&t, UnsignedMin(sizeof(t), S));
+ cipher->ProcessBlock(dtbuf);
+ }
+
+ // combine enciphered timestamp with seed
+ xorbuf(randseed, dtbuf, S);
+
+ // generate a new block of random bytes
+ cipher->ProcessBlock(randseed);
+ if (memcmp(m_lastBlock, randseed, S) == 0)
+ throw SelfTestFailure("X917RNG: Continuous random number generator test failed.");
+
+ // output random bytes
+ size_t len = UnsignedMin(S, size);
+ target.ChannelPut(channel, randseed, len);
+ size -= len;
+
+ // compute new seed vector
+ memcpy(m_lastBlock, randseed, S);
+ xorbuf(randseed, dtbuf, S);
+ cipher->ProcessBlock(randseed);
+ }
+}
+
+#endif
+
+MaurerRandomnessTest::MaurerRandomnessTest()
+ : sum(0.0), n(0)
+{
+ for (unsigned i=0; i<V; i++)
+ tab[i] = 0;
+}
+
+size_t MaurerRandomnessTest::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
+{
+ while (length--)
+ {
+ byte inByte = *inString++;
+ if (n >= Q)
+ sum += log(double(n - tab[inByte]));
+ tab[inByte] = n;
+ n++;
+ }
+ return 0;
+}
+
+double MaurerRandomnessTest::GetTestValue() const
+{
+ if (BytesNeeded() > 0)
+ throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed");
+
+ double fTu = (sum/(n-Q))/log(2.0); // this is the test value defined by Maurer
+
+ double value = fTu * 0.1392; // arbitrarily normalize it to
+ return value > 1.0 ? 1.0 : value; // a number between 0 and 1
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/rng.h b/lib/cryptopp/rng.h
new file mode 100644
index 000000000..2439dee69
--- /dev/null
+++ b/lib/cryptopp/rng.h
@@ -0,0 +1,77 @@
+// rng.h - misc RNG related classes, see also osrng.h, randpool.h
+
+#ifndef CRYPTOPP_RNG_H
+#define CRYPTOPP_RNG_H
+
+#include "cryptlib.h"
+#include "filters.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! linear congruential generator
+/*! originally by William S. England, do not use for cryptographic purposes */
+class LC_RNG : public RandomNumberGenerator
+{
+public:
+ LC_RNG(word32 init_seed)
+ : seed(init_seed) {}
+
+ void GenerateBlock(byte *output, size_t size);
+
+ word32 GetSeed() {return seed;}
+
+private:
+ word32 seed;
+
+ static const word32 m;
+ static const word32 q;
+ static const word16 a;
+ static const word16 r;
+};
+
+//! RNG derived from ANSI X9.17 Appendix C
+
+class CRYPTOPP_DLL X917RNG : public RandomNumberGenerator, public NotCopyable
+{
+public:
+ // cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system
+ X917RNG(BlockTransformation *cipher, const byte *seed, const byte *deterministicTimeVector = 0);
+
+ void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size);
+
+private:
+ member_ptr<BlockTransformation> cipher;
+ unsigned int S; // blocksize of cipher
+ SecByteBlock dtbuf; // buffer for enciphered timestamp
+ SecByteBlock randseed, m_lastBlock, m_deterministicTimeVector;
+};
+
+/** This class implements Maurer's Universal Statistical Test for Random Bit Generators
+ it is intended for measuring the randomness of *PHYSICAL* RNGs.
+ For more details see his paper in Journal of Cryptology, 1992. */
+
+class MaurerRandomnessTest : public Bufferless<Sink>
+{
+public:
+ MaurerRandomnessTest();
+
+ size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
+
+ // BytesNeeded() returns how many more bytes of input is needed by the test
+ // GetTestValue() should not be called before BytesNeeded()==0
+ unsigned int BytesNeeded() const {return n >= (Q+K) ? 0 : Q+K-n;}
+
+ // returns a number between 0.0 and 1.0, describing the quality of the
+ // random numbers entered
+ double GetTestValue() const;
+
+private:
+ enum {L=8, V=256, Q=2000, K=2000};
+ double sum;
+ unsigned int n;
+ unsigned int tab[V];
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/rsa.cpp b/lib/cryptopp/rsa.cpp
new file mode 100644
index 000000000..59449c40e
--- /dev/null
+++ b/lib/cryptopp/rsa.cpp
@@ -0,0 +1,304 @@
+// rsa.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "rsa.h"
+#include "asn.h"
+#include "oids.h"
+#include "modarith.h"
+#include "nbtheory.h"
+#include "sha.h"
+#include "algparam.h"
+#include "fips140.h"
+
+#if !defined(NDEBUG) && !defined(CRYPTOPP_IS_DLL)
+#include "pssr.h"
+NAMESPACE_BEGIN(CryptoPP)
+void RSA_TestInstantiations()
+{
+ RSASS<PKCS1v15, SHA>::Verifier x1(1, 1);
+ RSASS<PKCS1v15, SHA>::Signer x2(NullRNG(), 1);
+ RSASS<PKCS1v15, SHA>::Verifier x3(x2);
+ RSASS<PKCS1v15, SHA>::Verifier x4(x2.GetKey());
+ RSASS<PSS, SHA>::Verifier x5(x3);
+#ifndef __MWERKS__
+ RSASS<PSSR, SHA>::Signer x6 = x2;
+ x3 = x2;
+ x6 = x2;
+#endif
+ RSAES<PKCS1v15>::Encryptor x7(x2);
+#ifndef __GNUC__
+ RSAES<PKCS1v15>::Encryptor x8(x3);
+#endif
+ RSAES<OAEP<SHA> >::Encryptor x9(x2);
+
+ x4 = x2.GetKey();
+}
+NAMESPACE_END
+#endif
+
+#ifndef CRYPTOPP_IMPORTS
+
+NAMESPACE_BEGIN(CryptoPP)
+
+OID RSAFunction::GetAlgorithmID() const
+{
+ return ASN1::rsaEncryption();
+}
+
+void RSAFunction::BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
+{
+ BERSequenceDecoder seq(bt);
+ m_n.BERDecode(seq);
+ m_e.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void RSAFunction::DEREncodePublicKey(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ m_n.DEREncode(seq);
+ m_e.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer RSAFunction::ApplyFunction(const Integer &x) const
+{
+ DoQuickSanityCheck();
+ return a_exp_b_mod_c(x, m_e, m_n);
+}
+
+bool RSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = true;
+ pass = pass && m_n > Integer::One() && m_n.IsOdd();
+ pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n;
+ return pass;
+}
+
+bool RSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
+ ;
+}
+
+void RSAFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
+ CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
+ ;
+}
+
+// *****************************************************************************
+
+class RSAPrimeSelector : public PrimeSelector
+{
+public:
+ RSAPrimeSelector(const Integer &e) : m_e(e) {}
+ bool IsAcceptable(const Integer &candidate) const {return RelativelyPrime(m_e, candidate-Integer::One());}
+ Integer m_e;
+};
+
+void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ int modulusSize = 2048;
+ alg.GetIntValue(Name::ModulusSize(), modulusSize) || alg.GetIntValue(Name::KeySize(), modulusSize);
+
+ if (modulusSize < 16)
+ throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small");
+
+ m_e = alg.GetValueWithDefault(Name::PublicExponent(), Integer(17));
+
+ if (m_e < 3 || m_e.IsEven())
+ throw InvalidArgument("InvertibleRSAFunction: invalid public exponent");
+
+ RSAPrimeSelector selector(m_e);
+ AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize)
+ (Name::PointerToPrimeSelector(), selector.GetSelectorPointer());
+ m_p.GenerateRandom(rng, primeParam);
+ m_q.GenerateRandom(rng, primeParam);
+
+ m_d = m_e.InverseMod(LCM(m_p-1, m_q-1));
+ assert(m_d.IsPositive());
+
+ m_dp = m_d % (m_p-1);
+ m_dq = m_d % (m_q-1);
+ m_n = m_p * m_q;
+ m_u = m_q.InverseMod(m_p);
+
+ if (FIPS_140_2_ComplianceEnabled())
+ {
+ RSASS<PKCS1v15, SHA>::Signer signer(*this);
+ RSASS<PKCS1v15, SHA>::Verifier verifier(signer);
+ SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);
+
+ RSAES<OAEP<SHA> >::Decryptor decryptor(*this);
+ RSAES<OAEP<SHA> >::Encryptor encryptor(decryptor);
+ EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor);
+ }
+}
+
+void InvertibleRSAFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e)
+{
+ GenerateRandom(rng, MakeParameters(Name::ModulusSize(), (int)keybits)(Name::PublicExponent(), e+e.IsEven()));
+}
+
+void InvertibleRSAFunction::Initialize(const Integer &n, const Integer &e, const Integer &d)
+{
+ if (n.IsEven() || e.IsEven() | d.IsEven())
+ throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key");
+
+ m_n = n;
+ m_e = e;
+ m_d = d;
+
+ Integer r = --(d*e);
+ unsigned int s = 0;
+ while (r.IsEven())
+ {
+ r >>= 1;
+ s++;
+ }
+
+ ModularArithmetic modn(n);
+ for (Integer i = 2; ; ++i)
+ {
+ Integer a = modn.Exponentiate(i, r);
+ if (a == 1)
+ continue;
+ Integer b;
+ unsigned int j = 0;
+ while (a != n-1)
+ {
+ b = modn.Square(a);
+ if (b == 1)
+ {
+ m_p = GCD(a-1, n);
+ m_q = n/m_p;
+ m_dp = m_d % (m_p-1);
+ m_dq = m_d % (m_q-1);
+ m_u = m_q.InverseMod(m_p);
+ return;
+ }
+ if (++j == s)
+ throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key");
+ a = b;
+ }
+ }
+}
+
+void InvertibleRSAFunction::BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t)
+{
+ BERSequenceDecoder privateKey(bt);
+ word32 version;
+ BERDecodeUnsigned<word32>(privateKey, version, INTEGER, 0, 0); // check version
+ m_n.BERDecode(privateKey);
+ m_e.BERDecode(privateKey);
+ m_d.BERDecode(privateKey);
+ m_p.BERDecode(privateKey);
+ m_q.BERDecode(privateKey);
+ m_dp.BERDecode(privateKey);
+ m_dq.BERDecode(privateKey);
+ m_u.BERDecode(privateKey);
+ privateKey.MessageEnd();
+}
+
+void InvertibleRSAFunction::DEREncodePrivateKey(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder privateKey(bt);
+ DEREncodeUnsigned<word32>(privateKey, 0); // version
+ m_n.DEREncode(privateKey);
+ m_e.DEREncode(privateKey);
+ m_d.DEREncode(privateKey);
+ m_p.DEREncode(privateKey);
+ m_q.DEREncode(privateKey);
+ m_dp.DEREncode(privateKey);
+ m_dq.DEREncode(privateKey);
+ m_u.DEREncode(privateKey);
+ privateKey.MessageEnd();
+}
+
+Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
+{
+ DoQuickSanityCheck();
+ ModularArithmetic modn(m_n);
+ Integer r, rInv;
+ do { // do this in a loop for people using small numbers for testing
+ r.Randomize(rng, Integer::One(), m_n - Integer::One());
+ rInv = modn.MultiplicativeInverse(r);
+ } while (rInv.IsZero());
+ Integer re = modn.Exponentiate(r, m_e);
+ re = modn.Multiply(re, x); // blind
+ // here we follow the notation of PKCS #1 and let u=q inverse mod p
+ // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q
+ Integer y = ModularRoot(re, m_dq, m_dp, m_q, m_p, m_u);
+ y = modn.Multiply(y, rInv); // unblind
+ if (modn.Exponentiate(y, m_e) != x) // check
+ throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: computational error during private key operation");
+ return y;
+}
+
+bool InvertibleRSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = RSAFunction::Validate(rng, level);
+ pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
+ pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
+ pass = pass && m_d > Integer::One() && m_d.IsOdd() && m_d < m_n;
+ pass = pass && m_dp > Integer::One() && m_dp.IsOdd() && m_dp < m_p;
+ pass = pass && m_dq > Integer::One() && m_dq.IsOdd() && m_dq < m_q;
+ pass = pass && m_u.IsPositive() && m_u < m_p;
+ if (level >= 1)
+ {
+ pass = pass && m_p * m_q == m_n;
+ pass = pass && m_e*m_d % LCM(m_p-1, m_q-1) == 1;
+ pass = pass && m_dp == m_d%(m_p-1) && m_dq == m_d%(m_q-1);
+ pass = pass && m_u * m_q % m_p == 1;
+ }
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
+ return pass;
+}
+
+bool InvertibleRSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper<RSAFunction>(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent)
+ CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime1PrivateExponent)
+ CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime2PrivateExponent)
+ CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+void InvertibleRSAFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper<RSAFunction>(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent)
+ CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime1PrivateExponent)
+ CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime2PrivateExponent)
+ CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+// *****************************************************************************
+
+Integer RSAFunction_ISO::ApplyFunction(const Integer &x) const
+{
+ Integer t = RSAFunction::ApplyFunction(x);
+ return t % 16 == 12 ? t : m_n - t;
+}
+
+Integer InvertibleRSAFunction_ISO::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
+{
+ Integer t = InvertibleRSAFunction::CalculateInverse(rng, x);
+ return STDMIN(t, m_n-t);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/rsa.h b/lib/cryptopp/rsa.h
new file mode 100644
index 000000000..6a8b18525
--- /dev/null
+++ b/lib/cryptopp/rsa.h
@@ -0,0 +1,174 @@
+#ifndef CRYPTOPP_RSA_H
+#define CRYPTOPP_RSA_H
+
+/** \file
+ This file contains classes that implement the RSA
+ ciphers and signature schemes as defined in PKCS #1 v2.0.
+*/
+
+#include "pubkey.h"
+#include "asn.h"
+#include "pkcspad.h"
+#include "oaep.h"
+#include "emsa2.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL RSAFunction : public TrapdoorFunction, public X509PublicKey
+{
+ typedef RSAFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n, const Integer &e)
+ {m_n = n; m_e = e;}
+
+ // X509PublicKey
+ OID GetAlgorithmID() const;
+ void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
+ void DEREncodePublicKey(BufferedTransformation &bt) const;
+
+ // CryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ // TrapdoorFunction
+ Integer ApplyFunction(const Integer &x) const;
+ Integer PreimageBound() const {return m_n;}
+ Integer ImageBound() const {return m_n;}
+
+ // non-derived
+ const Integer & GetModulus() const {return m_n;}
+ const Integer & GetPublicExponent() const {return m_e;}
+
+ void SetModulus(const Integer &n) {m_n = n;}
+ void SetPublicExponent(const Integer &e) {m_e = e;}
+
+protected:
+ Integer m_n, m_e;
+};
+
+//! _
+class CRYPTOPP_DLL InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey
+{
+ typedef InvertibleRSAFunction ThisClass;
+
+public:
+ void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &e = 17);
+ void Initialize(const Integer &n, const Integer &e, const Integer &d, const Integer &p, const Integer &q, const Integer &dp, const Integer &dq, const Integer &u)
+ {m_n = n; m_e = e; m_d = d; m_p = p; m_q = q; m_dp = dp; m_dq = dq; m_u = u;}
+ //! factor n given private exponent
+ void Initialize(const Integer &n, const Integer &e, const Integer &d);
+
+ // PKCS8PrivateKey
+ void BERDecode(BufferedTransformation &bt)
+ {PKCS8PrivateKey::BERDecode(bt);}
+ void DEREncode(BufferedTransformation &bt) const
+ {PKCS8PrivateKey::DEREncode(bt);}
+ void Load(BufferedTransformation &bt)
+ {PKCS8PrivateKey::BERDecode(bt);}
+ void Save(BufferedTransformation &bt) const
+ {PKCS8PrivateKey::DEREncode(bt);}
+ OID GetAlgorithmID() const {return RSAFunction::GetAlgorithmID();}
+ void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
+ void DEREncodePrivateKey(BufferedTransformation &bt) const;
+
+ // TrapdoorFunctionInverse
+ Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const;
+
+ // GeneratableCryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ /*! parameters: (ModulusSize, PublicExponent (default 17)) */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ // non-derived interface
+ const Integer& GetPrime1() const {return m_p;}
+ const Integer& GetPrime2() const {return m_q;}
+ const Integer& GetPrivateExponent() const {return m_d;}
+ const Integer& GetModPrime1PrivateExponent() const {return m_dp;}
+ const Integer& GetModPrime2PrivateExponent() const {return m_dq;}
+ const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;}
+
+ void SetPrime1(const Integer &p) {m_p = p;}
+ void SetPrime2(const Integer &q) {m_q = q;}
+ void SetPrivateExponent(const Integer &d) {m_d = d;}
+ void SetModPrime1PrivateExponent(const Integer &dp) {m_dp = dp;}
+ void SetModPrime2PrivateExponent(const Integer &dq) {m_dq = dq;}
+ void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;}
+
+protected:
+ Integer m_d, m_p, m_q, m_dp, m_dq, m_u;
+};
+
+class CRYPTOPP_DLL RSAFunction_ISO : public RSAFunction
+{
+public:
+ Integer ApplyFunction(const Integer &x) const;
+ Integer PreimageBound() const {return ++(m_n>>1);}
+};
+
+class CRYPTOPP_DLL InvertibleRSAFunction_ISO : public InvertibleRSAFunction
+{
+public:
+ Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const;
+ Integer PreimageBound() const {return ++(m_n>>1);}
+};
+
+//! RSA
+struct CRYPTOPP_DLL RSA
+{
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "RSA";}
+ typedef RSAFunction PublicKey;
+ typedef InvertibleRSAFunction PrivateKey;
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/ca.html#RSA">RSA cryptosystem</a>
+template <class STANDARD>
+struct RSAES : public TF_ES<STANDARD, RSA>
+{
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/sig.html#RSA">RSA signature scheme with appendix</a>
+/*! See documentation of PKCS1v15 for a list of hash functions that can be used with it. */
+template <class STANDARD, class H>
+struct RSASS : public TF_SS<STANDARD, H, RSA>
+{
+};
+
+struct CRYPTOPP_DLL RSA_ISO
+{
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "RSA-ISO";}
+ typedef RSAFunction_ISO PublicKey;
+ typedef InvertibleRSAFunction_ISO PrivateKey;
+};
+
+template <class H>
+struct RSASS_ISO : public TF_SS<P1363_EMSA2, H, RSA_ISO>
+{
+};
+
+// The two RSA encryption schemes defined in PKCS #1 v2.0
+typedef RSAES<PKCS1v15>::Decryptor RSAES_PKCS1v15_Decryptor;
+typedef RSAES<PKCS1v15>::Encryptor RSAES_PKCS1v15_Encryptor;
+
+typedef RSAES<OAEP<SHA> >::Decryptor RSAES_OAEP_SHA_Decryptor;
+typedef RSAES<OAEP<SHA> >::Encryptor RSAES_OAEP_SHA_Encryptor;
+
+// The three RSA signature schemes defined in PKCS #1 v2.0
+typedef RSASS<PKCS1v15, SHA>::Signer RSASSA_PKCS1v15_SHA_Signer;
+typedef RSASS<PKCS1v15, SHA>::Verifier RSASSA_PKCS1v15_SHA_Verifier;
+
+namespace Weak {
+typedef RSASS<PKCS1v15, Weak1::MD2>::Signer RSASSA_PKCS1v15_MD2_Signer;
+typedef RSASS<PKCS1v15, Weak1::MD2>::Verifier RSASSA_PKCS1v15_MD2_Verifier;
+
+typedef RSASS<PKCS1v15, Weak1::MD5>::Signer RSASSA_PKCS1v15_MD5_Signer;
+typedef RSASS<PKCS1v15, Weak1::MD5>::Verifier RSASSA_PKCS1v15_MD5_Verifier;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/rw.cpp b/lib/cryptopp/rw.cpp
new file mode 100644
index 000000000..cdd9f2d22
--- /dev/null
+++ b/lib/cryptopp/rw.cpp
@@ -0,0 +1,196 @@
+// rw.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "rw.h"
+#include "nbtheory.h"
+#include "asn.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void RWFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ m_n.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void RWFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ m_n.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer RWFunction::ApplyFunction(const Integer &in) const
+{
+ DoQuickSanityCheck();
+
+ Integer out = in.Squared()%m_n;
+ const word r = 12;
+ // this code was written to handle both r = 6 and r = 12,
+ // but now only r = 12 is used in P1363
+ const word r2 = r/2;
+ const word r3a = (16 + 5 - r) % 16; // n%16 could be 5 or 13
+ const word r3b = (16 + 13 - r) % 16;
+ const word r4 = (8 + 5 - r/2) % 8; // n%8 == 5
+ switch (out % 16)
+ {
+ case r:
+ break;
+ case r2:
+ case r2+8:
+ out <<= 1;
+ break;
+ case r3a:
+ case r3b:
+ out.Negate();
+ out += m_n;
+ break;
+ case r4:
+ case r4+8:
+ out.Negate();
+ out += m_n;
+ out <<= 1;
+ break;
+ default:
+ out = Integer::Zero();
+ }
+ return out;
+}
+
+bool RWFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = true;
+ pass = pass && m_n > Integer::One() && m_n%8 == 5;
+ return pass;
+}
+
+bool RWFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
+ ;
+}
+
+void RWFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
+ ;
+}
+
+// *****************************************************************************
+// private key operations:
+
+// generate a random private key
+void InvertibleRWFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
+{
+ int modulusSize = 2048;
+ alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
+
+ if (modulusSize < 16)
+ throw InvalidArgument("InvertibleRWFunction: specified modulus length is too small");
+
+ AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize);
+ m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 3)("Mod", 8)));
+ m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 7)("Mod", 8)));
+
+ m_n = m_p * m_q;
+ m_u = m_q.InverseMod(m_p);
+}
+
+void InvertibleRWFunction::BERDecode(BufferedTransformation &bt)
+{
+ BERSequenceDecoder seq(bt);
+ m_n.BERDecode(seq);
+ m_p.BERDecode(seq);
+ m_q.BERDecode(seq);
+ m_u.BERDecode(seq);
+ seq.MessageEnd();
+}
+
+void InvertibleRWFunction::DEREncode(BufferedTransformation &bt) const
+{
+ DERSequenceEncoder seq(bt);
+ m_n.DEREncode(seq);
+ m_p.DEREncode(seq);
+ m_q.DEREncode(seq);
+ m_u.DEREncode(seq);
+ seq.MessageEnd();
+}
+
+Integer InvertibleRWFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
+{
+ DoQuickSanityCheck();
+ ModularArithmetic modn(m_n);
+ Integer r, rInv;
+ do { // do this in a loop for people using small numbers for testing
+ r.Randomize(rng, Integer::One(), m_n - Integer::One());
+ rInv = modn.MultiplicativeInverse(r);
+ } while (rInv.IsZero());
+ Integer re = modn.Square(r);
+ re = modn.Multiply(re, x); // blind
+
+ Integer cp=re%m_p, cq=re%m_q;
+ if (Jacobi(cp, m_p) * Jacobi(cq, m_q) != 1)
+ {
+ cp = cp.IsOdd() ? (cp+m_p) >> 1 : cp >> 1;
+ cq = cq.IsOdd() ? (cq+m_q) >> 1 : cq >> 1;
+ }
+
+ #pragma omp parallel
+ #pragma omp sections
+ {
+ #pragma omp section
+ cp = ModularSquareRoot(cp, m_p);
+ #pragma omp section
+ cq = ModularSquareRoot(cq, m_q);
+ }
+
+ Integer y = CRT(cq, m_q, cp, m_p, m_u);
+ y = modn.Multiply(y, rInv); // unblind
+ y = STDMIN(y, m_n-y);
+ if (ApplyFunction(y) != x) // check
+ throw Exception(Exception::OTHER_ERROR, "InvertibleRWFunction: computational error during private key operation");
+ return y;
+}
+
+bool InvertibleRWFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
+{
+ bool pass = RWFunction::Validate(rng, level);
+ pass = pass && m_p > Integer::One() && m_p%8 == 3 && m_p < m_n;
+ pass = pass && m_q > Integer::One() && m_q%8 == 7 && m_q < m_n;
+ pass = pass && m_u.IsPositive() && m_u < m_p;
+ if (level >= 1)
+ {
+ pass = pass && m_p * m_q == m_n;
+ pass = pass && m_u * m_q % m_p == 1;
+ }
+ if (level >= 2)
+ pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
+ return pass;
+}
+
+bool InvertibleRWFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
+{
+ return GetValueHelper<RWFunction>(this, name, valueType, pValue).Assignable()
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+void InvertibleRWFunction::AssignFrom(const NameValuePairs &source)
+{
+ AssignFromHelper<RWFunction>(this, source)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
+ CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
+ CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
+ ;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/rw.h b/lib/cryptopp/rw.h
new file mode 100644
index 000000000..6820251e8
--- /dev/null
+++ b/lib/cryptopp/rw.h
@@ -0,0 +1,102 @@
+#ifndef CRYPTOPP_RW_H
+#define CRYPTOPP_RW_H
+
+/** \file
+ This file contains classes that implement the
+ Rabin-Williams signature schemes as defined in IEEE P1363.
+*/
+
+#include "pubkey.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL RWFunction : public TrapdoorFunction, public PublicKey
+{
+ typedef RWFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n)
+ {m_n = n;}
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ void Save(BufferedTransformation &bt) const
+ {DEREncode(bt);}
+ void Load(BufferedTransformation &bt)
+ {BERDecode(bt);}
+
+ Integer ApplyFunction(const Integer &x) const;
+ Integer PreimageBound() const {return ++(m_n>>1);}
+ Integer ImageBound() const {return m_n;}
+
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+
+ const Integer& GetModulus() const {return m_n;}
+ void SetModulus(const Integer &n) {m_n = n;}
+
+protected:
+ Integer m_n;
+};
+
+//! _
+class CRYPTOPP_DLL InvertibleRWFunction : public RWFunction, public TrapdoorFunctionInverse, public PrivateKey
+{
+ typedef InvertibleRWFunction ThisClass;
+
+public:
+ void Initialize(const Integer &n, const Integer &p, const Integer &q, const Integer &u)
+ {m_n = n; m_p = p; m_q = q; m_u = u;}
+ // generate a random private key
+ void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
+ {GenerateRandomWithKeySize(rng, modulusBits);}
+
+ void BERDecode(BufferedTransformation &bt);
+ void DEREncode(BufferedTransformation &bt) const;
+
+ void Save(BufferedTransformation &bt) const
+ {DEREncode(bt);}
+ void Load(BufferedTransformation &bt)
+ {BERDecode(bt);}
+
+ Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const;
+
+ // GeneratibleCryptoMaterial
+ bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
+ bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
+ void AssignFrom(const NameValuePairs &source);
+ /*! parameters: (ModulusSize) */
+ void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
+
+ const Integer& GetPrime1() const {return m_p;}
+ const Integer& GetPrime2() const {return m_q;}
+ const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;}
+
+ void SetPrime1(const Integer &p) {m_p = p;}
+ void SetPrime2(const Integer &q) {m_q = q;}
+ void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;}
+
+protected:
+ Integer m_p, m_q, m_u;
+};
+
+//! RW
+struct RW
+{
+ static std::string StaticAlgorithmName() {return "RW";}
+ typedef RWFunction PublicKey;
+ typedef InvertibleRWFunction PrivateKey;
+};
+
+//! RWSS
+template <class STANDARD, class H>
+struct RWSS : public TF_SS<STANDARD, H, RW>
+{
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/safer.cpp b/lib/cryptopp/safer.cpp
new file mode 100644
index 000000000..d46ca6417
--- /dev/null
+++ b/lib/cryptopp/safer.cpp
@@ -0,0 +1,153 @@
+// safer.cpp - modified by by Wei Dai from Richard De Moliner's safer.c
+
+#include "pch.h"
+#include "safer.h"
+#include "misc.h"
+#include "argnames.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+const byte SAFER::Base::exp_tab[256] =
+ {1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63,
+ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247,
+ 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177,
+ 255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131,
+ 241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20,
+ 129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160,
+ 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252,
+ 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217,
+ 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194,
+ 249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10,
+ 193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80,
+ 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126,
+ 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237,
+ 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97,
+ 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5,
+ 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40};
+
+const byte SAFER::Base::log_tab[256] =
+ {128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248,
+ 192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130,
+ 112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37,
+ 201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15,
+ 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198,
+ 175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84,
+ 121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188,
+ 189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217,
+ 208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158,
+ 210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42,
+ 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219,
+ 164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29,
+ 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14,
+ 122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104,
+ 109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66,
+ 184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48};
+
+#define EXP(x) exp_tab[(x)]
+#define LOG(x) log_tab[(x)]
+#define PHT(x, y) { y += x; x += y; }
+#define IPHT(x, y) { x -= y; y -= x; }
+
+static const unsigned int BLOCKSIZE = 8;
+static const unsigned int MAX_ROUNDS = 13;
+
+void SAFER::Base::UncheckedSetKey(const byte *userkey_1, unsigned int length, const NameValuePairs &params)
+{
+ bool strengthened = Strengthened();
+ unsigned int nof_rounds = params.GetIntValueWithDefault(Name::Rounds(), length == 8 ? (strengthened ? 8 : 6) : 10);
+
+ const byte *userkey_2 = length == 8 ? userkey_1 : userkey_1 + 8;
+ keySchedule.New(1 + BLOCKSIZE * (1 + 2 * nof_rounds));
+
+ unsigned int i, j;
+ byte *key = keySchedule;
+ SecByteBlock ka(BLOCKSIZE + 1), kb(BLOCKSIZE + 1);
+
+ if (MAX_ROUNDS < nof_rounds)
+ nof_rounds = MAX_ROUNDS;
+ *key++ = (unsigned char)nof_rounds;
+ ka[BLOCKSIZE] = 0;
+ kb[BLOCKSIZE] = 0;
+ for (j = 0; j < BLOCKSIZE; j++)
+ {
+ ka[BLOCKSIZE] ^= ka[j] = rotlFixed(userkey_1[j], 5U);
+ kb[BLOCKSIZE] ^= kb[j] = *key++ = userkey_2[j];
+ }
+
+ for (i = 1; i <= nof_rounds; i++)
+ {
+ for (j = 0; j < BLOCKSIZE + 1; j++)
+ {
+ ka[j] = rotlFixed(ka[j], 6U);
+ kb[j] = rotlFixed(kb[j], 6U);
+ }
+ for (j = 0; j < BLOCKSIZE; j++)
+ if (strengthened)
+ *key++ = (ka[(j + 2 * i - 1) % (BLOCKSIZE + 1)]
+ + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF;
+ else
+ *key++ = (ka[j] + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF;
+ for (j = 0; j < BLOCKSIZE; j++)
+ if (strengthened)
+ *key++ = (kb[(j + 2 * i) % (BLOCKSIZE + 1)]
+ + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF;
+ else
+ *key++ = (kb[j] + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF;
+ }
+}
+
+typedef BlockGetAndPut<byte, BigEndian> Block;
+
+void SAFER::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ byte a, b, c, d, e, f, g, h, t;
+ const byte *key = keySchedule+1;
+ unsigned int round = keySchedule[0];
+
+ Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+ while(round--)
+ {
+ a ^= key[0]; b += key[1]; c += key[2]; d ^= key[3];
+ e ^= key[4]; f += key[5]; g += key[6]; h ^= key[7];
+ a = EXP(a) + key[ 8]; b = LOG(b) ^ key[ 9];
+ c = LOG(c) ^ key[10]; d = EXP(d) + key[11];
+ e = EXP(e) + key[12]; f = LOG(f) ^ key[13];
+ g = LOG(g) ^ key[14]; h = EXP(h) + key[15];
+ key += 16;
+ PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h);
+ PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h);
+ PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h);
+ t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t;
+ }
+ a ^= key[0]; b += key[1]; c += key[2]; d ^= key[3];
+ e ^= key[4]; f += key[5]; g += key[6]; h ^= key[7];
+ Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+}
+
+void SAFER::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ byte a, b, c, d, e, f, g, h, t;
+ unsigned int round = keySchedule[0];
+ const byte *key = keySchedule + BLOCKSIZE * (1 + 2 * round) - 7;
+
+ Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+ h ^= key[7]; g -= key[6]; f -= key[5]; e ^= key[4];
+ d ^= key[3]; c -= key[2]; b -= key[1]; a ^= key[0];
+ while (round--)
+ {
+ key -= 16;
+ t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t;
+ IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h);
+ IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h);
+ IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h);
+ h -= key[15]; g ^= key[14]; f ^= key[13]; e -= key[12];
+ d -= key[11]; c ^= key[10]; b ^= key[9]; a -= key[8];
+ h = LOG(h) ^ key[7]; g = EXP(g) - key[6];
+ f = EXP(f) - key[5]; e = LOG(e) ^ key[4];
+ d = LOG(d) ^ key[3]; c = EXP(c) - key[2];
+ b = EXP(b) - key[1]; a = LOG(a) ^ key[0];
+ }
+ Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/safer.h b/lib/cryptopp/safer.h
new file mode 100644
index 000000000..f9a3c9e1f
--- /dev/null
+++ b/lib/cryptopp/safer.h
@@ -0,0 +1,86 @@
+#ifndef CRYPTOPP_SAFER_H
+#define CRYPTOPP_SAFER_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// base class, do not use directly
+class SAFER
+{
+public:
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipher
+ {
+ public:
+ unsigned int OptimalDataAlignment() const {return 1;}
+ void UncheckedSetKey(const byte *userkey, unsigned int length, const NameValuePairs &params);
+
+ protected:
+ virtual bool Strengthened() const =0;
+
+ SecByteBlock keySchedule;
+ static const byte exp_tab[256];
+ static const byte log_tab[256];
+ };
+
+ class CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+ class CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+};
+
+template <class BASE, class INFO, bool STR>
+class CRYPTOPP_NO_VTABLE SAFER_Impl : public BlockCipherImpl<INFO, BASE>
+{
+protected:
+ bool Strengthened() const {return STR;}
+};
+
+//! _
+struct SAFER_K_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 8, 16, 8>, public VariableRounds<10, 1, 13>
+{
+ static const char *StaticAlgorithmName() {return "SAFER-K";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#SAFER-K">SAFER-K</a>
+class SAFER_K : public SAFER_K_Info, public SAFER, public BlockCipherDocumentation
+{
+public:
+ typedef BlockCipherFinal<ENCRYPTION, SAFER_Impl<Enc, SAFER_K_Info, false> > Encryption;
+ typedef BlockCipherFinal<DECRYPTION, SAFER_Impl<Dec, SAFER_K_Info, false> > Decryption;
+};
+
+//! _
+struct SAFER_SK_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 8, 16, 8>, public VariableRounds<10, 1, 13>
+{
+ static const char *StaticAlgorithmName() {return "SAFER-SK";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#SAFER-SK">SAFER-SK</a>
+class SAFER_SK : public SAFER_SK_Info, public SAFER, public BlockCipherDocumentation
+{
+public:
+ typedef BlockCipherFinal<ENCRYPTION, SAFER_Impl<Enc, SAFER_SK_Info, true> > Encryption;
+ typedef BlockCipherFinal<DECRYPTION, SAFER_Impl<Dec, SAFER_SK_Info, true> > Decryption;
+};
+
+typedef SAFER_K::Encryption SAFER_K_Encryption;
+typedef SAFER_K::Decryption SAFER_K_Decryption;
+
+typedef SAFER_SK::Encryption SAFER_SK_Encryption;
+typedef SAFER_SK::Decryption SAFER_SK_Decryption;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/seal.cpp b/lib/cryptopp/seal.cpp
new file mode 100644
index 000000000..f49b52203
--- /dev/null
+++ b/lib/cryptopp/seal.cpp
@@ -0,0 +1,213 @@
+// seal.cpp - written and placed in the public domain by Wei Dai
+// updated to SEAL 3.0 by Leonard Janke
+
+#include "pch.h"
+
+#include "seal.h"
+#include "sha.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void SEAL_TestInstantiations()
+{
+ SEAL<>::Encryption x;
+}
+
+struct SEAL_Gamma
+{
+ SEAL_Gamma(const byte *key)
+ : H(5), Z(5), D(16), lastIndex(0xffffffff)
+ {
+ GetUserKey(BIG_ENDIAN_ORDER, H.begin(), 5, key, 20);
+ memset(D, 0, 64);
+ }
+
+ word32 Apply(word32 i);
+
+ SecBlock<word32> H, Z, D;
+ word32 lastIndex;
+};
+
+word32 SEAL_Gamma::Apply(word32 i)
+{
+ word32 shaIndex = i/5;
+ if (shaIndex != lastIndex)
+ {
+ memcpy(Z, H, 20);
+ D[0] = shaIndex;
+ SHA::Transform(Z, D);
+ lastIndex = shaIndex;
+ }
+ return Z[i%5];
+}
+
+template <class B>
+void SEAL_Policy<B>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
+{
+ m_insideCounter = m_outsideCounter = m_startCount = 0;
+
+ unsigned int L = params.GetIntValueWithDefault("NumberOfOutputBitsPerPositionIndex", 32*1024);
+ m_iterationsPerCount = L / 8192;
+
+ SEAL_Gamma gamma(key);
+ unsigned int i;
+
+ for (i=0; i<512; i++)
+ m_T[i] = gamma.Apply(i);
+
+ for (i=0; i<256; i++)
+ m_S[i] = gamma.Apply(0x1000+i);
+
+ m_R.New(4*(L/8192));
+
+ for (i=0; i<m_R.size(); i++)
+ m_R[i] = gamma.Apply(0x2000+i);
+}
+
+template <class B>
+void SEAL_Policy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
+{
+ assert(length==4);
+ m_outsideCounter = IV ? GetWord<word32>(false, BIG_ENDIAN_ORDER, IV) : 0;
+ m_startCount = m_outsideCounter;
+ m_insideCounter = 0;
+}
+
+template <class B>
+void SEAL_Policy<B>::SeekToIteration(lword iterationCount)
+{
+ m_outsideCounter = m_startCount + (unsigned int)(iterationCount / m_iterationsPerCount);
+ m_insideCounter = (unsigned int)(iterationCount % m_iterationsPerCount);
+}
+
+template <class B>
+void SEAL_Policy<B>::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
+{
+ word32 a, b, c, d, n1, n2, n3, n4;
+ unsigned int p, q;
+
+ for (size_t iteration = 0; iteration < iterationCount; ++iteration)
+ {
+#define Ttab(x) *(word32 *)((byte *)m_T.begin()+x)
+
+ a = m_outsideCounter ^ m_R[4*m_insideCounter];
+ b = rotrFixed(m_outsideCounter, 8U) ^ m_R[4*m_insideCounter+1];
+ c = rotrFixed(m_outsideCounter, 16U) ^ m_R[4*m_insideCounter+2];
+ d = rotrFixed(m_outsideCounter, 24U) ^ m_R[4*m_insideCounter+3];
+
+ for (unsigned int j=0; j<2; j++)
+ {
+ p = a & 0x7fc;
+ b += Ttab(p);
+ a = rotrFixed(a, 9U);
+
+ p = b & 0x7fc;
+ c += Ttab(p);
+ b = rotrFixed(b, 9U);
+
+ p = c & 0x7fc;
+ d += Ttab(p);
+ c = rotrFixed(c, 9U);
+
+ p = d & 0x7fc;
+ a += Ttab(p);
+ d = rotrFixed(d, 9U);
+ }
+
+ n1 = d, n2 = b, n3 = a, n4 = c;
+
+ p = a & 0x7fc;
+ b += Ttab(p);
+ a = rotrFixed(a, 9U);
+
+ p = b & 0x7fc;
+ c += Ttab(p);
+ b = rotrFixed(b, 9U);
+
+ p = c & 0x7fc;
+ d += Ttab(p);
+ c = rotrFixed(c, 9U);
+
+ p = d & 0x7fc;
+ a += Ttab(p);
+ d = rotrFixed(d, 9U);
+
+ // generate 8192 bits
+ for (unsigned int i=0; i<64; i++)
+ {
+ p = a & 0x7fc;
+ a = rotrFixed(a, 9U);
+ b += Ttab(p);
+ b ^= a;
+
+ q = b & 0x7fc;
+ b = rotrFixed(b, 9U);
+ c ^= Ttab(q);
+ c += b;
+
+ p = (p+c) & 0x7fc;
+ c = rotrFixed(c, 9U);
+ d += Ttab(p);
+ d ^= c;
+
+ q = (q+d) & 0x7fc;
+ d = rotrFixed(d, 9U);
+ a ^= Ttab(q);
+ a += d;
+
+ p = (p+a) & 0x7fc;
+ b ^= Ttab(p);
+ a = rotrFixed(a, 9U);
+
+ q = (q+b) & 0x7fc;
+ c += Ttab(q);
+ b = rotrFixed(b, 9U);
+
+ p = (p+c) & 0x7fc;
+ d ^= Ttab(p);
+ c = rotrFixed(c, 9U);
+
+ q = (q+d) & 0x7fc;
+ d = rotrFixed(d, 9U);
+ a += Ttab(q);
+
+#define SEAL_OUTPUT(x) \
+ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, b + m_S[4*i+0]);\
+ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 1, c ^ m_S[4*i+1]);\
+ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 2, d + m_S[4*i+2]);\
+ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 3, a ^ m_S[4*i+3]);
+
+ CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SEAL_OUTPUT, 4*4);
+
+ if (i & 1)
+ {
+ a += n3;
+ b += n4;
+ c ^= n3;
+ d ^= n4;
+ }
+ else
+ {
+ a += n1;
+ b += n2;
+ c ^= n1;
+ d ^= n2;
+ }
+ }
+
+ if (++m_insideCounter == m_iterationsPerCount)
+ {
+ ++m_outsideCounter;
+ m_insideCounter = 0;
+ }
+ }
+
+ a = b = c = d = n1 = n2 = n3 = n4 = 0;
+ p = q = 0;
+}
+
+template class SEAL_Policy<BigEndian>;
+template class SEAL_Policy<LittleEndian>;
+
+NAMESPACE_END
diff --git a/lib/cryptopp/seal.h b/lib/cryptopp/seal.h
new file mode 100644
index 000000000..e14ae1caf
--- /dev/null
+++ b/lib/cryptopp/seal.h
@@ -0,0 +1,44 @@
+#ifndef CRYPTOPP_SEAL_H
+#define CRYPTOPP_SEAL_H
+
+#include "strciphr.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+template <class B = BigEndian>
+struct SEAL_Info : public FixedKeyLength<20, SimpleKeyingInterface::INTERNALLY_GENERATED_IV, 4>
+{
+ static const char *StaticAlgorithmName() {return B::ToEnum() == LITTLE_ENDIAN_ORDER ? "SEAL-3.0-LE" : "SEAL-3.0-BE";}
+};
+
+template <class B = BigEndian>
+class CRYPTOPP_NO_VTABLE SEAL_Policy : public AdditiveCipherConcretePolicy<word32, 256>, public SEAL_Info<B>
+{
+protected:
+ void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
+ void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
+ bool CipherIsRandomAccess() const {return true;}
+ void SeekToIteration(lword iterationCount);
+
+private:
+ FixedSizeSecBlock<word32, 512> m_T;
+ FixedSizeSecBlock<word32, 256> m_S;
+ SecBlock<word32> m_R;
+
+ word32 m_startCount, m_iterationsPerCount;
+ word32 m_outsideCounter, m_insideCounter;
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/cs.html#SEAL-3.0-BE">SEAL</a>
+template <class B = BigEndian>
+struct SEAL : public SEAL_Info<B>, public SymmetricCipherDocumentation
+{
+ typedef SymmetricCipherFinal<ConcretePolicyHolder<SEAL_Policy<B>, AdditiveCipherTemplate<> >, SEAL_Info<B> > Encryption;
+ typedef Encryption Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/secblock.h b/lib/cryptopp/secblock.h
new file mode 100644
index 000000000..40cce3341
--- /dev/null
+++ b/lib/cryptopp/secblock.h
@@ -0,0 +1,467 @@
+// secblock.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_SECBLOCK_H
+#define CRYPTOPP_SECBLOCK_H
+
+#include "config.h"
+#include "misc.h"
+#include <assert.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ************** secure memory allocation ***************
+
+template<class T>
+class AllocatorBase
+{
+public:
+ typedef T value_type;
+ typedef size_t size_type;
+#ifdef CRYPTOPP_MSVCRT6
+ typedef ptrdiff_t difference_type;
+#else
+ typedef std::ptrdiff_t difference_type;
+#endif
+ typedef T * pointer;
+ typedef const T * const_pointer;
+ typedef T & reference;
+ typedef const T & const_reference;
+
+ pointer address(reference r) const {return (&r);}
+ const_pointer address(const_reference r) const {return (&r); }
+ void construct(pointer p, const T& val) {new (p) T(val);}
+ void destroy(pointer p) {p->~T();}
+ size_type max_size() const {return ~size_type(0)/sizeof(T);} // switch to std::numeric_limits<T>::max later
+
+protected:
+ static void CheckSize(size_t n)
+ {
+ if (n > ~size_t(0) / sizeof(T))
+ throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
+ }
+};
+
+#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \
+typedef typename AllocatorBase<T>::value_type value_type;\
+typedef typename AllocatorBase<T>::size_type size_type;\
+typedef typename AllocatorBase<T>::difference_type difference_type;\
+typedef typename AllocatorBase<T>::pointer pointer;\
+typedef typename AllocatorBase<T>::const_pointer const_pointer;\
+typedef typename AllocatorBase<T>::reference reference;\
+typedef typename AllocatorBase<T>::const_reference const_reference;
+
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+// this pragma causes an internal compiler error if placed immediately before std::swap(a, b)
+#pragma warning(push)
+#pragma warning(disable: 4700) // VC60 workaround: don't know how to get rid of this warning
+#endif
+
+template <class T, class A>
+typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
+{
+ if (oldSize == newSize)
+ return p;
+
+ if (preserve)
+ {
+ typename A::pointer newPointer = a.allocate(newSize, NULL);
+ memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize));
+ a.deallocate(p, oldSize);
+ return newPointer;
+ }
+ else
+ {
+ a.deallocate(p, oldSize);
+ return a.allocate(newSize, NULL);
+ }
+}
+
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+#pragma warning(pop)
+#endif
+
+template <class T, bool T_Align16 = false>
+class AllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+ CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+ pointer allocate(size_type n, const void * = NULL)
+ {
+ this->CheckSize(n);
+ if (n == 0)
+ return NULL;
+
+#if CRYPTOPP_BOOL_ALIGN16_ENABLED
+ if (T_Align16 && n*sizeof(T) >= 16)
+ return (pointer)AlignedAllocate(n*sizeof(T));
+#endif
+
+ return (pointer)UnalignedAllocate(n*sizeof(T));
+ }
+
+ void deallocate(void *p, size_type n)
+ {
+ SecureWipeArray((pointer)p, n);
+
+#if CRYPTOPP_BOOL_ALIGN16_ENABLED
+ if (T_Align16 && n*sizeof(T) >= 16)
+ return AlignedDeallocate(p);
+#endif
+
+ UnalignedDeallocate(p);
+ }
+
+ pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
+ {
+ return StandardReallocate(*this, p, oldSize, newSize, preserve);
+ }
+
+ // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
+ // template class member called rebind".
+ template <class U> struct rebind { typedef AllocatorWithCleanup<U, T_Align16> other; };
+#if _MSC_VER >= 1500
+ AllocatorWithCleanup() {}
+ template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {}
+#endif
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
+#if CRYPTOPP_BOOL_X86
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>; // for Integer
+#endif
+
+template <class T>
+class NullAllocator : public AllocatorBase<T>
+{
+public:
+ CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+ pointer allocate(size_type n, const void * = NULL)
+ {
+ assert(false);
+ return NULL;
+ }
+
+ void deallocate(void *p, size_type n)
+ {
+ assert(false);
+ }
+
+ size_type max_size() const {return 0;}
+};
+
+// This allocator can't be used with standard collections because
+// they require that all objects of the same allocator type are equivalent.
+// So this is for use with SecBlock only.
+template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
+class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+ CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+ FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
+
+ pointer allocate(size_type n)
+ {
+ assert(IsAlignedOn(m_array, 8));
+
+ if (n <= S && !m_allocated)
+ {
+ m_allocated = true;
+ return GetAlignedArray();
+ }
+ else
+ return m_fallbackAllocator.allocate(n);
+ }
+
+ pointer allocate(size_type n, const void *hint)
+ {
+ if (n <= S && !m_allocated)
+ {
+ m_allocated = true;
+ return GetAlignedArray();
+ }
+ else
+ return m_fallbackAllocator.allocate(n, hint);
+ }
+
+ void deallocate(void *p, size_type n)
+ {
+ if (p == GetAlignedArray())
+ {
+ assert(n <= S);
+ assert(m_allocated);
+ m_allocated = false;
+ SecureWipeArray((pointer)p, n);
+ }
+ else
+ m_fallbackAllocator.deallocate(p, n);
+ }
+
+ pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
+ {
+ if (p == GetAlignedArray() && newSize <= S)
+ {
+ assert(oldSize <= S);
+ if (oldSize > newSize)
+ SecureWipeArray(p+newSize, oldSize-newSize);
+ return p;
+ }
+
+ pointer newPointer = allocate(newSize, NULL);
+ if (preserve)
+ memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
+ deallocate(p, oldSize);
+ return newPointer;
+ }
+
+ size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
+
+private:
+#ifdef __BORLANDC__
+ T* GetAlignedArray() {return m_array;}
+ T m_array[S];
+#else
+ T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;}
+ CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? S+8/sizeof(T) : S];
+#endif
+ A m_fallbackAllocator;
+ bool m_allocated;
+};
+
+//! a block of memory allocated using A
+template <class T, class A = AllocatorWithCleanup<T> >
+class SecBlock
+{
+public:
+ typedef typename A::value_type value_type;
+ typedef typename A::pointer iterator;
+ typedef typename A::const_pointer const_iterator;
+ typedef typename A::size_type size_type;
+
+ explicit SecBlock(size_type size=0)
+ : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
+ SecBlock(const SecBlock<T, A> &t)
+ : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));}
+ SecBlock(const T *t, size_type len)
+ : m_size(len)
+ {
+ m_ptr = m_alloc.allocate(len, NULL);
+ if (t == NULL)
+ memset_z(m_ptr, 0, len*sizeof(T));
+ else
+ memcpy(m_ptr, t, len*sizeof(T));
+ }
+
+ ~SecBlock()
+ {m_alloc.deallocate(m_ptr, m_size);}
+
+#ifdef __BORLANDC__
+ operator T *() const
+ {return (T*)m_ptr;}
+#else
+ operator const void *() const
+ {return m_ptr;}
+ operator void *()
+ {return m_ptr;}
+
+ operator const T *() const
+ {return m_ptr;}
+ operator T *()
+ {return m_ptr;}
+#endif
+
+// T *operator +(size_type offset)
+// {return m_ptr+offset;}
+
+// const T *operator +(size_type offset) const
+// {return m_ptr+offset;}
+
+// T& operator[](size_type index)
+// {assert(index >= 0 && index < m_size); return m_ptr[index];}
+
+// const T& operator[](size_type index) const
+// {assert(index >= 0 && index < m_size); return m_ptr[index];}
+
+ iterator begin()
+ {return m_ptr;}
+ const_iterator begin() const
+ {return m_ptr;}
+ iterator end()
+ {return m_ptr+m_size;}
+ const_iterator end() const
+ {return m_ptr+m_size;}
+
+ typename A::pointer data() {return m_ptr;}
+ typename A::const_pointer data() const {return m_ptr;}
+
+ size_type size() const {return m_size;}
+ bool empty() const {return m_size == 0;}
+
+ byte * BytePtr() {return (byte *)m_ptr;}
+ const byte * BytePtr() const {return (const byte *)m_ptr;}
+ size_type SizeInBytes() const {return m_size*sizeof(T);}
+
+ //! set contents and size
+ void Assign(const T *t, size_type len)
+ {
+ New(len);
+ memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T));
+ }
+
+ //! copy contents and size from another SecBlock
+ void Assign(const SecBlock<T, A> &t)
+ {
+ if (this != &t)
+ {
+ New(t.m_size);
+ memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));
+ }
+ }
+
+ SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
+ {
+ Assign(t);
+ return *this;
+ }
+
+ // append to this object
+ SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
+ {
+ size_type oldSize = m_size;
+ Grow(m_size+t.m_size);
+ memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
+ return *this;
+ }
+
+ // append operator
+ SecBlock<T, A> operator+(const SecBlock<T, A> &t)
+ {
+ SecBlock<T, A> result(m_size+t.m_size);
+ memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
+ memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
+ return result;
+ }
+
+ bool operator==(const SecBlock<T, A> &t) const
+ {
+ return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
+ }
+
+ bool operator!=(const SecBlock<T, A> &t) const
+ {
+ return !operator==(t);
+ }
+
+ //! change size, without preserving contents
+ void New(size_type newSize)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
+ m_size = newSize;
+ }
+
+ //! change size and set contents to 0
+ void CleanNew(size_type newSize)
+ {
+ New(newSize);
+ memset_z(m_ptr, 0, m_size*sizeof(T));
+ }
+
+ //! change size only if newSize > current size. contents are preserved
+ void Grow(size_type newSize)
+ {
+ if (newSize > m_size)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+ m_size = newSize;
+ }
+ }
+
+ //! change size only if newSize > current size. contents are preserved and additional area is set to 0
+ void CleanGrow(size_type newSize)
+ {
+ if (newSize > m_size)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+ memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
+ m_size = newSize;
+ }
+ }
+
+ //! change size and preserve contents
+ void resize(size_type newSize)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+ m_size = newSize;
+ }
+
+ //! swap contents and size with another SecBlock
+ void swap(SecBlock<T, A> &b)
+ {
+ std::swap(m_alloc, b.m_alloc);
+ std::swap(m_size, b.m_size);
+ std::swap(m_ptr, b.m_ptr);
+ }
+
+//private:
+ A m_alloc;
+ size_type m_size;
+ T *m_ptr;
+};
+
+typedef SecBlock<byte> SecByteBlock;
+typedef SecBlock<byte, AllocatorWithCleanup<byte, true> > AlignedSecByteBlock;
+typedef SecBlock<word> SecWordBlock;
+
+//! a SecBlock with fixed size, allocated statically
+template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
+class FixedSizeSecBlock : public SecBlock<T, A>
+{
+public:
+ explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
+};
+
+template <class T, unsigned int S, bool T_Align16 = true>
+class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
+{
+};
+
+//! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded
+template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
+class SecBlockWithHint : public SecBlock<T, A>
+{
+public:
+ explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
+};
+
+template<class T, bool A, class U, bool B>
+inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);}
+template<class T, bool A, class U, bool B>
+inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);}
+
+NAMESPACE_END
+
+NAMESPACE_BEGIN(std)
+template <class T, class A>
+inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
+{
+ a.swap(b);
+}
+
+#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
+// working for STLport 5.1.3 and MSVC 6 SP5
+template <class _Tp1, class _Tp2>
+inline CryptoPP::AllocatorWithCleanup<_Tp2>&
+__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
+{
+ return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
+}
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/seckey.h b/lib/cryptopp/seckey.h
new file mode 100644
index 000000000..35046a61b
--- /dev/null
+++ b/lib/cryptopp/seckey.h
@@ -0,0 +1,221 @@
+// seckey.h - written and placed in the public domain by Wei Dai
+
+// This file contains helper classes/functions for implementing secret key algorithms.
+
+#ifndef CRYPTOPP_SECKEY_H
+#define CRYPTOPP_SECKEY_H
+
+#include "cryptlib.h"
+#include "misc.h"
+#include "simple.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+inline CipherDir ReverseCipherDir(CipherDir dir)
+{
+ return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION;
+}
+
+//! to be inherited by block ciphers with fixed block size
+template <unsigned int N>
+class FixedBlockSize
+{
+public:
+ CRYPTOPP_CONSTANT(BLOCKSIZE = N)
+};
+
+// ************** rounds ***************
+
+//! to be inherited by ciphers with fixed number of rounds
+template <unsigned int R>
+class FixedRounds
+{
+public:
+ CRYPTOPP_CONSTANT(ROUNDS = R)
+};
+
+//! to be inherited by ciphers with variable number of rounds
+template <unsigned int D, unsigned int N=1, unsigned int M=INT_MAX> // use INT_MAX here because enums are treated as signed ints
+class VariableRounds
+{
+public:
+ CRYPTOPP_CONSTANT(DEFAULT_ROUNDS = D)
+ CRYPTOPP_CONSTANT(MIN_ROUNDS = N)
+ CRYPTOPP_CONSTANT(MAX_ROUNDS = M)
+ static unsigned int StaticGetDefaultRounds(size_t keylength) {return DEFAULT_ROUNDS;}
+
+protected:
+ inline void ThrowIfInvalidRounds(int rounds, const Algorithm *alg)
+ {
+ if (rounds < MIN_ROUNDS || rounds > MAX_ROUNDS)
+ throw InvalidRounds(alg->AlgorithmName(), rounds);
+ }
+
+ inline unsigned int GetRoundsAndThrowIfInvalid(const NameValuePairs &param, const Algorithm *alg)
+ {
+ int rounds = param.GetIntValueWithDefault("Rounds", DEFAULT_ROUNDS);
+ ThrowIfInvalidRounds(rounds, alg);
+ return (unsigned int)rounds;
+ }
+};
+
+// ************** key length ***************
+
+//! to be inherited by keyed algorithms with fixed key length
+template <unsigned int N, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE, unsigned int IV_L = 0>
+class FixedKeyLength
+{
+public:
+ CRYPTOPP_CONSTANT(KEYLENGTH=N)
+ CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N)
+ CRYPTOPP_CONSTANT(MAX_KEYLENGTH=N)
+ CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=N)
+ CRYPTOPP_CONSTANT(IV_REQUIREMENT = IV_REQ)
+ CRYPTOPP_CONSTANT(IV_LENGTH = IV_L)
+ static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t) {return KEYLENGTH;}
+};
+
+/// support query of variable key length, template parameters are default, min, max, multiple (default multiple 1)
+template <unsigned int D, unsigned int N, unsigned int M, unsigned int Q = 1, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE, unsigned int IV_L = 0>
+class VariableKeyLength
+{
+ // make these private to avoid Doxygen documenting them in all derived classes
+ CRYPTOPP_COMPILE_ASSERT(Q > 0);
+ CRYPTOPP_COMPILE_ASSERT(N % Q == 0);
+ CRYPTOPP_COMPILE_ASSERT(M % Q == 0);
+ CRYPTOPP_COMPILE_ASSERT(N < M);
+ CRYPTOPP_COMPILE_ASSERT(D >= N);
+ CRYPTOPP_COMPILE_ASSERT(M >= D);
+
+public:
+ CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N)
+ CRYPTOPP_CONSTANT(MAX_KEYLENGTH=M)
+ CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=D)
+ CRYPTOPP_CONSTANT(KEYLENGTH_MULTIPLE=Q)
+ CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ)
+ CRYPTOPP_CONSTANT(IV_LENGTH=IV_L)
+
+ static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t n)
+ {
+ if (n < (size_t)MIN_KEYLENGTH)
+ return MIN_KEYLENGTH;
+ else if (n > (size_t)MAX_KEYLENGTH)
+ return (size_t)MAX_KEYLENGTH;
+ else
+ {
+ n += KEYLENGTH_MULTIPLE-1;
+ return n - n%KEYLENGTH_MULTIPLE;
+ }
+ }
+};
+
+/// support query of key length that's the same as another class
+template <class T, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE, unsigned int IV_L = 0>
+class SameKeyLengthAs
+{
+public:
+ CRYPTOPP_CONSTANT(MIN_KEYLENGTH=T::MIN_KEYLENGTH)
+ CRYPTOPP_CONSTANT(MAX_KEYLENGTH=T::MAX_KEYLENGTH)
+ CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH)
+ CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ)
+ CRYPTOPP_CONSTANT(IV_LENGTH=IV_L)
+
+ static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength)
+ {return T::StaticGetValidKeyLength(keylength);}
+};
+
+// ************** implementation helper for SimpleKeyed ***************
+
+//! _
+template <class BASE, class INFO = BASE>
+class CRYPTOPP_NO_VTABLE SimpleKeyingInterfaceImpl : public BASE
+{
+public:
+ size_t MinKeyLength() const {return INFO::MIN_KEYLENGTH;}
+ size_t MaxKeyLength() const {return (size_t)INFO::MAX_KEYLENGTH;}
+ size_t DefaultKeyLength() const {return INFO::DEFAULT_KEYLENGTH;}
+ size_t GetValidKeyLength(size_t n) const {return INFO::StaticGetValidKeyLength(n);}
+ SimpleKeyingInterface::IV_Requirement IVRequirement() const {return (SimpleKeyingInterface::IV_Requirement)INFO::IV_REQUIREMENT;}
+ unsigned int IVSize() const {return INFO::IV_LENGTH;}
+};
+
+template <class INFO, class BASE = BlockCipher>
+class CRYPTOPP_NO_VTABLE BlockCipherImpl : public AlgorithmImpl<SimpleKeyingInterfaceImpl<TwoBases<BASE, INFO> > >
+{
+public:
+ unsigned int BlockSize() const {return this->BLOCKSIZE;}
+};
+
+//! _
+template <CipherDir DIR, class BASE>
+class BlockCipherFinal : public ClonableImpl<BlockCipherFinal<DIR, BASE>, BASE>
+{
+public:
+ BlockCipherFinal() {}
+ BlockCipherFinal(const byte *key)
+ {this->SetKey(key, this->DEFAULT_KEYLENGTH);}
+ BlockCipherFinal(const byte *key, size_t length)
+ {this->SetKey(key, length);}
+ BlockCipherFinal(const byte *key, size_t length, unsigned int rounds)
+ {this->SetKeyWithRounds(key, length, rounds);}
+
+ bool IsForwardTransformation() const {return DIR == ENCRYPTION;}
+};
+
+//! _
+template <class BASE, class INFO = BASE>
+class MessageAuthenticationCodeImpl : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
+{
+};
+
+//! _
+template <class BASE>
+class MessageAuthenticationCodeFinal : public ClonableImpl<MessageAuthenticationCodeFinal<BASE>, MessageAuthenticationCodeImpl<BASE> >
+{
+public:
+ MessageAuthenticationCodeFinal() {}
+ MessageAuthenticationCodeFinal(const byte *key)
+ {this->SetKey(key, this->DEFAULT_KEYLENGTH);}
+ MessageAuthenticationCodeFinal(const byte *key, size_t length)
+ {this->SetKey(key, length);}
+};
+
+// ************** documentation ***************
+
+//! These objects usually should not be used directly. See CipherModeDocumentation instead.
+/*! Each class derived from this one defines two types, Encryption and Decryption,
+ both of which implement the BlockCipher interface. */
+struct BlockCipherDocumentation
+{
+ //! implements the BlockCipher interface
+ typedef BlockCipher Encryption;
+ //! implements the BlockCipher interface
+ typedef BlockCipher Decryption;
+};
+
+/*! \brief Each class derived from this one defines two types, Encryption and Decryption,
+ both of which implement the SymmetricCipher interface. Two types of classes derive
+ from this class: stream ciphers and block cipher modes. Stream ciphers can be used
+ alone, cipher mode classes need to be used with a block cipher. See CipherModeDocumentation
+ for more for information about using cipher modes and block ciphers. */
+struct SymmetricCipherDocumentation
+{
+ //! implements the SymmetricCipher interface
+ typedef SymmetricCipher Encryption;
+ //! implements the SymmetricCipher interface
+ typedef SymmetricCipher Decryption;
+};
+
+/*! \brief Each class derived from this one defines two types, Encryption and Decryption,
+ both of which implement the AuthenticatedSymmetricCipher interface. */
+struct AuthenticatedSymmetricCipherDocumentation
+{
+ //! implements the AuthenticatedSymmetricCipher interface
+ typedef AuthenticatedSymmetricCipher Encryption;
+ //! implements the AuthenticatedSymmetricCipher interface
+ typedef AuthenticatedSymmetricCipher Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/seed.cpp b/lib/cryptopp/seed.cpp
new file mode 100644
index 000000000..101902dce
--- /dev/null
+++ b/lib/cryptopp/seed.cpp
@@ -0,0 +1,104 @@
+// seed.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "seed.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const word32 s_kc[16] = {
+ 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf,
+ 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b};
+
+static const byte s_s0[256] = {
+ 0xA9, 0x85, 0xD6, 0xD3, 0x54, 0x1D, 0xAC, 0x25, 0x5D, 0x43, 0x18, 0x1E, 0x51, 0xFC, 0xCA, 0x63, 0x28,
+ 0x44, 0x20, 0x9D, 0xE0, 0xE2, 0xC8, 0x17, 0xA5, 0x8F, 0x03, 0x7B, 0xBB, 0x13, 0xD2, 0xEE, 0x70, 0x8C,
+ 0x3F, 0xA8, 0x32, 0xDD, 0xF6, 0x74, 0xEC, 0x95, 0x0B, 0x57, 0x5C, 0x5B, 0xBD, 0x01, 0x24, 0x1C, 0x73,
+ 0x98, 0x10, 0xCC, 0xF2, 0xD9, 0x2C, 0xE7, 0x72, 0x83, 0x9B, 0xD1, 0x86, 0xC9, 0x60, 0x50, 0xA3, 0xEB,
+ 0x0D, 0xB6, 0x9E, 0x4F, 0xB7, 0x5A, 0xC6, 0x78, 0xA6, 0x12, 0xAF, 0xD5, 0x61, 0xC3, 0xB4, 0x41, 0x52,
+ 0x7D, 0x8D, 0x08, 0x1F, 0x99, 0x00, 0x19, 0x04, 0x53, 0xF7, 0xE1, 0xFD, 0x76, 0x2F, 0x27, 0xB0, 0x8B,
+ 0x0E, 0xAB, 0xA2, 0x6E, 0x93, 0x4D, 0x69, 0x7C, 0x09, 0x0A, 0xBF, 0xEF, 0xF3, 0xC5, 0x87, 0x14, 0xFE,
+ 0x64, 0xDE, 0x2E, 0x4B, 0x1A, 0x06, 0x21, 0x6B, 0x66, 0x02, 0xF5, 0x92, 0x8A, 0x0C, 0xB3, 0x7E, 0xD0,
+ 0x7A, 0x47, 0x96, 0xE5, 0x26, 0x80, 0xAD, 0xDF, 0xA1, 0x30, 0x37, 0xAE, 0x36, 0x15, 0x22, 0x38, 0xF4,
+ 0xA7, 0x45, 0x4C, 0x81, 0xE9, 0x84, 0x97, 0x35, 0xCB, 0xCE, 0x3C, 0x71, 0x11, 0xC7, 0x89, 0x75, 0xFB,
+ 0xDA, 0xF8, 0x94, 0x59, 0x82, 0xC4, 0xFF, 0x49, 0x39, 0x67, 0xC0, 0xCF, 0xD7, 0xB8, 0x0F, 0x8E, 0x42,
+ 0x23, 0x91, 0x6C, 0xDB, 0xA4, 0x34, 0xF1, 0x48, 0xC2, 0x6F, 0x3D, 0x2D, 0x40, 0xBE, 0x3E, 0xBC, 0xC1,
+ 0xAA, 0xBA, 0x4E, 0x55, 0x3B, 0xDC, 0x68, 0x7F, 0x9C, 0xD8, 0x4A, 0x56, 0x77, 0xA0, 0xED, 0x46, 0xB5,
+ 0x2B, 0x65, 0xFA, 0xE3, 0xB9, 0xB1, 0x9F, 0x5E, 0xF9, 0xE6, 0xB2, 0x31, 0xEA, 0x6D, 0x5F, 0xE4, 0xF0,
+ 0xCD, 0x88, 0x16, 0x3A, 0x58, 0xD4, 0x62, 0x29, 0x07, 0x33, 0xE8, 0x1B, 0x05, 0x79, 0x90, 0x6A, 0x2A,
+ 0x9A};
+
+static const byte s_s1[256] = {
+ 0x38, 0xE8, 0x2D, 0xA6, 0xCF, 0xDE, 0xB3, 0xB8, 0xAF, 0x60, 0x55, 0xC7, 0x44, 0x6F, 0x6B, 0x5B, 0xC3,
+ 0x62, 0x33, 0xB5, 0x29, 0xA0, 0xE2, 0xA7, 0xD3, 0x91, 0x11, 0x06, 0x1C, 0xBC, 0x36, 0x4B, 0xEF, 0x88,
+ 0x6C, 0xA8, 0x17, 0xC4, 0x16, 0xF4, 0xC2, 0x45, 0xE1, 0xD6, 0x3F, 0x3D, 0x8E, 0x98, 0x28, 0x4E, 0xF6,
+ 0x3E, 0xA5, 0xF9, 0x0D, 0xDF, 0xD8, 0x2B, 0x66, 0x7A, 0x27, 0x2F, 0xF1, 0x72, 0x42, 0xD4, 0x41, 0xC0,
+ 0x73, 0x67, 0xAC, 0x8B, 0xF7, 0xAD, 0x80, 0x1F, 0xCA, 0x2C, 0xAA, 0x34, 0xD2, 0x0B, 0xEE, 0xE9, 0x5D,
+ 0x94, 0x18, 0xF8, 0x57, 0xAE, 0x08, 0xC5, 0x13, 0xCD, 0x86, 0xB9, 0xFF, 0x7D, 0xC1, 0x31, 0xF5, 0x8A,
+ 0x6A, 0xB1, 0xD1, 0x20, 0xD7, 0x02, 0x22, 0x04, 0x68, 0x71, 0x07, 0xDB, 0x9D, 0x99, 0x61, 0xBE, 0xE6,
+ 0x59, 0xDD, 0x51, 0x90, 0xDC, 0x9A, 0xA3, 0xAB, 0xD0, 0x81, 0x0F, 0x47, 0x1A, 0xE3, 0xEC, 0x8D, 0xBF,
+ 0x96, 0x7B, 0x5C, 0xA2, 0xA1, 0x63, 0x23, 0x4D, 0xC8, 0x9E, 0x9C, 0x3A, 0x0C, 0x2E, 0xBA, 0x6E, 0x9F,
+ 0x5A, 0xF2, 0x92, 0xF3, 0x49, 0x78, 0xCC, 0x15, 0xFB, 0x70, 0x75, 0x7F, 0x35, 0x10, 0x03, 0x64, 0x6D,
+ 0xC6, 0x74, 0xD5, 0xB4, 0xEA, 0x09, 0x76, 0x19, 0xFE, 0x40, 0x12, 0xE0, 0xBD, 0x05, 0xFA, 0x01, 0xF0,
+ 0x2A, 0x5E, 0xA9, 0x56, 0x43, 0x85, 0x14, 0x89, 0x9B, 0xB0, 0xE5, 0x48, 0x79, 0x97, 0xFC, 0x1E, 0x82,
+ 0x21, 0x8C, 0x1B, 0x5F, 0x77, 0x54, 0xB2, 0x1D, 0x25, 0x4F, 0x00, 0x46, 0xED, 0x58, 0x52, 0xEB, 0x7E,
+ 0xDA, 0xC9, 0xFD, 0x30, 0x95, 0x65, 0x3C, 0xB6, 0xE4, 0xBB, 0x7C, 0x0E, 0x50, 0x39, 0x26, 0x32, 0x84,
+ 0x69, 0x93, 0x37, 0xE7, 0x24, 0xA4, 0xCB, 0x53, 0x0A, 0x87, 0xD9, 0x4C, 0x83, 0x8F, 0xCE, 0x3B, 0x4A,
+ 0xB7};
+
+#define SS0(x) ((s_s0[x]*0x01010101UL) & 0x3FCFF3FC)
+#define SS1(x) ((s_s1[x]*0x01010101UL) & 0xFC3FCFF3)
+#define SS2(x) ((s_s0[x]*0x01010101UL) & 0xF3FC3FCF)
+#define SS3(x) ((s_s1[x]*0x01010101UL) & 0xCFF3FC3F)
+#define G(x) (SS0(GETBYTE(x, 0)) ^ SS1(GETBYTE(x, 1)) ^ SS2(GETBYTE(x, 2)) ^ SS3(GETBYTE(x, 3)))
+
+void SEED::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
+{
+ AssertValidKeyLength(length);
+
+ word64 key01, key23;
+ GetBlock<word64, BigEndian> get(userKey);
+ get(key01)(key23);
+ word32 *k = m_k;
+ size_t kInc = 2;
+ if (!IsForwardTransformation())
+ {
+ k = k+30;
+ kInc = 0-kInc;
+ }
+
+ for (int i=0; i<ROUNDS; i++)
+ {
+ word32 t0 = word32(key01>>32) + word32(key23>>32) - s_kc[i];
+ word32 t1 = word32(key01) - word32(key23) + s_kc[i];
+ k[0] = G(t0);
+ k[1] = G(t1);
+ k+=kInc;
+ if (i&1)
+ key23 = rotlFixed<word64>(key23, 8);
+ else
+ key01 = rotrFixed<word64>(key01, 8);
+ }
+}
+
+void SEED::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ typedef BlockGetAndPut<word32, BigEndian> Block;
+ word32 a0, a1, b0, b1, t0, t1;
+ Block::Get(inBlock)(a0)(a1)(b0)(b1);
+
+ for (int i=0; i<ROUNDS; i+=2)
+ {
+ t0 = b0 ^ m_k[2*i+0]; t1 = b1 ^ m_k[2*i+1] ^ t0;
+ t1 = G(t1); t0 += t1; t0 = G(t0); t1 += t0; t1 = G(t1);
+ a0 ^= t0 + t1; a1 ^= t1;
+
+ t0 = a0 ^ m_k[2*i+2]; t1 = a1 ^ m_k[2*i+3] ^ t0;
+ t1 = G(t1); t0 += t1; t0 = G(t0); t1 += t0; t1 = G(t1);
+ b0 ^= t0 + t1; b1 ^= t1;
+ }
+
+ Block::Put(xorBlock, outBlock)(b0)(b1)(a0)(a1);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/seed.h b/lib/cryptopp/seed.h
new file mode 100644
index 000000000..871284de7
--- /dev/null
+++ b/lib/cryptopp/seed.h
@@ -0,0 +1,38 @@
+#ifndef CRYPTOPP_SEED_H
+#define CRYPTOPP_SEED_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+struct SEED_Info : public FixedBlockSize<16>, public FixedKeyLength<16>, public FixedRounds<16>
+{
+ static const char *StaticAlgorithmName() {return "SEED";}
+};
+
+/// <a href="http://www.cryptolounge.org/wiki/SEED">SEED</a>
+class SEED : public SEED_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<SEED_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+ protected:
+ FixedSizeSecBlock<word32, 32> m_k;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/sha.cpp b/lib/cryptopp/sha.cpp
new file mode 100644
index 000000000..df947ad16
--- /dev/null
+++ b/lib/cryptopp/sha.cpp
@@ -0,0 +1,900 @@
+// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c
+
+// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2.
+// Both are in the public domain.
+
+// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#include "sha.h"
+#include "misc.h"
+#include "cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// start of Steve Reid's code
+
+#define blk0(i) (W[i] = data[i])
+#define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
+
+void SHA1::InitState(HashWordType *state)
+{
+ state[0] = 0x67452301L;
+ state[1] = 0xEFCDAB89L;
+ state[2] = 0x98BADCFEL;
+ state[3] = 0x10325476L;
+ state[4] = 0xC3D2E1F0L;
+}
+
+#define f1(x,y,z) (z^(x&(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);
+
+void SHA1::Transform(word32 *state, const word32 *data)
+{
+ word32 W[16];
+ /* Copy context->state[] to working vars */
+ word32 a = state[0];
+ word32 b = state[1];
+ word32 c = state[2];
+ word32 d = state[3];
+ word32 e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+}
+
+// end of Steve Reid's code
+
+// *************************************************************
+
+void SHA224::InitState(HashWordType *state)
+{
+ static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
+ memcpy(state, s, sizeof(s));
+}
+
+void SHA256::InitState(HashWordType *state)
+{
+ static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+ memcpy(state, s, sizeof(s));
+}
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+CRYPTOPP_ALIGN_DATA(16) extern const word32 SHA256_K[64] CRYPTOPP_SECTION_ALIGN16 = {
+#else
+extern const word32 SHA256_K[64] = {
+#endif
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
+
+#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
+
+static void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+ , ... // VC60 workaround: prevent VC 6 from inlining this function
+#endif
+ )
+{
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+ AS2(mov ecx, [state])
+ AS2(mov edx, [data])
+#endif
+
+ #define LOCALS_SIZE 8*4 + 16*4 + 4*WORD_SZ
+ #define H(i) [BASE+ASM_MOD(1024+7-(i),8)*4]
+ #define G(i) H(i+1)
+ #define F(i) H(i+2)
+ #define E(i) H(i+3)
+ #define D(i) H(i+4)
+ #define C(i) H(i+5)
+ #define B(i) H(i+6)
+ #define A(i) H(i+7)
+ #define Wt(i) BASE+8*4+ASM_MOD(1024+15-(i),16)*4
+ #define Wt_2(i) Wt((i)-2)
+ #define Wt_15(i) Wt((i)-15)
+ #define Wt_7(i) Wt((i)-7)
+ #define K_END [BASE+8*4+16*4+0*WORD_SZ]
+ #define STATE_SAVE [BASE+8*4+16*4+1*WORD_SZ]
+ #define DATA_SAVE [BASE+8*4+16*4+2*WORD_SZ]
+ #define DATA_END [BASE+8*4+16*4+3*WORD_SZ]
+ #define Kt(i) WORD_REG(si)+(i)*4
+#if CRYPTOPP_BOOL_X86
+ #define BASE esp+4
+#elif defined(__GNUC__)
+ #define BASE r8
+#else
+ #define BASE rsp
+#endif
+
+#define RA0(i, edx, edi) \
+ AS2( add edx, [Kt(i)] )\
+ AS2( add edx, [Wt(i)] )\
+ AS2( add edx, H(i) )\
+
+#define RA1(i, edx, edi)
+
+#define RB0(i, edx, edi)
+
+#define RB1(i, edx, edi) \
+ AS2( mov AS_REG_7d, [Wt_2(i)] )\
+ AS2( mov edi, [Wt_15(i)])\
+ AS2( mov ebx, AS_REG_7d )\
+ AS2( shr AS_REG_7d, 10 )\
+ AS2( ror ebx, 17 )\
+ AS2( xor AS_REG_7d, ebx )\
+ AS2( ror ebx, 2 )\
+ AS2( xor ebx, AS_REG_7d )/* s1(W_t-2) */\
+ AS2( add ebx, [Wt_7(i)])\
+ AS2( mov AS_REG_7d, edi )\
+ AS2( shr AS_REG_7d, 3 )\
+ AS2( ror edi, 7 )\
+ AS2( add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\
+ AS2( xor AS_REG_7d, edi )\
+ AS2( add edx, [Kt(i)])\
+ AS2( ror edi, 11 )\
+ AS2( add edx, H(i) )\
+ AS2( xor AS_REG_7d, edi )/* s0(W_t-15) */\
+ AS2( add AS_REG_7d, ebx )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\
+ AS2( mov [Wt(i)], AS_REG_7d)\
+ AS2( add edx, AS_REG_7d )\
+
+#define ROUND(i, r, eax, ecx, edi, edx)\
+ /* in: edi = E */\
+ /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\
+ AS2( mov edx, F(i) )\
+ AS2( xor edx, G(i) )\
+ AS2( and edx, edi )\
+ AS2( xor edx, G(i) )/* Ch(E,F,G) = (G^(E&(F^G))) */\
+ AS2( mov AS_REG_7d, edi )\
+ AS2( ror edi, 6 )\
+ AS2( ror AS_REG_7d, 25 )\
+ RA##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\
+ AS2( xor AS_REG_7d, edi )\
+ AS2( ror edi, 5 )\
+ AS2( xor AS_REG_7d, edi )/* S1(E) */\
+ AS2( add edx, AS_REG_7d )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\
+ RB##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\
+ /* in: ecx = A, eax = B^C, edx = T1 */\
+ /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\
+ AS2( mov ebx, ecx )\
+ AS2( xor ecx, B(i) )/* A^B */\
+ AS2( and eax, ecx )\
+ AS2( xor eax, B(i) )/* Maj(A,B,C) = B^((A^B)&(B^C) */\
+ AS2( mov AS_REG_7d, ebx )\
+ AS2( ror ebx, 2 )\
+ AS2( add eax, edx )/* T1 + Maj(A,B,C) */\
+ AS2( add edx, D(i) )\
+ AS2( mov D(i), edx )\
+ AS2( ror AS_REG_7d, 22 )\
+ AS2( xor AS_REG_7d, ebx )\
+ AS2( ror ebx, 11 )\
+ AS2( xor AS_REG_7d, ebx )\
+ AS2( add eax, AS_REG_7d )/* T1 + S0(A) + Maj(A,B,C) */\
+ AS2( mov H(i), eax )\
+
+#define SWAP_COPY(i) \
+ AS2( mov WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\
+ AS1( bswap WORD_REG(bx))\
+ AS2( mov [Wt(i*(1+CRYPTOPP_BOOL_X64)+CRYPTOPP_BOOL_X64)], WORD_REG(bx))
+
+#if defined(__GNUC__)
+ #if CRYPTOPP_BOOL_X64
+ FixedSizeAlignedSecBlock<byte, LOCALS_SIZE> workspace;
+ #endif
+ __asm__ __volatile__
+ (
+ #if CRYPTOPP_BOOL_X64
+ "lea %4, %%r8;"
+ #endif
+ ".intel_syntax noprefix;"
+#elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ ALIGN 8
+ X86_SHA256_HashBlocks PROC FRAME
+ rex_push_reg rsi
+ push_reg rdi
+ push_reg rbx
+ push_reg rbp
+ alloc_stack(LOCALS_SIZE+8)
+ .endprolog
+ mov rdi, r8
+ lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4]
+#endif
+
+#if CRYPTOPP_BOOL_X86
+ #ifndef __GNUC__
+ AS2( mov edi, [len])
+ AS2( lea WORD_REG(si), [SHA256_K+48*4])
+ #endif
+ #if !defined(_MSC_VER) || (_MSC_VER < 1400)
+ AS_PUSH_IF86(bx)
+ #endif
+
+ AS_PUSH_IF86(bp)
+ AS2( mov ebx, esp)
+ AS2( and esp, -16)
+ AS2( sub WORD_REG(sp), LOCALS_SIZE)
+ AS_PUSH_IF86(bx)
+#endif
+ AS2( mov STATE_SAVE, WORD_REG(cx))
+ AS2( mov DATA_SAVE, WORD_REG(dx))
+ AS2( lea WORD_REG(ax), [WORD_REG(di) + WORD_REG(dx)])
+ AS2( mov DATA_END, WORD_REG(ax))
+ AS2( mov K_END, WORD_REG(si))
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+#if CRYPTOPP_BOOL_X86
+ AS2( test edi, 1)
+ ASJ( jnz, 2, f)
+ AS1( dec DWORD PTR K_END)
+#endif
+ AS2( movdqa xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16])
+ AS2( movdqa xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16])
+#endif
+
+#if CRYPTOPP_BOOL_X86
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ ASJ( jmp, 0, f)
+#endif
+ ASL(2) // non-SSE2
+ AS2( mov esi, ecx)
+ AS2( lea edi, A(0))
+ AS2( mov ecx, 8)
+ AS1( rep movsd)
+ AS2( mov esi, K_END)
+ ASJ( jmp, 3, f)
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ ASL(0)
+ AS2( movdqa E(0), xmm1)
+ AS2( movdqa A(0), xmm0)
+#endif
+#if CRYPTOPP_BOOL_X86
+ ASL(3)
+#endif
+ AS2( sub WORD_REG(si), 48*4)
+ SWAP_COPY(0) SWAP_COPY(1) SWAP_COPY(2) SWAP_COPY(3)
+ SWAP_COPY(4) SWAP_COPY(5) SWAP_COPY(6) SWAP_COPY(7)
+#if CRYPTOPP_BOOL_X86
+ SWAP_COPY(8) SWAP_COPY(9) SWAP_COPY(10) SWAP_COPY(11)
+ SWAP_COPY(12) SWAP_COPY(13) SWAP_COPY(14) SWAP_COPY(15)
+#endif
+ AS2( mov edi, E(0)) // E
+ AS2( mov eax, B(0)) // B
+ AS2( xor eax, C(0)) // B^C
+ AS2( mov ecx, A(0)) // A
+
+ ROUND(0, 0, eax, ecx, edi, edx)
+ ROUND(1, 0, ecx, eax, edx, edi)
+ ROUND(2, 0, eax, ecx, edi, edx)
+ ROUND(3, 0, ecx, eax, edx, edi)
+ ROUND(4, 0, eax, ecx, edi, edx)
+ ROUND(5, 0, ecx, eax, edx, edi)
+ ROUND(6, 0, eax, ecx, edi, edx)
+ ROUND(7, 0, ecx, eax, edx, edi)
+ ROUND(8, 0, eax, ecx, edi, edx)
+ ROUND(9, 0, ecx, eax, edx, edi)
+ ROUND(10, 0, eax, ecx, edi, edx)
+ ROUND(11, 0, ecx, eax, edx, edi)
+ ROUND(12, 0, eax, ecx, edi, edx)
+ ROUND(13, 0, ecx, eax, edx, edi)
+ ROUND(14, 0, eax, ecx, edi, edx)
+ ROUND(15, 0, ecx, eax, edx, edi)
+
+ ASL(1)
+ AS2(add WORD_REG(si), 4*16)
+ ROUND(0, 1, eax, ecx, edi, edx)
+ ROUND(1, 1, ecx, eax, edx, edi)
+ ROUND(2, 1, eax, ecx, edi, edx)
+ ROUND(3, 1, ecx, eax, edx, edi)
+ ROUND(4, 1, eax, ecx, edi, edx)
+ ROUND(5, 1, ecx, eax, edx, edi)
+ ROUND(6, 1, eax, ecx, edi, edx)
+ ROUND(7, 1, ecx, eax, edx, edi)
+ ROUND(8, 1, eax, ecx, edi, edx)
+ ROUND(9, 1, ecx, eax, edx, edi)
+ ROUND(10, 1, eax, ecx, edi, edx)
+ ROUND(11, 1, ecx, eax, edx, edi)
+ ROUND(12, 1, eax, ecx, edi, edx)
+ ROUND(13, 1, ecx, eax, edx, edi)
+ ROUND(14, 1, eax, ecx, edi, edx)
+ ROUND(15, 1, ecx, eax, edx, edi)
+ AS2( cmp WORD_REG(si), K_END)
+ ASJ( jb, 1, b)
+
+ AS2( mov WORD_REG(dx), DATA_SAVE)
+ AS2( add WORD_REG(dx), 64)
+ AS2( mov AS_REG_7, STATE_SAVE)
+ AS2( mov DATA_SAVE, WORD_REG(dx))
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+#if CRYPTOPP_BOOL_X86
+ AS2( test DWORD PTR K_END, 1)
+ ASJ( jz, 4, f)
+#endif
+ AS2( movdqa xmm1, XMMWORD_PTR [AS_REG_7+1*16])
+ AS2( movdqa xmm0, XMMWORD_PTR [AS_REG_7+0*16])
+ AS2( paddd xmm1, E(0))
+ AS2( paddd xmm0, A(0))
+ AS2( movdqa [AS_REG_7+1*16], xmm1)
+ AS2( movdqa [AS_REG_7+0*16], xmm0)
+ AS2( cmp WORD_REG(dx), DATA_END)
+ ASJ( jb, 0, b)
+#endif
+
+#if CRYPTOPP_BOOL_X86
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ ASJ( jmp, 5, f)
+ ASL(4) // non-SSE2
+#endif
+ AS2( add [AS_REG_7+0*4], ecx) // A
+ AS2( add [AS_REG_7+4*4], edi) // E
+ AS2( mov eax, B(0))
+ AS2( mov ebx, C(0))
+ AS2( mov ecx, D(0))
+ AS2( add [AS_REG_7+1*4], eax)
+ AS2( add [AS_REG_7+2*4], ebx)
+ AS2( add [AS_REG_7+3*4], ecx)
+ AS2( mov eax, F(0))
+ AS2( mov ebx, G(0))
+ AS2( mov ecx, H(0))
+ AS2( add [AS_REG_7+5*4], eax)
+ AS2( add [AS_REG_7+6*4], ebx)
+ AS2( add [AS_REG_7+7*4], ecx)
+ AS2( mov ecx, AS_REG_7d)
+ AS2( cmp WORD_REG(dx), DATA_END)
+ ASJ( jb, 2, b)
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ ASL(5)
+#endif
+#endif
+
+ AS_POP_IF86(sp)
+ AS_POP_IF86(bp)
+ #if !defined(_MSC_VER) || (_MSC_VER < 1400)
+ AS_POP_IF86(bx)
+ #endif
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+ add rsp, LOCALS_SIZE+8
+ pop rbp
+ pop rbx
+ pop rdi
+ pop rsi
+ ret
+ X86_SHA256_HashBlocks ENDP
+#endif
+
+#ifdef __GNUC__
+ ".att_syntax prefix;"
+ :
+ : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len)
+ #if CRYPTOPP_BOOL_X64
+ , "m" (workspace[0])
+ #endif
+ : "memory", "cc", "%eax"
+ #if CRYPTOPP_BOOL_X64
+ , "%rbx", "%r8", "%r10"
+ #endif
+ );
+#endif
+}
+
+#endif // #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
+
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len);
+}
+#endif
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+
+size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length)
+{
+ X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
+ return length % BLOCKSIZE;
+}
+
+size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length)
+{
+ X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
+ return length % BLOCKSIZE;
+}
+
+#endif
+
+#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
+
+#define Ch(x,y,z) (z^(x&(y^z)))
+#define Maj(x,y,z) (y^((x^y)&(y^z)))
+
+#define a(i) T[(0-i)&7]
+#define b(i) T[(1-i)&7]
+#define c(i) T[(2-i)&7]
+#define d(i) T[(3-i)&7]
+#define e(i) T[(4-i)&7]
+#define f(i) T[(5-i)&7]
+#define g(i) T[(6-i)&7]
+#define h(i) T[(7-i)&7]
+
+#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
+ d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
+
+// for SHA256
+#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
+#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
+#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
+#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
+
+void SHA256::Transform(word32 *state, const word32 *data)
+{
+ word32 W[16];
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ // this byte reverse is a waste of time, but this function is only called by MDC
+ ByteReverse(W, data, BLOCKSIZE);
+ X86_SHA256_HashBlocks(state, W, BLOCKSIZE - !HasSSE2());
+#else
+ word32 T[8];
+ /* Copy context->state[] to working vars */
+ memcpy(T, state, sizeof(T));
+ /* 64 operations, partially loop unrolled */
+ for (unsigned int j=0; j<64; j+=16)
+ {
+ R( 0); R( 1); R( 2); R( 3);
+ R( 4); R( 5); R( 6); R( 7);
+ R( 8); R( 9); R(10); R(11);
+ R(12); R(13); R(14); R(15);
+ }
+ /* Add the working vars back into context.state[] */
+ state[0] += a(0);
+ state[1] += b(0);
+ state[2] += c(0);
+ state[3] += d(0);
+ state[4] += e(0);
+ state[5] += f(0);
+ state[6] += g(0);
+ state[7] += h(0);
+#endif
+}
+
+/*
+// smaller but slower
+void SHA256::Transform(word32 *state, const word32 *data)
+{
+ word32 T[20];
+ word32 W[32];
+ unsigned int i = 0, j = 0;
+ word32 *t = T+8;
+
+ memcpy(t, state, 8*4);
+ word32 e = t[4], a = t[0];
+
+ do
+ {
+ word32 w = data[j];
+ W[j] = w;
+ w += SHA256_K[j];
+ w += t[7];
+ w += S1(e);
+ w += Ch(e, t[5], t[6]);
+ e = t[3] + w;
+ t[3] = t[3+8] = e;
+ w += S0(t[0]);
+ a = w + Maj(a, t[1], t[2]);
+ t[-1] = t[7] = a;
+ --t;
+ ++j;
+ if (j%8 == 0)
+ t += 8;
+ } while (j<16);
+
+ do
+ {
+ i = j&0xf;
+ word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7];
+ W[i+16] = W[i] = w;
+ w += SHA256_K[j];
+ w += t[7];
+ w += S1(e);
+ w += Ch(e, t[5], t[6]);
+ e = t[3] + w;
+ t[3] = t[3+8] = e;
+ w += S0(t[0]);
+ a = w + Maj(a, t[1], t[2]);
+ t[-1] = t[7] = a;
+
+ w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7];
+ W[(i+1)+16] = W[(i+1)] = w;
+ w += SHA256_K[j+1];
+ w += (t-1)[7];
+ w += S1(e);
+ w += Ch(e, (t-1)[5], (t-1)[6]);
+ e = (t-1)[3] + w;
+ (t-1)[3] = (t-1)[3+8] = e;
+ w += S0((t-1)[0]);
+ a = w + Maj(a, (t-1)[1], (t-1)[2]);
+ (t-1)[-1] = (t-1)[7] = a;
+
+ t-=2;
+ j+=2;
+ if (j%8 == 0)
+ t += 8;
+ } while (j<64);
+
+ state[0] += a;
+ state[1] += t[1];
+ state[2] += t[2];
+ state[3] += t[3];
+ state[4] += e;
+ state[5] += t[5];
+ state[6] += t[6];
+ state[7] += t[7];
+}
+*/
+
+#undef S0
+#undef S1
+#undef s0
+#undef s1
+#undef R
+
+// *************************************************************
+
+void SHA384::InitState(HashWordType *state)
+{
+ static const word64 s[8] = {
+ W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),
+ W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),
+ W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),
+ W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};
+ memcpy(state, s, sizeof(s));
+}
+
+void SHA512::InitState(HashWordType *state)
+{
+ static const word64 s[8] = {
+ W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
+ W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
+ W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
+ W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};
+ memcpy(state, s, sizeof(s));
+}
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = {
+#else
+static const word64 SHA512_K[80] = {
+#endif
+ W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
+ W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
+ W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
+ W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
+ W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
+ W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
+ W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
+ W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
+ W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
+ W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
+ W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
+ W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
+ W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
+ W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
+ W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
+ W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
+ W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
+ W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
+ W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
+ W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
+ W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
+ W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
+ W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
+ W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
+ W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
+ W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
+ W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
+ W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
+ W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
+ W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
+ W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
+ W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
+ W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
+ W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
+ W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
+ W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
+ W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
+ W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
+ W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
+ W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
+};
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+// put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version
+CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data)
+{
+#ifdef __GNUC__
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ AS1( push ebx)
+ AS2( mov ebx, eax)
+#else
+ AS1( push ebx)
+ AS1( push esi)
+ AS1( push edi)
+ AS2( lea ebx, SHA512_K)
+#endif
+
+ AS2( mov eax, esp)
+ AS2( and esp, 0xfffffff0)
+ AS2( sub esp, 27*16) // 17*16 for expanded data, 20*8 for state
+ AS1( push eax)
+ AS2( xor eax, eax)
+ AS2( lea edi, [esp+4+8*8]) // start at middle of state buffer. will decrement pointer each round to avoid copying
+ AS2( lea esi, [esp+4+20*8+8]) // 16-byte alignment, then add 8
+
+ AS2( movdqa xmm0, [ecx+0*16])
+ AS2( movdq2q mm4, xmm0)
+ AS2( movdqa [edi+0*16], xmm0)
+ AS2( movdqa xmm0, [ecx+1*16])
+ AS2( movdqa [edi+1*16], xmm0)
+ AS2( movdqa xmm0, [ecx+2*16])
+ AS2( movdq2q mm5, xmm0)
+ AS2( movdqa [edi+2*16], xmm0)
+ AS2( movdqa xmm0, [ecx+3*16])
+ AS2( movdqa [edi+3*16], xmm0)
+ ASJ( jmp, 0, f)
+
+#define SSE2_S0_S1(r, a, b, c) \
+ AS2( movq mm6, r)\
+ AS2( psrlq r, a)\
+ AS2( movq mm7, r)\
+ AS2( psllq mm6, 64-c)\
+ AS2( pxor mm7, mm6)\
+ AS2( psrlq r, b-a)\
+ AS2( pxor mm7, r)\
+ AS2( psllq mm6, c-b)\
+ AS2( pxor mm7, mm6)\
+ AS2( psrlq r, c-b)\
+ AS2( pxor r, mm7)\
+ AS2( psllq mm6, b-a)\
+ AS2( pxor r, mm6)
+
+#define SSE2_s0(r, a, b, c) \
+ AS2( movdqa xmm6, r)\
+ AS2( psrlq r, a)\
+ AS2( movdqa xmm7, r)\
+ AS2( psllq xmm6, 64-c)\
+ AS2( pxor xmm7, xmm6)\
+ AS2( psrlq r, b-a)\
+ AS2( pxor xmm7, r)\
+ AS2( psrlq r, c-b)\
+ AS2( pxor r, xmm7)\
+ AS2( psllq xmm6, c-a)\
+ AS2( pxor r, xmm6)
+
+#define SSE2_s1(r, a, b, c) \
+ AS2( movdqa xmm6, r)\
+ AS2( psrlq r, a)\
+ AS2( movdqa xmm7, r)\
+ AS2( psllq xmm6, 64-c)\
+ AS2( pxor xmm7, xmm6)\
+ AS2( psrlq r, b-a)\
+ AS2( pxor xmm7, r)\
+ AS2( psllq xmm6, c-b)\
+ AS2( pxor xmm7, xmm6)\
+ AS2( psrlq r, c-b)\
+ AS2( pxor r, xmm7)
+
+ ASL(SHA512_Round)
+ // k + w is in mm0, a is in mm4, e is in mm5
+ AS2( paddq mm0, [edi+7*8]) // h
+ AS2( movq mm2, [edi+5*8]) // f
+ AS2( movq mm3, [edi+6*8]) // g
+ AS2( pxor mm2, mm3)
+ AS2( pand mm2, mm5)
+ SSE2_S0_S1(mm5,14,18,41)
+ AS2( pxor mm2, mm3)
+ AS2( paddq mm0, mm2) // h += Ch(e,f,g)
+ AS2( paddq mm5, mm0) // h += S1(e)
+ AS2( movq mm2, [edi+1*8]) // b
+ AS2( movq mm1, mm2)
+ AS2( por mm2, mm4)
+ AS2( pand mm2, [edi+2*8]) // c
+ AS2( pand mm1, mm4)
+ AS2( por mm1, mm2)
+ AS2( paddq mm1, mm5) // temp = h + Maj(a,b,c)
+ AS2( paddq mm5, [edi+3*8]) // e = d + h
+ AS2( movq [edi+3*8], mm5)
+ AS2( movq [edi+11*8], mm5)
+ SSE2_S0_S1(mm4,28,34,39) // S0(a)
+ AS2( paddq mm4, mm1) // a = temp + S0(a)
+ AS2( movq [edi-8], mm4)
+ AS2( movq [edi+7*8], mm4)
+ AS1( ret)
+
+ // first 16 rounds
+ ASL(0)
+ AS2( movq mm0, [edx+eax*8])
+ AS2( movq [esi+eax*8], mm0)
+ AS2( movq [esi+eax*8+16*8], mm0)
+ AS2( paddq mm0, [ebx+eax*8])
+ ASC( call, SHA512_Round)
+ AS1( inc eax)
+ AS2( sub edi, 8)
+ AS2( test eax, 7)
+ ASJ( jnz, 0, b)
+ AS2( add edi, 8*8)
+ AS2( cmp eax, 16)
+ ASJ( jne, 0, b)
+
+ // rest of the rounds
+ AS2( movdqu xmm0, [esi+(16-2)*8])
+ ASL(1)
+ // data expansion, W[i-2] already in xmm0
+ AS2( movdqu xmm3, [esi])
+ AS2( paddq xmm3, [esi+(16-7)*8])
+ AS2( movdqa xmm2, [esi+(16-15)*8])
+ SSE2_s1(xmm0, 6, 19, 61)
+ AS2( paddq xmm0, xmm3)
+ SSE2_s0(xmm2, 1, 7, 8)
+ AS2( paddq xmm0, xmm2)
+ AS2( movdq2q mm0, xmm0)
+ AS2( movhlps xmm1, xmm0)
+ AS2( paddq mm0, [ebx+eax*8])
+ AS2( movlps [esi], xmm0)
+ AS2( movlps [esi+8], xmm1)
+ AS2( movlps [esi+8*16], xmm0)
+ AS2( movlps [esi+8*17], xmm1)
+ // 2 rounds
+ ASC( call, SHA512_Round)
+ AS2( sub edi, 8)
+ AS2( movdq2q mm0, xmm1)
+ AS2( paddq mm0, [ebx+eax*8+8])
+ ASC( call, SHA512_Round)
+ // update indices and loop
+ AS2( add esi, 16)
+ AS2( add eax, 2)
+ AS2( sub edi, 8)
+ AS2( test eax, 7)
+ ASJ( jnz, 1, b)
+ // do housekeeping every 8 rounds
+ AS2( mov esi, 0xf)
+ AS2( and esi, eax)
+ AS2( lea esi, [esp+4+20*8+8+esi*8])
+ AS2( add edi, 8*8)
+ AS2( cmp eax, 80)
+ ASJ( jne, 1, b)
+
+#define SSE2_CombineState(i) \
+ AS2( movdqa xmm0, [edi+i*16])\
+ AS2( paddq xmm0, [ecx+i*16])\
+ AS2( movdqa [ecx+i*16], xmm0)
+
+ SSE2_CombineState(0)
+ SSE2_CombineState(1)
+ SSE2_CombineState(2)
+ SSE2_CombineState(3)
+
+ AS1( pop esp)
+ AS1( emms)
+
+#if defined(__GNUC__)
+ AS1( pop ebx)
+ ".att_syntax prefix;"
+ :
+ : "a" (SHA512_K), "c" (state), "d" (data)
+ : "%esi", "%edi", "memory", "cc"
+ );
+#else
+ AS1( pop edi)
+ AS1( pop esi)
+ AS1( pop ebx)
+ AS1( ret)
+#endif
+}
+#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+
+void SHA512::Transform(word64 *state, const word64 *data)
+{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+ if (HasSSE2())
+ {
+ SHA512_SSE2_Transform(state, data);
+ return;
+ }
+#endif
+
+#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
+#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
+#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
+#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
+
+#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\
+ d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
+
+ word64 W[16];
+ word64 T[8];
+ /* Copy context->state[] to working vars */
+ memcpy(T, state, sizeof(T));
+ /* 80 operations, partially loop unrolled */
+ for (unsigned int j=0; j<80; j+=16)
+ {
+ R( 0); R( 1); R( 2); R( 3);
+ R( 4); R( 5); R( 6); R( 7);
+ R( 8); R( 9); R(10); R(11);
+ R(12); R(13); R(14); R(15);
+ }
+ /* Add the working vars back into context.state[] */
+ state[0] += a(0);
+ state[1] += b(0);
+ state[2] += c(0);
+ state[3] += d(0);
+ state[4] += e(0);
+ state[5] += f(0);
+ state[6] += g(0);
+ state[7] += h(0);
+}
+
+NAMESPACE_END
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+#endif // #ifndef CRYPTOPP_IMPORTS
diff --git a/lib/cryptopp/sha.h b/lib/cryptopp/sha.h
new file mode 100644
index 000000000..679081e8f
--- /dev/null
+++ b/lib/cryptopp/sha.h
@@ -0,0 +1,63 @@
+#ifndef CRYPTOPP_SHA_H
+#define CRYPTOPP_SHA_H
+
+#include "iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// <a href="http://www.weidai.com/scan-mirror/md.html#SHA-1">SHA-1</a>
+class CRYPTOPP_DLL SHA1 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 20, SHA1>
+{
+public:
+ static void CRYPTOPP_API InitState(HashWordType *state);
+ static void CRYPTOPP_API Transform(word32 *digest, const word32 *data);
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-1";}
+};
+
+typedef SHA1 SHA; // for backwards compatibility
+
+//! implements the SHA-256 standard
+class CRYPTOPP_DLL SHA256 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 32, SHA256, 32, true>
+{
+public:
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ size_t HashMultipleBlocks(const word32 *input, size_t length);
+#endif
+ static void CRYPTOPP_API InitState(HashWordType *state);
+ static void CRYPTOPP_API Transform(word32 *digest, const word32 *data);
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-256";}
+};
+
+//! implements the SHA-224 standard
+class CRYPTOPP_DLL SHA224 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 32, SHA224, 28, true>
+{
+public:
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ size_t HashMultipleBlocks(const word32 *input, size_t length);
+#endif
+ static void CRYPTOPP_API InitState(HashWordType *state);
+ static void CRYPTOPP_API Transform(word32 *digest, const word32 *data) {SHA256::Transform(digest, data);}
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-224";}
+};
+
+//! implements the SHA-512 standard
+class CRYPTOPP_DLL SHA512 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, 64, SHA512, 64, CRYPTOPP_BOOL_X86>
+{
+public:
+ static void CRYPTOPP_API InitState(HashWordType *state);
+ static void CRYPTOPP_API Transform(word64 *digest, const word64 *data);
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-512";}
+};
+
+//! implements the SHA-384 standard
+class CRYPTOPP_DLL SHA384 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, 64, SHA384, 48, CRYPTOPP_BOOL_X86>
+{
+public:
+ static void CRYPTOPP_API InitState(HashWordType *state);
+ static void CRYPTOPP_API Transform(word64 *digest, const word64 *data) {SHA512::Transform(digest, data);}
+ static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-384";}
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/shacal2.cpp b/lib/cryptopp/shacal2.cpp
new file mode 100644
index 000000000..b0360e404
--- /dev/null
+++ b/lib/cryptopp/shacal2.cpp
@@ -0,0 +1,140 @@
+// shacal2.cpp - by Kevin Springle, 2003
+//
+// Portions of this code were derived from
+// Wei Dai's implementation of SHA-2
+//
+// The original code and all modifications are in the public domain.
+
+#include "pch.h"
+#include "shacal2.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// SHACAL-2 function and round definitions
+
+#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
+#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
+#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
+#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
+
+#define Ch(x,y,z) (z^(x&(y^z)))
+#define Maj(x,y,z) ((x&y)|(z&(x|y)))
+
+/* R is the SHA-256 round function. */
+/* This macro increments the k argument as a side effect. */
+#define R(a,b,c,d,e,f,g,h,k) \
+ h+=S1(e)+Ch(e,f,g)+*k++;d+=h;h+=S0(a)+Maj(a,b,c);
+
+/* P is the inverse of the SHA-256 round function. */
+/* This macro decrements the k argument as a side effect. */
+#define P(a,b,c,d,e,f,g,h,k) \
+ h-=S0(a)+Maj(a,b,c);d-=h;h-=S1(e)+Ch(e,f,g)+*--k;
+
+void SHACAL2::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &)
+{
+ AssertValidKeyLength(keylen);
+
+ word32 *rk = m_key;
+ unsigned int i;
+
+ GetUserKey(BIG_ENDIAN_ORDER, rk, m_key.size(), userKey, keylen);
+ for (i = 0; i < 48; i++, rk++)
+ {
+ rk[16] = rk[0] + s0(rk[1]) + rk[9] + s1(rk[14]);
+ rk[0] += K[i];
+ }
+ for (i = 48; i < 64; i++, rk++)
+ {
+ rk[0] += K[i];
+ }
+}
+
+typedef BlockGetAndPut<word32, BigEndian> Block;
+
+void SHACAL2::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 a, b, c, d, e, f, g, h;
+ const word32 *rk = m_key;
+
+ /*
+ * map byte array block to cipher state:
+ */
+ Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+
+ // Perform SHA-256 transformation.
+
+ /* 64 operations, partially loop unrolled */
+ for (unsigned int j=0; j<64; j+=8)
+ {
+ R(a,b,c,d,e,f,g,h,rk);
+ R(h,a,b,c,d,e,f,g,rk);
+ R(g,h,a,b,c,d,e,f,rk);
+ R(f,g,h,a,b,c,d,e,rk);
+ R(e,f,g,h,a,b,c,d,rk);
+ R(d,e,f,g,h,a,b,c,rk);
+ R(c,d,e,f,g,h,a,b,rk);
+ R(b,c,d,e,f,g,h,a,rk);
+ }
+
+ /*
+ * map cipher state to byte array block:
+ */
+
+ Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+}
+
+void SHACAL2::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 a, b, c, d, e, f, g, h;
+ const word32 *rk = m_key + 64;
+
+ /*
+ * map byte array block to cipher state:
+ */
+ Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+
+ // Perform inverse SHA-256 transformation.
+
+ /* 64 operations, partially loop unrolled */
+ for (unsigned int j=0; j<64; j+=8)
+ {
+ P(b,c,d,e,f,g,h,a,rk);
+ P(c,d,e,f,g,h,a,b,rk);
+ P(d,e,f,g,h,a,b,c,rk);
+ P(e,f,g,h,a,b,c,d,rk);
+ P(f,g,h,a,b,c,d,e,rk);
+ P(g,h,a,b,c,d,e,f,rk);
+ P(h,a,b,c,d,e,f,g,rk);
+ P(a,b,c,d,e,f,g,h,rk);
+ }
+
+ /*
+ * map cipher state to byte array block:
+ */
+
+ Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h);
+}
+
+// The SHACAL-2 round constants are identical to the SHA-256 round constants.
+const word32 SHACAL2::Base::K[64] =
+{
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+NAMESPACE_END
diff --git a/lib/cryptopp/shacal2.h b/lib/cryptopp/shacal2.h
new file mode 100644
index 000000000..66c987fd7
--- /dev/null
+++ b/lib/cryptopp/shacal2.h
@@ -0,0 +1,54 @@
+#ifndef CRYPTOPP_SHACAL2_H
+#define CRYPTOPP_SHACAL2_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+struct SHACAL2_Info : public FixedBlockSize<32>, public VariableKeyLength<16, 16, 64>
+{
+ static const char *StaticAlgorithmName() {return "SHACAL-2";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#SHACAL-2">SHACAL-2</a>
+class SHACAL2 : public SHACAL2_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<SHACAL2_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+
+ protected:
+ FixedSizeSecBlock<word32, 64> m_key;
+
+ static const word32 K[64];
+ };
+
+ class CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+ class CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+typedef SHACAL2::Encryption SHACAL2Encryption;
+typedef SHACAL2::Decryption SHACAL2Decryption;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/simple.cpp b/lib/cryptopp/simple.cpp
new file mode 100644
index 000000000..96f256b40
--- /dev/null
+++ b/lib/cryptopp/simple.cpp
@@ -0,0 +1,14 @@
+// simple.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "simple.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/simple.h b/lib/cryptopp/simple.h
new file mode 100644
index 000000000..35fd65ae4
--- /dev/null
+++ b/lib/cryptopp/simple.h
@@ -0,0 +1,209 @@
+// simple.h - written and placed in the public domain by Wei Dai
+/*! \file
+ Simple non-interface classes derived from classes in cryptlib.h.
+*/
+
+#ifndef CRYPTOPP_SIMPLE_H
+#define CRYPTOPP_SIMPLE_H
+
+#include "cryptlib.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+template <class DERIVED, class BASE>
+class CRYPTOPP_NO_VTABLE ClonableImpl : public BASE
+{
+public:
+ Clonable * Clone() const {return new DERIVED(*static_cast<const DERIVED *>(this));}
+};
+
+//! _
+template <class BASE, class ALGORITHM_INFO=BASE>
+class CRYPTOPP_NO_VTABLE AlgorithmImpl : public BASE
+{
+public:
+ static std::string CRYPTOPP_API StaticAlgorithmName() {return ALGORITHM_INFO::StaticAlgorithmName();}
+ std::string AlgorithmName() const {return ALGORITHM_INFO::StaticAlgorithmName();}
+};
+
+//! _
+class CRYPTOPP_DLL InvalidKeyLength : public InvalidArgument
+{
+public:
+ explicit InvalidKeyLength(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid key length") {}
+};
+
+//! _
+class CRYPTOPP_DLL InvalidRounds : public InvalidArgument
+{
+public:
+ explicit InvalidRounds(const std::string &algorithm, unsigned int rounds) : InvalidArgument(algorithm + ": " + IntToString(rounds) + " is not a valid number of rounds") {}
+};
+
+// *****************************
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE Bufferless : public T
+{
+public:
+ bool IsolatedFlush(bool hardFlush, bool blocking) {return false;}
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE Unflushable : public T
+{
+public:
+ bool Flush(bool completeFlush, int propagation=-1, bool blocking=true)
+ {return ChannelFlush(DEFAULT_CHANNEL, completeFlush, propagation, blocking);}
+ bool IsolatedFlush(bool hardFlush, bool blocking)
+ {assert(false); return false;}
+ bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true)
+ {
+ if (hardFlush && !InputBufferIsEmpty())
+ throw CannotFlush("Unflushable<T>: this object has buffered input that cannot be flushed");
+ else
+ {
+ BufferedTransformation *attached = this->AttachedTransformation();
+ return attached && propagation ? attached->ChannelFlush(channel, hardFlush, propagation-1, blocking) : false;
+ }
+ }
+
+protected:
+ virtual bool InputBufferIsEmpty() const {return false;}
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE InputRejecting : public T
+{
+public:
+ struct InputRejected : public NotImplemented
+ {InputRejected() : NotImplemented("BufferedTransformation: this object doesn't allow input") {}};
+
+ // shouldn't be calling these functions on this class
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+ {throw InputRejected();}
+ bool IsolatedFlush(bool, bool) {return false;}
+ bool IsolatedMessageSeriesEnd(bool) {throw InputRejected();}
+
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+ {throw InputRejected();}
+ bool ChannelMessageSeriesEnd(const std::string &, int, bool) {throw InputRejected();}
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE CustomFlushPropagation : public T
+{
+public:
+ virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0;
+
+private:
+ bool IsolatedFlush(bool hardFlush, bool blocking) {assert(false); return false;}
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE CustomSignalPropagation : public CustomFlushPropagation<T>
+{
+public:
+ virtual void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1) =0;
+
+private:
+ void IsolatedInitialize(const NameValuePairs &parameters) {assert(false);}
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE Multichannel : public CustomFlushPropagation<T>
+{
+public:
+ bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
+ {return this->ChannelFlush(DEFAULT_CHANNEL, hardFlush, propagation, blocking);}
+ bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
+ {return this->ChannelMessageSeriesEnd(DEFAULT_CHANNEL, propagation, blocking);}
+ byte * CreatePutSpace(size_t &size)
+ {return this->ChannelCreatePutSpace(DEFAULT_CHANNEL, size);}
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+ {return this->ChannelPut2(DEFAULT_CHANNEL, begin, length, messageEnd, blocking);}
+ size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
+ {return this->ChannelPutModifiable2(DEFAULT_CHANNEL, inString, length, messageEnd, blocking);}
+
+// void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1)
+// {PropagateMessageSeriesEnd(propagation, channel);}
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
+ {size = 0; return NULL;}
+ bool ChannelPutModifiable(const std::string &channel, byte *inString, size_t length)
+ {this->ChannelPut(channel, inString, length); return false;}
+
+ virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) =0;
+ size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
+ {return ChannelPut2(channel, begin, length, messageEnd, blocking);}
+
+ virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) =0;
+};
+
+//! _
+template <class T>
+class CRYPTOPP_NO_VTABLE AutoSignaling : public T
+{
+public:
+ AutoSignaling(int propagation=-1) : m_autoSignalPropagation(propagation) {}
+
+ void SetAutoSignalPropagation(int propagation)
+ {m_autoSignalPropagation = propagation;}
+ int GetAutoSignalPropagation() const
+ {return m_autoSignalPropagation;}
+
+private:
+ int m_autoSignalPropagation;
+};
+
+//! A BufferedTransformation that only contains pre-existing data as "output"
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Store : public AutoSignaling<InputRejecting<BufferedTransformation> >
+{
+public:
+ Store() : m_messageEnd(false) {}
+
+ void IsolatedInitialize(const NameValuePairs &parameters)
+ {
+ m_messageEnd = false;
+ StoreInitialize(parameters);
+ }
+
+ unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;}
+ bool GetNextMessage();
+ unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
+
+protected:
+ virtual void StoreInitialize(const NameValuePairs &parameters) =0;
+
+ bool m_messageEnd;
+};
+
+//! A BufferedTransformation that doesn't produce any retrievable output
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Sink : public BufferedTransformation
+{
+public:
+ size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)
+ {transferBytes = 0; return 0;}
+ size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
+ {return 0;}
+};
+
+class CRYPTOPP_DLL BitBucket : public Bufferless<Sink>
+{
+public:
+ std::string AlgorithmName() const {return "BitBucket";}
+ void IsolatedInitialize(const NameValuePairs &parameters) {}
+ size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
+ {return 0;}
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/smartptr.h b/lib/cryptopp/smartptr.h
new file mode 100644
index 000000000..a0a727edc
--- /dev/null
+++ b/lib/cryptopp/smartptr.h
@@ -0,0 +1,223 @@
+#ifndef CRYPTOPP_SMARTPTR_H
+#define CRYPTOPP_SMARTPTR_H
+
+#include "config.h"
+#include <algorithm>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T> class simple_ptr
+{
+public:
+ simple_ptr(T *p = NULL) : m_p(p) {}
+ ~simple_ptr() {delete m_p; m_p = NULL;} // set m_p to NULL so double destruction (which might occur in Singleton) will be harmless
+ T *m_p;
+};
+
+template <class T> class member_ptr
+{
+public:
+ explicit member_ptr(T *p = NULL) : m_p(p) {}
+
+ ~member_ptr();
+
+ const T& operator*() const { return *m_p; }
+ T& operator*() { return *m_p; }
+
+ const T* operator->() const { return m_p; }
+ T* operator->() { return m_p; }
+
+ const T* get() const { return m_p; }
+ T* get() { return m_p; }
+
+ T* release()
+ {
+ T *old_p = m_p;
+ m_p = 0;
+ return old_p;
+ }
+
+ void reset(T *p = 0);
+
+protected:
+ member_ptr(const member_ptr<T>& rhs); // copy not allowed
+ void operator=(const member_ptr<T>& rhs); // assignment not allowed
+
+ T *m_p;
+};
+
+template <class T> member_ptr<T>::~member_ptr() {delete m_p;}
+template <class T> void member_ptr<T>::reset(T *p) {delete m_p; m_p = p;}
+
+// ********************************************************
+
+template<class T> class value_ptr : public member_ptr<T>
+{
+public:
+ value_ptr(const T &obj) : member_ptr<T>(new T(obj)) {}
+ value_ptr(T *p = NULL) : member_ptr<T>(p) {}
+ value_ptr(const value_ptr<T>& rhs)
+ : member_ptr<T>(rhs.m_p ? new T(*rhs.m_p) : NULL) {}
+
+ value_ptr<T>& operator=(const value_ptr<T>& rhs);
+ bool operator==(const value_ptr<T>& rhs)
+ {
+ return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p);
+ }
+};
+
+template <class T> value_ptr<T>& value_ptr<T>::operator=(const value_ptr<T>& rhs)
+{
+ T *old_p = this->m_p;
+ this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULL;
+ delete old_p;
+ return *this;
+}
+
+// ********************************************************
+
+template<class T> class clonable_ptr : public member_ptr<T>
+{
+public:
+ clonable_ptr(const T &obj) : member_ptr<T>(obj.Clone()) {}
+ clonable_ptr(T *p = NULL) : member_ptr<T>(p) {}
+ clonable_ptr(const clonable_ptr<T>& rhs)
+ : member_ptr<T>(rhs.m_p ? rhs.m_p->Clone() : NULL) {}
+
+ clonable_ptr<T>& operator=(const clonable_ptr<T>& rhs);
+};
+
+template <class T> clonable_ptr<T>& clonable_ptr<T>::operator=(const clonable_ptr<T>& rhs)
+{
+ T *old_p = this->m_p;
+ this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULL;
+ delete old_p;
+ return *this;
+}
+
+// ********************************************************
+
+template<class T> class counted_ptr
+{
+public:
+ explicit counted_ptr(T *p = 0);
+ counted_ptr(const T &r) : m_p(0) {attach(r);}
+ counted_ptr(const counted_ptr<T>& rhs);
+
+ ~counted_ptr();
+
+ const T& operator*() const { return *m_p; }
+ T& operator*() { return *m_p; }
+
+ const T* operator->() const { return m_p; }
+ T* operator->() { return get(); }
+
+ const T* get() const { return m_p; }
+ T* get();
+
+ void attach(const T &p);
+
+ counted_ptr<T> & operator=(const counted_ptr<T>& rhs);
+
+private:
+ T *m_p;
+};
+
+template <class T> counted_ptr<T>::counted_ptr(T *p)
+ : m_p(p)
+{
+ if (m_p)
+ m_p->m_referenceCount = 1;
+}
+
+template <class T> counted_ptr<T>::counted_ptr(const counted_ptr<T>& rhs)
+ : m_p(rhs.m_p)
+{
+ if (m_p)
+ m_p->m_referenceCount++;
+}
+
+template <class T> counted_ptr<T>::~counted_ptr()
+{
+ if (m_p && --m_p->m_referenceCount == 0)
+ delete m_p;
+}
+
+template <class T> void counted_ptr<T>::attach(const T &r)
+{
+ if (m_p && --m_p->m_referenceCount == 0)
+ delete m_p;
+ if (r.m_referenceCount == 0)
+ {
+ m_p = r.clone();
+ m_p->m_referenceCount = 1;
+ }
+ else
+ {
+ m_p = const_cast<T *>(&r);
+ m_p->m_referenceCount++;
+ }
+}
+
+template <class T> T* counted_ptr<T>::get()
+{
+ if (m_p && m_p->m_referenceCount > 1)
+ {
+ T *temp = m_p->clone();
+ m_p->m_referenceCount--;
+ m_p = temp;
+ m_p->m_referenceCount = 1;
+ }
+ return m_p;
+}
+
+template <class T> counted_ptr<T> & counted_ptr<T>::operator=(const counted_ptr<T>& rhs)
+{
+ if (m_p != rhs.m_p)
+ {
+ if (m_p && --m_p->m_referenceCount == 0)
+ delete m_p;
+ m_p = rhs.m_p;
+ if (m_p)
+ m_p->m_referenceCount++;
+ }
+ return *this;
+}
+
+// ********************************************************
+
+template <class T> class vector_member_ptrs
+{
+public:
+ vector_member_ptrs(size_t size=0)
+ : m_size(size), m_ptr(new member_ptr<T>[size]) {}
+ ~vector_member_ptrs()
+ {delete [] this->m_ptr;}
+
+ member_ptr<T>& operator[](size_t index)
+ {assert(index<this->m_size); return this->m_ptr[index];}
+ const member_ptr<T>& operator[](size_t index) const
+ {assert(index<this->m_size); return this->m_ptr[index];}
+
+ size_t size() const {return this->m_size;}
+ void resize(size_t newSize)
+ {
+ member_ptr<T> *newPtr = new member_ptr<T>[newSize];
+ for (size_t i=0; i<this->m_size && i<newSize; i++)
+ newPtr[i].reset(this->m_ptr[i].release());
+ delete [] this->m_ptr;
+ this->m_size = newSize;
+ this->m_ptr = newPtr;
+ }
+
+private:
+ vector_member_ptrs(const vector_member_ptrs<T> &c); // copy not allowed
+ void operator=(const vector_member_ptrs<T> &x); // assignment not allowed
+
+ size_t m_size;
+ member_ptr<T> *m_ptr;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/socketft.cpp b/lib/cryptopp/socketft.cpp
new file mode 100644
index 000000000..6c5a8ff9d
--- /dev/null
+++ b/lib/cryptopp/socketft.cpp
@@ -0,0 +1,531 @@
+// socketft.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "socketft.h"
+
+#ifdef SOCKETS_AVAILABLE
+
+#include "wait.h"
+
+#ifdef USE_BERKELEY_STYLE_SOCKETS
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+const int SOCKET_EINVAL = WSAEINVAL;
+const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
+typedef int socklen_t;
+#else
+const int SOCKET_EINVAL = EINVAL;
+const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
+#endif
+
+Socket::Err::Err(socket_t s, const std::string& operation, int error)
+ : OS_Error(IO_ERROR, "Socket: " + operation + " operation failed with error " + IntToString(error), operation, error)
+ , m_s(s)
+{
+}
+
+Socket::~Socket()
+{
+ if (m_own)
+ {
+ try
+ {
+ CloseSocket();
+ }
+ catch (...)
+ {
+ }
+ }
+}
+
+void Socket::AttachSocket(socket_t s, bool own)
+{
+ if (m_own)
+ CloseSocket();
+
+ m_s = s;
+ m_own = own;
+ SocketChanged();
+}
+
+socket_t Socket::DetachSocket()
+{
+ socket_t s = m_s;
+ m_s = INVALID_SOCKET;
+ SocketChanged();
+ return s;
+}
+
+void Socket::Create(int nType)
+{
+ assert(m_s == INVALID_SOCKET);
+ m_s = socket(AF_INET, nType, 0);
+ CheckAndHandleError("socket", m_s);
+ m_own = true;
+ SocketChanged();
+}
+
+void Socket::CloseSocket()
+{
+ if (m_s != INVALID_SOCKET)
+ {
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ CancelIo((HANDLE) m_s);
+ CheckAndHandleError_int("closesocket", closesocket(m_s));
+#else
+ CheckAndHandleError_int("close", close(m_s));
+#endif
+ m_s = INVALID_SOCKET;
+ SocketChanged();
+ }
+}
+
+void Socket::Bind(unsigned int port, const char *addr)
+{
+ sockaddr_in sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+
+ if (addr == NULL)
+ sa.sin_addr.s_addr = htonl(INADDR_ANY);
+ else
+ {
+ unsigned long result = inet_addr(addr);
+ if (result == -1) // Solaris doesn't have INADDR_NONE
+ {
+ SetLastError(SOCKET_EINVAL);
+ CheckAndHandleError_int("inet_addr", SOCKET_ERROR);
+ }
+ sa.sin_addr.s_addr = result;
+ }
+
+ sa.sin_port = htons((u_short)port);
+
+ Bind((sockaddr *)&sa, sizeof(sa));
+}
+
+void Socket::Bind(const sockaddr *psa, socklen_t saLen)
+{
+ assert(m_s != INVALID_SOCKET);
+ // cygwin workaround: needs const_cast
+ CheckAndHandleError_int("bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
+}
+
+void Socket::Listen(int backlog)
+{
+ assert(m_s != INVALID_SOCKET);
+ CheckAndHandleError_int("listen", listen(m_s, backlog));
+}
+
+bool Socket::Connect(const char *addr, unsigned int port)
+{
+ assert(addr != NULL);
+
+ sockaddr_in sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = inet_addr(addr);
+
+ if (sa.sin_addr.s_addr == -1) // Solaris doesn't have INADDR_NONE
+ {
+ hostent *lphost = gethostbyname(addr);
+ if (lphost == NULL)
+ {
+ SetLastError(SOCKET_EINVAL);
+ CheckAndHandleError_int("gethostbyname", SOCKET_ERROR);
+ }
+
+ sa.sin_addr.s_addr = ((in_addr *)lphost->h_addr)->s_addr;
+ }
+
+ sa.sin_port = htons((u_short)port);
+
+ return Connect((const sockaddr *)&sa, sizeof(sa));
+}
+
+bool Socket::Connect(const sockaddr* psa, socklen_t saLen)
+{
+ assert(m_s != INVALID_SOCKET);
+ int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
+ if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
+ return false;
+ CheckAndHandleError_int("connect", result);
+ return true;
+}
+
+bool Socket::Accept(Socket& target, sockaddr *psa, socklen_t *psaLen)
+{
+ assert(m_s != INVALID_SOCKET);
+ socket_t s = accept(m_s, psa, psaLen);
+ if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
+ return false;
+ CheckAndHandleError("accept", s);
+ target.AttachSocket(s, true);
+ return true;
+}
+
+void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
+{
+ assert(m_s != INVALID_SOCKET);
+ CheckAndHandleError_int("getsockname", getsockname(m_s, psa, psaLen));
+}
+
+void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
+{
+ assert(m_s != INVALID_SOCKET);
+ CheckAndHandleError_int("getpeername", getpeername(m_s, psa, psaLen));
+}
+
+unsigned int Socket::Send(const byte* buf, size_t bufLen, int flags)
+{
+ assert(m_s != INVALID_SOCKET);
+ int result = send(m_s, (const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
+ CheckAndHandleError_int("send", result);
+ return result;
+}
+
+unsigned int Socket::Receive(byte* buf, size_t bufLen, int flags)
+{
+ assert(m_s != INVALID_SOCKET);
+ int result = recv(m_s, (char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
+ CheckAndHandleError_int("recv", result);
+ return result;
+}
+
+void Socket::ShutDown(int how)
+{
+ assert(m_s != INVALID_SOCKET);
+ int result = shutdown(m_s, how);
+ CheckAndHandleError_int("shutdown", result);
+}
+
+void Socket::IOCtl(long cmd, unsigned long *argp)
+{
+ assert(m_s != INVALID_SOCKET);
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ CheckAndHandleError_int("ioctlsocket", ioctlsocket(m_s, cmd, argp));
+#else
+ CheckAndHandleError_int("ioctl", ioctl(m_s, cmd, argp));
+#endif
+}
+
+bool Socket::SendReady(const timeval *timeout)
+{
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(m_s, &fds);
+ int ready;
+ if (timeout == NULL)
+ ready = select((int)m_s+1, NULL, &fds, NULL, NULL);
+ else
+ {
+ timeval timeoutCopy = *timeout; // select() modified timeout on Linux
+ ready = select((int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
+ }
+ CheckAndHandleError_int("select", ready);
+ return ready > 0;
+}
+
+bool Socket::ReceiveReady(const timeval *timeout)
+{
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(m_s, &fds);
+ int ready;
+ if (timeout == NULL)
+ ready = select((int)m_s+1, &fds, NULL, NULL, NULL);
+ else
+ {
+ timeval timeoutCopy = *timeout; // select() modified timeout on Linux
+ ready = select((int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
+ }
+ CheckAndHandleError_int("select", ready);
+ return ready > 0;
+}
+
+unsigned int Socket::PortNameToNumber(const char *name, const char *protocol)
+{
+ int port = atoi(name);
+ if (IntToString(port) == name)
+ return port;
+
+ servent *se = getservbyname(name, protocol);
+ if (!se)
+ throw Err(INVALID_SOCKET, "getservbyname", SOCKET_EINVAL);
+ return ntohs(se->s_port);
+}
+
+void Socket::StartSockets()
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ WSADATA wsd;
+ int result = WSAStartup(0x0202, &wsd);
+ if (result != 0)
+ throw Err(INVALID_SOCKET, "WSAStartup", result);
+#endif
+}
+
+void Socket::ShutdownSockets()
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ int result = WSACleanup();
+ if (result != 0)
+ throw Err(INVALID_SOCKET, "WSACleanup", result);
+#endif
+}
+
+int Socket::GetLastError()
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+void Socket::SetLastError(int errorCode)
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ WSASetLastError(errorCode);
+#else
+ errno = errorCode;
+#endif
+}
+
+void Socket::HandleError(const char *operation) const
+{
+ int err = GetLastError();
+ throw Err(m_s, operation, err);
+}
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+
+SocketReceiver::SocketReceiver(Socket &s)
+ : m_s(s), m_resultPending(false), m_eofReceived(false)
+{
+ m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
+ m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
+ memset(&m_overlapped, 0, sizeof(m_overlapped));
+ m_overlapped.hEvent = m_event;
+}
+
+SocketReceiver::~SocketReceiver()
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ CancelIo((HANDLE) m_s.GetSocket());
+#endif
+}
+
+bool SocketReceiver::Receive(byte* buf, size_t bufLen)
+{
+ assert(!m_resultPending && !m_eofReceived);
+
+ DWORD flags = 0;
+ // don't queue too much at once, or we might use up non-paged memory
+ WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
+ if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
+ {
+ if (m_lastResult == 0)
+ m_eofReceived = true;
+ }
+ else
+ {
+ switch (WSAGetLastError())
+ {
+ default:
+ m_s.CheckAndHandleError_int("WSARecv", SOCKET_ERROR);
+ case WSAEDISCON:
+ m_lastResult = 0;
+ m_eofReceived = true;
+ break;
+ case WSA_IO_PENDING:
+ m_resultPending = true;
+ }
+ }
+ return !m_resultPending;
+}
+
+void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ if (m_resultPending)
+ container.AddHandle(m_event, CallStack("SocketReceiver::GetWaitObjects() - result pending", &callStack));
+ else if (!m_eofReceived)
+ container.SetNoWait(CallStack("SocketReceiver::GetWaitObjects() - result ready", &callStack));
+}
+
+unsigned int SocketReceiver::GetReceiveResult()
+{
+ if (m_resultPending)
+ {
+ DWORD flags = 0;
+ if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags))
+ {
+ if (m_lastResult == 0)
+ m_eofReceived = true;
+ }
+ else
+ {
+ switch (WSAGetLastError())
+ {
+ default:
+ m_s.CheckAndHandleError("WSAGetOverlappedResult", FALSE);
+ case WSAEDISCON:
+ m_lastResult = 0;
+ m_eofReceived = true;
+ }
+ }
+ m_resultPending = false;
+ }
+ return m_lastResult;
+}
+
+// *************************************************************
+
+SocketSender::SocketSender(Socket &s)
+ : m_s(s), m_resultPending(false), m_lastResult(0)
+{
+ m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
+ m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
+ memset(&m_overlapped, 0, sizeof(m_overlapped));
+ m_overlapped.hEvent = m_event;
+}
+
+
+SocketSender::~SocketSender()
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ CancelIo((HANDLE) m_s.GetSocket());
+#endif
+}
+
+void SocketSender::Send(const byte* buf, size_t bufLen)
+{
+ assert(!m_resultPending);
+ DWORD written = 0;
+ // don't queue too much at once, or we might use up non-paged memory
+ WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
+ if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
+ {
+ m_resultPending = false;
+ m_lastResult = written;
+ }
+ else
+ {
+ if (WSAGetLastError() != WSA_IO_PENDING)
+ m_s.CheckAndHandleError_int("WSASend", SOCKET_ERROR);
+
+ m_resultPending = true;
+ }
+}
+
+void SocketSender::SendEof()
+{
+ assert(!m_resultPending);
+ m_s.ShutDown(SD_SEND);
+ m_s.CheckAndHandleError("ResetEvent", ResetEvent(m_event));
+ m_s.CheckAndHandleError_int("WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
+ m_resultPending = true;
+}
+
+bool SocketSender::EofSent()
+{
+ if (m_resultPending)
+ {
+ WSANETWORKEVENTS events;
+ m_s.CheckAndHandleError_int("WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
+ if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
+ throw Socket::Err(m_s, "WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
+ if (events.iErrorCode[FD_CLOSE_BIT] != 0)
+ throw Socket::Err(m_s, "FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
+ m_resultPending = false;
+ }
+ return m_lastResult != 0;
+}
+
+void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ if (m_resultPending)
+ container.AddHandle(m_event, CallStack("SocketSender::GetWaitObjects() - result pending", &callStack));
+ else
+ container.SetNoWait(CallStack("SocketSender::GetWaitObjects() - result ready", &callStack));
+}
+
+unsigned int SocketSender::GetSendResult()
+{
+ if (m_resultPending)
+ {
+ DWORD flags = 0;
+ BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags);
+ m_s.CheckAndHandleError("WSAGetOverlappedResult", result);
+ m_resultPending = false;
+ }
+ return m_lastResult;
+}
+
+#endif
+
+#ifdef USE_BERKELEY_STYLE_SOCKETS
+
+SocketReceiver::SocketReceiver(Socket &s)
+ : m_s(s), m_lastResult(0), m_eofReceived(false)
+{
+}
+
+void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ if (!m_eofReceived)
+ container.AddReadFd(m_s, CallStack("SocketReceiver::GetWaitObjects()", &callStack));
+}
+
+bool SocketReceiver::Receive(byte* buf, size_t bufLen)
+{
+ m_lastResult = m_s.Receive(buf, bufLen);
+ if (bufLen > 0 && m_lastResult == 0)
+ m_eofReceived = true;
+ return true;
+}
+
+unsigned int SocketReceiver::GetReceiveResult()
+{
+ return m_lastResult;
+}
+
+SocketSender::SocketSender(Socket &s)
+ : m_s(s), m_lastResult(0)
+{
+}
+
+void SocketSender::Send(const byte* buf, size_t bufLen)
+{
+ m_lastResult = m_s.Send(buf, bufLen);
+}
+
+void SocketSender::SendEof()
+{
+ m_s.ShutDown(SD_SEND);
+}
+
+unsigned int SocketSender::GetSendResult()
+{
+ return m_lastResult;
+}
+
+void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ container.AddWriteFd(m_s, CallStack("SocketSender::GetWaitObjects()", &callStack));
+}
+
+#endif
+
+NAMESPACE_END
+
+#endif // #ifdef SOCKETS_AVAILABLE
diff --git a/lib/cryptopp/socketft.h b/lib/cryptopp/socketft.h
new file mode 100644
index 000000000..e414aa68f
--- /dev/null
+++ b/lib/cryptopp/socketft.h
@@ -0,0 +1,224 @@
+#ifndef CRYPTOPP_SOCKETFT_H
+#define CRYPTOPP_SOCKETFT_H
+
+#include "config.h"
+
+#ifdef SOCKETS_AVAILABLE
+
+#include "network.h"
+#include "queue.h"
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
+# error Winsock 1 is not supported by this library. Please include this file or winsock2.h before windows.h.
+# endif
+#include <winsock2.h>
+#include "winpipes.h"
+#else
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+typedef ::SOCKET socket_t;
+#else
+typedef int socket_t;
+const socket_t INVALID_SOCKET = -1;
+// cygwin 1.1.4 doesn't have SHUT_RD
+const int SD_RECEIVE = 0;
+const int SD_SEND = 1;
+const int SD_BOTH = 2;
+const int SOCKET_ERROR = -1;
+#endif
+
+#ifndef socklen_t
+typedef TYPE_OF_SOCKLEN_T socklen_t; // see config.h
+#endif
+
+//! wrapper for Windows or Berkeley Sockets
+class Socket
+{
+public:
+ //! exception thrown by Socket class
+ class Err : public OS_Error
+ {
+ public:
+ Err(socket_t s, const std::string& operation, int error);
+ socket_t GetSocket() const {return m_s;}
+
+ private:
+ socket_t m_s;
+ };
+
+ Socket(socket_t s = INVALID_SOCKET, bool own=false) : m_s(s), m_own(own) {}
+ Socket(const Socket &s) : m_s(s.m_s), m_own(false) {}
+ virtual ~Socket();
+
+ bool GetOwnership() const {return m_own;}
+ void SetOwnership(bool own) {m_own = own;}
+
+ operator socket_t() {return m_s;}
+ socket_t GetSocket() const {return m_s;}
+ void AttachSocket(socket_t s, bool own=false);
+ socket_t DetachSocket();
+ void CloseSocket();
+
+ void Create(int nType = SOCK_STREAM);
+ void Bind(unsigned int port, const char *addr=NULL);
+ void Bind(const sockaddr* psa, socklen_t saLen);
+ void Listen(int backlog=5);
+ // the next three functions return false if the socket is in nonblocking mode
+ // and the operation cannot be completed immediately
+ bool Connect(const char *addr, unsigned int port);
+ bool Connect(const sockaddr* psa, socklen_t saLen);
+ bool Accept(Socket& s, sockaddr *psa=NULL, socklen_t *psaLen=NULL);
+ void GetSockName(sockaddr *psa, socklen_t *psaLen);
+ void GetPeerName(sockaddr *psa, socklen_t *psaLen);
+ unsigned int Send(const byte* buf, size_t bufLen, int flags=0);
+ unsigned int Receive(byte* buf, size_t bufLen, int flags=0);
+ void ShutDown(int how = SD_SEND);
+
+ void IOCtl(long cmd, unsigned long *argp);
+ bool SendReady(const timeval *timeout);
+ bool ReceiveReady(const timeval *timeout);
+
+ virtual void HandleError(const char *operation) const;
+ void CheckAndHandleError_int(const char *operation, int result) const
+ {if (result == SOCKET_ERROR) HandleError(operation);}
+ void CheckAndHandleError(const char *operation, socket_t result) const
+ {if (result == SOCKET_ERROR) HandleError(operation);}
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ void CheckAndHandleError(const char *operation, BOOL result) const
+ {assert(result==TRUE || result==FALSE); if (!result) HandleError(operation);}
+ void CheckAndHandleError(const char *operation, bool result) const
+ {if (!result) HandleError(operation);}
+#endif
+
+ //! look up the port number given its name, returns 0 if not found
+ static unsigned int PortNameToNumber(const char *name, const char *protocol="tcp");
+ //! start Windows Sockets 2
+ static void StartSockets();
+ //! calls WSACleanup for Windows Sockets
+ static void ShutdownSockets();
+ //! returns errno or WSAGetLastError
+ static int GetLastError();
+ //! sets errno or calls WSASetLastError
+ static void SetLastError(int errorCode);
+
+protected:
+ virtual void SocketChanged() {}
+
+ socket_t m_s;
+ bool m_own;
+};
+
+class SocketsInitializer
+{
+public:
+ SocketsInitializer() {Socket::StartSockets();}
+ ~SocketsInitializer() {try {Socket::ShutdownSockets();} catch (...) {}}
+};
+
+class SocketReceiver : public NetworkReceiver
+{
+public:
+ SocketReceiver(Socket &s);
+
+#ifdef USE_BERKELEY_STYLE_SOCKETS
+ bool MustWaitToReceive() {return true;}
+#else
+ ~SocketReceiver();
+ bool MustWaitForResult() {return true;}
+#endif
+ bool Receive(byte* buf, size_t bufLen);
+ unsigned int GetReceiveResult();
+ bool EofReceived() const {return m_eofReceived;}
+
+ unsigned int GetMaxWaitObjectCount() const {return 1;}
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+
+private:
+ Socket &m_s;
+ bool m_eofReceived;
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ WindowsHandle m_event;
+ OVERLAPPED m_overlapped;
+ bool m_resultPending;
+ DWORD m_lastResult;
+#else
+ unsigned int m_lastResult;
+#endif
+};
+
+class SocketSender : public NetworkSender
+{
+public:
+ SocketSender(Socket &s);
+
+#ifdef USE_BERKELEY_STYLE_SOCKETS
+ bool MustWaitToSend() {return true;}
+#else
+ ~SocketSender();
+ bool MustWaitForResult() {return true;}
+ bool MustWaitForEof() { return true; }
+ bool EofSent();
+#endif
+ void Send(const byte* buf, size_t bufLen);
+ unsigned int GetSendResult();
+ void SendEof();
+
+ unsigned int GetMaxWaitObjectCount() const {return 1;}
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+
+private:
+ Socket &m_s;
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ WindowsHandle m_event;
+ OVERLAPPED m_overlapped;
+ bool m_resultPending;
+ DWORD m_lastResult;
+#else
+ unsigned int m_lastResult;
+#endif
+};
+
+//! socket-based implementation of NetworkSource
+class SocketSource : public NetworkSource, public Socket
+{
+public:
+ SocketSource(socket_t s = INVALID_SOCKET, bool pumpAll = false, BufferedTransformation *attachment = NULL)
+ : NetworkSource(attachment), Socket(s), m_receiver(*this)
+ {
+ if (pumpAll)
+ PumpAll();
+ }
+
+private:
+ NetworkReceiver & AccessReceiver() {return m_receiver;}
+ SocketReceiver m_receiver;
+};
+
+//! socket-based implementation of NetworkSink
+class SocketSink : public NetworkSink, public Socket
+{
+public:
+ SocketSink(socket_t s=INVALID_SOCKET, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024)
+ : NetworkSink(maxBufferSize, autoFlushBound), Socket(s), m_sender(*this) {}
+
+ void SendEof() {ShutDown(SD_SEND);}
+
+private:
+ NetworkSender & AccessSender() {return m_sender;}
+ SocketSender m_sender;
+};
+
+NAMESPACE_END
+
+#endif // #ifdef SOCKETS_AVAILABLE
+
+#endif
diff --git a/lib/cryptopp/square.cpp b/lib/cryptopp/square.cpp
new file mode 100644
index 000000000..00e6bddbe
--- /dev/null
+++ b/lib/cryptopp/square.cpp
@@ -0,0 +1,177 @@
+// square.cpp - written and placed in the public domain by Wei Dai
+// Based on Paulo S.L.M. Barreto's public domain implementation
+
+#include "pch.h"
+#include "square.h"
+#include "misc.h"
+#include "gf256.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// apply theta to a roundkey
+static void SquareTransform (word32 in[4], word32 out[4])
+{
+ static const byte G[4][4] =
+ {
+ 0x02U, 0x01U, 0x01U, 0x03U,
+ 0x03U, 0x02U, 0x01U, 0x01U,
+ 0x01U, 0x03U, 0x02U, 0x01U,
+ 0x01U, 0x01U, 0x03U, 0x02U
+ };
+
+ GF256 gf256(0xf5);
+
+ for (int i = 0; i < 4; i++)
+ {
+ word32 temp = 0;
+ for (int j = 0; j < 4; j++)
+ for (int k = 0; k < 4; k++)
+ temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8);
+ out[i] = temp;
+ }
+}
+
+#define roundkeys(i, j) m_roundkeys[(i)*4+(j)]
+#define roundkeys4(i) (m_roundkeys+(i)*4)
+
+void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
+{
+ AssertValidKeyLength(length);
+
+ static const word32 offset[ROUNDS] = {
+ 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
+ 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
+ };
+
+ GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH);
+
+ /* apply the key evolution function */
+ for (int i = 1; i < ROUNDS+1; i++)
+ {
+ roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlFixed(roundkeys(i-1, 3), 8U) ^ offset[i-1];
+ roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0);
+ roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1);
+ roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2);
+ }
+
+ /* produce the round keys */
+ if (IsForwardTransformation())
+ {
+ for (int i = 0; i < ROUNDS; i++)
+ SquareTransform (roundkeys4(i), roundkeys4(i));
+ }
+ else
+ {
+ for (int i = 0; i < ROUNDS/2; i++)
+ for (int j = 0; j < 4; j++)
+ std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j));
+ SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS));
+ }
+}
+
+#define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */
+#define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */
+#define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */
+#define LSB(x) (((x) ) & 0xffU) /* least significant byte */
+
+#define squareRound(text, temp, T0, T1, T2, T3, roundkey) \
+{ \
+ temp[0] = T0[MSB (text[0])] \
+ ^ T1[MSB (text[1])] \
+ ^ T2[MSB (text[2])] \
+ ^ T3[MSB (text[3])] \
+ ^ roundkey[0]; \
+ temp[1] = T0[SSB (text[0])] \
+ ^ T1[SSB (text[1])] \
+ ^ T2[SSB (text[2])] \
+ ^ T3[SSB (text[3])] \
+ ^ roundkey[1]; \
+ temp[2] = T0[TSB (text[0])] \
+ ^ T1[TSB (text[1])] \
+ ^ T2[TSB (text[2])] \
+ ^ T3[TSB (text[3])] \
+ ^ roundkey[2]; \
+ temp[3] = T0[LSB (text[0])] \
+ ^ T1[LSB (text[1])] \
+ ^ T2[LSB (text[2])] \
+ ^ T3[LSB (text[3])] \
+ ^ roundkey[3]; \
+} /* squareRound */
+
+#define squareFinal(text, temp, S, roundkey) \
+{ \
+ text[0] = ((word32) (S[MSB (temp[0])]) << 24) \
+ ^ ((word32) (S[MSB (temp[1])]) << 16) \
+ ^ ((word32) (S[MSB (temp[2])]) << 8) \
+ ^ (word32) (S[MSB (temp[3])]) \
+ ^ roundkey[0]; \
+ text[1] = ((word32) (S[SSB (temp[0])]) << 24) \
+ ^ ((word32) (S[SSB (temp[1])]) << 16) \
+ ^ ((word32) (S[SSB (temp[2])]) << 8) \
+ ^ (word32) (S[SSB (temp[3])]) \
+ ^ roundkey[1]; \
+ text[2] = ((word32) (S[TSB (temp[0])]) << 24) \
+ ^ ((word32) (S[TSB (temp[1])]) << 16) \
+ ^ ((word32) (S[TSB (temp[2])]) << 8) \
+ ^ (word32) (S[TSB (temp[3])]) \
+ ^ roundkey[2]; \
+ text[3] = ((word32) (S[LSB (temp[0])]) << 24) \
+ ^ ((word32) (S[LSB (temp[1])]) << 16) \
+ ^ ((word32) (S[LSB (temp[2])]) << 8) \
+ ^ (word32) (S[LSB (temp[3])]) \
+ ^ roundkey[3]; \
+} /* squareFinal */
+
+typedef BlockGetAndPut<word32, BigEndian> Block;
+
+void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 text[4], temp[4];
+ Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
+
+ /* initial key addition */
+ text[0] ^= roundkeys(0, 0);
+ text[1] ^= roundkeys(0, 1);
+ text[2] ^= roundkeys(0, 2);
+ text[3] ^= roundkeys(0, 3);
+
+ /* ROUNDS - 1 full rounds */
+ for (int i=1; i+1<ROUNDS; i+=2)
+ {
+ squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(i));
+ squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys4(i+1));
+ }
+ squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(ROUNDS-1));
+
+ /* last round (diffusion becomes only transposition) */
+ squareFinal (text, temp, Se, roundkeys4(ROUNDS));
+
+ Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
+}
+
+void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 text[4], temp[4];
+ Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
+
+ /* initial key addition */
+ text[0] ^= roundkeys(0, 0);
+ text[1] ^= roundkeys(0, 1);
+ text[2] ^= roundkeys(0, 2);
+ text[3] ^= roundkeys(0, 3);
+
+ /* ROUNDS - 1 full rounds */
+ for (int i=1; i+1<ROUNDS; i+=2)
+ {
+ squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(i));
+ squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys4(i+1));
+ }
+ squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(ROUNDS-1));
+
+ /* last round (diffusion becomes only transposition) */
+ squareFinal (text, temp, Sd, roundkeys4(ROUNDS));
+
+ Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/square.h b/lib/cryptopp/square.h
new file mode 100644
index 000000000..d7e23c284
--- /dev/null
+++ b/lib/cryptopp/square.h
@@ -0,0 +1,58 @@
+#ifndef CRYPTOPP_SQUARE_H
+#define CRYPTOPP_SQUARE_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+struct Square_Info : public FixedBlockSize<16>, public FixedKeyLength<16>, FixedRounds<8>
+{
+ static const char *StaticAlgorithmName() {return "Square";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#Square">Square</a>
+class Square : public Square_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<Square_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+
+ protected:
+ FixedSizeSecBlock<word32, 4*(ROUNDS+1)> m_roundkeys;
+ };
+
+ class CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ private:
+ static const byte Se[256];
+ static const word32 Te[4][256];
+ };
+
+ class CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ private:
+ static const byte Sd[256];
+ static const word32 Td[4][256];
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+typedef Square::Encryption SquareEncryption;
+typedef Square::Decryption SquareDecryption;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/squaretb.cpp b/lib/cryptopp/squaretb.cpp
new file mode 100644
index 000000000..bc3bee7df
--- /dev/null
+++ b/lib/cryptopp/squaretb.cpp
@@ -0,0 +1,582 @@
+#include "pch.h"
+#include "square.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+const byte Square::Enc::Se[256] = {
+177, 206, 195, 149, 90, 173, 231, 2, 77, 68, 251, 145, 12, 135, 161, 80,
+203, 103, 84, 221, 70, 143, 225, 78, 240, 253, 252, 235, 249, 196, 26, 110,
+ 94, 245, 204, 141, 28, 86, 67, 254, 7, 97, 248, 117, 89, 255, 3, 34,
+138, 209, 19, 238, 136, 0, 14, 52, 21, 128, 148, 227, 237, 181, 83, 35,
+ 75, 71, 23, 167, 144, 53, 171, 216, 184, 223, 79, 87, 154, 146, 219, 27,
+ 60, 200, 153, 4, 142, 224, 215, 125, 133, 187, 64, 44, 58, 69, 241, 66,
+101, 32, 65, 24, 114, 37, 147, 112, 54, 5, 242, 11, 163, 121, 236, 8,
+ 39, 49, 50, 182, 124, 176, 10, 115, 91, 123, 183, 129, 210, 13, 106, 38,
+158, 88, 156, 131, 116, 179, 172, 48, 122, 105, 119, 15, 174, 33, 222, 208,
+ 46, 151, 16, 164, 152, 168, 212, 104, 45, 98, 41, 109, 22, 73, 118, 199,
+232, 193, 150, 55, 229, 202, 244, 233, 99, 18, 194, 166, 20, 188, 211, 40,
+175, 47, 230, 36, 82, 198, 160, 9, 189, 140, 207, 93, 17, 95, 1, 197,
+159, 61, 162, 155, 201, 59, 190, 81, 25, 31, 63, 92, 178, 239, 74, 205,
+191, 186, 111, 100, 217, 243, 62, 180, 170, 220, 213, 6, 192, 126, 246, 102,
+108, 132, 113, 56, 185, 29, 127, 157, 72, 139, 42, 218, 165, 51, 130, 57,
+214, 120, 134, 250, 228, 43, 169, 30, 137, 96, 107, 234, 85, 76, 247, 226,
+};
+
+const byte Square::Dec::Sd[256] = {
+ 53, 190, 7, 46, 83, 105, 219, 40, 111, 183, 118, 107, 12, 125, 54, 139,
+146, 188, 169, 50, 172, 56, 156, 66, 99, 200, 30, 79, 36, 229, 247, 201,
+ 97, 141, 47, 63, 179, 101, 127, 112, 175, 154, 234, 245, 91, 152, 144, 177,
+135, 113, 114, 237, 55, 69, 104, 163, 227, 239, 92, 197, 80, 193, 214, 202,
+ 90, 98, 95, 38, 9, 93, 20, 65, 232, 157, 206, 64, 253, 8, 23, 74,
+ 15, 199, 180, 62, 18, 252, 37, 75, 129, 44, 4, 120, 203, 187, 32, 189,
+249, 41, 153, 168, 211, 96, 223, 17, 151, 137, 126, 250, 224, 155, 31, 210,
+103, 226, 100, 119, 132, 43, 158, 138, 241, 109, 136, 121, 116, 87, 221, 230,
+ 57, 123, 238, 131, 225, 88, 242, 13, 52, 248, 48, 233, 185, 35, 84, 21,
+ 68, 11, 77, 102, 58, 3, 162, 145, 148, 82, 76, 195, 130, 231, 128, 192,
+182, 14, 194, 108, 147, 236, 171, 67, 149, 246, 216, 70, 134, 5, 140, 176,
+117, 0, 204, 133, 215, 61, 115, 122, 72, 228, 209, 89, 173, 184, 198, 208,
+220, 161, 170, 2, 29, 191, 181, 159, 81, 196, 165, 16, 34, 207, 1, 186,
+143, 49, 124, 174, 150, 218, 240, 86, 71, 212, 235, 78, 217, 19, 142, 73,
+ 85, 22, 255, 59, 244, 164, 178, 6, 160, 167, 251, 27, 110, 60, 51, 205,
+ 24, 94, 106, 213, 166, 33, 222, 254, 42, 28, 243, 10, 26, 25, 39, 45,
+};
+
+const word32 Square::Enc::Te[4][256] = {
+{
+0x97b1b126UL, 0x69cecea7UL, 0x73c3c3b0UL, 0xdf95954aUL,
+0xb45a5aeeUL, 0xafadad02UL, 0x3be7e7dcUL, 0x04020206UL,
+0x9a4d4dd7UL, 0x884444ccUL, 0x03fbfbf8UL, 0xd7919146UL,
+0x180c0c14UL, 0xfb87877cUL, 0xb7a1a116UL, 0xa05050f0UL,
+0x63cbcba8UL, 0xce6767a9UL, 0xa85454fcUL, 0x4fdddd92UL,
+0x8c4646caUL, 0xeb8f8f64UL, 0x37e1e1d6UL, 0x9c4e4ed2UL,
+0x15f0f0e5UL, 0x0ffdfdf2UL, 0x0dfcfcf1UL, 0x23ebebc8UL,
+0x07f9f9feUL, 0x7dc4c4b9UL, 0x341a1a2eUL, 0xdc6e6eb2UL,
+0xbc5e5ee2UL, 0x1ff5f5eaUL, 0x6dcccca1UL, 0xef8d8d62UL,
+0x381c1c24UL, 0xac5656faUL, 0x864343c5UL, 0x09fefef7UL,
+0x0e070709UL, 0xc26161a3UL, 0x05f8f8fdUL, 0xea75759fUL,
+0xb25959ebUL, 0x0bfffff4UL, 0x06030305UL, 0x44222266UL,
+0xe18a8a6bUL, 0x57d1d186UL, 0x26131335UL, 0x29eeeec7UL,
+0xe588886dUL, 0x00000000UL, 0x1c0e0e12UL, 0x6834345cUL,
+0x2a15153fUL, 0xf5808075UL, 0xdd949449UL, 0x33e3e3d0UL,
+0x2fededc2UL, 0x9fb5b52aUL, 0xa65353f5UL, 0x46232365UL,
+0x964b4bddUL, 0x8e4747c9UL, 0x2e171739UL, 0xbba7a71cUL,
+0xd5909045UL, 0x6a35355fUL, 0xa3abab08UL, 0x45d8d89dUL,
+0x85b8b83dUL, 0x4bdfdf94UL, 0x9e4f4fd1UL, 0xae5757f9UL,
+0xc19a9a5bUL, 0xd1929243UL, 0x43dbdb98UL, 0x361b1b2dUL,
+0x783c3c44UL, 0x65c8c8adUL, 0xc799995eUL, 0x0804040cUL,
+0xe98e8e67UL, 0x35e0e0d5UL, 0x5bd7d78cUL, 0xfa7d7d87UL,
+0xff85857aUL, 0x83bbbb38UL, 0x804040c0UL, 0x582c2c74UL,
+0x743a3a4eUL, 0x8a4545cfUL, 0x17f1f1e6UL, 0x844242c6UL,
+0xca6565afUL, 0x40202060UL, 0x824141c3UL, 0x30181828UL,
+0xe4727296UL, 0x4a25256fUL, 0xd3939340UL, 0xe0707090UL,
+0x6c36365aUL, 0x0a05050fUL, 0x11f2f2e3UL, 0x160b0b1dUL,
+0xb3a3a310UL, 0xf279798bUL, 0x2dececc1UL, 0x10080818UL,
+0x4e272769UL, 0x62313153UL, 0x64323256UL, 0x99b6b62fUL,
+0xf87c7c84UL, 0x95b0b025UL, 0x140a0a1eUL, 0xe6737395UL,
+0xb65b5bedUL, 0xf67b7b8dUL, 0x9bb7b72cUL, 0xf7818176UL,
+0x51d2d283UL, 0x1a0d0d17UL, 0xd46a6abeUL, 0x4c26266aUL,
+0xc99e9e57UL, 0xb05858e8UL, 0xcd9c9c51UL, 0xf3838370UL,
+0xe874749cUL, 0x93b3b320UL, 0xadacac01UL, 0x60303050UL,
+0xf47a7a8eUL, 0xd26969bbUL, 0xee777799UL, 0x1e0f0f11UL,
+0xa9aeae07UL, 0x42212163UL, 0x49dede97UL, 0x55d0d085UL,
+0x5c2e2e72UL, 0xdb97974cUL, 0x20101030UL, 0xbda4a419UL,
+0xc598985dUL, 0xa5a8a80dUL, 0x5dd4d489UL, 0xd06868b8UL,
+0x5a2d2d77UL, 0xc46262a6UL, 0x5229297bUL, 0xda6d6db7UL,
+0x2c16163aUL, 0x924949dbUL, 0xec76769aUL, 0x7bc7c7bcUL,
+0x25e8e8cdUL, 0x77c1c1b6UL, 0xd996964fUL, 0x6e373759UL,
+0x3fe5e5daUL, 0x61cacaabUL, 0x1df4f4e9UL, 0x27e9e9ceUL,
+0xc66363a5UL, 0x24121236UL, 0x71c2c2b3UL, 0xb9a6a61fUL,
+0x2814143cUL, 0x8dbcbc31UL, 0x53d3d380UL, 0x50282878UL,
+0xabafaf04UL, 0x5e2f2f71UL, 0x39e6e6dfUL, 0x4824246cUL,
+0xa45252f6UL, 0x79c6c6bfUL, 0xb5a0a015UL, 0x1209091bUL,
+0x8fbdbd32UL, 0xed8c8c61UL, 0x6bcfcfa4UL, 0xba5d5de7UL,
+0x22111133UL, 0xbe5f5fe1UL, 0x02010103UL, 0x7fc5c5baUL,
+0xcb9f9f54UL, 0x7a3d3d47UL, 0xb1a2a213UL, 0xc39b9b58UL,
+0x67c9c9aeUL, 0x763b3b4dUL, 0x89bebe37UL, 0xa25151f3UL,
+0x3219192bUL, 0x3e1f1f21UL, 0x7e3f3f41UL, 0xb85c5ce4UL,
+0x91b2b223UL, 0x2befefc4UL, 0x944a4adeUL, 0x6fcdcda2UL,
+0x8bbfbf34UL, 0x81baba3bUL, 0xde6f6fb1UL, 0xc86464acUL,
+0x47d9d99eUL, 0x13f3f3e0UL, 0x7c3e3e42UL, 0x9db4b429UL,
+0xa1aaaa0bUL, 0x4ddcdc91UL, 0x5fd5d58aUL, 0x0c06060aUL,
+0x75c0c0b5UL, 0xfc7e7e82UL, 0x19f6f6efUL, 0xcc6666aaUL,
+0xd86c6cb4UL, 0xfd848479UL, 0xe2717193UL, 0x70383848UL,
+0x87b9b93eUL, 0x3a1d1d27UL, 0xfe7f7f81UL, 0xcf9d9d52UL,
+0x904848d8UL, 0xe38b8b68UL, 0x542a2a7eUL, 0x41dada9bUL,
+0xbfa5a51aUL, 0x66333355UL, 0xf1828273UL, 0x7239394bUL,
+0x59d6d68fUL, 0xf0787888UL, 0xf986867fUL, 0x01fafafbUL,
+0x3de4e4d9UL, 0x562b2b7dUL, 0xa7a9a90eUL, 0x3c1e1e22UL,
+0xe789896eUL, 0xc06060a0UL, 0xd66b6bbdUL, 0x21eaeacbUL,
+0xaa5555ffUL, 0x984c4cd4UL, 0x1bf7f7ecUL, 0x31e2e2d3UL,
+},
+
+{
+0x2697b1b1UL, 0xa769ceceUL, 0xb073c3c3UL, 0x4adf9595UL,
+0xeeb45a5aUL, 0x02afadadUL, 0xdc3be7e7UL, 0x06040202UL,
+0xd79a4d4dUL, 0xcc884444UL, 0xf803fbfbUL, 0x46d79191UL,
+0x14180c0cUL, 0x7cfb8787UL, 0x16b7a1a1UL, 0xf0a05050UL,
+0xa863cbcbUL, 0xa9ce6767UL, 0xfca85454UL, 0x924fddddUL,
+0xca8c4646UL, 0x64eb8f8fUL, 0xd637e1e1UL, 0xd29c4e4eUL,
+0xe515f0f0UL, 0xf20ffdfdUL, 0xf10dfcfcUL, 0xc823ebebUL,
+0xfe07f9f9UL, 0xb97dc4c4UL, 0x2e341a1aUL, 0xb2dc6e6eUL,
+0xe2bc5e5eUL, 0xea1ff5f5UL, 0xa16dccccUL, 0x62ef8d8dUL,
+0x24381c1cUL, 0xfaac5656UL, 0xc5864343UL, 0xf709fefeUL,
+0x090e0707UL, 0xa3c26161UL, 0xfd05f8f8UL, 0x9fea7575UL,
+0xebb25959UL, 0xf40bffffUL, 0x05060303UL, 0x66442222UL,
+0x6be18a8aUL, 0x8657d1d1UL, 0x35261313UL, 0xc729eeeeUL,
+0x6de58888UL, 0x00000000UL, 0x121c0e0eUL, 0x5c683434UL,
+0x3f2a1515UL, 0x75f58080UL, 0x49dd9494UL, 0xd033e3e3UL,
+0xc22fededUL, 0x2a9fb5b5UL, 0xf5a65353UL, 0x65462323UL,
+0xdd964b4bUL, 0xc98e4747UL, 0x392e1717UL, 0x1cbba7a7UL,
+0x45d59090UL, 0x5f6a3535UL, 0x08a3ababUL, 0x9d45d8d8UL,
+0x3d85b8b8UL, 0x944bdfdfUL, 0xd19e4f4fUL, 0xf9ae5757UL,
+0x5bc19a9aUL, 0x43d19292UL, 0x9843dbdbUL, 0x2d361b1bUL,
+0x44783c3cUL, 0xad65c8c8UL, 0x5ec79999UL, 0x0c080404UL,
+0x67e98e8eUL, 0xd535e0e0UL, 0x8c5bd7d7UL, 0x87fa7d7dUL,
+0x7aff8585UL, 0x3883bbbbUL, 0xc0804040UL, 0x74582c2cUL,
+0x4e743a3aUL, 0xcf8a4545UL, 0xe617f1f1UL, 0xc6844242UL,
+0xafca6565UL, 0x60402020UL, 0xc3824141UL, 0x28301818UL,
+0x96e47272UL, 0x6f4a2525UL, 0x40d39393UL, 0x90e07070UL,
+0x5a6c3636UL, 0x0f0a0505UL, 0xe311f2f2UL, 0x1d160b0bUL,
+0x10b3a3a3UL, 0x8bf27979UL, 0xc12dececUL, 0x18100808UL,
+0x694e2727UL, 0x53623131UL, 0x56643232UL, 0x2f99b6b6UL,
+0x84f87c7cUL, 0x2595b0b0UL, 0x1e140a0aUL, 0x95e67373UL,
+0xedb65b5bUL, 0x8df67b7bUL, 0x2c9bb7b7UL, 0x76f78181UL,
+0x8351d2d2UL, 0x171a0d0dUL, 0xbed46a6aUL, 0x6a4c2626UL,
+0x57c99e9eUL, 0xe8b05858UL, 0x51cd9c9cUL, 0x70f38383UL,
+0x9ce87474UL, 0x2093b3b3UL, 0x01adacacUL, 0x50603030UL,
+0x8ef47a7aUL, 0xbbd26969UL, 0x99ee7777UL, 0x111e0f0fUL,
+0x07a9aeaeUL, 0x63422121UL, 0x9749dedeUL, 0x8555d0d0UL,
+0x725c2e2eUL, 0x4cdb9797UL, 0x30201010UL, 0x19bda4a4UL,
+0x5dc59898UL, 0x0da5a8a8UL, 0x895dd4d4UL, 0xb8d06868UL,
+0x775a2d2dUL, 0xa6c46262UL, 0x7b522929UL, 0xb7da6d6dUL,
+0x3a2c1616UL, 0xdb924949UL, 0x9aec7676UL, 0xbc7bc7c7UL,
+0xcd25e8e8UL, 0xb677c1c1UL, 0x4fd99696UL, 0x596e3737UL,
+0xda3fe5e5UL, 0xab61cacaUL, 0xe91df4f4UL, 0xce27e9e9UL,
+0xa5c66363UL, 0x36241212UL, 0xb371c2c2UL, 0x1fb9a6a6UL,
+0x3c281414UL, 0x318dbcbcUL, 0x8053d3d3UL, 0x78502828UL,
+0x04abafafUL, 0x715e2f2fUL, 0xdf39e6e6UL, 0x6c482424UL,
+0xf6a45252UL, 0xbf79c6c6UL, 0x15b5a0a0UL, 0x1b120909UL,
+0x328fbdbdUL, 0x61ed8c8cUL, 0xa46bcfcfUL, 0xe7ba5d5dUL,
+0x33221111UL, 0xe1be5f5fUL, 0x03020101UL, 0xba7fc5c5UL,
+0x54cb9f9fUL, 0x477a3d3dUL, 0x13b1a2a2UL, 0x58c39b9bUL,
+0xae67c9c9UL, 0x4d763b3bUL, 0x3789bebeUL, 0xf3a25151UL,
+0x2b321919UL, 0x213e1f1fUL, 0x417e3f3fUL, 0xe4b85c5cUL,
+0x2391b2b2UL, 0xc42befefUL, 0xde944a4aUL, 0xa26fcdcdUL,
+0x348bbfbfUL, 0x3b81babaUL, 0xb1de6f6fUL, 0xacc86464UL,
+0x9e47d9d9UL, 0xe013f3f3UL, 0x427c3e3eUL, 0x299db4b4UL,
+0x0ba1aaaaUL, 0x914ddcdcUL, 0x8a5fd5d5UL, 0x0a0c0606UL,
+0xb575c0c0UL, 0x82fc7e7eUL, 0xef19f6f6UL, 0xaacc6666UL,
+0xb4d86c6cUL, 0x79fd8484UL, 0x93e27171UL, 0x48703838UL,
+0x3e87b9b9UL, 0x273a1d1dUL, 0x81fe7f7fUL, 0x52cf9d9dUL,
+0xd8904848UL, 0x68e38b8bUL, 0x7e542a2aUL, 0x9b41dadaUL,
+0x1abfa5a5UL, 0x55663333UL, 0x73f18282UL, 0x4b723939UL,
+0x8f59d6d6UL, 0x88f07878UL, 0x7ff98686UL, 0xfb01fafaUL,
+0xd93de4e4UL, 0x7d562b2bUL, 0x0ea7a9a9UL, 0x223c1e1eUL,
+0x6ee78989UL, 0xa0c06060UL, 0xbdd66b6bUL, 0xcb21eaeaUL,
+0xffaa5555UL, 0xd4984c4cUL, 0xec1bf7f7UL, 0xd331e2e2UL,
+},
+
+{
+0xb12697b1UL, 0xcea769ceUL, 0xc3b073c3UL, 0x954adf95UL,
+0x5aeeb45aUL, 0xad02afadUL, 0xe7dc3be7UL, 0x02060402UL,
+0x4dd79a4dUL, 0x44cc8844UL, 0xfbf803fbUL, 0x9146d791UL,
+0x0c14180cUL, 0x877cfb87UL, 0xa116b7a1UL, 0x50f0a050UL,
+0xcba863cbUL, 0x67a9ce67UL, 0x54fca854UL, 0xdd924fddUL,
+0x46ca8c46UL, 0x8f64eb8fUL, 0xe1d637e1UL, 0x4ed29c4eUL,
+0xf0e515f0UL, 0xfdf20ffdUL, 0xfcf10dfcUL, 0xebc823ebUL,
+0xf9fe07f9UL, 0xc4b97dc4UL, 0x1a2e341aUL, 0x6eb2dc6eUL,
+0x5ee2bc5eUL, 0xf5ea1ff5UL, 0xcca16dccUL, 0x8d62ef8dUL,
+0x1c24381cUL, 0x56faac56UL, 0x43c58643UL, 0xfef709feUL,
+0x07090e07UL, 0x61a3c261UL, 0xf8fd05f8UL, 0x759fea75UL,
+0x59ebb259UL, 0xfff40bffUL, 0x03050603UL, 0x22664422UL,
+0x8a6be18aUL, 0xd18657d1UL, 0x13352613UL, 0xeec729eeUL,
+0x886de588UL, 0x00000000UL, 0x0e121c0eUL, 0x345c6834UL,
+0x153f2a15UL, 0x8075f580UL, 0x9449dd94UL, 0xe3d033e3UL,
+0xedc22fedUL, 0xb52a9fb5UL, 0x53f5a653UL, 0x23654623UL,
+0x4bdd964bUL, 0x47c98e47UL, 0x17392e17UL, 0xa71cbba7UL,
+0x9045d590UL, 0x355f6a35UL, 0xab08a3abUL, 0xd89d45d8UL,
+0xb83d85b8UL, 0xdf944bdfUL, 0x4fd19e4fUL, 0x57f9ae57UL,
+0x9a5bc19aUL, 0x9243d192UL, 0xdb9843dbUL, 0x1b2d361bUL,
+0x3c44783cUL, 0xc8ad65c8UL, 0x995ec799UL, 0x040c0804UL,
+0x8e67e98eUL, 0xe0d535e0UL, 0xd78c5bd7UL, 0x7d87fa7dUL,
+0x857aff85UL, 0xbb3883bbUL, 0x40c08040UL, 0x2c74582cUL,
+0x3a4e743aUL, 0x45cf8a45UL, 0xf1e617f1UL, 0x42c68442UL,
+0x65afca65UL, 0x20604020UL, 0x41c38241UL, 0x18283018UL,
+0x7296e472UL, 0x256f4a25UL, 0x9340d393UL, 0x7090e070UL,
+0x365a6c36UL, 0x050f0a05UL, 0xf2e311f2UL, 0x0b1d160bUL,
+0xa310b3a3UL, 0x798bf279UL, 0xecc12decUL, 0x08181008UL,
+0x27694e27UL, 0x31536231UL, 0x32566432UL, 0xb62f99b6UL,
+0x7c84f87cUL, 0xb02595b0UL, 0x0a1e140aUL, 0x7395e673UL,
+0x5bedb65bUL, 0x7b8df67bUL, 0xb72c9bb7UL, 0x8176f781UL,
+0xd28351d2UL, 0x0d171a0dUL, 0x6abed46aUL, 0x266a4c26UL,
+0x9e57c99eUL, 0x58e8b058UL, 0x9c51cd9cUL, 0x8370f383UL,
+0x749ce874UL, 0xb32093b3UL, 0xac01adacUL, 0x30506030UL,
+0x7a8ef47aUL, 0x69bbd269UL, 0x7799ee77UL, 0x0f111e0fUL,
+0xae07a9aeUL, 0x21634221UL, 0xde9749deUL, 0xd08555d0UL,
+0x2e725c2eUL, 0x974cdb97UL, 0x10302010UL, 0xa419bda4UL,
+0x985dc598UL, 0xa80da5a8UL, 0xd4895dd4UL, 0x68b8d068UL,
+0x2d775a2dUL, 0x62a6c462UL, 0x297b5229UL, 0x6db7da6dUL,
+0x163a2c16UL, 0x49db9249UL, 0x769aec76UL, 0xc7bc7bc7UL,
+0xe8cd25e8UL, 0xc1b677c1UL, 0x964fd996UL, 0x37596e37UL,
+0xe5da3fe5UL, 0xcaab61caUL, 0xf4e91df4UL, 0xe9ce27e9UL,
+0x63a5c663UL, 0x12362412UL, 0xc2b371c2UL, 0xa61fb9a6UL,
+0x143c2814UL, 0xbc318dbcUL, 0xd38053d3UL, 0x28785028UL,
+0xaf04abafUL, 0x2f715e2fUL, 0xe6df39e6UL, 0x246c4824UL,
+0x52f6a452UL, 0xc6bf79c6UL, 0xa015b5a0UL, 0x091b1209UL,
+0xbd328fbdUL, 0x8c61ed8cUL, 0xcfa46bcfUL, 0x5de7ba5dUL,
+0x11332211UL, 0x5fe1be5fUL, 0x01030201UL, 0xc5ba7fc5UL,
+0x9f54cb9fUL, 0x3d477a3dUL, 0xa213b1a2UL, 0x9b58c39bUL,
+0xc9ae67c9UL, 0x3b4d763bUL, 0xbe3789beUL, 0x51f3a251UL,
+0x192b3219UL, 0x1f213e1fUL, 0x3f417e3fUL, 0x5ce4b85cUL,
+0xb22391b2UL, 0xefc42befUL, 0x4ade944aUL, 0xcda26fcdUL,
+0xbf348bbfUL, 0xba3b81baUL, 0x6fb1de6fUL, 0x64acc864UL,
+0xd99e47d9UL, 0xf3e013f3UL, 0x3e427c3eUL, 0xb4299db4UL,
+0xaa0ba1aaUL, 0xdc914ddcUL, 0xd58a5fd5UL, 0x060a0c06UL,
+0xc0b575c0UL, 0x7e82fc7eUL, 0xf6ef19f6UL, 0x66aacc66UL,
+0x6cb4d86cUL, 0x8479fd84UL, 0x7193e271UL, 0x38487038UL,
+0xb93e87b9UL, 0x1d273a1dUL, 0x7f81fe7fUL, 0x9d52cf9dUL,
+0x48d89048UL, 0x8b68e38bUL, 0x2a7e542aUL, 0xda9b41daUL,
+0xa51abfa5UL, 0x33556633UL, 0x8273f182UL, 0x394b7239UL,
+0xd68f59d6UL, 0x7888f078UL, 0x867ff986UL, 0xfafb01faUL,
+0xe4d93de4UL, 0x2b7d562bUL, 0xa90ea7a9UL, 0x1e223c1eUL,
+0x896ee789UL, 0x60a0c060UL, 0x6bbdd66bUL, 0xeacb21eaUL,
+0x55ffaa55UL, 0x4cd4984cUL, 0xf7ec1bf7UL, 0xe2d331e2UL,
+},
+
+{
+0xb1b12697UL, 0xcecea769UL, 0xc3c3b073UL, 0x95954adfUL,
+0x5a5aeeb4UL, 0xadad02afUL, 0xe7e7dc3bUL, 0x02020604UL,
+0x4d4dd79aUL, 0x4444cc88UL, 0xfbfbf803UL, 0x919146d7UL,
+0x0c0c1418UL, 0x87877cfbUL, 0xa1a116b7UL, 0x5050f0a0UL,
+0xcbcba863UL, 0x6767a9ceUL, 0x5454fca8UL, 0xdddd924fUL,
+0x4646ca8cUL, 0x8f8f64ebUL, 0xe1e1d637UL, 0x4e4ed29cUL,
+0xf0f0e515UL, 0xfdfdf20fUL, 0xfcfcf10dUL, 0xebebc823UL,
+0xf9f9fe07UL, 0xc4c4b97dUL, 0x1a1a2e34UL, 0x6e6eb2dcUL,
+0x5e5ee2bcUL, 0xf5f5ea1fUL, 0xcccca16dUL, 0x8d8d62efUL,
+0x1c1c2438UL, 0x5656faacUL, 0x4343c586UL, 0xfefef709UL,
+0x0707090eUL, 0x6161a3c2UL, 0xf8f8fd05UL, 0x75759feaUL,
+0x5959ebb2UL, 0xfffff40bUL, 0x03030506UL, 0x22226644UL,
+0x8a8a6be1UL, 0xd1d18657UL, 0x13133526UL, 0xeeeec729UL,
+0x88886de5UL, 0x00000000UL, 0x0e0e121cUL, 0x34345c68UL,
+0x15153f2aUL, 0x808075f5UL, 0x949449ddUL, 0xe3e3d033UL,
+0xededc22fUL, 0xb5b52a9fUL, 0x5353f5a6UL, 0x23236546UL,
+0x4b4bdd96UL, 0x4747c98eUL, 0x1717392eUL, 0xa7a71cbbUL,
+0x909045d5UL, 0x35355f6aUL, 0xabab08a3UL, 0xd8d89d45UL,
+0xb8b83d85UL, 0xdfdf944bUL, 0x4f4fd19eUL, 0x5757f9aeUL,
+0x9a9a5bc1UL, 0x929243d1UL, 0xdbdb9843UL, 0x1b1b2d36UL,
+0x3c3c4478UL, 0xc8c8ad65UL, 0x99995ec7UL, 0x04040c08UL,
+0x8e8e67e9UL, 0xe0e0d535UL, 0xd7d78c5bUL, 0x7d7d87faUL,
+0x85857affUL, 0xbbbb3883UL, 0x4040c080UL, 0x2c2c7458UL,
+0x3a3a4e74UL, 0x4545cf8aUL, 0xf1f1e617UL, 0x4242c684UL,
+0x6565afcaUL, 0x20206040UL, 0x4141c382UL, 0x18182830UL,
+0x727296e4UL, 0x25256f4aUL, 0x939340d3UL, 0x707090e0UL,
+0x36365a6cUL, 0x05050f0aUL, 0xf2f2e311UL, 0x0b0b1d16UL,
+0xa3a310b3UL, 0x79798bf2UL, 0xececc12dUL, 0x08081810UL,
+0x2727694eUL, 0x31315362UL, 0x32325664UL, 0xb6b62f99UL,
+0x7c7c84f8UL, 0xb0b02595UL, 0x0a0a1e14UL, 0x737395e6UL,
+0x5b5bedb6UL, 0x7b7b8df6UL, 0xb7b72c9bUL, 0x818176f7UL,
+0xd2d28351UL, 0x0d0d171aUL, 0x6a6abed4UL, 0x26266a4cUL,
+0x9e9e57c9UL, 0x5858e8b0UL, 0x9c9c51cdUL, 0x838370f3UL,
+0x74749ce8UL, 0xb3b32093UL, 0xacac01adUL, 0x30305060UL,
+0x7a7a8ef4UL, 0x6969bbd2UL, 0x777799eeUL, 0x0f0f111eUL,
+0xaeae07a9UL, 0x21216342UL, 0xdede9749UL, 0xd0d08555UL,
+0x2e2e725cUL, 0x97974cdbUL, 0x10103020UL, 0xa4a419bdUL,
+0x98985dc5UL, 0xa8a80da5UL, 0xd4d4895dUL, 0x6868b8d0UL,
+0x2d2d775aUL, 0x6262a6c4UL, 0x29297b52UL, 0x6d6db7daUL,
+0x16163a2cUL, 0x4949db92UL, 0x76769aecUL, 0xc7c7bc7bUL,
+0xe8e8cd25UL, 0xc1c1b677UL, 0x96964fd9UL, 0x3737596eUL,
+0xe5e5da3fUL, 0xcacaab61UL, 0xf4f4e91dUL, 0xe9e9ce27UL,
+0x6363a5c6UL, 0x12123624UL, 0xc2c2b371UL, 0xa6a61fb9UL,
+0x14143c28UL, 0xbcbc318dUL, 0xd3d38053UL, 0x28287850UL,
+0xafaf04abUL, 0x2f2f715eUL, 0xe6e6df39UL, 0x24246c48UL,
+0x5252f6a4UL, 0xc6c6bf79UL, 0xa0a015b5UL, 0x09091b12UL,
+0xbdbd328fUL, 0x8c8c61edUL, 0xcfcfa46bUL, 0x5d5de7baUL,
+0x11113322UL, 0x5f5fe1beUL, 0x01010302UL, 0xc5c5ba7fUL,
+0x9f9f54cbUL, 0x3d3d477aUL, 0xa2a213b1UL, 0x9b9b58c3UL,
+0xc9c9ae67UL, 0x3b3b4d76UL, 0xbebe3789UL, 0x5151f3a2UL,
+0x19192b32UL, 0x1f1f213eUL, 0x3f3f417eUL, 0x5c5ce4b8UL,
+0xb2b22391UL, 0xefefc42bUL, 0x4a4ade94UL, 0xcdcda26fUL,
+0xbfbf348bUL, 0xbaba3b81UL, 0x6f6fb1deUL, 0x6464acc8UL,
+0xd9d99e47UL, 0xf3f3e013UL, 0x3e3e427cUL, 0xb4b4299dUL,
+0xaaaa0ba1UL, 0xdcdc914dUL, 0xd5d58a5fUL, 0x06060a0cUL,
+0xc0c0b575UL, 0x7e7e82fcUL, 0xf6f6ef19UL, 0x6666aaccUL,
+0x6c6cb4d8UL, 0x848479fdUL, 0x717193e2UL, 0x38384870UL,
+0xb9b93e87UL, 0x1d1d273aUL, 0x7f7f81feUL, 0x9d9d52cfUL,
+0x4848d890UL, 0x8b8b68e3UL, 0x2a2a7e54UL, 0xdada9b41UL,
+0xa5a51abfUL, 0x33335566UL, 0x828273f1UL, 0x39394b72UL,
+0xd6d68f59UL, 0x787888f0UL, 0x86867ff9UL, 0xfafafb01UL,
+0xe4e4d93dUL, 0x2b2b7d56UL, 0xa9a90ea7UL, 0x1e1e223cUL,
+0x89896ee7UL, 0x6060a0c0UL, 0x6b6bbdd6UL, 0xeaeacb21UL,
+0x5555ffaaUL, 0x4c4cd498UL, 0xf7f7ec1bUL, 0xe2e2d331UL,
+}};
+
+const word32 Square::Dec::Td[4][256] = {
+{
+0xe368bc02UL, 0x5585620cUL, 0x2a3f2331UL, 0x61ab13f7UL,
+0x98d46d72UL, 0x21cb9a19UL, 0x3c22a461UL, 0x459d3dcdUL,
+0x05fdb423UL, 0x2bc4075fUL, 0x9b2c01c0UL, 0x3dd9800fUL,
+0x486c5c74UL, 0xf97f7e85UL, 0xf173ab1fUL, 0xb6edde0eUL,
+0x283c6bedUL, 0x4997781aUL, 0x9f2a918dUL, 0xc9579f33UL,
+0xa907a8aaUL, 0xa50ded7dUL, 0x7c422d8fUL, 0x764db0c9UL,
+0x4d91e857UL, 0xcea963ccUL, 0xb4ee96d2UL, 0x3028e1b6UL,
+0x0df161b9UL, 0xbd196726UL, 0x419bad80UL, 0xc0a06ec7UL,
+0x5183f241UL, 0x92dbf034UL, 0x6fa21efcUL, 0x8f32ce4cUL,
+0x13e03373UL, 0x69a7c66dUL, 0xe56d6493UL, 0xbf1a2ffaUL,
+0xbb1cbfb7UL, 0x587403b5UL, 0xe76e2c4fUL, 0x5d89b796UL,
+0xe89c052aUL, 0x446619a3UL, 0x342e71fbUL, 0x0ff22965UL,
+0xfe81827aUL, 0xb11322f1UL, 0xa30835ecUL, 0xcd510f7eUL,
+0xff7aa614UL, 0x5c7293f8UL, 0x2fc29712UL, 0xf370e3c3UL,
+0x992f491cUL, 0xd1431568UL, 0xc2a3261bUL, 0x88cc32b3UL,
+0x8acf7a6fUL, 0xb0e8069fUL, 0x7a47f51eUL, 0xd2bb79daUL,
+0xe6950821UL, 0x4398e55cUL, 0xd0b83106UL, 0x11e37bafUL,
+0x7e416553UL, 0xccaa2b10UL, 0xd8b4e49cUL, 0x6456a7d4UL,
+0xfb7c3659UL, 0x724b2084UL, 0xea9f4df6UL, 0x6a5faadfUL,
+0x2dc1dfceUL, 0x70486858UL, 0xcaaff381UL, 0x0605d891UL,
+0x5a774b69UL, 0x94de28a5UL, 0x39df1042UL, 0x813bc347UL,
+0xfc82caa6UL, 0x23c8d2c5UL, 0x03f86cb2UL, 0x080cd59aUL,
+0xdab7ac40UL, 0x7db909e1UL, 0x3824342cUL, 0xcf5247a2UL,
+0xdcb274d1UL, 0x63a85b2bUL, 0x35d55595UL, 0x479e7511UL,
+0x15e5ebe2UL, 0x4b9430c6UL, 0x4a6f14a8UL, 0x91239c86UL,
+0x4c6acc39UL, 0x5f8aff4aUL, 0x0406904dUL, 0xee99ddbbUL,
+0x1e1152caUL, 0xaaffc418UL, 0xeb646998UL, 0x07fefcffUL,
+0x8b345e01UL, 0x567d0ebeUL, 0xbae79bd9UL, 0x4263c132UL,
+0x75b5dc7bUL, 0x97264417UL, 0x67aecb66UL, 0x95250ccbUL,
+0xec9a9567UL, 0x57862ad0UL, 0x60503799UL, 0xb8e4d305UL,
+0x65ad83baUL, 0x19efae35UL, 0xa4f6c913UL, 0xc15b4aa9UL,
+0x873e1bd6UL, 0xa0f0595eUL, 0x18148a5bUL, 0xaf02703bUL,
+0xab04e076UL, 0xdd4950bfUL, 0xdf4a1863UL, 0xc6a5b656UL,
+0x853d530aUL, 0xfa871237UL, 0x77b694a7UL, 0x4665517fUL,
+0xed61b109UL, 0x1bece6e9UL, 0xd5458525UL, 0xf5753b52UL,
+0x7fba413dUL, 0x27ce4288UL, 0xb2eb4e43UL, 0xd6bde997UL,
+0x527b9ef3UL, 0x62537f45UL, 0x2c3afba0UL, 0x7bbcd170UL,
+0xb91ff76bUL, 0x121b171dUL, 0xfd79eec8UL, 0x3a277cf0UL,
+0x0c0a45d7UL, 0x96dd6079UL, 0x2233f6abUL, 0xacfa1c89UL,
+0xc8acbb5dUL, 0xa10b7d30UL, 0xd4bea14bUL, 0xbee10b94UL,
+0x25cd0a54UL, 0x547e4662UL, 0xa2f31182UL, 0x17e6a33eUL,
+0x263566e6UL, 0xc3580275UL, 0x83388b9bUL, 0x7844bdc2UL,
+0x020348dcUL, 0x4f92a08bUL, 0x2e39b37cUL, 0x4e6984e5UL,
+0xf0888f71UL, 0x362d3927UL, 0x9cd2fd3fUL, 0x01fb246eUL,
+0x893716ddUL, 0x00000000UL, 0xf68d57e0UL, 0xe293986cUL,
+0x744ef815UL, 0x9320d45aUL, 0xad0138e7UL, 0xd3405db4UL,
+0x1a17c287UL, 0xb3106a2dUL, 0x5078d62fUL, 0xf48e1f3cUL,
+0xa70ea5a1UL, 0x71b34c36UL, 0x9ad725aeUL, 0x5e71db24UL,
+0x161d8750UL, 0xef62f9d5UL, 0x8d318690UL, 0x1c121a16UL,
+0xa6f581cfUL, 0x5b8c6f07UL, 0x37d61d49UL, 0x6e593a92UL,
+0x84c67764UL, 0x86c53fb8UL, 0xd746cdf9UL, 0xe090d0b0UL,
+0x29c74f83UL, 0xe49640fdUL, 0x0e090d0bUL, 0x6da15620UL,
+0x8ec9ea22UL, 0xdb4c882eUL, 0xf776738eUL, 0xb515b2bcUL,
+0x10185fc1UL, 0x322ba96aUL, 0x6ba48eb1UL, 0xaef95455UL,
+0x406089eeUL, 0x6655ef08UL, 0xe9672144UL, 0x3e21ecbdUL,
+0x2030be77UL, 0xf28bc7adUL, 0x80c0e729UL, 0x141ecf8cUL,
+0xbce24348UL, 0xc4a6fe8aUL, 0x31d3c5d8UL, 0xb716fa60UL,
+0x5380ba9dUL, 0xd94fc0f2UL, 0x1de93e78UL, 0x24362e3aUL,
+0xe16bf4deUL, 0xcb54d7efUL, 0x09f7f1f4UL, 0x82c3aff5UL,
+0x0bf4b928UL, 0x9d29d951UL, 0xc75e9238UL, 0xf8845aebUL,
+0x90d8b8e8UL, 0xdeb13c0dUL, 0x33d08d04UL, 0x685ce203UL,
+0xc55ddae4UL, 0x3bdc589eUL, 0x0a0f9d46UL, 0x3fdac8d3UL,
+0x598f27dbUL, 0xa8fc8cc4UL, 0x79bf99acUL, 0x6c5a724eUL,
+0x8ccaa2feUL, 0x9ed1b5e3UL, 0x1fea76a4UL, 0x73b004eaUL,
+},
+
+{
+0x02e368bcUL, 0x0c558562UL, 0x312a3f23UL, 0xf761ab13UL,
+0x7298d46dUL, 0x1921cb9aUL, 0x613c22a4UL, 0xcd459d3dUL,
+0x2305fdb4UL, 0x5f2bc407UL, 0xc09b2c01UL, 0x0f3dd980UL,
+0x74486c5cUL, 0x85f97f7eUL, 0x1ff173abUL, 0x0eb6eddeUL,
+0xed283c6bUL, 0x1a499778UL, 0x8d9f2a91UL, 0x33c9579fUL,
+0xaaa907a8UL, 0x7da50dedUL, 0x8f7c422dUL, 0xc9764db0UL,
+0x574d91e8UL, 0xcccea963UL, 0xd2b4ee96UL, 0xb63028e1UL,
+0xb90df161UL, 0x26bd1967UL, 0x80419badUL, 0xc7c0a06eUL,
+0x415183f2UL, 0x3492dbf0UL, 0xfc6fa21eUL, 0x4c8f32ceUL,
+0x7313e033UL, 0x6d69a7c6UL, 0x93e56d64UL, 0xfabf1a2fUL,
+0xb7bb1cbfUL, 0xb5587403UL, 0x4fe76e2cUL, 0x965d89b7UL,
+0x2ae89c05UL, 0xa3446619UL, 0xfb342e71UL, 0x650ff229UL,
+0x7afe8182UL, 0xf1b11322UL, 0xeca30835UL, 0x7ecd510fUL,
+0x14ff7aa6UL, 0xf85c7293UL, 0x122fc297UL, 0xc3f370e3UL,
+0x1c992f49UL, 0x68d14315UL, 0x1bc2a326UL, 0xb388cc32UL,
+0x6f8acf7aUL, 0x9fb0e806UL, 0x1e7a47f5UL, 0xdad2bb79UL,
+0x21e69508UL, 0x5c4398e5UL, 0x06d0b831UL, 0xaf11e37bUL,
+0x537e4165UL, 0x10ccaa2bUL, 0x9cd8b4e4UL, 0xd46456a7UL,
+0x59fb7c36UL, 0x84724b20UL, 0xf6ea9f4dUL, 0xdf6a5faaUL,
+0xce2dc1dfUL, 0x58704868UL, 0x81caaff3UL, 0x910605d8UL,
+0x695a774bUL, 0xa594de28UL, 0x4239df10UL, 0x47813bc3UL,
+0xa6fc82caUL, 0xc523c8d2UL, 0xb203f86cUL, 0x9a080cd5UL,
+0x40dab7acUL, 0xe17db909UL, 0x2c382434UL, 0xa2cf5247UL,
+0xd1dcb274UL, 0x2b63a85bUL, 0x9535d555UL, 0x11479e75UL,
+0xe215e5ebUL, 0xc64b9430UL, 0xa84a6f14UL, 0x8691239cUL,
+0x394c6accUL, 0x4a5f8affUL, 0x4d040690UL, 0xbbee99ddUL,
+0xca1e1152UL, 0x18aaffc4UL, 0x98eb6469UL, 0xff07fefcUL,
+0x018b345eUL, 0xbe567d0eUL, 0xd9bae79bUL, 0x324263c1UL,
+0x7b75b5dcUL, 0x17972644UL, 0x6667aecbUL, 0xcb95250cUL,
+0x67ec9a95UL, 0xd057862aUL, 0x99605037UL, 0x05b8e4d3UL,
+0xba65ad83UL, 0x3519efaeUL, 0x13a4f6c9UL, 0xa9c15b4aUL,
+0xd6873e1bUL, 0x5ea0f059UL, 0x5b18148aUL, 0x3baf0270UL,
+0x76ab04e0UL, 0xbfdd4950UL, 0x63df4a18UL, 0x56c6a5b6UL,
+0x0a853d53UL, 0x37fa8712UL, 0xa777b694UL, 0x7f466551UL,
+0x09ed61b1UL, 0xe91bece6UL, 0x25d54585UL, 0x52f5753bUL,
+0x3d7fba41UL, 0x8827ce42UL, 0x43b2eb4eUL, 0x97d6bde9UL,
+0xf3527b9eUL, 0x4562537fUL, 0xa02c3afbUL, 0x707bbcd1UL,
+0x6bb91ff7UL, 0x1d121b17UL, 0xc8fd79eeUL, 0xf03a277cUL,
+0xd70c0a45UL, 0x7996dd60UL, 0xab2233f6UL, 0x89acfa1cUL,
+0x5dc8acbbUL, 0x30a10b7dUL, 0x4bd4bea1UL, 0x94bee10bUL,
+0x5425cd0aUL, 0x62547e46UL, 0x82a2f311UL, 0x3e17e6a3UL,
+0xe6263566UL, 0x75c35802UL, 0x9b83388bUL, 0xc27844bdUL,
+0xdc020348UL, 0x8b4f92a0UL, 0x7c2e39b3UL, 0xe54e6984UL,
+0x71f0888fUL, 0x27362d39UL, 0x3f9cd2fdUL, 0x6e01fb24UL,
+0xdd893716UL, 0x00000000UL, 0xe0f68d57UL, 0x6ce29398UL,
+0x15744ef8UL, 0x5a9320d4UL, 0xe7ad0138UL, 0xb4d3405dUL,
+0x871a17c2UL, 0x2db3106aUL, 0x2f5078d6UL, 0x3cf48e1fUL,
+0xa1a70ea5UL, 0x3671b34cUL, 0xae9ad725UL, 0x245e71dbUL,
+0x50161d87UL, 0xd5ef62f9UL, 0x908d3186UL, 0x161c121aUL,
+0xcfa6f581UL, 0x075b8c6fUL, 0x4937d61dUL, 0x926e593aUL,
+0x6484c677UL, 0xb886c53fUL, 0xf9d746cdUL, 0xb0e090d0UL,
+0x8329c74fUL, 0xfde49640UL, 0x0b0e090dUL, 0x206da156UL,
+0x228ec9eaUL, 0x2edb4c88UL, 0x8ef77673UL, 0xbcb515b2UL,
+0xc110185fUL, 0x6a322ba9UL, 0xb16ba48eUL, 0x55aef954UL,
+0xee406089UL, 0x086655efUL, 0x44e96721UL, 0xbd3e21ecUL,
+0x772030beUL, 0xadf28bc7UL, 0x2980c0e7UL, 0x8c141ecfUL,
+0x48bce243UL, 0x8ac4a6feUL, 0xd831d3c5UL, 0x60b716faUL,
+0x9d5380baUL, 0xf2d94fc0UL, 0x781de93eUL, 0x3a24362eUL,
+0xdee16bf4UL, 0xefcb54d7UL, 0xf409f7f1UL, 0xf582c3afUL,
+0x280bf4b9UL, 0x519d29d9UL, 0x38c75e92UL, 0xebf8845aUL,
+0xe890d8b8UL, 0x0ddeb13cUL, 0x0433d08dUL, 0x03685ce2UL,
+0xe4c55ddaUL, 0x9e3bdc58UL, 0x460a0f9dUL, 0xd33fdac8UL,
+0xdb598f27UL, 0xc4a8fc8cUL, 0xac79bf99UL, 0x4e6c5a72UL,
+0xfe8ccaa2UL, 0xe39ed1b5UL, 0xa41fea76UL, 0xea73b004UL,
+},
+
+{
+0xbc02e368UL, 0x620c5585UL, 0x23312a3fUL, 0x13f761abUL,
+0x6d7298d4UL, 0x9a1921cbUL, 0xa4613c22UL, 0x3dcd459dUL,
+0xb42305fdUL, 0x075f2bc4UL, 0x01c09b2cUL, 0x800f3dd9UL,
+0x5c74486cUL, 0x7e85f97fUL, 0xab1ff173UL, 0xde0eb6edUL,
+0x6bed283cUL, 0x781a4997UL, 0x918d9f2aUL, 0x9f33c957UL,
+0xa8aaa907UL, 0xed7da50dUL, 0x2d8f7c42UL, 0xb0c9764dUL,
+0xe8574d91UL, 0x63cccea9UL, 0x96d2b4eeUL, 0xe1b63028UL,
+0x61b90df1UL, 0x6726bd19UL, 0xad80419bUL, 0x6ec7c0a0UL,
+0xf2415183UL, 0xf03492dbUL, 0x1efc6fa2UL, 0xce4c8f32UL,
+0x337313e0UL, 0xc66d69a7UL, 0x6493e56dUL, 0x2ffabf1aUL,
+0xbfb7bb1cUL, 0x03b55874UL, 0x2c4fe76eUL, 0xb7965d89UL,
+0x052ae89cUL, 0x19a34466UL, 0x71fb342eUL, 0x29650ff2UL,
+0x827afe81UL, 0x22f1b113UL, 0x35eca308UL, 0x0f7ecd51UL,
+0xa614ff7aUL, 0x93f85c72UL, 0x97122fc2UL, 0xe3c3f370UL,
+0x491c992fUL, 0x1568d143UL, 0x261bc2a3UL, 0x32b388ccUL,
+0x7a6f8acfUL, 0x069fb0e8UL, 0xf51e7a47UL, 0x79dad2bbUL,
+0x0821e695UL, 0xe55c4398UL, 0x3106d0b8UL, 0x7baf11e3UL,
+0x65537e41UL, 0x2b10ccaaUL, 0xe49cd8b4UL, 0xa7d46456UL,
+0x3659fb7cUL, 0x2084724bUL, 0x4df6ea9fUL, 0xaadf6a5fUL,
+0xdfce2dc1UL, 0x68587048UL, 0xf381caafUL, 0xd8910605UL,
+0x4b695a77UL, 0x28a594deUL, 0x104239dfUL, 0xc347813bUL,
+0xcaa6fc82UL, 0xd2c523c8UL, 0x6cb203f8UL, 0xd59a080cUL,
+0xac40dab7UL, 0x09e17db9UL, 0x342c3824UL, 0x47a2cf52UL,
+0x74d1dcb2UL, 0x5b2b63a8UL, 0x559535d5UL, 0x7511479eUL,
+0xebe215e5UL, 0x30c64b94UL, 0x14a84a6fUL, 0x9c869123UL,
+0xcc394c6aUL, 0xff4a5f8aUL, 0x904d0406UL, 0xddbbee99UL,
+0x52ca1e11UL, 0xc418aaffUL, 0x6998eb64UL, 0xfcff07feUL,
+0x5e018b34UL, 0x0ebe567dUL, 0x9bd9bae7UL, 0xc1324263UL,
+0xdc7b75b5UL, 0x44179726UL, 0xcb6667aeUL, 0x0ccb9525UL,
+0x9567ec9aUL, 0x2ad05786UL, 0x37996050UL, 0xd305b8e4UL,
+0x83ba65adUL, 0xae3519efUL, 0xc913a4f6UL, 0x4aa9c15bUL,
+0x1bd6873eUL, 0x595ea0f0UL, 0x8a5b1814UL, 0x703baf02UL,
+0xe076ab04UL, 0x50bfdd49UL, 0x1863df4aUL, 0xb656c6a5UL,
+0x530a853dUL, 0x1237fa87UL, 0x94a777b6UL, 0x517f4665UL,
+0xb109ed61UL, 0xe6e91becUL, 0x8525d545UL, 0x3b52f575UL,
+0x413d7fbaUL, 0x428827ceUL, 0x4e43b2ebUL, 0xe997d6bdUL,
+0x9ef3527bUL, 0x7f456253UL, 0xfba02c3aUL, 0xd1707bbcUL,
+0xf76bb91fUL, 0x171d121bUL, 0xeec8fd79UL, 0x7cf03a27UL,
+0x45d70c0aUL, 0x607996ddUL, 0xf6ab2233UL, 0x1c89acfaUL,
+0xbb5dc8acUL, 0x7d30a10bUL, 0xa14bd4beUL, 0x0b94bee1UL,
+0x0a5425cdUL, 0x4662547eUL, 0x1182a2f3UL, 0xa33e17e6UL,
+0x66e62635UL, 0x0275c358UL, 0x8b9b8338UL, 0xbdc27844UL,
+0x48dc0203UL, 0xa08b4f92UL, 0xb37c2e39UL, 0x84e54e69UL,
+0x8f71f088UL, 0x3927362dUL, 0xfd3f9cd2UL, 0x246e01fbUL,
+0x16dd8937UL, 0x00000000UL, 0x57e0f68dUL, 0x986ce293UL,
+0xf815744eUL, 0xd45a9320UL, 0x38e7ad01UL, 0x5db4d340UL,
+0xc2871a17UL, 0x6a2db310UL, 0xd62f5078UL, 0x1f3cf48eUL,
+0xa5a1a70eUL, 0x4c3671b3UL, 0x25ae9ad7UL, 0xdb245e71UL,
+0x8750161dUL, 0xf9d5ef62UL, 0x86908d31UL, 0x1a161c12UL,
+0x81cfa6f5UL, 0x6f075b8cUL, 0x1d4937d6UL, 0x3a926e59UL,
+0x776484c6UL, 0x3fb886c5UL, 0xcdf9d746UL, 0xd0b0e090UL,
+0x4f8329c7UL, 0x40fde496UL, 0x0d0b0e09UL, 0x56206da1UL,
+0xea228ec9UL, 0x882edb4cUL, 0x738ef776UL, 0xb2bcb515UL,
+0x5fc11018UL, 0xa96a322bUL, 0x8eb16ba4UL, 0x5455aef9UL,
+0x89ee4060UL, 0xef086655UL, 0x2144e967UL, 0xecbd3e21UL,
+0xbe772030UL, 0xc7adf28bUL, 0xe72980c0UL, 0xcf8c141eUL,
+0x4348bce2UL, 0xfe8ac4a6UL, 0xc5d831d3UL, 0xfa60b716UL,
+0xba9d5380UL, 0xc0f2d94fUL, 0x3e781de9UL, 0x2e3a2436UL,
+0xf4dee16bUL, 0xd7efcb54UL, 0xf1f409f7UL, 0xaff582c3UL,
+0xb9280bf4UL, 0xd9519d29UL, 0x9238c75eUL, 0x5aebf884UL,
+0xb8e890d8UL, 0x3c0ddeb1UL, 0x8d0433d0UL, 0xe203685cUL,
+0xdae4c55dUL, 0x589e3bdcUL, 0x9d460a0fUL, 0xc8d33fdaUL,
+0x27db598fUL, 0x8cc4a8fcUL, 0x99ac79bfUL, 0x724e6c5aUL,
+0xa2fe8ccaUL, 0xb5e39ed1UL, 0x76a41feaUL, 0x04ea73b0UL,
+},
+
+{
+0x68bc02e3UL, 0x85620c55UL, 0x3f23312aUL, 0xab13f761UL,
+0xd46d7298UL, 0xcb9a1921UL, 0x22a4613cUL, 0x9d3dcd45UL,
+0xfdb42305UL, 0xc4075f2bUL, 0x2c01c09bUL, 0xd9800f3dUL,
+0x6c5c7448UL, 0x7f7e85f9UL, 0x73ab1ff1UL, 0xedde0eb6UL,
+0x3c6bed28UL, 0x97781a49UL, 0x2a918d9fUL, 0x579f33c9UL,
+0x07a8aaa9UL, 0x0ded7da5UL, 0x422d8f7cUL, 0x4db0c976UL,
+0x91e8574dUL, 0xa963ccceUL, 0xee96d2b4UL, 0x28e1b630UL,
+0xf161b90dUL, 0x196726bdUL, 0x9bad8041UL, 0xa06ec7c0UL,
+0x83f24151UL, 0xdbf03492UL, 0xa21efc6fUL, 0x32ce4c8fUL,
+0xe0337313UL, 0xa7c66d69UL, 0x6d6493e5UL, 0x1a2ffabfUL,
+0x1cbfb7bbUL, 0x7403b558UL, 0x6e2c4fe7UL, 0x89b7965dUL,
+0x9c052ae8UL, 0x6619a344UL, 0x2e71fb34UL, 0xf229650fUL,
+0x81827afeUL, 0x1322f1b1UL, 0x0835eca3UL, 0x510f7ecdUL,
+0x7aa614ffUL, 0x7293f85cUL, 0xc297122fUL, 0x70e3c3f3UL,
+0x2f491c99UL, 0x431568d1UL, 0xa3261bc2UL, 0xcc32b388UL,
+0xcf7a6f8aUL, 0xe8069fb0UL, 0x47f51e7aUL, 0xbb79dad2UL,
+0x950821e6UL, 0x98e55c43UL, 0xb83106d0UL, 0xe37baf11UL,
+0x4165537eUL, 0xaa2b10ccUL, 0xb4e49cd8UL, 0x56a7d464UL,
+0x7c3659fbUL, 0x4b208472UL, 0x9f4df6eaUL, 0x5faadf6aUL,
+0xc1dfce2dUL, 0x48685870UL, 0xaff381caUL, 0x05d89106UL,
+0x774b695aUL, 0xde28a594UL, 0xdf104239UL, 0x3bc34781UL,
+0x82caa6fcUL, 0xc8d2c523UL, 0xf86cb203UL, 0x0cd59a08UL,
+0xb7ac40daUL, 0xb909e17dUL, 0x24342c38UL, 0x5247a2cfUL,
+0xb274d1dcUL, 0xa85b2b63UL, 0xd5559535UL, 0x9e751147UL,
+0xe5ebe215UL, 0x9430c64bUL, 0x6f14a84aUL, 0x239c8691UL,
+0x6acc394cUL, 0x8aff4a5fUL, 0x06904d04UL, 0x99ddbbeeUL,
+0x1152ca1eUL, 0xffc418aaUL, 0x646998ebUL, 0xfefcff07UL,
+0x345e018bUL, 0x7d0ebe56UL, 0xe79bd9baUL, 0x63c13242UL,
+0xb5dc7b75UL, 0x26441797UL, 0xaecb6667UL, 0x250ccb95UL,
+0x9a9567ecUL, 0x862ad057UL, 0x50379960UL, 0xe4d305b8UL,
+0xad83ba65UL, 0xefae3519UL, 0xf6c913a4UL, 0x5b4aa9c1UL,
+0x3e1bd687UL, 0xf0595ea0UL, 0x148a5b18UL, 0x02703bafUL,
+0x04e076abUL, 0x4950bfddUL, 0x4a1863dfUL, 0xa5b656c6UL,
+0x3d530a85UL, 0x871237faUL, 0xb694a777UL, 0x65517f46UL,
+0x61b109edUL, 0xece6e91bUL, 0x458525d5UL, 0x753b52f5UL,
+0xba413d7fUL, 0xce428827UL, 0xeb4e43b2UL, 0xbde997d6UL,
+0x7b9ef352UL, 0x537f4562UL, 0x3afba02cUL, 0xbcd1707bUL,
+0x1ff76bb9UL, 0x1b171d12UL, 0x79eec8fdUL, 0x277cf03aUL,
+0x0a45d70cUL, 0xdd607996UL, 0x33f6ab22UL, 0xfa1c89acUL,
+0xacbb5dc8UL, 0x0b7d30a1UL, 0xbea14bd4UL, 0xe10b94beUL,
+0xcd0a5425UL, 0x7e466254UL, 0xf31182a2UL, 0xe6a33e17UL,
+0x3566e626UL, 0x580275c3UL, 0x388b9b83UL, 0x44bdc278UL,
+0x0348dc02UL, 0x92a08b4fUL, 0x39b37c2eUL, 0x6984e54eUL,
+0x888f71f0UL, 0x2d392736UL, 0xd2fd3f9cUL, 0xfb246e01UL,
+0x3716dd89UL, 0x00000000UL, 0x8d57e0f6UL, 0x93986ce2UL,
+0x4ef81574UL, 0x20d45a93UL, 0x0138e7adUL, 0x405db4d3UL,
+0x17c2871aUL, 0x106a2db3UL, 0x78d62f50UL, 0x8e1f3cf4UL,
+0x0ea5a1a7UL, 0xb34c3671UL, 0xd725ae9aUL, 0x71db245eUL,
+0x1d875016UL, 0x62f9d5efUL, 0x3186908dUL, 0x121a161cUL,
+0xf581cfa6UL, 0x8c6f075bUL, 0xd61d4937UL, 0x593a926eUL,
+0xc6776484UL, 0xc53fb886UL, 0x46cdf9d7UL, 0x90d0b0e0UL,
+0xc74f8329UL, 0x9640fde4UL, 0x090d0b0eUL, 0xa156206dUL,
+0xc9ea228eUL, 0x4c882edbUL, 0x76738ef7UL, 0x15b2bcb5UL,
+0x185fc110UL, 0x2ba96a32UL, 0xa48eb16bUL, 0xf95455aeUL,
+0x6089ee40UL, 0x55ef0866UL, 0x672144e9UL, 0x21ecbd3eUL,
+0x30be7720UL, 0x8bc7adf2UL, 0xc0e72980UL, 0x1ecf8c14UL,
+0xe24348bcUL, 0xa6fe8ac4UL, 0xd3c5d831UL, 0x16fa60b7UL,
+0x80ba9d53UL, 0x4fc0f2d9UL, 0xe93e781dUL, 0x362e3a24UL,
+0x6bf4dee1UL, 0x54d7efcbUL, 0xf7f1f409UL, 0xc3aff582UL,
+0xf4b9280bUL, 0x29d9519dUL, 0x5e9238c7UL, 0x845aebf8UL,
+0xd8b8e890UL, 0xb13c0ddeUL, 0xd08d0433UL, 0x5ce20368UL,
+0x5ddae4c5UL, 0xdc589e3bUL, 0x0f9d460aUL, 0xdac8d33fUL,
+0x8f27db59UL, 0xfc8cc4a8UL, 0xbf99ac79UL, 0x5a724e6cUL,
+0xcaa2fe8cUL, 0xd1b5e39eUL, 0xea76a41fUL, 0xb004ea73UL,
+}};
+
+NAMESPACE_END
diff --git a/lib/cryptopp/stdcpp.h b/lib/cryptopp/stdcpp.h
new file mode 100644
index 000000000..6511c4fa2
--- /dev/null
+++ b/lib/cryptopp/stdcpp.h
@@ -0,0 +1,41 @@
+#ifndef CRYPTOPP_STDCPP_H
+#define CRYPTOPP_STDCPP_H
+
+#if _MSC_VER >= 1500
+#define _DO_NOT_DECLARE_INTERLOCKED_INTRINSICS_IN_MEMORY
+#include <intrin.h>
+#endif
+
+#include <stddef.h>
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory>
+#include <string>
+#include <exception>
+#include <typeinfo>
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#ifdef CRYPTOPP_INCLUDE_VECTOR_CC
+// workaround needed on Sun Studio 12u1 Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21
+#include <vector.cc>
+#endif
+
+// for alloca
+#ifdef __sun
+#include <alloca.h>
+#elif defined(__MINGW32__) || defined(__BORLANDC__)
+#include <malloc.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4231) // re-disable this
+#ifdef _CRTAPI1
+#define CRYPTOPP_MSVCRT6
+#endif
+#endif
+
+#endif
diff --git a/lib/cryptopp/strciphr.cpp b/lib/cryptopp/strciphr.cpp
new file mode 100644
index 000000000..53e007376
--- /dev/null
+++ b/lib/cryptopp/strciphr.cpp
@@ -0,0 +1,252 @@
+// strciphr.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "strciphr.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class S>
+void AdditiveCipherTemplate<S>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+{
+ PolicyInterface &policy = this->AccessPolicy();
+ policy.CipherSetKey(params, key, length);
+ m_leftOver = 0;
+ unsigned int bufferByteSize = policy.CanOperateKeystream() ? GetBufferByteSize(policy) : RoundUpToMultipleOf(1024U, GetBufferByteSize(policy));
+ m_buffer.New(bufferByteSize);
+
+ if (this->IsResynchronizable())
+ {
+ size_t ivLength;
+ const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength);
+ policy.CipherResynchronize(m_buffer, iv, ivLength);
+ }
+}
+
+template <class S>
+void AdditiveCipherTemplate<S>::GenerateBlock(byte *outString, size_t length)
+{
+ if (m_leftOver > 0)
+ {
+ size_t len = STDMIN(m_leftOver, length);
+ memcpy(outString, KeystreamBufferEnd()-m_leftOver, len);
+ length -= len;
+ m_leftOver -= len;
+ outString += len;
+
+ if (!length)
+ return;
+ }
+ assert(m_leftOver == 0);
+
+ PolicyInterface &policy = this->AccessPolicy();
+ unsigned int bytesPerIteration = policy.GetBytesPerIteration();
+
+ if (length >= bytesPerIteration)
+ {
+ size_t iterations = length / bytesPerIteration;
+ policy.WriteKeystream(outString, iterations);
+ outString += iterations * bytesPerIteration;
+ length -= iterations * bytesPerIteration;
+ }
+
+ if (length > 0)
+ {
+ size_t bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration);
+ size_t bufferIterations = bufferByteSize / bytesPerIteration;
+
+ policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations);
+ memcpy(outString, KeystreamBufferEnd()-bufferByteSize, length);
+ m_leftOver = bufferByteSize - length;
+ }
+}
+
+template <class S>
+void AdditiveCipherTemplate<S>::ProcessData(byte *outString, const byte *inString, size_t length)
+{
+ if (m_leftOver > 0)
+ {
+ size_t len = STDMIN(m_leftOver, length);
+ xorbuf(outString, inString, KeystreamBufferEnd()-m_leftOver, len);
+ length -= len;
+ m_leftOver -= len;
+ inString += len;
+ outString += len;
+
+ if (!length)
+ return;
+ }
+ assert(m_leftOver == 0);
+
+ PolicyInterface &policy = this->AccessPolicy();
+ unsigned int bytesPerIteration = policy.GetBytesPerIteration();
+
+ if (policy.CanOperateKeystream() && length >= bytesPerIteration)
+ {
+ size_t iterations = length / bytesPerIteration;
+ unsigned int alignment = policy.GetAlignment();
+ KeystreamOperation operation = KeystreamOperation((IsAlignedOn(inString, alignment) * 2) | (int)IsAlignedOn(outString, alignment));
+
+ policy.OperateKeystream(operation, outString, inString, iterations);
+
+ inString += iterations * bytesPerIteration;
+ outString += iterations * bytesPerIteration;
+ length -= iterations * bytesPerIteration;
+
+ if (!length)
+ return;
+ }
+
+ size_t bufferByteSize = m_buffer.size();
+ size_t bufferIterations = bufferByteSize / bytesPerIteration;
+
+ while (length >= bufferByteSize)
+ {
+ policy.WriteKeystream(m_buffer, bufferIterations);
+ xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize);
+ length -= bufferByteSize;
+ inString += bufferByteSize;
+ outString += bufferByteSize;
+ }
+
+ if (length > 0)
+ {
+ bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration);
+ bufferIterations = bufferByteSize / bytesPerIteration;
+
+ policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations);
+ xorbuf(outString, inString, KeystreamBufferEnd()-bufferByteSize, length);
+ m_leftOver = bufferByteSize - length;
+ }
+}
+
+template <class S>
+void AdditiveCipherTemplate<S>::Resynchronize(const byte *iv, int length)
+{
+ PolicyInterface &policy = this->AccessPolicy();
+ m_leftOver = 0;
+ m_buffer.New(GetBufferByteSize(policy));
+ policy.CipherResynchronize(m_buffer, iv, this->ThrowIfInvalidIVLength(length));
+}
+
+template <class BASE>
+void AdditiveCipherTemplate<BASE>::Seek(lword position)
+{
+ PolicyInterface &policy = this->AccessPolicy();
+ unsigned int bytesPerIteration = policy.GetBytesPerIteration();
+
+ policy.SeekToIteration(position / bytesPerIteration);
+ position %= bytesPerIteration;
+
+ if (position > 0)
+ {
+ policy.WriteKeystream(KeystreamBufferEnd()-bytesPerIteration, 1);
+ m_leftOver = bytesPerIteration - (unsigned int)position;
+ }
+ else
+ m_leftOver = 0;
+}
+
+template <class BASE>
+void CFB_CipherTemplate<BASE>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+{
+ PolicyInterface &policy = this->AccessPolicy();
+ policy.CipherSetKey(params, key, length);
+
+ if (this->IsResynchronizable())
+ {
+ size_t ivLength;
+ const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength);
+ policy.CipherResynchronize(iv, ivLength);
+ }
+
+ m_leftOver = policy.GetBytesPerIteration();
+}
+
+template <class BASE>
+void CFB_CipherTemplate<BASE>::Resynchronize(const byte *iv, int length)
+{
+ PolicyInterface &policy = this->AccessPolicy();
+ policy.CipherResynchronize(iv, this->ThrowIfInvalidIVLength(length));
+ m_leftOver = policy.GetBytesPerIteration();
+}
+
+template <class BASE>
+void CFB_CipherTemplate<BASE>::ProcessData(byte *outString, const byte *inString, size_t length)
+{
+ assert(length % this->MandatoryBlockSize() == 0);
+
+ PolicyInterface &policy = this->AccessPolicy();
+ unsigned int bytesPerIteration = policy.GetBytesPerIteration();
+ unsigned int alignment = policy.GetAlignment();
+ byte *reg = policy.GetRegisterBegin();
+
+ if (m_leftOver)
+ {
+ size_t len = STDMIN(m_leftOver, length);
+ CombineMessageAndShiftRegister(outString, reg + bytesPerIteration - m_leftOver, inString, len);
+ m_leftOver -= len;
+ length -= len;
+ inString += len;
+ outString += len;
+ }
+
+ if (!length)
+ return;
+
+ assert(m_leftOver == 0);
+
+ if (policy.CanIterate() && length >= bytesPerIteration && IsAlignedOn(outString, alignment))
+ {
+ if (IsAlignedOn(inString, alignment))
+ policy.Iterate(outString, inString, GetCipherDir(*this), length / bytesPerIteration);
+ else
+ {
+ memcpy(outString, inString, length);
+ policy.Iterate(outString, outString, GetCipherDir(*this), length / bytesPerIteration);
+ }
+ inString += length - length % bytesPerIteration;
+ outString += length - length % bytesPerIteration;
+ length %= bytesPerIteration;
+ }
+
+ while (length >= bytesPerIteration)
+ {
+ policy.TransformRegister();
+ CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration);
+ length -= bytesPerIteration;
+ inString += bytesPerIteration;
+ outString += bytesPerIteration;
+ }
+
+ if (length > 0)
+ {
+ policy.TransformRegister();
+ CombineMessageAndShiftRegister(outString, reg, inString, length);
+ m_leftOver = bytesPerIteration - length;
+ }
+}
+
+template <class BASE>
+void CFB_EncryptionTemplate<BASE>::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length)
+{
+ xorbuf(reg, message, length);
+ memcpy(output, reg, length);
+}
+
+template <class BASE>
+void CFB_DecryptionTemplate<BASE>::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length)
+{
+ for (unsigned int i=0; i<length; i++)
+ {
+ byte b = message[i];
+ output[i] = reg[i] ^ b;
+ reg[i] = b;
+ }
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/strciphr.h b/lib/cryptopp/strciphr.h
new file mode 100644
index 000000000..d1d11a17b
--- /dev/null
+++ b/lib/cryptopp/strciphr.h
@@ -0,0 +1,306 @@
+/*! \file
+ This file contains helper classes for implementing stream ciphers.
+
+ All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
+ but stream ciphers implementations now support a lot of new functionality,
+ including better performance (minimizing copying), resetting of keys and IVs, and methods to
+ query which features are supported by a cipher.
+
+ Here's an explanation of these classes. The word "policy" is used here to mean a class with a
+ set of methods that must be implemented by individual stream cipher implementations.
+ This is usually much simpler than the full stream cipher API, which is implemented by
+ either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an
+ implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface
+ (since it's an additive cipher, i.e., it xors a keystream into the plaintext).
+ See this line in seal.h:
+
+ typedef SymmetricCipherFinal\<ConcretePolicyHolder\<SEAL_Policy\<B\>, AdditiveCipherTemplate\<\> \> \> Encryption;
+
+ AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need
+ to take a policy class as a template parameter (although this is allowed), so that
+ their code is not duplicated for each new cipher. Instead they each
+ get a reference to an abstract policy interface by calling AccessPolicy() on itself, so
+ AccessPolicy() must be overriden to return the actual policy reference. This is done
+ by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and
+ other functions that must be implemented by the most derived class.
+*/
+
+#ifndef CRYPTOPP_STRCIPHR_H
+#define CRYPTOPP_STRCIPHR_H
+
+#include "seckey.h"
+#include "secblock.h"
+#include "argnames.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class POLICY_INTERFACE, class BASE = Empty>
+class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
+{
+public:
+ typedef POLICY_INTERFACE PolicyInterface;
+ virtual ~AbstractPolicyHolder() {}
+
+protected:
+ virtual const POLICY_INTERFACE & GetPolicy() const =0;
+ virtual POLICY_INTERFACE & AccessPolicy() =0;
+};
+
+template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
+class ConcretePolicyHolder : public BASE, protected POLICY
+{
+protected:
+ const POLICY_INTERFACE & GetPolicy() const {return *this;}
+ POLICY_INTERFACE & AccessPolicy() {return *this;}
+};
+
+enum KeystreamOperationFlags {OUTPUT_ALIGNED=1, INPUT_ALIGNED=2, INPUT_NULL = 4};
+enum KeystreamOperation {
+ WRITE_KEYSTREAM = INPUT_NULL,
+ WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED,
+ XOR_KEYSTREAM = 0,
+ XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED,
+ XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
+ XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED};
+
+struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
+{
+ virtual ~AdditiveCipherAbstractPolicy() {}
+ virtual unsigned int GetAlignment() const {return 1;}
+ virtual unsigned int GetBytesPerIteration() const =0;
+ virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();}
+ virtual unsigned int GetIterationsToBuffer() const =0;
+ virtual void WriteKeystream(byte *keystream, size_t iterationCount)
+ {OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);}
+ virtual bool CanOperateKeystream() const {return false;}
+ virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) {assert(false);}
+ virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
+ virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
+ virtual bool CipherIsRandomAccess() const =0;
+ virtual void SeekToIteration(lword iterationCount) {assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
+};
+
+template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
+struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
+{
+ typedef WT WordType;
+ CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W)
+
+#if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64)
+ unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();}
+#endif
+ unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;}
+ unsigned int GetIterationsToBuffer() const {return X;}
+ bool CanOperateKeystream() const {return true;}
+ virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
+};
+
+// use these to implement OperateKeystream
+#define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \
+ PutWord(bool(x & OUTPUT_ALIGNED), b, output+i*sizeof(WordType), (x & INPUT_NULL) ? a : a ^ GetWord<WordType>(bool(x & INPUT_ALIGNED), b, input+i*sizeof(WordType)));
+#define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\
+ __m128i t = (x & INPUT_NULL) ? a : _mm_xor_si128(a, (x & INPUT_ALIGNED) ? _mm_load_si128((__m128i *)input+i) : _mm_loadu_si128((__m128i *)input+i));\
+ if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\
+ else _mm_storeu_si128((__m128i *)output+i, t);}
+#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \
+ switch (operation) \
+ { \
+ case WRITE_KEYSTREAM: \
+ x(WRITE_KEYSTREAM) \
+ break; \
+ case XOR_KEYSTREAM: \
+ x(XOR_KEYSTREAM) \
+ input += y; \
+ break; \
+ case XOR_KEYSTREAM_INPUT_ALIGNED: \
+ x(XOR_KEYSTREAM_INPUT_ALIGNED) \
+ input += y; \
+ break; \
+ case XOR_KEYSTREAM_OUTPUT_ALIGNED: \
+ x(XOR_KEYSTREAM_OUTPUT_ALIGNED) \
+ input += y; \
+ break; \
+ case WRITE_KEYSTREAM_ALIGNED: \
+ x(WRITE_KEYSTREAM_ALIGNED) \
+ break; \
+ case XOR_KEYSTREAM_BOTH_ALIGNED: \
+ x(XOR_KEYSTREAM_BOTH_ALIGNED) \
+ input += y; \
+ break; \
+ } \
+ output += y;
+
+template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >
+class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator
+{
+public:
+ void GenerateBlock(byte *output, size_t size);
+ void ProcessData(byte *outString, const byte *inString, size_t length);
+ void Resynchronize(const byte *iv, int length=-1);
+ unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();}
+ unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
+ unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
+ bool IsSelfInverting() const {return true;}
+ bool IsForwardTransformation() const {return true;}
+ bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();}
+ void Seek(lword position);
+
+ typedef typename BASE::PolicyInterface PolicyInterface;
+
+protected:
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+
+ unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
+
+ inline byte * KeystreamBufferBegin() {return this->m_buffer.data();}
+ inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());}
+
+ SecByteBlock m_buffer;
+ size_t m_leftOver;
+};
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
+{
+public:
+ virtual ~CFB_CipherAbstractPolicy() {}
+ virtual unsigned int GetAlignment() const =0;
+ virtual unsigned int GetBytesPerIteration() const =0;
+ virtual byte * GetRegisterBegin() =0;
+ virtual void TransformRegister() =0;
+ virtual bool CanIterate() const {return false;}
+ virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false); throw 0;}
+ virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
+ virtual void CipherResynchronize(const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
+};
+
+template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
+struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
+{
+ typedef WT WordType;
+
+ unsigned int GetAlignment() const {return sizeof(WordType);}
+ unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
+ bool CanIterate() const {return true;}
+ void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);}
+
+ template <class B>
+ struct RegisterOutput
+ {
+ RegisterOutput(byte *output, const byte *input, CipherDir dir)
+ : m_output(output), m_input(input), m_dir(dir) {}
+
+ inline RegisterOutput& operator()(WordType &registerWord)
+ {
+ assert(IsAligned<WordType>(m_output));
+ assert(IsAligned<WordType>(m_input));
+
+ if (!NativeByteOrderIs(B::ToEnum()))
+ registerWord = ByteReverse(registerWord);
+
+ if (m_dir == ENCRYPTION)
+ {
+ if (m_input == NULL)
+ assert(m_output == NULL);
+ else
+ {
+ WordType ct = *(const WordType *)m_input ^ registerWord;
+ registerWord = ct;
+ *(WordType*)m_output = ct;
+ m_input += sizeof(WordType);
+ m_output += sizeof(WordType);
+ }
+ }
+ else
+ {
+ WordType ct = *(const WordType *)m_input;
+ *(WordType*)m_output = registerWord ^ ct;
+ registerWord = ct;
+ m_input += sizeof(WordType);
+ m_output += sizeof(WordType);
+ }
+
+ // registerWord is left unreversed so it can be xor-ed with further input
+
+ return *this;
+ }
+
+ byte *m_output;
+ const byte *m_input;
+ CipherDir m_dir;
+ };
+};
+
+template <class BASE>
+class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
+{
+public:
+ void ProcessData(byte *outString, const byte *inString, size_t length);
+ void Resynchronize(const byte *iv, int length=-1);
+ unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
+ unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
+ unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
+ bool IsRandomAccess() const {return false;}
+ bool IsSelfInverting() const {return false;}
+
+ typedef typename BASE::PolicyInterface PolicyInterface;
+
+protected:
+ virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0;
+
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+
+ size_t m_leftOver;
+};
+
+template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
+class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
+{
+ bool IsForwardTransformation() const {return true;}
+ void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
+};
+
+template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
+class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
+{
+ bool IsForwardTransformation() const {return false;}
+ void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
+};
+
+template <class BASE>
+class CFB_RequireFullDataBlocks : public BASE
+{
+public:
+ unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
+};
+
+//! _
+template <class BASE, class INFO = BASE>
+class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
+{
+public:
+ SymmetricCipherFinal() {}
+ SymmetricCipherFinal(const byte *key)
+ {this->SetKey(key, this->DEFAULT_KEYLENGTH);}
+ SymmetricCipherFinal(const byte *key, size_t length)
+ {this->SetKey(key, length);}
+ SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
+ {this->SetKeyWithIV(key, length, iv);}
+
+ Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
+};
+
+NAMESPACE_END
+
+#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
+#include "strciphr.cpp"
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
+CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/tea.cpp b/lib/cryptopp/tea.cpp
new file mode 100644
index 000000000..b1fb6f140
--- /dev/null
+++ b/lib/cryptopp/tea.cpp
@@ -0,0 +1,159 @@
+// tea.cpp - modified by Wei Dai from code in the original paper
+
+#include "pch.h"
+#include "tea.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const word32 DELTA = 0x9e3779b9;
+typedef BlockGetAndPut<word32, BigEndian> Block;
+
+void TEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
+{
+ AssertValidKeyLength(length);
+
+ GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH);
+ m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA;
+}
+
+void TEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 y, z;
+ Block::Get(inBlock)(y)(z);
+
+ word32 sum = 0;
+ while (sum != m_limit)
+ {
+ sum += DELTA;
+ y += (z << 4) + m_k[0] ^ z + sum ^ (z >> 5) + m_k[1];
+ z += (y << 4) + m_k[2] ^ y + sum ^ (y >> 5) + m_k[3];
+ }
+
+ Block::Put(xorBlock, outBlock)(y)(z);
+}
+
+void TEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 y, z;
+ Block::Get(inBlock)(y)(z);
+
+ word32 sum = m_limit;
+ while (sum != 0)
+ {
+ z -= (y << 4) + m_k[2] ^ y + sum ^ (y >> 5) + m_k[3];
+ y -= (z << 4) + m_k[0] ^ z + sum ^ (z >> 5) + m_k[1];
+ sum -= DELTA;
+ }
+
+ Block::Put(xorBlock, outBlock)(y)(z);
+}
+
+void XTEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
+{
+ AssertValidKeyLength(length);
+
+ GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, userKey, KEYLENGTH);
+ m_limit = GetRoundsAndThrowIfInvalid(params, this) * DELTA;
+}
+
+void XTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 y, z;
+ Block::Get(inBlock)(y)(z);
+
+#ifdef __SUNPRO_CC
+ // workaround needed on Sun Studio 12u1 Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21
+ size_t sum = 0;
+ while ((sum&0xffffffff) != m_limit)
+#else
+ word32 sum = 0;
+ while (sum != m_limit)
+#endif
+ {
+ y += (z<<4 ^ z>>5) + z ^ sum + m_k[sum&3];
+ sum += DELTA;
+ z += (y<<4 ^ y>>5) + y ^ sum + m_k[sum>>11 & 3];
+ }
+
+ Block::Put(xorBlock, outBlock)(y)(z);
+}
+
+void XTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ word32 y, z;
+ Block::Get(inBlock)(y)(z);
+
+#ifdef __SUNPRO_CC
+ // workaround needed on Sun Studio 12u1 Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21
+ size_t sum = m_limit;
+ while ((sum&0xffffffff) != 0)
+#else
+ word32 sum = m_limit;
+ while (sum != 0)
+#endif
+ {
+ z -= (y<<4 ^ y>>5) + y ^ sum + m_k[sum>>11 & 3];
+ sum -= DELTA;
+ y -= (z<<4 ^ z>>5) + z ^ sum + m_k[sum&3];
+ }
+
+ Block::Put(xorBlock, outBlock)(y)(z);
+}
+
+#define MX (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(m_k[p&3^e]^z)
+
+void BTEA::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ unsigned int n = m_blockSize / 4;
+ word32 *v = (word32*)outBlock;
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, v, (const word32*)inBlock, m_blockSize);
+
+ word32 y = v[0], z = v[n-1], e;
+ word32 p, q = 6+52/n;
+ word32 sum = 0;
+
+ while (q-- > 0)
+ {
+ sum += DELTA;
+ e = sum>>2 & 3;
+ for (p = 0; p < n-1; p++)
+ {
+ y = v[p+1];
+ z = v[p] += MX;
+ }
+ y = v[0];
+ z = v[n-1] += MX;
+ }
+
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize);
+}
+
+void BTEA::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ unsigned int n = m_blockSize / 4;
+ word32 *v = (word32*)outBlock;
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, v, (const word32*)inBlock, m_blockSize);
+
+ word32 y = v[0], z = v[n-1], e;
+ word32 p, q = 6+52/n;
+ word32 sum = q * DELTA;
+
+ while (sum != 0)
+ {
+ e = sum>>2 & 3;
+ for (p = n-1; p > 0; p--)
+ {
+ z = v[p-1];
+ y = v[p] -= MX;
+ }
+
+ z = v[n-1];
+ y = v[0] -= MX;
+ sum -= DELTA;
+ }
+
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, v, v, m_blockSize);
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/tea.h b/lib/cryptopp/tea.h
new file mode 100644
index 000000000..d8ddded86
--- /dev/null
+++ b/lib/cryptopp/tea.h
@@ -0,0 +1,132 @@
+#ifndef CRYPTOPP_TEA_H
+#define CRYPTOPP_TEA_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+struct TEA_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public VariableRounds<32>
+{
+ static const char *StaticAlgorithmName() {return "TEA";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#TEA">TEA</a>
+class TEA : public TEA_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<TEA_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+
+ protected:
+ FixedSizeSecBlock<word32, 4> m_k;
+ word32 m_limit;
+ };
+
+ class CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+ class CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+typedef TEA::Encryption TEAEncryption;
+typedef TEA::Decryption TEADecryption;
+
+//! _
+struct XTEA_Info : public FixedBlockSize<8>, public FixedKeyLength<16>, public VariableRounds<32>
+{
+ static const char *StaticAlgorithmName() {return "XTEA";}
+};
+
+/// <a href="http://www.weidai.com/scan-mirror/cs.html#TEA">XTEA</a>
+class XTEA : public XTEA_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<XTEA_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+
+ protected:
+ FixedSizeSecBlock<word32, 4> m_k;
+ word32 m_limit;
+ };
+
+ class CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+ class CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+//! _
+struct BTEA_Info : public FixedKeyLength<16>
+{
+ static const char *StaticAlgorithmName() {return "BTEA";}
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/cs.html#TEA">corrected Block TEA</a> (as described in "xxtea").
+/*! This class hasn't been tested yet. */
+class BTEA : public BTEA_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BlockCipher, BTEA_Info>, BTEA_Info>, public BTEA_Info
+ {
+ public:
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+ {
+ m_blockSize = params.GetIntValueWithDefault("BlockSize", 60*4);
+ GetUserKey(BIG_ENDIAN_ORDER, m_k.begin(), 4, key, KEYLENGTH);
+ }
+
+ unsigned int BlockSize() const {return m_blockSize;}
+
+ protected:
+ FixedSizeSecBlock<word32, 4> m_k;
+ unsigned int m_blockSize;
+ };
+
+ class CRYPTOPP_NO_VTABLE Enc : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+ class CRYPTOPP_NO_VTABLE Dec : public Base
+ {
+ public:
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/tiger.cpp b/lib/cryptopp/tiger.cpp
new file mode 100644
index 000000000..c6c05caed
--- /dev/null
+++ b/lib/cryptopp/tiger.cpp
@@ -0,0 +1,265 @@
+// tiger.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "tiger.h"
+#include "misc.h"
+#include "cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void Tiger::InitState(HashWordType *state)
+{
+ state[0] = W64LIT(0x0123456789ABCDEF);
+ state[1] = W64LIT(0xFEDCBA9876543210);
+ state[2] = W64LIT(0xF096A5B4C3B2E187);
+}
+
+void Tiger::TruncatedFinal(byte *hash, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ PadLastBlock(56, 0x01);
+ CorrectEndianess(m_data, m_data, 56);
+
+ m_data[7] = GetBitCountLo();
+
+ Transform(m_state, m_data);
+ CorrectEndianess(m_state, m_state, DigestSize());
+ memcpy(hash, m_state, size);
+
+ Restart(); // reinit for next use
+}
+
+void Tiger::Transform (word64 *digest, const word64 *X)
+{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+ if (HasSSE2())
+ {
+#ifdef __GNUC__
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ AS1( push ebx)
+#else
+ #if _MSC_VER < 1300
+ const word64 *t = table;
+ AS2( mov edx, t)
+ #else
+ AS2( lea edx, [table])
+ #endif
+ AS2( mov eax, digest)
+ AS2( mov esi, X)
+#endif
+ AS2( movq mm0, [eax])
+ AS2( movq mm1, [eax+1*8])
+ AS2( movq mm5, mm1)
+ AS2( movq mm2, [eax+2*8])
+ AS2( movq mm7, [edx+4*2048+0*8])
+ AS2( movq mm6, [edx+4*2048+1*8])
+ AS2( mov ecx, esp)
+ AS2( and esp, 0xfffffff0)
+ AS2( sub esp, 8*8)
+ AS1( push ecx)
+
+#define SSE2_round(a,b,c,x,mul) \
+ AS2( pxor c, [x])\
+ AS2( movd ecx, c)\
+ AS2( movzx edi, cl)\
+ AS2( movq mm3, [edx+0*2048+edi*8])\
+ AS2( movzx edi, ch)\
+ AS2( movq mm4, [edx+3*2048+edi*8])\
+ AS2( shr ecx, 16)\
+ AS2( movzx edi, cl)\
+ AS2( pxor mm3, [edx+1*2048+edi*8])\
+ AS2( movzx edi, ch)\
+ AS2( pxor mm4, [edx+2*2048+edi*8])\
+ AS3( pextrw ecx, c, 2)\
+ AS2( movzx edi, cl)\
+ AS2( pxor mm3, [edx+2*2048+edi*8])\
+ AS2( movzx edi, ch)\
+ AS2( pxor mm4, [edx+1*2048+edi*8])\
+ AS3( pextrw ecx, c, 3)\
+ AS2( movzx edi, cl)\
+ AS2( pxor mm3, [edx+3*2048+edi*8])\
+ AS2( psubq a, mm3)\
+ AS2( movzx edi, ch)\
+ AS2( pxor mm4, [edx+0*2048+edi*8])\
+ AS2( paddq b, mm4)\
+ SSE2_mul_##mul(b)
+
+#define SSE2_mul_5(b) \
+ AS2( movq mm3, b)\
+ AS2( psllq b, 2)\
+ AS2( paddq b, mm3)
+
+#define SSE2_mul_7(b) \
+ AS2( movq mm3, b)\
+ AS2( psllq b, 3)\
+ AS2( psubq b, mm3)
+
+#define SSE2_mul_9(b) \
+ AS2( movq mm3, b)\
+ AS2( psllq b, 3)\
+ AS2( paddq b, mm3)
+
+#define label2_5 1
+#define label2_7 2
+#define label2_9 3
+
+#define SSE2_pass(A,B,C,mul,X) \
+ AS2( xor ebx, ebx)\
+ ASL(mul)\
+ SSE2_round(A,B,C,X+0*8+ebx,mul)\
+ SSE2_round(B,C,A,X+1*8+ebx,mul)\
+ AS2( cmp ebx, 6*8)\
+ ASJ( je, label2_##mul, f)\
+ SSE2_round(C,A,B,X+2*8+ebx,mul)\
+ AS2( add ebx, 3*8)\
+ ASJ( jmp, mul, b)\
+ ASL(label2_##mul)
+
+#define SSE2_key_schedule(Y,X) \
+ AS2( movq mm3, [X+7*8])\
+ AS2( pxor mm3, mm6)\
+ AS2( movq mm4, [X+0*8])\
+ AS2( psubq mm4, mm3)\
+ AS2( movq [Y+0*8], mm4)\
+ AS2( pxor mm4, [X+1*8])\
+ AS2( movq mm3, mm4)\
+ AS2( movq [Y+1*8], mm4)\
+ AS2( paddq mm4, [X+2*8])\
+ AS2( pxor mm3, mm7)\
+ AS2( psllq mm3, 19)\
+ AS2( movq [Y+2*8], mm4)\
+ AS2( pxor mm3, mm4)\
+ AS2( movq mm4, [X+3*8])\
+ AS2( psubq mm4, mm3)\
+ AS2( movq [Y+3*8], mm4)\
+ AS2( pxor mm4, [X+4*8])\
+ AS2( movq mm3, mm4)\
+ AS2( movq [Y+4*8], mm4)\
+ AS2( paddq mm4, [X+5*8])\
+ AS2( pxor mm3, mm7)\
+ AS2( psrlq mm3, 23)\
+ AS2( movq [Y+5*8], mm4)\
+ AS2( pxor mm3, mm4)\
+ AS2( movq mm4, [X+6*8])\
+ AS2( psubq mm4, mm3)\
+ AS2( movq [Y+6*8], mm4)\
+ AS2( pxor mm4, [X+7*8])\
+ AS2( movq mm3, mm4)\
+ AS2( movq [Y+7*8], mm4)\
+ AS2( paddq mm4, [Y+0*8])\
+ AS2( pxor mm3, mm7)\
+ AS2( psllq mm3, 19)\
+ AS2( movq [Y+0*8], mm4)\
+ AS2( pxor mm3, mm4)\
+ AS2( movq mm4, [Y+1*8])\
+ AS2( psubq mm4, mm3)\
+ AS2( movq [Y+1*8], mm4)\
+ AS2( pxor mm4, [Y+2*8])\
+ AS2( movq mm3, mm4)\
+ AS2( movq [Y+2*8], mm4)\
+ AS2( paddq mm4, [Y+3*8])\
+ AS2( pxor mm3, mm7)\
+ AS2( psrlq mm3, 23)\
+ AS2( movq [Y+3*8], mm4)\
+ AS2( pxor mm3, mm4)\
+ AS2( movq mm4, [Y+4*8])\
+ AS2( psubq mm4, mm3)\
+ AS2( movq [Y+4*8], mm4)\
+ AS2( pxor mm4, [Y+5*8])\
+ AS2( movq [Y+5*8], mm4)\
+ AS2( paddq mm4, [Y+6*8])\
+ AS2( movq [Y+6*8], mm4)\
+ AS2( pxor mm4, [edx+4*2048+2*8])\
+ AS2( movq mm3, [Y+7*8])\
+ AS2( psubq mm3, mm4)\
+ AS2( movq [Y+7*8], mm3)
+
+ SSE2_pass(mm0, mm1, mm2, 5, esi)
+ SSE2_key_schedule(esp+4, esi)
+ SSE2_pass(mm2, mm0, mm1, 7, esp+4)
+ SSE2_key_schedule(esp+4, esp+4)
+ SSE2_pass(mm1, mm2, mm0, 9, esp+4)
+
+ AS2( pxor mm0, [eax+0*8])
+ AS2( movq [eax+0*8], mm0)
+ AS2( psubq mm1, mm5)
+ AS2( movq [eax+1*8], mm1)
+ AS2( paddq mm2, [eax+2*8])
+ AS2( movq [eax+2*8], mm2)
+
+ AS1( pop esp)
+ AS1( emms)
+#ifdef __GNUC__
+ AS1( pop ebx)
+ ".att_syntax prefix;"
+ :
+ : "a" (digest), "S" (X), "d" (table)
+ : "%ecx", "%edi", "memory", "cc"
+ );
+#endif
+ }
+ else
+#endif
+ {
+ word64 a = digest[0];
+ word64 b = digest[1];
+ word64 c = digest[2];
+ word64 Y[8];
+
+#define t1 (table)
+#define t2 (table+256)
+#define t3 (table+256*2)
+#define t4 (table+256*3)
+
+#define round(a,b,c,x,mul) \
+ c ^= x; \
+ a -= t1[GETBYTE(c,0)] ^ t2[GETBYTE(c,2)] ^ t3[GETBYTE(c,4)] ^ t4[GETBYTE(c,6)]; \
+ b += t4[GETBYTE(c,1)] ^ t3[GETBYTE(c,3)] ^ t2[GETBYTE(c,5)] ^ t1[GETBYTE(c,7)]; \
+ b *= mul
+
+#define pass(a,b,c,mul,X) {\
+ int i=0;\
+ while (true)\
+ {\
+ round(a,b,c,X[i+0],mul); \
+ round(b,c,a,X[i+1],mul); \
+ if (i==6)\
+ break;\
+ round(c,a,b,X[i+2],mul); \
+ i+=3;\
+ }}
+
+#define key_schedule(Y,X) \
+ Y[0] = X[0] - (X[7]^W64LIT(0xA5A5A5A5A5A5A5A5)); \
+ Y[1] = X[1] ^ Y[0]; \
+ Y[2] = X[2] + Y[1]; \
+ Y[3] = X[3] - (Y[2] ^ ((~Y[1])<<19)); \
+ Y[4] = X[4] ^ Y[3]; \
+ Y[5] = X[5] + Y[4]; \
+ Y[6] = X[6] - (Y[5] ^ ((~Y[4])>>23)); \
+ Y[7] = X[7] ^ Y[6]; \
+ Y[0] += Y[7]; \
+ Y[1] -= Y[0] ^ ((~Y[7])<<19); \
+ Y[2] ^= Y[1]; \
+ Y[3] += Y[2]; \
+ Y[4] -= Y[3] ^ ((~Y[2])>>23); \
+ Y[5] ^= Y[4]; \
+ Y[6] += Y[5]; \
+ Y[7] -= Y[6] ^ W64LIT(0x0123456789ABCDEF)
+
+ pass(a,b,c,5,X);
+ key_schedule(Y,X);
+ pass(c,a,b,7,Y);
+ key_schedule(Y,Y);
+ pass(b,c,a,9,Y);
+
+ digest[0] = a ^ digest[0];
+ digest[1] = b - digest[1];
+ digest[2] = c + digest[2];
+ }
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/tiger.h b/lib/cryptopp/tiger.h
new file mode 100644
index 000000000..5f6e941ac
--- /dev/null
+++ b/lib/cryptopp/tiger.h
@@ -0,0 +1,24 @@
+#ifndef CRYPTOPP_TIGER_H
+#define CRYPTOPP_TIGER_H
+
+#include "config.h"
+#include "iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// <a href="http://www.cryptolounge.org/wiki/Tiger">Tiger</a>
+class Tiger : public IteratedHashWithStaticTransform<word64, LittleEndian, 64, 24, Tiger>
+{
+public:
+ static void InitState(HashWordType *state);
+ static void Transform(word64 *digest, const word64 *data);
+ void TruncatedFinal(byte *hash, size_t size);
+ static const char * StaticAlgorithmName() {return "Tiger";}
+
+protected:
+ static const word64 table[4*256+3];
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/tigertab.cpp b/lib/cryptopp/tigertab.cpp
new file mode 100644
index 000000000..5c1595b5b
--- /dev/null
+++ b/lib/cryptopp/tigertab.cpp
@@ -0,0 +1,525 @@
+#include "pch.h"
+#include "tiger.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+const word64 Tiger::table[4*256+3] =
+{
+ W64LIT(0x02AAB17CF7E90C5E) /* 0 */, W64LIT(0xAC424B03E243A8EC) /* 1 */,
+ W64LIT(0x72CD5BE30DD5FCD3) /* 2 */, W64LIT(0x6D019B93F6F97F3A) /* 3 */,
+ W64LIT(0xCD9978FFD21F9193) /* 4 */, W64LIT(0x7573A1C9708029E2) /* 5 */,
+ W64LIT(0xB164326B922A83C3) /* 6 */, W64LIT(0x46883EEE04915870) /* 7 */,
+ W64LIT(0xEAACE3057103ECE6) /* 8 */, W64LIT(0xC54169B808A3535C) /* 9 */,
+ W64LIT(0x4CE754918DDEC47C) /* 10 */, W64LIT(0x0AA2F4DFDC0DF40C) /* 11 */,
+ W64LIT(0x10B76F18A74DBEFA) /* 12 */, W64LIT(0xC6CCB6235AD1AB6A) /* 13 */,
+ W64LIT(0x13726121572FE2FF) /* 14 */, W64LIT(0x1A488C6F199D921E) /* 15 */,
+ W64LIT(0x4BC9F9F4DA0007CA) /* 16 */, W64LIT(0x26F5E6F6E85241C7) /* 17 */,
+ W64LIT(0x859079DBEA5947B6) /* 18 */, W64LIT(0x4F1885C5C99E8C92) /* 19 */,
+ W64LIT(0xD78E761EA96F864B) /* 20 */, W64LIT(0x8E36428C52B5C17D) /* 21 */,
+ W64LIT(0x69CF6827373063C1) /* 22 */, W64LIT(0xB607C93D9BB4C56E) /* 23 */,
+ W64LIT(0x7D820E760E76B5EA) /* 24 */, W64LIT(0x645C9CC6F07FDC42) /* 25 */,
+ W64LIT(0xBF38A078243342E0) /* 26 */, W64LIT(0x5F6B343C9D2E7D04) /* 27 */,
+ W64LIT(0xF2C28AEB600B0EC6) /* 28 */, W64LIT(0x6C0ED85F7254BCAC) /* 29 */,
+ W64LIT(0x71592281A4DB4FE5) /* 30 */, W64LIT(0x1967FA69CE0FED9F) /* 31 */,
+ W64LIT(0xFD5293F8B96545DB) /* 32 */, W64LIT(0xC879E9D7F2A7600B) /* 33 */,
+ W64LIT(0x860248920193194E) /* 34 */, W64LIT(0xA4F9533B2D9CC0B3) /* 35 */,
+ W64LIT(0x9053836C15957613) /* 36 */, W64LIT(0xDB6DCF8AFC357BF1) /* 37 */,
+ W64LIT(0x18BEEA7A7A370F57) /* 38 */, W64LIT(0x037117CA50B99066) /* 39 */,
+ W64LIT(0x6AB30A9774424A35) /* 40 */, W64LIT(0xF4E92F02E325249B) /* 41 */,
+ W64LIT(0x7739DB07061CCAE1) /* 42 */, W64LIT(0xD8F3B49CECA42A05) /* 43 */,
+ W64LIT(0xBD56BE3F51382F73) /* 44 */, W64LIT(0x45FAED5843B0BB28) /* 45 */,
+ W64LIT(0x1C813D5C11BF1F83) /* 46 */, W64LIT(0x8AF0E4B6D75FA169) /* 47 */,
+ W64LIT(0x33EE18A487AD9999) /* 48 */, W64LIT(0x3C26E8EAB1C94410) /* 49 */,
+ W64LIT(0xB510102BC0A822F9) /* 50 */, W64LIT(0x141EEF310CE6123B) /* 51 */,
+ W64LIT(0xFC65B90059DDB154) /* 52 */, W64LIT(0xE0158640C5E0E607) /* 53 */,
+ W64LIT(0x884E079826C3A3CF) /* 54 */, W64LIT(0x930D0D9523C535FD) /* 55 */,
+ W64LIT(0x35638D754E9A2B00) /* 56 */, W64LIT(0x4085FCCF40469DD5) /* 57 */,
+ W64LIT(0xC4B17AD28BE23A4C) /* 58 */, W64LIT(0xCAB2F0FC6A3E6A2E) /* 59 */,
+ W64LIT(0x2860971A6B943FCD) /* 60 */, W64LIT(0x3DDE6EE212E30446) /* 61 */,
+ W64LIT(0x6222F32AE01765AE) /* 62 */, W64LIT(0x5D550BB5478308FE) /* 63 */,
+ W64LIT(0xA9EFA98DA0EDA22A) /* 64 */, W64LIT(0xC351A71686C40DA7) /* 65 */,
+ W64LIT(0x1105586D9C867C84) /* 66 */, W64LIT(0xDCFFEE85FDA22853) /* 67 */,
+ W64LIT(0xCCFBD0262C5EEF76) /* 68 */, W64LIT(0xBAF294CB8990D201) /* 69 */,
+ W64LIT(0xE69464F52AFAD975) /* 70 */, W64LIT(0x94B013AFDF133E14) /* 71 */,
+ W64LIT(0x06A7D1A32823C958) /* 72 */, W64LIT(0x6F95FE5130F61119) /* 73 */,
+ W64LIT(0xD92AB34E462C06C0) /* 74 */, W64LIT(0xED7BDE33887C71D2) /* 75 */,
+ W64LIT(0x79746D6E6518393E) /* 76 */, W64LIT(0x5BA419385D713329) /* 77 */,
+ W64LIT(0x7C1BA6B948A97564) /* 78 */, W64LIT(0x31987C197BFDAC67) /* 79 */,
+ W64LIT(0xDE6C23C44B053D02) /* 80 */, W64LIT(0x581C49FED002D64D) /* 81 */,
+ W64LIT(0xDD474D6338261571) /* 82 */, W64LIT(0xAA4546C3E473D062) /* 83 */,
+ W64LIT(0x928FCE349455F860) /* 84 */, W64LIT(0x48161BBACAAB94D9) /* 85 */,
+ W64LIT(0x63912430770E6F68) /* 86 */, W64LIT(0x6EC8A5E602C6641C) /* 87 */,
+ W64LIT(0x87282515337DDD2B) /* 88 */, W64LIT(0x2CDA6B42034B701B) /* 89 */,
+ W64LIT(0xB03D37C181CB096D) /* 90 */, W64LIT(0xE108438266C71C6F) /* 91 */,
+ W64LIT(0x2B3180C7EB51B255) /* 92 */, W64LIT(0xDF92B82F96C08BBC) /* 93 */,
+ W64LIT(0x5C68C8C0A632F3BA) /* 94 */, W64LIT(0x5504CC861C3D0556) /* 95 */,
+ W64LIT(0xABBFA4E55FB26B8F) /* 96 */, W64LIT(0x41848B0AB3BACEB4) /* 97 */,
+ W64LIT(0xB334A273AA445D32) /* 98 */, W64LIT(0xBCA696F0A85AD881) /* 99 */,
+ W64LIT(0x24F6EC65B528D56C) /* 100 */, W64LIT(0x0CE1512E90F4524A) /* 101 */,
+ W64LIT(0x4E9DD79D5506D35A) /* 102 */, W64LIT(0x258905FAC6CE9779) /* 103 */,
+ W64LIT(0x2019295B3E109B33) /* 104 */, W64LIT(0xF8A9478B73A054CC) /* 105 */,
+ W64LIT(0x2924F2F934417EB0) /* 106 */, W64LIT(0x3993357D536D1BC4) /* 107 */,
+ W64LIT(0x38A81AC21DB6FF8B) /* 108 */, W64LIT(0x47C4FBF17D6016BF) /* 109 */,
+ W64LIT(0x1E0FAADD7667E3F5) /* 110 */, W64LIT(0x7ABCFF62938BEB96) /* 111 */,
+ W64LIT(0xA78DAD948FC179C9) /* 112 */, W64LIT(0x8F1F98B72911E50D) /* 113 */,
+ W64LIT(0x61E48EAE27121A91) /* 114 */, W64LIT(0x4D62F7AD31859808) /* 115 */,
+ W64LIT(0xECEBA345EF5CEAEB) /* 116 */, W64LIT(0xF5CEB25EBC9684CE) /* 117 */,
+ W64LIT(0xF633E20CB7F76221) /* 118 */, W64LIT(0xA32CDF06AB8293E4) /* 119 */,
+ W64LIT(0x985A202CA5EE2CA4) /* 120 */, W64LIT(0xCF0B8447CC8A8FB1) /* 121 */,
+ W64LIT(0x9F765244979859A3) /* 122 */, W64LIT(0xA8D516B1A1240017) /* 123 */,
+ W64LIT(0x0BD7BA3EBB5DC726) /* 124 */, W64LIT(0xE54BCA55B86ADB39) /* 125 */,
+ W64LIT(0x1D7A3AFD6C478063) /* 126 */, W64LIT(0x519EC608E7669EDD) /* 127 */,
+ W64LIT(0x0E5715A2D149AA23) /* 128 */, W64LIT(0x177D4571848FF194) /* 129 */,
+ W64LIT(0xEEB55F3241014C22) /* 130 */, W64LIT(0x0F5E5CA13A6E2EC2) /* 131 */,
+ W64LIT(0x8029927B75F5C361) /* 132 */, W64LIT(0xAD139FABC3D6E436) /* 133 */,
+ W64LIT(0x0D5DF1A94CCF402F) /* 134 */, W64LIT(0x3E8BD948BEA5DFC8) /* 135 */,
+ W64LIT(0xA5A0D357BD3FF77E) /* 136 */, W64LIT(0xA2D12E251F74F645) /* 137 */,
+ W64LIT(0x66FD9E525E81A082) /* 138 */, W64LIT(0x2E0C90CE7F687A49) /* 139 */,
+ W64LIT(0xC2E8BCBEBA973BC5) /* 140 */, W64LIT(0x000001BCE509745F) /* 141 */,
+ W64LIT(0x423777BBE6DAB3D6) /* 142 */, W64LIT(0xD1661C7EAEF06EB5) /* 143 */,
+ W64LIT(0xA1781F354DAACFD8) /* 144 */, W64LIT(0x2D11284A2B16AFFC) /* 145 */,
+ W64LIT(0xF1FC4F67FA891D1F) /* 146 */, W64LIT(0x73ECC25DCB920ADA) /* 147 */,
+ W64LIT(0xAE610C22C2A12651) /* 148 */, W64LIT(0x96E0A810D356B78A) /* 149 */,
+ W64LIT(0x5A9A381F2FE7870F) /* 150 */, W64LIT(0xD5AD62EDE94E5530) /* 151 */,
+ W64LIT(0xD225E5E8368D1427) /* 152 */, W64LIT(0x65977B70C7AF4631) /* 153 */,
+ W64LIT(0x99F889B2DE39D74F) /* 154 */, W64LIT(0x233F30BF54E1D143) /* 155 */,
+ W64LIT(0x9A9675D3D9A63C97) /* 156 */, W64LIT(0x5470554FF334F9A8) /* 157 */,
+ W64LIT(0x166ACB744A4F5688) /* 158 */, W64LIT(0x70C74CAAB2E4AEAD) /* 159 */,
+ W64LIT(0xF0D091646F294D12) /* 160 */, W64LIT(0x57B82A89684031D1) /* 161 */,
+ W64LIT(0xEFD95A5A61BE0B6B) /* 162 */, W64LIT(0x2FBD12E969F2F29A) /* 163 */,
+ W64LIT(0x9BD37013FEFF9FE8) /* 164 */, W64LIT(0x3F9B0404D6085A06) /* 165 */,
+ W64LIT(0x4940C1F3166CFE15) /* 166 */, W64LIT(0x09542C4DCDF3DEFB) /* 167 */,
+ W64LIT(0xB4C5218385CD5CE3) /* 168 */, W64LIT(0xC935B7DC4462A641) /* 169 */,
+ W64LIT(0x3417F8A68ED3B63F) /* 170 */, W64LIT(0xB80959295B215B40) /* 171 */,
+ W64LIT(0xF99CDAEF3B8C8572) /* 172 */, W64LIT(0x018C0614F8FCB95D) /* 173 */,
+ W64LIT(0x1B14ACCD1A3ACDF3) /* 174 */, W64LIT(0x84D471F200BB732D) /* 175 */,
+ W64LIT(0xC1A3110E95E8DA16) /* 176 */, W64LIT(0x430A7220BF1A82B8) /* 177 */,
+ W64LIT(0xB77E090D39DF210E) /* 178 */, W64LIT(0x5EF4BD9F3CD05E9D) /* 179 */,
+ W64LIT(0x9D4FF6DA7E57A444) /* 180 */, W64LIT(0xDA1D60E183D4A5F8) /* 181 */,
+ W64LIT(0xB287C38417998E47) /* 182 */, W64LIT(0xFE3EDC121BB31886) /* 183 */,
+ W64LIT(0xC7FE3CCC980CCBEF) /* 184 */, W64LIT(0xE46FB590189BFD03) /* 185 */,
+ W64LIT(0x3732FD469A4C57DC) /* 186 */, W64LIT(0x7EF700A07CF1AD65) /* 187 */,
+ W64LIT(0x59C64468A31D8859) /* 188 */, W64LIT(0x762FB0B4D45B61F6) /* 189 */,
+ W64LIT(0x155BAED099047718) /* 190 */, W64LIT(0x68755E4C3D50BAA6) /* 191 */,
+ W64LIT(0xE9214E7F22D8B4DF) /* 192 */, W64LIT(0x2ADDBF532EAC95F4) /* 193 */,
+ W64LIT(0x32AE3909B4BD0109) /* 194 */, W64LIT(0x834DF537B08E3450) /* 195 */,
+ W64LIT(0xFA209DA84220728D) /* 196 */, W64LIT(0x9E691D9B9EFE23F7) /* 197 */,
+ W64LIT(0x0446D288C4AE8D7F) /* 198 */, W64LIT(0x7B4CC524E169785B) /* 199 */,
+ W64LIT(0x21D87F0135CA1385) /* 200 */, W64LIT(0xCEBB400F137B8AA5) /* 201 */,
+ W64LIT(0x272E2B66580796BE) /* 202 */, W64LIT(0x3612264125C2B0DE) /* 203 */,
+ W64LIT(0x057702BDAD1EFBB2) /* 204 */, W64LIT(0xD4BABB8EACF84BE9) /* 205 */,
+ W64LIT(0x91583139641BC67B) /* 206 */, W64LIT(0x8BDC2DE08036E024) /* 207 */,
+ W64LIT(0x603C8156F49F68ED) /* 208 */, W64LIT(0xF7D236F7DBEF5111) /* 209 */,
+ W64LIT(0x9727C4598AD21E80) /* 210 */, W64LIT(0xA08A0896670A5FD7) /* 211 */,
+ W64LIT(0xCB4A8F4309EBA9CB) /* 212 */, W64LIT(0x81AF564B0F7036A1) /* 213 */,
+ W64LIT(0xC0B99AA778199ABD) /* 214 */, W64LIT(0x959F1EC83FC8E952) /* 215 */,
+ W64LIT(0x8C505077794A81B9) /* 216 */, W64LIT(0x3ACAAF8F056338F0) /* 217 */,
+ W64LIT(0x07B43F50627A6778) /* 218 */, W64LIT(0x4A44AB49F5ECCC77) /* 219 */,
+ W64LIT(0x3BC3D6E4B679EE98) /* 220 */, W64LIT(0x9CC0D4D1CF14108C) /* 221 */,
+ W64LIT(0x4406C00B206BC8A0) /* 222 */, W64LIT(0x82A18854C8D72D89) /* 223 */,
+ W64LIT(0x67E366B35C3C432C) /* 224 */, W64LIT(0xB923DD61102B37F2) /* 225 */,
+ W64LIT(0x56AB2779D884271D) /* 226 */, W64LIT(0xBE83E1B0FF1525AF) /* 227 */,
+ W64LIT(0xFB7C65D4217E49A9) /* 228 */, W64LIT(0x6BDBE0E76D48E7D4) /* 229 */,
+ W64LIT(0x08DF828745D9179E) /* 230 */, W64LIT(0x22EA6A9ADD53BD34) /* 231 */,
+ W64LIT(0xE36E141C5622200A) /* 232 */, W64LIT(0x7F805D1B8CB750EE) /* 233 */,
+ W64LIT(0xAFE5C7A59F58E837) /* 234 */, W64LIT(0xE27F996A4FB1C23C) /* 235 */,
+ W64LIT(0xD3867DFB0775F0D0) /* 236 */, W64LIT(0xD0E673DE6E88891A) /* 237 */,
+ W64LIT(0x123AEB9EAFB86C25) /* 238 */, W64LIT(0x30F1D5D5C145B895) /* 239 */,
+ W64LIT(0xBB434A2DEE7269E7) /* 240 */, W64LIT(0x78CB67ECF931FA38) /* 241 */,
+ W64LIT(0xF33B0372323BBF9C) /* 242 */, W64LIT(0x52D66336FB279C74) /* 243 */,
+ W64LIT(0x505F33AC0AFB4EAA) /* 244 */, W64LIT(0xE8A5CD99A2CCE187) /* 245 */,
+ W64LIT(0x534974801E2D30BB) /* 246 */, W64LIT(0x8D2D5711D5876D90) /* 247 */,
+ W64LIT(0x1F1A412891BC038E) /* 248 */, W64LIT(0xD6E2E71D82E56648) /* 249 */,
+ W64LIT(0x74036C3A497732B7) /* 250 */, W64LIT(0x89B67ED96361F5AB) /* 251 */,
+ W64LIT(0xFFED95D8F1EA02A2) /* 252 */, W64LIT(0xE72B3BD61464D43D) /* 253 */,
+ W64LIT(0xA6300F170BDC4820) /* 254 */, W64LIT(0xEBC18760ED78A77A) /* 255 */,
+ W64LIT(0xE6A6BE5A05A12138) /* 256 */, W64LIT(0xB5A122A5B4F87C98) /* 257 */,
+ W64LIT(0x563C6089140B6990) /* 258 */, W64LIT(0x4C46CB2E391F5DD5) /* 259 */,
+ W64LIT(0xD932ADDBC9B79434) /* 260 */, W64LIT(0x08EA70E42015AFF5) /* 261 */,
+ W64LIT(0xD765A6673E478CF1) /* 262 */, W64LIT(0xC4FB757EAB278D99) /* 263 */,
+ W64LIT(0xDF11C6862D6E0692) /* 264 */, W64LIT(0xDDEB84F10D7F3B16) /* 265 */,
+ W64LIT(0x6F2EF604A665EA04) /* 266 */, W64LIT(0x4A8E0F0FF0E0DFB3) /* 267 */,
+ W64LIT(0xA5EDEEF83DBCBA51) /* 268 */, W64LIT(0xFC4F0A2A0EA4371E) /* 269 */,
+ W64LIT(0xE83E1DA85CB38429) /* 270 */, W64LIT(0xDC8FF882BA1B1CE2) /* 271 */,
+ W64LIT(0xCD45505E8353E80D) /* 272 */, W64LIT(0x18D19A00D4DB0717) /* 273 */,
+ W64LIT(0x34A0CFEDA5F38101) /* 274 */, W64LIT(0x0BE77E518887CAF2) /* 275 */,
+ W64LIT(0x1E341438B3C45136) /* 276 */, W64LIT(0xE05797F49089CCF9) /* 277 */,
+ W64LIT(0xFFD23F9DF2591D14) /* 278 */, W64LIT(0x543DDA228595C5CD) /* 279 */,
+ W64LIT(0x661F81FD99052A33) /* 280 */, W64LIT(0x8736E641DB0F7B76) /* 281 */,
+ W64LIT(0x15227725418E5307) /* 282 */, W64LIT(0xE25F7F46162EB2FA) /* 283 */,
+ W64LIT(0x48A8B2126C13D9FE) /* 284 */, W64LIT(0xAFDC541792E76EEA) /* 285 */,
+ W64LIT(0x03D912BFC6D1898F) /* 286 */, W64LIT(0x31B1AAFA1B83F51B) /* 287 */,
+ W64LIT(0xF1AC2796E42AB7D9) /* 288 */, W64LIT(0x40A3A7D7FCD2EBAC) /* 289 */,
+ W64LIT(0x1056136D0AFBBCC5) /* 290 */, W64LIT(0x7889E1DD9A6D0C85) /* 291 */,
+ W64LIT(0xD33525782A7974AA) /* 292 */, W64LIT(0xA7E25D09078AC09B) /* 293 */,
+ W64LIT(0xBD4138B3EAC6EDD0) /* 294 */, W64LIT(0x920ABFBE71EB9E70) /* 295 */,
+ W64LIT(0xA2A5D0F54FC2625C) /* 296 */, W64LIT(0xC054E36B0B1290A3) /* 297 */,
+ W64LIT(0xF6DD59FF62FE932B) /* 298 */, W64LIT(0x3537354511A8AC7D) /* 299 */,
+ W64LIT(0xCA845E9172FADCD4) /* 300 */, W64LIT(0x84F82B60329D20DC) /* 301 */,
+ W64LIT(0x79C62CE1CD672F18) /* 302 */, W64LIT(0x8B09A2ADD124642C) /* 303 */,
+ W64LIT(0xD0C1E96A19D9E726) /* 304 */, W64LIT(0x5A786A9B4BA9500C) /* 305 */,
+ W64LIT(0x0E020336634C43F3) /* 306 */, W64LIT(0xC17B474AEB66D822) /* 307 */,
+ W64LIT(0x6A731AE3EC9BAAC2) /* 308 */, W64LIT(0x8226667AE0840258) /* 309 */,
+ W64LIT(0x67D4567691CAECA5) /* 310 */, W64LIT(0x1D94155C4875ADB5) /* 311 */,
+ W64LIT(0x6D00FD985B813FDF) /* 312 */, W64LIT(0x51286EFCB774CD06) /* 313 */,
+ W64LIT(0x5E8834471FA744AF) /* 314 */, W64LIT(0xF72CA0AEE761AE2E) /* 315 */,
+ W64LIT(0xBE40E4CDAEE8E09A) /* 316 */, W64LIT(0xE9970BBB5118F665) /* 317 */,
+ W64LIT(0x726E4BEB33DF1964) /* 318 */, W64LIT(0x703B000729199762) /* 319 */,
+ W64LIT(0x4631D816F5EF30A7) /* 320 */, W64LIT(0xB880B5B51504A6BE) /* 321 */,
+ W64LIT(0x641793C37ED84B6C) /* 322 */, W64LIT(0x7B21ED77F6E97D96) /* 323 */,
+ W64LIT(0x776306312EF96B73) /* 324 */, W64LIT(0xAE528948E86FF3F4) /* 325 */,
+ W64LIT(0x53DBD7F286A3F8F8) /* 326 */, W64LIT(0x16CADCE74CFC1063) /* 327 */,
+ W64LIT(0x005C19BDFA52C6DD) /* 328 */, W64LIT(0x68868F5D64D46AD3) /* 329 */,
+ W64LIT(0x3A9D512CCF1E186A) /* 330 */, W64LIT(0x367E62C2385660AE) /* 331 */,
+ W64LIT(0xE359E7EA77DCB1D7) /* 332 */, W64LIT(0x526C0773749ABE6E) /* 333 */,
+ W64LIT(0x735AE5F9D09F734B) /* 334 */, W64LIT(0x493FC7CC8A558BA8) /* 335 */,
+ W64LIT(0xB0B9C1533041AB45) /* 336 */, W64LIT(0x321958BA470A59BD) /* 337 */,
+ W64LIT(0x852DB00B5F46C393) /* 338 */, W64LIT(0x91209B2BD336B0E5) /* 339 */,
+ W64LIT(0x6E604F7D659EF19F) /* 340 */, W64LIT(0xB99A8AE2782CCB24) /* 341 */,
+ W64LIT(0xCCF52AB6C814C4C7) /* 342 */, W64LIT(0x4727D9AFBE11727B) /* 343 */,
+ W64LIT(0x7E950D0C0121B34D) /* 344 */, W64LIT(0x756F435670AD471F) /* 345 */,
+ W64LIT(0xF5ADD442615A6849) /* 346 */, W64LIT(0x4E87E09980B9957A) /* 347 */,
+ W64LIT(0x2ACFA1DF50AEE355) /* 348 */, W64LIT(0xD898263AFD2FD556) /* 349 */,
+ W64LIT(0xC8F4924DD80C8FD6) /* 350 */, W64LIT(0xCF99CA3D754A173A) /* 351 */,
+ W64LIT(0xFE477BACAF91BF3C) /* 352 */, W64LIT(0xED5371F6D690C12D) /* 353 */,
+ W64LIT(0x831A5C285E687094) /* 354 */, W64LIT(0xC5D3C90A3708A0A4) /* 355 */,
+ W64LIT(0x0F7F903717D06580) /* 356 */, W64LIT(0x19F9BB13B8FDF27F) /* 357 */,
+ W64LIT(0xB1BD6F1B4D502843) /* 358 */, W64LIT(0x1C761BA38FFF4012) /* 359 */,
+ W64LIT(0x0D1530C4E2E21F3B) /* 360 */, W64LIT(0x8943CE69A7372C8A) /* 361 */,
+ W64LIT(0xE5184E11FEB5CE66) /* 362 */, W64LIT(0x618BDB80BD736621) /* 363 */,
+ W64LIT(0x7D29BAD68B574D0B) /* 364 */, W64LIT(0x81BB613E25E6FE5B) /* 365 */,
+ W64LIT(0x071C9C10BC07913F) /* 366 */, W64LIT(0xC7BEEB7909AC2D97) /* 367 */,
+ W64LIT(0xC3E58D353BC5D757) /* 368 */, W64LIT(0xEB017892F38F61E8) /* 369 */,
+ W64LIT(0xD4EFFB9C9B1CC21A) /* 370 */, W64LIT(0x99727D26F494F7AB) /* 371 */,
+ W64LIT(0xA3E063A2956B3E03) /* 372 */, W64LIT(0x9D4A8B9A4AA09C30) /* 373 */,
+ W64LIT(0x3F6AB7D500090FB4) /* 374 */, W64LIT(0x9CC0F2A057268AC0) /* 375 */,
+ W64LIT(0x3DEE9D2DEDBF42D1) /* 376 */, W64LIT(0x330F49C87960A972) /* 377 */,
+ W64LIT(0xC6B2720287421B41) /* 378 */, W64LIT(0x0AC59EC07C00369C) /* 379 */,
+ W64LIT(0xEF4EAC49CB353425) /* 380 */, W64LIT(0xF450244EEF0129D8) /* 381 */,
+ W64LIT(0x8ACC46E5CAF4DEB6) /* 382 */, W64LIT(0x2FFEAB63989263F7) /* 383 */,
+ W64LIT(0x8F7CB9FE5D7A4578) /* 384 */, W64LIT(0x5BD8F7644E634635) /* 385 */,
+ W64LIT(0x427A7315BF2DC900) /* 386 */, W64LIT(0x17D0C4AA2125261C) /* 387 */,
+ W64LIT(0x3992486C93518E50) /* 388 */, W64LIT(0xB4CBFEE0A2D7D4C3) /* 389 */,
+ W64LIT(0x7C75D6202C5DDD8D) /* 390 */, W64LIT(0xDBC295D8E35B6C61) /* 391 */,
+ W64LIT(0x60B369D302032B19) /* 392 */, W64LIT(0xCE42685FDCE44132) /* 393 */,
+ W64LIT(0x06F3DDB9DDF65610) /* 394 */, W64LIT(0x8EA4D21DB5E148F0) /* 395 */,
+ W64LIT(0x20B0FCE62FCD496F) /* 396 */, W64LIT(0x2C1B912358B0EE31) /* 397 */,
+ W64LIT(0xB28317B818F5A308) /* 398 */, W64LIT(0xA89C1E189CA6D2CF) /* 399 */,
+ W64LIT(0x0C6B18576AAADBC8) /* 400 */, W64LIT(0xB65DEAA91299FAE3) /* 401 */,
+ W64LIT(0xFB2B794B7F1027E7) /* 402 */, W64LIT(0x04E4317F443B5BEB) /* 403 */,
+ W64LIT(0x4B852D325939D0A6) /* 404 */, W64LIT(0xD5AE6BEEFB207FFC) /* 405 */,
+ W64LIT(0x309682B281C7D374) /* 406 */, W64LIT(0xBAE309A194C3B475) /* 407 */,
+ W64LIT(0x8CC3F97B13B49F05) /* 408 */, W64LIT(0x98A9422FF8293967) /* 409 */,
+ W64LIT(0x244B16B01076FF7C) /* 410 */, W64LIT(0xF8BF571C663D67EE) /* 411 */,
+ W64LIT(0x1F0D6758EEE30DA1) /* 412 */, W64LIT(0xC9B611D97ADEB9B7) /* 413 */,
+ W64LIT(0xB7AFD5887B6C57A2) /* 414 */, W64LIT(0x6290AE846B984FE1) /* 415 */,
+ W64LIT(0x94DF4CDEACC1A5FD) /* 416 */, W64LIT(0x058A5BD1C5483AFF) /* 417 */,
+ W64LIT(0x63166CC142BA3C37) /* 418 */, W64LIT(0x8DB8526EB2F76F40) /* 419 */,
+ W64LIT(0xE10880036F0D6D4E) /* 420 */, W64LIT(0x9E0523C9971D311D) /* 421 */,
+ W64LIT(0x45EC2824CC7CD691) /* 422 */, W64LIT(0x575B8359E62382C9) /* 423 */,
+ W64LIT(0xFA9E400DC4889995) /* 424 */, W64LIT(0xD1823ECB45721568) /* 425 */,
+ W64LIT(0xDAFD983B8206082F) /* 426 */, W64LIT(0xAA7D29082386A8CB) /* 427 */,
+ W64LIT(0x269FCD4403B87588) /* 428 */, W64LIT(0x1B91F5F728BDD1E0) /* 429 */,
+ W64LIT(0xE4669F39040201F6) /* 430 */, W64LIT(0x7A1D7C218CF04ADE) /* 431 */,
+ W64LIT(0x65623C29D79CE5CE) /* 432 */, W64LIT(0x2368449096C00BB1) /* 433 */,
+ W64LIT(0xAB9BF1879DA503BA) /* 434 */, W64LIT(0xBC23ECB1A458058E) /* 435 */,
+ W64LIT(0x9A58DF01BB401ECC) /* 436 */, W64LIT(0xA070E868A85F143D) /* 437 */,
+ W64LIT(0x4FF188307DF2239E) /* 438 */, W64LIT(0x14D565B41A641183) /* 439 */,
+ W64LIT(0xEE13337452701602) /* 440 */, W64LIT(0x950E3DCF3F285E09) /* 441 */,
+ W64LIT(0x59930254B9C80953) /* 442 */, W64LIT(0x3BF299408930DA6D) /* 443 */,
+ W64LIT(0xA955943F53691387) /* 444 */, W64LIT(0xA15EDECAA9CB8784) /* 445 */,
+ W64LIT(0x29142127352BE9A0) /* 446 */, W64LIT(0x76F0371FFF4E7AFB) /* 447 */,
+ W64LIT(0x0239F450274F2228) /* 448 */, W64LIT(0xBB073AF01D5E868B) /* 449 */,
+ W64LIT(0xBFC80571C10E96C1) /* 450 */, W64LIT(0xD267088568222E23) /* 451 */,
+ W64LIT(0x9671A3D48E80B5B0) /* 452 */, W64LIT(0x55B5D38AE193BB81) /* 453 */,
+ W64LIT(0x693AE2D0A18B04B8) /* 454 */, W64LIT(0x5C48B4ECADD5335F) /* 455 */,
+ W64LIT(0xFD743B194916A1CA) /* 456 */, W64LIT(0x2577018134BE98C4) /* 457 */,
+ W64LIT(0xE77987E83C54A4AD) /* 458 */, W64LIT(0x28E11014DA33E1B9) /* 459 */,
+ W64LIT(0x270CC59E226AA213) /* 460 */, W64LIT(0x71495F756D1A5F60) /* 461 */,
+ W64LIT(0x9BE853FB60AFEF77) /* 462 */, W64LIT(0xADC786A7F7443DBF) /* 463 */,
+ W64LIT(0x0904456173B29A82) /* 464 */, W64LIT(0x58BC7A66C232BD5E) /* 465 */,
+ W64LIT(0xF306558C673AC8B2) /* 466 */, W64LIT(0x41F639C6B6C9772A) /* 467 */,
+ W64LIT(0x216DEFE99FDA35DA) /* 468 */, W64LIT(0x11640CC71C7BE615) /* 469 */,
+ W64LIT(0x93C43694565C5527) /* 470 */, W64LIT(0xEA038E6246777839) /* 471 */,
+ W64LIT(0xF9ABF3CE5A3E2469) /* 472 */, W64LIT(0x741E768D0FD312D2) /* 473 */,
+ W64LIT(0x0144B883CED652C6) /* 474 */, W64LIT(0xC20B5A5BA33F8552) /* 475 */,
+ W64LIT(0x1AE69633C3435A9D) /* 476 */, W64LIT(0x97A28CA4088CFDEC) /* 477 */,
+ W64LIT(0x8824A43C1E96F420) /* 478 */, W64LIT(0x37612FA66EEEA746) /* 479 */,
+ W64LIT(0x6B4CB165F9CF0E5A) /* 480 */, W64LIT(0x43AA1C06A0ABFB4A) /* 481 */,
+ W64LIT(0x7F4DC26FF162796B) /* 482 */, W64LIT(0x6CBACC8E54ED9B0F) /* 483 */,
+ W64LIT(0xA6B7FFEFD2BB253E) /* 484 */, W64LIT(0x2E25BC95B0A29D4F) /* 485 */,
+ W64LIT(0x86D6A58BDEF1388C) /* 486 */, W64LIT(0xDED74AC576B6F054) /* 487 */,
+ W64LIT(0x8030BDBC2B45805D) /* 488 */, W64LIT(0x3C81AF70E94D9289) /* 489 */,
+ W64LIT(0x3EFF6DDA9E3100DB) /* 490 */, W64LIT(0xB38DC39FDFCC8847) /* 491 */,
+ W64LIT(0x123885528D17B87E) /* 492 */, W64LIT(0xF2DA0ED240B1B642) /* 493 */,
+ W64LIT(0x44CEFADCD54BF9A9) /* 494 */, W64LIT(0x1312200E433C7EE6) /* 495 */,
+ W64LIT(0x9FFCC84F3A78C748) /* 496 */, W64LIT(0xF0CD1F72248576BB) /* 497 */,
+ W64LIT(0xEC6974053638CFE4) /* 498 */, W64LIT(0x2BA7B67C0CEC4E4C) /* 499 */,
+ W64LIT(0xAC2F4DF3E5CE32ED) /* 500 */, W64LIT(0xCB33D14326EA4C11) /* 501 */,
+ W64LIT(0xA4E9044CC77E58BC) /* 502 */, W64LIT(0x5F513293D934FCEF) /* 503 */,
+ W64LIT(0x5DC9645506E55444) /* 504 */, W64LIT(0x50DE418F317DE40A) /* 505 */,
+ W64LIT(0x388CB31A69DDE259) /* 506 */, W64LIT(0x2DB4A83455820A86) /* 507 */,
+ W64LIT(0x9010A91E84711AE9) /* 508 */, W64LIT(0x4DF7F0B7B1498371) /* 509 */,
+ W64LIT(0xD62A2EABC0977179) /* 510 */, W64LIT(0x22FAC097AA8D5C0E) /* 511 */,
+ W64LIT(0xF49FCC2FF1DAF39B) /* 512 */, W64LIT(0x487FD5C66FF29281) /* 513 */,
+ W64LIT(0xE8A30667FCDCA83F) /* 514 */, W64LIT(0x2C9B4BE3D2FCCE63) /* 515 */,
+ W64LIT(0xDA3FF74B93FBBBC2) /* 516 */, W64LIT(0x2FA165D2FE70BA66) /* 517 */,
+ W64LIT(0xA103E279970E93D4) /* 518 */, W64LIT(0xBECDEC77B0E45E71) /* 519 */,
+ W64LIT(0xCFB41E723985E497) /* 520 */, W64LIT(0xB70AAA025EF75017) /* 521 */,
+ W64LIT(0xD42309F03840B8E0) /* 522 */, W64LIT(0x8EFC1AD035898579) /* 523 */,
+ W64LIT(0x96C6920BE2B2ABC5) /* 524 */, W64LIT(0x66AF4163375A9172) /* 525 */,
+ W64LIT(0x2174ABDCCA7127FB) /* 526 */, W64LIT(0xB33CCEA64A72FF41) /* 527 */,
+ W64LIT(0xF04A4933083066A5) /* 528 */, W64LIT(0x8D970ACDD7289AF5) /* 529 */,
+ W64LIT(0x8F96E8E031C8C25E) /* 530 */, W64LIT(0xF3FEC02276875D47) /* 531 */,
+ W64LIT(0xEC7BF310056190DD) /* 532 */, W64LIT(0xF5ADB0AEBB0F1491) /* 533 */,
+ W64LIT(0x9B50F8850FD58892) /* 534 */, W64LIT(0x4975488358B74DE8) /* 535 */,
+ W64LIT(0xA3354FF691531C61) /* 536 */, W64LIT(0x0702BBE481D2C6EE) /* 537 */,
+ W64LIT(0x89FB24057DEDED98) /* 538 */, W64LIT(0xAC3075138596E902) /* 539 */,
+ W64LIT(0x1D2D3580172772ED) /* 540 */, W64LIT(0xEB738FC28E6BC30D) /* 541 */,
+ W64LIT(0x5854EF8F63044326) /* 542 */, W64LIT(0x9E5C52325ADD3BBE) /* 543 */,
+ W64LIT(0x90AA53CF325C4623) /* 544 */, W64LIT(0xC1D24D51349DD067) /* 545 */,
+ W64LIT(0x2051CFEEA69EA624) /* 546 */, W64LIT(0x13220F0A862E7E4F) /* 547 */,
+ W64LIT(0xCE39399404E04864) /* 548 */, W64LIT(0xD9C42CA47086FCB7) /* 549 */,
+ W64LIT(0x685AD2238A03E7CC) /* 550 */, W64LIT(0x066484B2AB2FF1DB) /* 551 */,
+ W64LIT(0xFE9D5D70EFBF79EC) /* 552 */, W64LIT(0x5B13B9DD9C481854) /* 553 */,
+ W64LIT(0x15F0D475ED1509AD) /* 554 */, W64LIT(0x0BEBCD060EC79851) /* 555 */,
+ W64LIT(0xD58C6791183AB7F8) /* 556 */, W64LIT(0xD1187C5052F3EEE4) /* 557 */,
+ W64LIT(0xC95D1192E54E82FF) /* 558 */, W64LIT(0x86EEA14CB9AC6CA2) /* 559 */,
+ W64LIT(0x3485BEB153677D5D) /* 560 */, W64LIT(0xDD191D781F8C492A) /* 561 */,
+ W64LIT(0xF60866BAA784EBF9) /* 562 */, W64LIT(0x518F643BA2D08C74) /* 563 */,
+ W64LIT(0x8852E956E1087C22) /* 564 */, W64LIT(0xA768CB8DC410AE8D) /* 565 */,
+ W64LIT(0x38047726BFEC8E1A) /* 566 */, W64LIT(0xA67738B4CD3B45AA) /* 567 */,
+ W64LIT(0xAD16691CEC0DDE19) /* 568 */, W64LIT(0xC6D4319380462E07) /* 569 */,
+ W64LIT(0xC5A5876D0BA61938) /* 570 */, W64LIT(0x16B9FA1FA58FD840) /* 571 */,
+ W64LIT(0x188AB1173CA74F18) /* 572 */, W64LIT(0xABDA2F98C99C021F) /* 573 */,
+ W64LIT(0x3E0580AB134AE816) /* 574 */, W64LIT(0x5F3B05B773645ABB) /* 575 */,
+ W64LIT(0x2501A2BE5575F2F6) /* 576 */, W64LIT(0x1B2F74004E7E8BA9) /* 577 */,
+ W64LIT(0x1CD7580371E8D953) /* 578 */, W64LIT(0x7F6ED89562764E30) /* 579 */,
+ W64LIT(0xB15926FF596F003D) /* 580 */, W64LIT(0x9F65293DA8C5D6B9) /* 581 */,
+ W64LIT(0x6ECEF04DD690F84C) /* 582 */, W64LIT(0x4782275FFF33AF88) /* 583 */,
+ W64LIT(0xE41433083F820801) /* 584 */, W64LIT(0xFD0DFE409A1AF9B5) /* 585 */,
+ W64LIT(0x4325A3342CDB396B) /* 586 */, W64LIT(0x8AE77E62B301B252) /* 587 */,
+ W64LIT(0xC36F9E9F6655615A) /* 588 */, W64LIT(0x85455A2D92D32C09) /* 589 */,
+ W64LIT(0xF2C7DEA949477485) /* 590 */, W64LIT(0x63CFB4C133A39EBA) /* 591 */,
+ W64LIT(0x83B040CC6EBC5462) /* 592 */, W64LIT(0x3B9454C8FDB326B0) /* 593 */,
+ W64LIT(0x56F56A9E87FFD78C) /* 594 */, W64LIT(0x2DC2940D99F42BC6) /* 595 */,
+ W64LIT(0x98F7DF096B096E2D) /* 596 */, W64LIT(0x19A6E01E3AD852BF) /* 597 */,
+ W64LIT(0x42A99CCBDBD4B40B) /* 598 */, W64LIT(0xA59998AF45E9C559) /* 599 */,
+ W64LIT(0x366295E807D93186) /* 600 */, W64LIT(0x6B48181BFAA1F773) /* 601 */,
+ W64LIT(0x1FEC57E2157A0A1D) /* 602 */, W64LIT(0x4667446AF6201AD5) /* 603 */,
+ W64LIT(0xE615EBCACFB0F075) /* 604 */, W64LIT(0xB8F31F4F68290778) /* 605 */,
+ W64LIT(0x22713ED6CE22D11E) /* 606 */, W64LIT(0x3057C1A72EC3C93B) /* 607 */,
+ W64LIT(0xCB46ACC37C3F1F2F) /* 608 */, W64LIT(0xDBB893FD02AAF50E) /* 609 */,
+ W64LIT(0x331FD92E600B9FCF) /* 610 */, W64LIT(0xA498F96148EA3AD6) /* 611 */,
+ W64LIT(0xA8D8426E8B6A83EA) /* 612 */, W64LIT(0xA089B274B7735CDC) /* 613 */,
+ W64LIT(0x87F6B3731E524A11) /* 614 */, W64LIT(0x118808E5CBC96749) /* 615 */,
+ W64LIT(0x9906E4C7B19BD394) /* 616 */, W64LIT(0xAFED7F7E9B24A20C) /* 617 */,
+ W64LIT(0x6509EADEEB3644A7) /* 618 */, W64LIT(0x6C1EF1D3E8EF0EDE) /* 619 */,
+ W64LIT(0xB9C97D43E9798FB4) /* 620 */, W64LIT(0xA2F2D784740C28A3) /* 621 */,
+ W64LIT(0x7B8496476197566F) /* 622 */, W64LIT(0x7A5BE3E6B65F069D) /* 623 */,
+ W64LIT(0xF96330ED78BE6F10) /* 624 */, W64LIT(0xEEE60DE77A076A15) /* 625 */,
+ W64LIT(0x2B4BEE4AA08B9BD0) /* 626 */, W64LIT(0x6A56A63EC7B8894E) /* 627 */,
+ W64LIT(0x02121359BA34FEF4) /* 628 */, W64LIT(0x4CBF99F8283703FC) /* 629 */,
+ W64LIT(0x398071350CAF30C8) /* 630 */, W64LIT(0xD0A77A89F017687A) /* 631 */,
+ W64LIT(0xF1C1A9EB9E423569) /* 632 */, W64LIT(0x8C7976282DEE8199) /* 633 */,
+ W64LIT(0x5D1737A5DD1F7ABD) /* 634 */, W64LIT(0x4F53433C09A9FA80) /* 635 */,
+ W64LIT(0xFA8B0C53DF7CA1D9) /* 636 */, W64LIT(0x3FD9DCBC886CCB77) /* 637 */,
+ W64LIT(0xC040917CA91B4720) /* 638 */, W64LIT(0x7DD00142F9D1DCDF) /* 639 */,
+ W64LIT(0x8476FC1D4F387B58) /* 640 */, W64LIT(0x23F8E7C5F3316503) /* 641 */,
+ W64LIT(0x032A2244E7E37339) /* 642 */, W64LIT(0x5C87A5D750F5A74B) /* 643 */,
+ W64LIT(0x082B4CC43698992E) /* 644 */, W64LIT(0xDF917BECB858F63C) /* 645 */,
+ W64LIT(0x3270B8FC5BF86DDA) /* 646 */, W64LIT(0x10AE72BB29B5DD76) /* 647 */,
+ W64LIT(0x576AC94E7700362B) /* 648 */, W64LIT(0x1AD112DAC61EFB8F) /* 649 */,
+ W64LIT(0x691BC30EC5FAA427) /* 650 */, W64LIT(0xFF246311CC327143) /* 651 */,
+ W64LIT(0x3142368E30E53206) /* 652 */, W64LIT(0x71380E31E02CA396) /* 653 */,
+ W64LIT(0x958D5C960AAD76F1) /* 654 */, W64LIT(0xF8D6F430C16DA536) /* 655 */,
+ W64LIT(0xC8FFD13F1BE7E1D2) /* 656 */, W64LIT(0x7578AE66004DDBE1) /* 657 */,
+ W64LIT(0x05833F01067BE646) /* 658 */, W64LIT(0xBB34B5AD3BFE586D) /* 659 */,
+ W64LIT(0x095F34C9A12B97F0) /* 660 */, W64LIT(0x247AB64525D60CA8) /* 661 */,
+ W64LIT(0xDCDBC6F3017477D1) /* 662 */, W64LIT(0x4A2E14D4DECAD24D) /* 663 */,
+ W64LIT(0xBDB5E6D9BE0A1EEB) /* 664 */, W64LIT(0x2A7E70F7794301AB) /* 665 */,
+ W64LIT(0xDEF42D8A270540FD) /* 666 */, W64LIT(0x01078EC0A34C22C1) /* 667 */,
+ W64LIT(0xE5DE511AF4C16387) /* 668 */, W64LIT(0x7EBB3A52BD9A330A) /* 669 */,
+ W64LIT(0x77697857AA7D6435) /* 670 */, W64LIT(0x004E831603AE4C32) /* 671 */,
+ W64LIT(0xE7A21020AD78E312) /* 672 */, W64LIT(0x9D41A70C6AB420F2) /* 673 */,
+ W64LIT(0x28E06C18EA1141E6) /* 674 */, W64LIT(0xD2B28CBD984F6B28) /* 675 */,
+ W64LIT(0x26B75F6C446E9D83) /* 676 */, W64LIT(0xBA47568C4D418D7F) /* 677 */,
+ W64LIT(0xD80BADBFE6183D8E) /* 678 */, W64LIT(0x0E206D7F5F166044) /* 679 */,
+ W64LIT(0xE258A43911CBCA3E) /* 680 */, W64LIT(0x723A1746B21DC0BC) /* 681 */,
+ W64LIT(0xC7CAA854F5D7CDD3) /* 682 */, W64LIT(0x7CAC32883D261D9C) /* 683 */,
+ W64LIT(0x7690C26423BA942C) /* 684 */, W64LIT(0x17E55524478042B8) /* 685 */,
+ W64LIT(0xE0BE477656A2389F) /* 686 */, W64LIT(0x4D289B5E67AB2DA0) /* 687 */,
+ W64LIT(0x44862B9C8FBBFD31) /* 688 */, W64LIT(0xB47CC8049D141365) /* 689 */,
+ W64LIT(0x822C1B362B91C793) /* 690 */, W64LIT(0x4EB14655FB13DFD8) /* 691 */,
+ W64LIT(0x1ECBBA0714E2A97B) /* 692 */, W64LIT(0x6143459D5CDE5F14) /* 693 */,
+ W64LIT(0x53A8FBF1D5F0AC89) /* 694 */, W64LIT(0x97EA04D81C5E5B00) /* 695 */,
+ W64LIT(0x622181A8D4FDB3F3) /* 696 */, W64LIT(0xE9BCD341572A1208) /* 697 */,
+ W64LIT(0x1411258643CCE58A) /* 698 */, W64LIT(0x9144C5FEA4C6E0A4) /* 699 */,
+ W64LIT(0x0D33D06565CF620F) /* 700 */, W64LIT(0x54A48D489F219CA1) /* 701 */,
+ W64LIT(0xC43E5EAC6D63C821) /* 702 */, W64LIT(0xA9728B3A72770DAF) /* 703 */,
+ W64LIT(0xD7934E7B20DF87EF) /* 704 */, W64LIT(0xE35503B61A3E86E5) /* 705 */,
+ W64LIT(0xCAE321FBC819D504) /* 706 */, W64LIT(0x129A50B3AC60BFA6) /* 707 */,
+ W64LIT(0xCD5E68EA7E9FB6C3) /* 708 */, W64LIT(0xB01C90199483B1C7) /* 709 */,
+ W64LIT(0x3DE93CD5C295376C) /* 710 */, W64LIT(0xAED52EDF2AB9AD13) /* 711 */,
+ W64LIT(0x2E60F512C0A07884) /* 712 */, W64LIT(0xBC3D86A3E36210C9) /* 713 */,
+ W64LIT(0x35269D9B163951CE) /* 714 */, W64LIT(0x0C7D6E2AD0CDB5FA) /* 715 */,
+ W64LIT(0x59E86297D87F5733) /* 716 */, W64LIT(0x298EF221898DB0E7) /* 717 */,
+ W64LIT(0x55000029D1A5AA7E) /* 718 */, W64LIT(0x8BC08AE1B5061B45) /* 719 */,
+ W64LIT(0xC2C31C2B6C92703A) /* 720 */, W64LIT(0x94CC596BAF25EF42) /* 721 */,
+ W64LIT(0x0A1D73DB22540456) /* 722 */, W64LIT(0x04B6A0F9D9C4179A) /* 723 */,
+ W64LIT(0xEFFDAFA2AE3D3C60) /* 724 */, W64LIT(0xF7C8075BB49496C4) /* 725 */,
+ W64LIT(0x9CC5C7141D1CD4E3) /* 726 */, W64LIT(0x78BD1638218E5534) /* 727 */,
+ W64LIT(0xB2F11568F850246A) /* 728 */, W64LIT(0xEDFABCFA9502BC29) /* 729 */,
+ W64LIT(0x796CE5F2DA23051B) /* 730 */, W64LIT(0xAAE128B0DC93537C) /* 731 */,
+ W64LIT(0x3A493DA0EE4B29AE) /* 732 */, W64LIT(0xB5DF6B2C416895D7) /* 733 */,
+ W64LIT(0xFCABBD25122D7F37) /* 734 */, W64LIT(0x70810B58105DC4B1) /* 735 */,
+ W64LIT(0xE10FDD37F7882A90) /* 736 */, W64LIT(0x524DCAB5518A3F5C) /* 737 */,
+ W64LIT(0x3C9E85878451255B) /* 738 */, W64LIT(0x4029828119BD34E2) /* 739 */,
+ W64LIT(0x74A05B6F5D3CECCB) /* 740 */, W64LIT(0xB610021542E13ECA) /* 741 */,
+ W64LIT(0x0FF979D12F59E2AC) /* 742 */, W64LIT(0x6037DA27E4F9CC50) /* 743 */,
+ W64LIT(0x5E92975A0DF1847D) /* 744 */, W64LIT(0xD66DE190D3E623FE) /* 745 */,
+ W64LIT(0x5032D6B87B568048) /* 746 */, W64LIT(0x9A36B7CE8235216E) /* 747 */,
+ W64LIT(0x80272A7A24F64B4A) /* 748 */, W64LIT(0x93EFED8B8C6916F7) /* 749 */,
+ W64LIT(0x37DDBFF44CCE1555) /* 750 */, W64LIT(0x4B95DB5D4B99BD25) /* 751 */,
+ W64LIT(0x92D3FDA169812FC0) /* 752 */, W64LIT(0xFB1A4A9A90660BB6) /* 753 */,
+ W64LIT(0x730C196946A4B9B2) /* 754 */, W64LIT(0x81E289AA7F49DA68) /* 755 */,
+ W64LIT(0x64669A0F83B1A05F) /* 756 */, W64LIT(0x27B3FF7D9644F48B) /* 757 */,
+ W64LIT(0xCC6B615C8DB675B3) /* 758 */, W64LIT(0x674F20B9BCEBBE95) /* 759 */,
+ W64LIT(0x6F31238275655982) /* 760 */, W64LIT(0x5AE488713E45CF05) /* 761 */,
+ W64LIT(0xBF619F9954C21157) /* 762 */, W64LIT(0xEABAC46040A8EAE9) /* 763 */,
+ W64LIT(0x454C6FE9F2C0C1CD) /* 764 */, W64LIT(0x419CF6496412691C) /* 765 */,
+ W64LIT(0xD3DC3BEF265B0F70) /* 766 */, W64LIT(0x6D0E60F5C3578A9E) /* 767 */,
+ W64LIT(0x5B0E608526323C55) /* 768 */, W64LIT(0x1A46C1A9FA1B59F5) /* 769 */,
+ W64LIT(0xA9E245A17C4C8FFA) /* 770 */, W64LIT(0x65CA5159DB2955D7) /* 771 */,
+ W64LIT(0x05DB0A76CE35AFC2) /* 772 */, W64LIT(0x81EAC77EA9113D45) /* 773 */,
+ W64LIT(0x528EF88AB6AC0A0D) /* 774 */, W64LIT(0xA09EA253597BE3FF) /* 775 */,
+ W64LIT(0x430DDFB3AC48CD56) /* 776 */, W64LIT(0xC4B3A67AF45CE46F) /* 777 */,
+ W64LIT(0x4ECECFD8FBE2D05E) /* 778 */, W64LIT(0x3EF56F10B39935F0) /* 779 */,
+ W64LIT(0x0B22D6829CD619C6) /* 780 */, W64LIT(0x17FD460A74DF2069) /* 781 */,
+ W64LIT(0x6CF8CC8E8510ED40) /* 782 */, W64LIT(0xD6C824BF3A6ECAA7) /* 783 */,
+ W64LIT(0x61243D581A817049) /* 784 */, W64LIT(0x048BACB6BBC163A2) /* 785 */,
+ W64LIT(0xD9A38AC27D44CC32) /* 786 */, W64LIT(0x7FDDFF5BAAF410AB) /* 787 */,
+ W64LIT(0xAD6D495AA804824B) /* 788 */, W64LIT(0xE1A6A74F2D8C9F94) /* 789 */,
+ W64LIT(0xD4F7851235DEE8E3) /* 790 */, W64LIT(0xFD4B7F886540D893) /* 791 */,
+ W64LIT(0x247C20042AA4BFDA) /* 792 */, W64LIT(0x096EA1C517D1327C) /* 793 */,
+ W64LIT(0xD56966B4361A6685) /* 794 */, W64LIT(0x277DA5C31221057D) /* 795 */,
+ W64LIT(0x94D59893A43ACFF7) /* 796 */, W64LIT(0x64F0C51CCDC02281) /* 797 */,
+ W64LIT(0x3D33BCC4FF6189DB) /* 798 */, W64LIT(0xE005CB184CE66AF1) /* 799 */,
+ W64LIT(0xFF5CCD1D1DB99BEA) /* 800 */, W64LIT(0xB0B854A7FE42980F) /* 801 */,
+ W64LIT(0x7BD46A6A718D4B9F) /* 802 */, W64LIT(0xD10FA8CC22A5FD8C) /* 803 */,
+ W64LIT(0xD31484952BE4BD31) /* 804 */, W64LIT(0xC7FA975FCB243847) /* 805 */,
+ W64LIT(0x4886ED1E5846C407) /* 806 */, W64LIT(0x28CDDB791EB70B04) /* 807 */,
+ W64LIT(0xC2B00BE2F573417F) /* 808 */, W64LIT(0x5C9590452180F877) /* 809 */,
+ W64LIT(0x7A6BDDFFF370EB00) /* 810 */, W64LIT(0xCE509E38D6D9D6A4) /* 811 */,
+ W64LIT(0xEBEB0F00647FA702) /* 812 */, W64LIT(0x1DCC06CF76606F06) /* 813 */,
+ W64LIT(0xE4D9F28BA286FF0A) /* 814 */, W64LIT(0xD85A305DC918C262) /* 815 */,
+ W64LIT(0x475B1D8732225F54) /* 816 */, W64LIT(0x2D4FB51668CCB5FE) /* 817 */,
+ W64LIT(0xA679B9D9D72BBA20) /* 818 */, W64LIT(0x53841C0D912D43A5) /* 819 */,
+ W64LIT(0x3B7EAA48BF12A4E8) /* 820 */, W64LIT(0x781E0E47F22F1DDF) /* 821 */,
+ W64LIT(0xEFF20CE60AB50973) /* 822 */, W64LIT(0x20D261D19DFFB742) /* 823 */,
+ W64LIT(0x16A12B03062A2E39) /* 824 */, W64LIT(0x1960EB2239650495) /* 825 */,
+ W64LIT(0x251C16FED50EB8B8) /* 826 */, W64LIT(0x9AC0C330F826016E) /* 827 */,
+ W64LIT(0xED152665953E7671) /* 828 */, W64LIT(0x02D63194A6369570) /* 829 */,
+ W64LIT(0x5074F08394B1C987) /* 830 */, W64LIT(0x70BA598C90B25CE1) /* 831 */,
+ W64LIT(0x794A15810B9742F6) /* 832 */, W64LIT(0x0D5925E9FCAF8C6C) /* 833 */,
+ W64LIT(0x3067716CD868744E) /* 834 */, W64LIT(0x910AB077E8D7731B) /* 835 */,
+ W64LIT(0x6A61BBDB5AC42F61) /* 836 */, W64LIT(0x93513EFBF0851567) /* 837 */,
+ W64LIT(0xF494724B9E83E9D5) /* 838 */, W64LIT(0xE887E1985C09648D) /* 839 */,
+ W64LIT(0x34B1D3C675370CFD) /* 840 */, W64LIT(0xDC35E433BC0D255D) /* 841 */,
+ W64LIT(0xD0AAB84234131BE0) /* 842 */, W64LIT(0x08042A50B48B7EAF) /* 843 */,
+ W64LIT(0x9997C4EE44A3AB35) /* 844 */, W64LIT(0x829A7B49201799D0) /* 845 */,
+ W64LIT(0x263B8307B7C54441) /* 846 */, W64LIT(0x752F95F4FD6A6CA6) /* 847 */,
+ W64LIT(0x927217402C08C6E5) /* 848 */, W64LIT(0x2A8AB754A795D9EE) /* 849 */,
+ W64LIT(0xA442F7552F72943D) /* 850 */, W64LIT(0x2C31334E19781208) /* 851 */,
+ W64LIT(0x4FA98D7CEAEE6291) /* 852 */, W64LIT(0x55C3862F665DB309) /* 853 */,
+ W64LIT(0xBD0610175D53B1F3) /* 854 */, W64LIT(0x46FE6CB840413F27) /* 855 */,
+ W64LIT(0x3FE03792DF0CFA59) /* 856 */, W64LIT(0xCFE700372EB85E8F) /* 857 */,
+ W64LIT(0xA7BE29E7ADBCE118) /* 858 */, W64LIT(0xE544EE5CDE8431DD) /* 859 */,
+ W64LIT(0x8A781B1B41F1873E) /* 860 */, W64LIT(0xA5C94C78A0D2F0E7) /* 861 */,
+ W64LIT(0x39412E2877B60728) /* 862 */, W64LIT(0xA1265EF3AFC9A62C) /* 863 */,
+ W64LIT(0xBCC2770C6A2506C5) /* 864 */, W64LIT(0x3AB66DD5DCE1CE12) /* 865 */,
+ W64LIT(0xE65499D04A675B37) /* 866 */, W64LIT(0x7D8F523481BFD216) /* 867 */,
+ W64LIT(0x0F6F64FCEC15F389) /* 868 */, W64LIT(0x74EFBE618B5B13C8) /* 869 */,
+ W64LIT(0xACDC82B714273E1D) /* 870 */, W64LIT(0xDD40BFE003199D17) /* 871 */,
+ W64LIT(0x37E99257E7E061F8) /* 872 */, W64LIT(0xFA52626904775AAA) /* 873 */,
+ W64LIT(0x8BBBF63A463D56F9) /* 874 */, W64LIT(0xF0013F1543A26E64) /* 875 */,
+ W64LIT(0xA8307E9F879EC898) /* 876 */, W64LIT(0xCC4C27A4150177CC) /* 877 */,
+ W64LIT(0x1B432F2CCA1D3348) /* 878 */, W64LIT(0xDE1D1F8F9F6FA013) /* 879 */,
+ W64LIT(0x606602A047A7DDD6) /* 880 */, W64LIT(0xD237AB64CC1CB2C7) /* 881 */,
+ W64LIT(0x9B938E7225FCD1D3) /* 882 */, W64LIT(0xEC4E03708E0FF476) /* 883 */,
+ W64LIT(0xFEB2FBDA3D03C12D) /* 884 */, W64LIT(0xAE0BCED2EE43889A) /* 885 */,
+ W64LIT(0x22CB8923EBFB4F43) /* 886 */, W64LIT(0x69360D013CF7396D) /* 887 */,
+ W64LIT(0x855E3602D2D4E022) /* 888 */, W64LIT(0x073805BAD01F784C) /* 889 */,
+ W64LIT(0x33E17A133852F546) /* 890 */, W64LIT(0xDF4874058AC7B638) /* 891 */,
+ W64LIT(0xBA92B29C678AA14A) /* 892 */, W64LIT(0x0CE89FC76CFAADCD) /* 893 */,
+ W64LIT(0x5F9D4E0908339E34) /* 894 */, W64LIT(0xF1AFE9291F5923B9) /* 895 */,
+ W64LIT(0x6E3480F60F4A265F) /* 896 */, W64LIT(0xEEBF3A2AB29B841C) /* 897 */,
+ W64LIT(0xE21938A88F91B4AD) /* 898 */, W64LIT(0x57DFEFF845C6D3C3) /* 899 */,
+ W64LIT(0x2F006B0BF62CAAF2) /* 900 */, W64LIT(0x62F479EF6F75EE78) /* 901 */,
+ W64LIT(0x11A55AD41C8916A9) /* 902 */, W64LIT(0xF229D29084FED453) /* 903 */,
+ W64LIT(0x42F1C27B16B000E6) /* 904 */, W64LIT(0x2B1F76749823C074) /* 905 */,
+ W64LIT(0x4B76ECA3C2745360) /* 906 */, W64LIT(0x8C98F463B91691BD) /* 907 */,
+ W64LIT(0x14BCC93CF1ADE66A) /* 908 */, W64LIT(0x8885213E6D458397) /* 909 */,
+ W64LIT(0x8E177DF0274D4711) /* 910 */, W64LIT(0xB49B73B5503F2951) /* 911 */,
+ W64LIT(0x10168168C3F96B6B) /* 912 */, W64LIT(0x0E3D963B63CAB0AE) /* 913 */,
+ W64LIT(0x8DFC4B5655A1DB14) /* 914 */, W64LIT(0xF789F1356E14DE5C) /* 915 */,
+ W64LIT(0x683E68AF4E51DAC1) /* 916 */, W64LIT(0xC9A84F9D8D4B0FD9) /* 917 */,
+ W64LIT(0x3691E03F52A0F9D1) /* 918 */, W64LIT(0x5ED86E46E1878E80) /* 919 */,
+ W64LIT(0x3C711A0E99D07150) /* 920 */, W64LIT(0x5A0865B20C4E9310) /* 921 */,
+ W64LIT(0x56FBFC1FE4F0682E) /* 922 */, W64LIT(0xEA8D5DE3105EDF9B) /* 923 */,
+ W64LIT(0x71ABFDB12379187A) /* 924 */, W64LIT(0x2EB99DE1BEE77B9C) /* 925 */,
+ W64LIT(0x21ECC0EA33CF4523) /* 926 */, W64LIT(0x59A4D7521805C7A1) /* 927 */,
+ W64LIT(0x3896F5EB56AE7C72) /* 928 */, W64LIT(0xAA638F3DB18F75DC) /* 929 */,
+ W64LIT(0x9F39358DABE9808E) /* 930 */, W64LIT(0xB7DEFA91C00B72AC) /* 931 */,
+ W64LIT(0x6B5541FD62492D92) /* 932 */, W64LIT(0x6DC6DEE8F92E4D5B) /* 933 */,
+ W64LIT(0x353F57ABC4BEEA7E) /* 934 */, W64LIT(0x735769D6DA5690CE) /* 935 */,
+ W64LIT(0x0A234AA642391484) /* 936 */, W64LIT(0xF6F9508028F80D9D) /* 937 */,
+ W64LIT(0xB8E319A27AB3F215) /* 938 */, W64LIT(0x31AD9C1151341A4D) /* 939 */,
+ W64LIT(0x773C22A57BEF5805) /* 940 */, W64LIT(0x45C7561A07968633) /* 941 */,
+ W64LIT(0xF913DA9E249DBE36) /* 942 */, W64LIT(0xDA652D9B78A64C68) /* 943 */,
+ W64LIT(0x4C27A97F3BC334EF) /* 944 */, W64LIT(0x76621220E66B17F4) /* 945 */,
+ W64LIT(0x967743899ACD7D0B) /* 946 */, W64LIT(0xF3EE5BCAE0ED6782) /* 947 */,
+ W64LIT(0x409F753600C879FC) /* 948 */, W64LIT(0x06D09A39B5926DB6) /* 949 */,
+ W64LIT(0x6F83AEB0317AC588) /* 950 */, W64LIT(0x01E6CA4A86381F21) /* 951 */,
+ W64LIT(0x66FF3462D19F3025) /* 952 */, W64LIT(0x72207C24DDFD3BFB) /* 953 */,
+ W64LIT(0x4AF6B6D3E2ECE2EB) /* 954 */, W64LIT(0x9C994DBEC7EA08DE) /* 955 */,
+ W64LIT(0x49ACE597B09A8BC4) /* 956 */, W64LIT(0xB38C4766CF0797BA) /* 957 */,
+ W64LIT(0x131B9373C57C2A75) /* 958 */, W64LIT(0xB1822CCE61931E58) /* 959 */,
+ W64LIT(0x9D7555B909BA1C0C) /* 960 */, W64LIT(0x127FAFDD937D11D2) /* 961 */,
+ W64LIT(0x29DA3BADC66D92E4) /* 962 */, W64LIT(0xA2C1D57154C2ECBC) /* 963 */,
+ W64LIT(0x58C5134D82F6FE24) /* 964 */, W64LIT(0x1C3AE3515B62274F) /* 965 */,
+ W64LIT(0xE907C82E01CB8126) /* 966 */, W64LIT(0xF8ED091913E37FCB) /* 967 */,
+ W64LIT(0x3249D8F9C80046C9) /* 968 */, W64LIT(0x80CF9BEDE388FB63) /* 969 */,
+ W64LIT(0x1881539A116CF19E) /* 970 */, W64LIT(0x5103F3F76BD52457) /* 971 */,
+ W64LIT(0x15B7E6F5AE47F7A8) /* 972 */, W64LIT(0xDBD7C6DED47E9CCF) /* 973 */,
+ W64LIT(0x44E55C410228BB1A) /* 974 */, W64LIT(0xB647D4255EDB4E99) /* 975 */,
+ W64LIT(0x5D11882BB8AAFC30) /* 976 */, W64LIT(0xF5098BBB29D3212A) /* 977 */,
+ W64LIT(0x8FB5EA14E90296B3) /* 978 */, W64LIT(0x677B942157DD025A) /* 979 */,
+ W64LIT(0xFB58E7C0A390ACB5) /* 980 */, W64LIT(0x89D3674C83BD4A01) /* 981 */,
+ W64LIT(0x9E2DA4DF4BF3B93B) /* 982 */, W64LIT(0xFCC41E328CAB4829) /* 983 */,
+ W64LIT(0x03F38C96BA582C52) /* 984 */, W64LIT(0xCAD1BDBD7FD85DB2) /* 985 */,
+ W64LIT(0xBBB442C16082AE83) /* 986 */, W64LIT(0xB95FE86BA5DA9AB0) /* 987 */,
+ W64LIT(0xB22E04673771A93F) /* 988 */, W64LIT(0x845358C9493152D8) /* 989 */,
+ W64LIT(0xBE2A488697B4541E) /* 990 */, W64LIT(0x95A2DC2DD38E6966) /* 991 */,
+ W64LIT(0xC02C11AC923C852B) /* 992 */, W64LIT(0x2388B1990DF2A87B) /* 993 */,
+ W64LIT(0x7C8008FA1B4F37BE) /* 994 */, W64LIT(0x1F70D0C84D54E503) /* 995 */,
+ W64LIT(0x5490ADEC7ECE57D4) /* 996 */, W64LIT(0x002B3C27D9063A3A) /* 997 */,
+ W64LIT(0x7EAEA3848030A2BF) /* 998 */, W64LIT(0xC602326DED2003C0) /* 999 */,
+ W64LIT(0x83A7287D69A94086) /* 1000 */, W64LIT(0xC57A5FCB30F57A8A) /* 1001 */,
+ W64LIT(0xB56844E479EBE779) /* 1002 */, W64LIT(0xA373B40F05DCBCE9) /* 1003 */,
+ W64LIT(0xD71A786E88570EE2) /* 1004 */, W64LIT(0x879CBACDBDE8F6A0) /* 1005 */,
+ W64LIT(0x976AD1BCC164A32F) /* 1006 */, W64LIT(0xAB21E25E9666D78B) /* 1007 */,
+ W64LIT(0x901063AAE5E5C33C) /* 1008 */, W64LIT(0x9818B34448698D90) /* 1009 */,
+ W64LIT(0xE36487AE3E1E8ABB) /* 1010 */, W64LIT(0xAFBDF931893BDCB4) /* 1011 */,
+ W64LIT(0x6345A0DC5FBBD519) /* 1012 */, W64LIT(0x8628FE269B9465CA) /* 1013 */,
+ W64LIT(0x1E5D01603F9C51EC) /* 1014 */, W64LIT(0x4DE44006A15049B7) /* 1015 */,
+ W64LIT(0xBF6C70E5F776CBB1) /* 1016 */, W64LIT(0x411218F2EF552BED) /* 1017 */,
+ W64LIT(0xCB0C0708705A36A3) /* 1018 */, W64LIT(0xE74D14754F986044) /* 1019 */,
+ W64LIT(0xCD56D9430EA8280E) /* 1020 */, W64LIT(0xC12591D7535F5065) /* 1021 */,
+ W64LIT(0xC83223F1720AEF96) /* 1022 */, W64LIT(0xC3A0396F7363A51F) /* 1023 */,
+ W64LIT(0xffffffffffffffff),
+ W64LIT(0xA5A5A5A5A5A5A5A5),
+ W64LIT(0x0123456789ABCDEF),
+};
+
+NAMESPACE_END
diff --git a/lib/cryptopp/trdlocal.cpp b/lib/cryptopp/trdlocal.cpp
new file mode 100644
index 000000000..6d6b822c0
--- /dev/null
+++ b/lib/cryptopp/trdlocal.cpp
@@ -0,0 +1,73 @@
+// trdlocal.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+#ifdef THREADS_AVAILABLE
+
+#include "trdlocal.h"
+
+#ifdef HAS_WINTHREADS
+#include <windows.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+ThreadLocalStorage::Err::Err(const std::string& operation, int error)
+ : OS_Error(OTHER_ERROR, "ThreadLocalStorage: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
+{
+}
+
+ThreadLocalStorage::ThreadLocalStorage()
+{
+#ifdef HAS_WINTHREADS
+ m_index = TlsAlloc();
+ if (m_index == TLS_OUT_OF_INDEXES)
+ throw Err("TlsAlloc", GetLastError());
+#else
+ int error = pthread_key_create(&m_index, NULL);
+ if (error)
+ throw Err("pthread_key_create", error);
+#endif
+}
+
+ThreadLocalStorage::~ThreadLocalStorage()
+{
+#ifdef HAS_WINTHREADS
+ if (!TlsFree(m_index))
+ throw Err("TlsFree", GetLastError());
+#else
+ int error = pthread_key_delete(m_index);
+ if (error)
+ throw Err("pthread_key_delete", error);
+#endif
+}
+
+void ThreadLocalStorage::SetValue(void *value)
+{
+#ifdef HAS_WINTHREADS
+ if (!TlsSetValue(m_index, value))
+ throw Err("TlsSetValue", GetLastError());
+#else
+ int error = pthread_setspecific(m_index, value);
+ if (error)
+ throw Err("pthread_key_getspecific", error);
+#endif
+}
+
+void *ThreadLocalStorage::GetValue() const
+{
+#ifdef HAS_WINTHREADS
+ void *result = TlsGetValue(m_index);
+ if (!result && GetLastError() != NO_ERROR)
+ throw Err("TlsGetValue", GetLastError());
+#else
+ void *result = pthread_getspecific(m_index);
+#endif
+ return result;
+}
+
+NAMESPACE_END
+
+#endif // #ifdef THREADS_AVAILABLE
+#endif
diff --git a/lib/cryptopp/trdlocal.h b/lib/cryptopp/trdlocal.h
new file mode 100644
index 000000000..92d244a0a
--- /dev/null
+++ b/lib/cryptopp/trdlocal.h
@@ -0,0 +1,44 @@
+#ifndef CRYPTOPP_TRDLOCAL_H
+#define CRYPTOPP_TRDLOCAL_H
+
+#include "config.h"
+
+#ifdef THREADS_AVAILABLE
+
+#include "misc.h"
+
+#ifdef HAS_WINTHREADS
+typedef unsigned long ThreadLocalIndexType;
+#else
+#include <pthread.h>
+typedef pthread_key_t ThreadLocalIndexType;
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! thread local storage
+class CRYPTOPP_DLL ThreadLocalStorage : public NotCopyable
+{
+public:
+ //! exception thrown by ThreadLocalStorage class
+ class Err : public OS_Error
+ {
+ public:
+ Err(const std::string& operation, int error);
+ };
+
+ ThreadLocalStorage();
+ ~ThreadLocalStorage();
+
+ void SetValue(void *value);
+ void *GetValue() const;
+
+private:
+ ThreadLocalIndexType m_index;
+};
+
+NAMESPACE_END
+
+#endif // #ifdef THREADS_AVAILABLE
+
+#endif
diff --git a/lib/cryptopp/trunhash.h b/lib/cryptopp/trunhash.h
new file mode 100644
index 000000000..c1c4e9b64
--- /dev/null
+++ b/lib/cryptopp/trunhash.h
@@ -0,0 +1,48 @@
+#ifndef CRYPTOPP_TRUNHASH_H
+#define CRYPTOPP_TRUNHASH_H
+
+#include "cryptlib.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+class NullHash : public HashTransformation
+{
+public:
+ void Update(const byte *input, size_t length) {}
+ unsigned int DigestSize() const {return 0;}
+ void TruncatedFinal(byte *digest, size_t digestSize) {}
+ bool TruncatedVerify(const byte *digest, size_t digestLength) {return true;}
+};
+
+//! construct new HashModule with smaller DigestSize() from existing one
+template <class T>
+class TruncatedHashTemplate : public HashTransformation
+{
+public:
+ TruncatedHashTemplate(T hm, unsigned int digestSize)
+ : m_hm(hm), m_digestSize(digestSize) {}
+ TruncatedHashTemplate(const byte *key, size_t keyLength, unsigned int digestSize)
+ : m_hm(key, keyLength), m_digestSize(digestSize) {}
+ TruncatedHashTemplate(size_t digestSize)
+ : m_digestSize(digestSize) {}
+
+ void Restart()
+ {m_hm.Restart();}
+ void Update(const byte *input, size_t length)
+ {m_hm.Update(input, length);}
+ unsigned int DigestSize() const {return m_digestSize;}
+ void TruncatedFinal(byte *digest, size_t digestSize)
+ {m_hm.TruncatedFinal(digest, digestSize);}
+ bool TruncatedVerify(const byte *digest, size_t digestLength)
+ {return m_hm.TruncatedVerify(digest, digestLength);}
+
+private:
+ T m_hm;
+ unsigned int m_digestSize;
+};
+
+typedef TruncatedHashTemplate<HashTransformation &> TruncatedHashModule;
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/ttmac.cpp b/lib/cryptopp/ttmac.cpp
new file mode 100644
index 000000000..d4ff38104
--- /dev/null
+++ b/lib/cryptopp/ttmac.cpp
@@ -0,0 +1,338 @@
+// ttmac.cpp - written and placed in the public domain by Kevin Springle
+
+#include "pch.h"
+#include "ttmac.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void TTMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &)
+{
+ AssertValidKeyLength(keylength);
+
+ memcpy(m_key, userKey, KEYLENGTH);
+ CorrectEndianess(m_key, m_key, KEYLENGTH);
+
+ Init();
+}
+
+void TTMAC_Base::Init()
+{
+ m_digest[0] = m_digest[5] = m_key[0];
+ m_digest[1] = m_digest[6] = m_key[1];
+ m_digest[2] = m_digest[7] = m_key[2];
+ m_digest[3] = m_digest[8] = m_key[3];
+ m_digest[4] = m_digest[9] = m_key[4];
+}
+
+void TTMAC_Base::TruncatedFinal(byte *hash, size_t size)
+{
+ PadLastBlock(BlockSize() - 2*sizeof(HashWordType));
+ CorrectEndianess(m_data, m_data, BlockSize() - 2*sizeof(HashWordType));
+
+ m_data[m_data.size()-2] = GetBitCountLo();
+ m_data[m_data.size()-1] = GetBitCountHi();
+
+ Transform(m_digest, m_data, true);
+
+ word32 t2 = m_digest[2];
+ word32 t3 = m_digest[3];
+ if (size != DIGESTSIZE)
+ {
+ switch (size)
+ {
+ case 16:
+ m_digest[3] += m_digest[1] + m_digest[4];
+
+ case 12:
+ m_digest[2] += m_digest[0] + t3;
+
+ case 8:
+ m_digest[0] += m_digest[1] + t3;
+ m_digest[1] += m_digest[4] + t2;
+ break;
+
+ case 4:
+ m_digest[0] +=
+ m_digest[1] +
+ m_digest[2] +
+ m_digest[3] +
+ m_digest[4];
+ break;
+
+ case 0:
+ // Used by HashTransformation::Restart()
+ break;
+
+ default:
+ throw InvalidArgument("TTMAC_Base: can't truncate a Two-Track-MAC 20 byte digest to " + IntToString(size) + " bytes");
+ break;
+ }
+ }
+
+ CorrectEndianess(m_digest, m_digest, size);
+ memcpy(hash, m_digest, size);
+
+ Restart(); // reinit for next use
+}
+
+// RIPEMD-160 definitions used by Two-Track-MAC
+
+#define F(x, y, z) (x ^ y ^ z)
+#define G(x, y, z) (z ^ (x & (y^z)))
+#define H(x, y, z) (z ^ (x | ~y))
+#define I(x, y, z) (y ^ (z & (x^y)))
+#define J(x, y, z) (x ^ (y | ~z))
+
+#define k0 0
+#define k1 0x5a827999UL
+#define k2 0x6ed9eba1UL
+#define k3 0x8f1bbcdcUL
+#define k4 0xa953fd4eUL
+#define k5 0x50a28be6UL
+#define k6 0x5c4dd124UL
+#define k7 0x6d703ef3UL
+#define k8 0x7a6d76e9UL
+#define k9 0
+
+void TTMAC_Base::Transform(word32 *digest, const word32 *X, bool last)
+{
+#define Subround(f, a, b, c, d, e, x, s, k) \
+ a += f(b, c, d) + x + k;\
+ a = rotlFixed((word32)a, s) + e;\
+ c = rotlFixed((word32)c, 10U)
+
+ word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2;
+ word32 *trackA, *trackB;
+
+ if (!last)
+ {
+ trackA = digest;
+ trackB = digest+5;
+ }
+ else
+ {
+ trackB = digest;
+ trackA = digest+5;
+ }
+ a1 = trackA[0];
+ b1 = trackA[1];
+ c1 = trackA[2];
+ d1 = trackA[3];
+ e1 = trackA[4];
+ a2 = trackB[0];
+ b2 = trackB[1];
+ c2 = trackB[2];
+ d2 = trackB[3];
+ e2 = trackB[4];
+
+ Subround(F, a1, b1, c1, d1, e1, X[ 0], 11, k0);
+ Subround(F, e1, a1, b1, c1, d1, X[ 1], 14, k0);
+ Subround(F, d1, e1, a1, b1, c1, X[ 2], 15, k0);
+ Subround(F, c1, d1, e1, a1, b1, X[ 3], 12, k0);
+ Subround(F, b1, c1, d1, e1, a1, X[ 4], 5, k0);
+ Subround(F, a1, b1, c1, d1, e1, X[ 5], 8, k0);
+ Subround(F, e1, a1, b1, c1, d1, X[ 6], 7, k0);
+ Subround(F, d1, e1, a1, b1, c1, X[ 7], 9, k0);
+ Subround(F, c1, d1, e1, a1, b1, X[ 8], 11, k0);
+ Subround(F, b1, c1, d1, e1, a1, X[ 9], 13, k0);
+ Subround(F, a1, b1, c1, d1, e1, X[10], 14, k0);
+ Subround(F, e1, a1, b1, c1, d1, X[11], 15, k0);
+ Subround(F, d1, e1, a1, b1, c1, X[12], 6, k0);
+ Subround(F, c1, d1, e1, a1, b1, X[13], 7, k0);
+ Subround(F, b1, c1, d1, e1, a1, X[14], 9, k0);
+ Subround(F, a1, b1, c1, d1, e1, X[15], 8, k0);
+
+ Subround(G, e1, a1, b1, c1, d1, X[ 7], 7, k1);
+ Subround(G, d1, e1, a1, b1, c1, X[ 4], 6, k1);
+ Subround(G, c1, d1, e1, a1, b1, X[13], 8, k1);
+ Subround(G, b1, c1, d1, e1, a1, X[ 1], 13, k1);
+ Subround(G, a1, b1, c1, d1, e1, X[10], 11, k1);
+ Subround(G, e1, a1, b1, c1, d1, X[ 6], 9, k1);
+ Subround(G, d1, e1, a1, b1, c1, X[15], 7, k1);
+ Subround(G, c1, d1, e1, a1, b1, X[ 3], 15, k1);
+ Subround(G, b1, c1, d1, e1, a1, X[12], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, X[ 0], 12, k1);
+ Subround(G, e1, a1, b1, c1, d1, X[ 9], 15, k1);
+ Subround(G, d1, e1, a1, b1, c1, X[ 5], 9, k1);
+ Subround(G, c1, d1, e1, a1, b1, X[ 2], 11, k1);
+ Subround(G, b1, c1, d1, e1, a1, X[14], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, X[11], 13, k1);
+ Subround(G, e1, a1, b1, c1, d1, X[ 8], 12, k1);
+
+ Subround(H, d1, e1, a1, b1, c1, X[ 3], 11, k2);
+ Subround(H, c1, d1, e1, a1, b1, X[10], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, X[14], 6, k2);
+ Subround(H, a1, b1, c1, d1, e1, X[ 4], 7, k2);
+ Subround(H, e1, a1, b1, c1, d1, X[ 9], 14, k2);
+ Subround(H, d1, e1, a1, b1, c1, X[15], 9, k2);
+ Subround(H, c1, d1, e1, a1, b1, X[ 8], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, X[ 1], 15, k2);
+ Subround(H, a1, b1, c1, d1, e1, X[ 2], 14, k2);
+ Subround(H, e1, a1, b1, c1, d1, X[ 7], 8, k2);
+ Subround(H, d1, e1, a1, b1, c1, X[ 0], 13, k2);
+ Subround(H, c1, d1, e1, a1, b1, X[ 6], 6, k2);
+ Subround(H, b1, c1, d1, e1, a1, X[13], 5, k2);
+ Subround(H, a1, b1, c1, d1, e1, X[11], 12, k2);
+ Subround(H, e1, a1, b1, c1, d1, X[ 5], 7, k2);
+ Subround(H, d1, e1, a1, b1, c1, X[12], 5, k2);
+
+ Subround(I, c1, d1, e1, a1, b1, X[ 1], 11, k3);
+ Subround(I, b1, c1, d1, e1, a1, X[ 9], 12, k3);
+ Subround(I, a1, b1, c1, d1, e1, X[11], 14, k3);
+ Subround(I, e1, a1, b1, c1, d1, X[10], 15, k3);
+ Subround(I, d1, e1, a1, b1, c1, X[ 0], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, X[ 8], 15, k3);
+ Subround(I, b1, c1, d1, e1, a1, X[12], 9, k3);
+ Subround(I, a1, b1, c1, d1, e1, X[ 4], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, X[13], 9, k3);
+ Subround(I, d1, e1, a1, b1, c1, X[ 3], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, X[ 7], 5, k3);
+ Subround(I, b1, c1, d1, e1, a1, X[15], 6, k3);
+ Subround(I, a1, b1, c1, d1, e1, X[14], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, X[ 5], 6, k3);
+ Subround(I, d1, e1, a1, b1, c1, X[ 6], 5, k3);
+ Subround(I, c1, d1, e1, a1, b1, X[ 2], 12, k3);
+
+ Subround(J, b1, c1, d1, e1, a1, X[ 4], 9, k4);
+ Subround(J, a1, b1, c1, d1, e1, X[ 0], 15, k4);
+ Subround(J, e1, a1, b1, c1, d1, X[ 5], 5, k4);
+ Subround(J, d1, e1, a1, b1, c1, X[ 9], 11, k4);
+ Subround(J, c1, d1, e1, a1, b1, X[ 7], 6, k4);
+ Subround(J, b1, c1, d1, e1, a1, X[12], 8, k4);
+ Subround(J, a1, b1, c1, d1, e1, X[ 2], 13, k4);
+ Subround(J, e1, a1, b1, c1, d1, X[10], 12, k4);
+ Subround(J, d1, e1, a1, b1, c1, X[14], 5, k4);
+ Subround(J, c1, d1, e1, a1, b1, X[ 1], 12, k4);
+ Subround(J, b1, c1, d1, e1, a1, X[ 3], 13, k4);
+ Subround(J, a1, b1, c1, d1, e1, X[ 8], 14, k4);
+ Subround(J, e1, a1, b1, c1, d1, X[11], 11, k4);
+ Subround(J, d1, e1, a1, b1, c1, X[ 6], 8, k4);
+ Subround(J, c1, d1, e1, a1, b1, X[15], 5, k4);
+ Subround(J, b1, c1, d1, e1, a1, X[13], 6, k4);
+
+ Subround(J, a2, b2, c2, d2, e2, X[ 5], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, X[14], 9, k5);
+ Subround(J, d2, e2, a2, b2, c2, X[ 7], 9, k5);
+ Subround(J, c2, d2, e2, a2, b2, X[ 0], 11, k5);
+ Subround(J, b2, c2, d2, e2, a2, X[ 9], 13, k5);
+ Subround(J, a2, b2, c2, d2, e2, X[ 2], 15, k5);
+ Subround(J, e2, a2, b2, c2, d2, X[11], 15, k5);
+ Subround(J, d2, e2, a2, b2, c2, X[ 4], 5, k5);
+ Subround(J, c2, d2, e2, a2, b2, X[13], 7, k5);
+ Subround(J, b2, c2, d2, e2, a2, X[ 6], 7, k5);
+ Subround(J, a2, b2, c2, d2, e2, X[15], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, X[ 8], 11, k5);
+ Subround(J, d2, e2, a2, b2, c2, X[ 1], 14, k5);
+ Subround(J, c2, d2, e2, a2, b2, X[10], 14, k5);
+ Subround(J, b2, c2, d2, e2, a2, X[ 3], 12, k5);
+ Subround(J, a2, b2, c2, d2, e2, X[12], 6, k5);
+
+ Subround(I, e2, a2, b2, c2, d2, X[ 6], 9, k6);
+ Subround(I, d2, e2, a2, b2, c2, X[11], 13, k6);
+ Subround(I, c2, d2, e2, a2, b2, X[ 3], 15, k6);
+ Subround(I, b2, c2, d2, e2, a2, X[ 7], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, X[ 0], 12, k6);
+ Subround(I, e2, a2, b2, c2, d2, X[13], 8, k6);
+ Subround(I, d2, e2, a2, b2, c2, X[ 5], 9, k6);
+ Subround(I, c2, d2, e2, a2, b2, X[10], 11, k6);
+ Subround(I, b2, c2, d2, e2, a2, X[14], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, X[15], 7, k6);
+ Subround(I, e2, a2, b2, c2, d2, X[ 8], 12, k6);
+ Subround(I, d2, e2, a2, b2, c2, X[12], 7, k6);
+ Subround(I, c2, d2, e2, a2, b2, X[ 4], 6, k6);
+ Subround(I, b2, c2, d2, e2, a2, X[ 9], 15, k6);
+ Subround(I, a2, b2, c2, d2, e2, X[ 1], 13, k6);
+ Subround(I, e2, a2, b2, c2, d2, X[ 2], 11, k6);
+
+ Subround(H, d2, e2, a2, b2, c2, X[15], 9, k7);
+ Subround(H, c2, d2, e2, a2, b2, X[ 5], 7, k7);
+ Subround(H, b2, c2, d2, e2, a2, X[ 1], 15, k7);
+ Subround(H, a2, b2, c2, d2, e2, X[ 3], 11, k7);
+ Subround(H, e2, a2, b2, c2, d2, X[ 7], 8, k7);
+ Subround(H, d2, e2, a2, b2, c2, X[14], 6, k7);
+ Subround(H, c2, d2, e2, a2, b2, X[ 6], 6, k7);
+ Subround(H, b2, c2, d2, e2, a2, X[ 9], 14, k7);
+ Subround(H, a2, b2, c2, d2, e2, X[11], 12, k7);
+ Subround(H, e2, a2, b2, c2, d2, X[ 8], 13, k7);
+ Subround(H, d2, e2, a2, b2, c2, X[12], 5, k7);
+ Subround(H, c2, d2, e2, a2, b2, X[ 2], 14, k7);
+ Subround(H, b2, c2, d2, e2, a2, X[10], 13, k7);
+ Subround(H, a2, b2, c2, d2, e2, X[ 0], 13, k7);
+ Subround(H, e2, a2, b2, c2, d2, X[ 4], 7, k7);
+ Subround(H, d2, e2, a2, b2, c2, X[13], 5, k7);
+
+ Subround(G, c2, d2, e2, a2, b2, X[ 8], 15, k8);
+ Subround(G, b2, c2, d2, e2, a2, X[ 6], 5, k8);
+ Subround(G, a2, b2, c2, d2, e2, X[ 4], 8, k8);
+ Subround(G, e2, a2, b2, c2, d2, X[ 1], 11, k8);
+ Subround(G, d2, e2, a2, b2, c2, X[ 3], 14, k8);
+ Subround(G, c2, d2, e2, a2, b2, X[11], 14, k8);
+ Subround(G, b2, c2, d2, e2, a2, X[15], 6, k8);
+ Subround(G, a2, b2, c2, d2, e2, X[ 0], 14, k8);
+ Subround(G, e2, a2, b2, c2, d2, X[ 5], 6, k8);
+ Subround(G, d2, e2, a2, b2, c2, X[12], 9, k8);
+ Subround(G, c2, d2, e2, a2, b2, X[ 2], 12, k8);
+ Subround(G, b2, c2, d2, e2, a2, X[13], 9, k8);
+ Subround(G, a2, b2, c2, d2, e2, X[ 9], 12, k8);
+ Subround(G, e2, a2, b2, c2, d2, X[ 7], 5, k8);
+ Subround(G, d2, e2, a2, b2, c2, X[10], 15, k8);
+ Subround(G, c2, d2, e2, a2, b2, X[14], 8, k8);
+
+ Subround(F, b2, c2, d2, e2, a2, X[12], 8, k9);
+ Subround(F, a2, b2, c2, d2, e2, X[15], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, X[10], 12, k9);
+ Subround(F, d2, e2, a2, b2, c2, X[ 4], 9, k9);
+ Subround(F, c2, d2, e2, a2, b2, X[ 1], 12, k9);
+ Subround(F, b2, c2, d2, e2, a2, X[ 5], 5, k9);
+ Subround(F, a2, b2, c2, d2, e2, X[ 8], 14, k9);
+ Subround(F, e2, a2, b2, c2, d2, X[ 7], 6, k9);
+ Subround(F, d2, e2, a2, b2, c2, X[ 6], 8, k9);
+ Subround(F, c2, d2, e2, a2, b2, X[ 2], 13, k9);
+ Subround(F, b2, c2, d2, e2, a2, X[13], 6, k9);
+ Subround(F, a2, b2, c2, d2, e2, X[14], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, X[ 0], 15, k9);
+ Subround(F, d2, e2, a2, b2, c2, X[ 3], 13, k9);
+ Subround(F, c2, d2, e2, a2, b2, X[ 9], 11, k9);
+ Subround(F, b2, c2, d2, e2, a2, X[11], 11, k9);
+
+ a1 -= trackA[0];
+ b1 -= trackA[1];
+ c1 -= trackA[2];
+ d1 -= trackA[3];
+ e1 -= trackA[4];
+ a2 -= trackB[0];
+ b2 -= trackB[1];
+ c2 -= trackB[2];
+ d2 -= trackB[3];
+ e2 -= trackB[4];
+
+ if (!last)
+ {
+ trackA[0] = (b1 + e1) - d2;
+ trackA[1] = c1 - e2;
+ trackA[2] = d1 - a2;
+ trackA[3] = e1 - b2;
+ trackA[4] = a1 - c2;
+ trackB[0] = d1 - e2;
+ trackB[1] = (e1 + c1) - a2;
+ trackB[2] = a1 - b2;
+ trackB[3] = b1 - c2;
+ trackB[4] = c1 - d2;
+ }
+ else
+ {
+ trackB[0] = a2 - a1;
+ trackB[1] = b2 - b1;
+ trackB[2] = c2 - c1;
+ trackB[3] = d2 - d1;
+ trackB[4] = e2 - e1;
+ trackA[0] = 0;
+ trackA[1] = 0;
+ trackA[2] = 0;
+ trackA[3] = 0;
+ trackA[4] = 0;
+ }
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/ttmac.h b/lib/cryptopp/ttmac.h
new file mode 100644
index 000000000..b4bf86e26
--- /dev/null
+++ b/lib/cryptopp/ttmac.h
@@ -0,0 +1,38 @@
+// ttmac.h - written and placed in the public domain by Kevin Springle
+
+#ifndef CRYPTOPP_TTMAC_H
+#define CRYPTOPP_TTMAC_H
+
+#include "seckey.h"
+#include "iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_NO_VTABLE TTMAC_Base : public FixedKeyLength<20>, public IteratedHash<word32, LittleEndian, 64, MessageAuthenticationCode>
+{
+public:
+ static std::string StaticAlgorithmName() {return std::string("Two-Track-MAC");}
+ CRYPTOPP_CONSTANT(DIGESTSIZE=20)
+
+ unsigned int DigestSize() const {return DIGESTSIZE;};
+ void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &params);
+ void TruncatedFinal(byte *mac, size_t size);
+
+protected:
+ static void Transform (word32 *digest, const word32 *X, bool last);
+ void HashEndianCorrectedBlock(const word32 *data) {Transform(m_digest, data, false);}
+ void Init();
+ word32* StateBuf() {return m_digest;}
+
+ FixedSizeSecBlock<word32, 10> m_digest;
+ FixedSizeSecBlock<word32, 5> m_key;
+};
+
+//! <a href="http://www.weidai.com/scan-mirror/mac.html#TTMAC">Two-Track-MAC</a>
+/*! 160 Bit MAC with 160 Bit Key */
+DOCUMENTED_TYPEDEF(MessageAuthenticationCodeFinal<TTMAC_Base>, TTMAC)
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/validate.h b/lib/cryptopp/validate.h
new file mode 100644
index 000000000..0ab23cba3
--- /dev/null
+++ b/lib/cryptopp/validate.h
@@ -0,0 +1,81 @@
+#ifndef CRYPTOPP_VALIDATE_H
+#define CRYPTOPP_VALIDATE_H
+
+#include "cryptlib.h"
+
+bool ValidateAll(bool thorough);
+bool TestSettings();
+bool TestOS_RNG();
+bool ValidateBaseCode();
+
+bool ValidateCRC32();
+bool ValidateAdler32();
+bool ValidateMD2();
+bool ValidateMD4();
+bool ValidateMD5();
+bool ValidateSHA();
+bool ValidateSHA2();
+bool ValidateTiger();
+bool ValidateRIPEMD();
+bool ValidatePanama();
+bool ValidateWhirlpool();
+
+bool ValidateHMAC();
+bool ValidateTTMAC();
+
+bool ValidateCipherModes();
+bool ValidatePBKDF();
+
+bool ValidateDES();
+bool ValidateIDEA();
+bool ValidateSAFER();
+bool ValidateRC2();
+bool ValidateARC4();
+
+bool ValidateRC5();
+bool ValidateBlowfish();
+bool ValidateThreeWay();
+bool ValidateGOST();
+bool ValidateSHARK();
+bool ValidateSEAL();
+bool ValidateCAST();
+bool ValidateSquare();
+bool ValidateSKIPJACK();
+bool ValidateRC6();
+bool ValidateMARS();
+bool ValidateRijndael();
+bool ValidateTwofish();
+bool ValidateSerpent();
+bool ValidateSHACAL2();
+bool ValidateCamellia();
+bool ValidateSalsa();
+bool ValidateSosemanuk();
+bool ValidateVMAC();
+bool ValidateCCM();
+bool ValidateGCM();
+bool ValidateCMAC();
+
+bool ValidateBBS();
+bool ValidateDH();
+bool ValidateMQV();
+bool ValidateRSA();
+bool ValidateElGamal();
+bool ValidateDLIES();
+bool ValidateNR();
+bool ValidateDSA(bool thorough);
+bool ValidateLUC();
+bool ValidateLUC_DL();
+bool ValidateLUC_DH();
+bool ValidateXTR_DH();
+bool ValidateRabin();
+bool ValidateRW();
+//bool ValidateBlumGoldwasser();
+bool ValidateECP();
+bool ValidateEC2N();
+bool ValidateECDSA();
+bool ValidateESIGN();
+
+CryptoPP::RandomNumberGenerator & GlobalRNG();
+bool RunTestDataFile(const char *filename, const CryptoPP::NameValuePairs &overrideParameters=CryptoPP::g_nullNameValuePairs, bool thorough=true);
+
+#endif
diff --git a/lib/cryptopp/vmac.cpp b/lib/cryptopp/vmac.cpp
new file mode 100644
index 000000000..6b490f904
--- /dev/null
+++ b/lib/cryptopp/vmac.cpp
@@ -0,0 +1,832 @@
+// vmac.cpp - written and placed in the public domain by Wei Dai
+// based on Ted Krovetz's public domain vmac.c and draft-krovetz-vmac-01.txt
+
+#include "pch.h"
+#include "vmac.h"
+#include "argnames.h"
+#include "cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64
+#include <intrin.h>
+#endif
+
+#define VMAC_BOOL_WORD128 (defined(CRYPTOPP_WORD128_AVAILABLE) && !defined(CRYPTOPP_X64_ASM_AVAILABLE))
+#ifdef __BORLANDC__
+#define const // Turbo C++ 2006 workaround
+#endif
+static const word64 p64 = W64LIT(0xfffffffffffffeff); /* 2^64 - 257 prime */
+static const word64 m62 = W64LIT(0x3fffffffffffffff); /* 62-bit mask */
+static const word64 m63 = W64LIT(0x7fffffffffffffff); /* 63-bit mask */
+static const word64 m64 = W64LIT(0xffffffffffffffff); /* 64-bit mask */
+static const word64 mpoly = W64LIT(0x1fffffff1fffffff); /* Poly key mask */
+#ifdef __BORLANDC__
+#undef const
+#endif
+#if VMAC_BOOL_WORD128
+#ifdef __powerpc__
+// workaround GCC Bug 31690: ICE with const __uint128_t and C++ front-end
+#define m126 ((word128(m62)<<64)|m64)
+#else
+static const word128 m126 = (word128(m62)<<64)|m64; /* 126-bit mask */
+#endif
+#endif
+
+void VMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &params)
+{
+ int digestLength = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
+ if (digestLength != 8 && digestLength != 16)
+ throw InvalidArgument("VMAC: DigestSize must be 8 or 16");
+ m_is128 = digestLength == 16;
+
+ m_L1KeyLength = params.GetIntValueWithDefault(Name::L1KeyLength(), 128);
+ if (m_L1KeyLength <= 0 || m_L1KeyLength % 128 != 0)
+ throw InvalidArgument("VMAC: L1KeyLength must be a positive multiple of 128");
+
+ AllocateBlocks();
+
+ BlockCipher &cipher = AccessCipher();
+ cipher.SetKey(userKey, keylength, params);
+ unsigned int blockSize = cipher.BlockSize();
+ unsigned int blockSizeInWords = blockSize / sizeof(word64);
+ SecBlock<word64> out(blockSizeInWords);
+ SecByteBlock in;
+ in.CleanNew(blockSize);
+ size_t i;
+
+ /* Fill nh key */
+ in[0] = 0x80;
+ cipher.AdvancedProcessBlocks(in, NULL, (byte *)m_nhKey(), m_nhKeySize()*sizeof(word64), cipher.BT_InBlockIsCounter);
+ ConditionalByteReverse<word64>(BIG_ENDIAN_ORDER, m_nhKey(), m_nhKey(), m_nhKeySize()*sizeof(word64));
+
+ /* Fill poly key */
+ in[0] = 0xC0;
+ in[15] = 0;
+ for (i = 0; i <= (size_t)m_is128; i++)
+ {
+ cipher.ProcessBlock(in, out.BytePtr());
+ m_polyState()[i*4+2] = GetWord<word64>(true, BIG_ENDIAN_ORDER, out.BytePtr()) & mpoly;
+ m_polyState()[i*4+3] = GetWord<word64>(true, BIG_ENDIAN_ORDER, out.BytePtr()+8) & mpoly;
+ in[15]++;
+ }
+
+ /* Fill ip key */
+ in[0] = 0xE0;
+ in[15] = 0;
+ word64 *l3Key = m_l3Key();
+ for (i = 0; i <= (size_t)m_is128; i++)
+ do
+ {
+ cipher.ProcessBlock(in, out.BytePtr());
+ l3Key[i*2+0] = GetWord<word64>(true, BIG_ENDIAN_ORDER, out.BytePtr());
+ l3Key[i*2+1] = GetWord<word64>(true, BIG_ENDIAN_ORDER, out.BytePtr()+8);
+ in[15]++;
+ } while ((l3Key[i*2+0] >= p64) || (l3Key[i*2+1] >= p64));
+
+ m_padCached = false;
+ size_t nonceLength;
+ const byte *nonce = GetIVAndThrowIfInvalid(params, nonceLength);
+ Resynchronize(nonce, (int)nonceLength);
+}
+
+void VMAC_Base::GetNextIV(RandomNumberGenerator &rng, byte *IV)
+{
+ SimpleKeyingInterface::GetNextIV(rng, IV);
+ IV[0] &= 0x7f;
+}
+
+void VMAC_Base::Resynchronize(const byte *nonce, int len)
+{
+ size_t length = ThrowIfInvalidIVLength(len);
+ size_t s = IVSize();
+ byte *storedNonce = m_nonce();
+
+ if (m_is128)
+ {
+ memset(storedNonce, 0, s-length);
+ memcpy(storedNonce+s-length, nonce, length);
+ AccessCipher().ProcessBlock(storedNonce, m_pad());
+ }
+ else
+ {
+ if (m_padCached && (storedNonce[s-1] | 1) == (nonce[length-1] | 1))
+ {
+ m_padCached = VerifyBufsEqual(storedNonce+s-length, nonce, length-1);
+ for (size_t i=0; m_padCached && i<s-length; i++)
+ m_padCached = (storedNonce[i] == 0);
+ }
+ if (!m_padCached)
+ {
+ memset(storedNonce, 0, s-length);
+ memcpy(storedNonce+s-length, nonce, length-1);
+ storedNonce[s-1] = nonce[length-1] & 0xfe;
+ AccessCipher().ProcessBlock(storedNonce, m_pad());
+ m_padCached = true;
+ }
+ storedNonce[s-1] = nonce[length-1];
+ }
+ m_isFirstBlock = true;
+ Restart();
+}
+
+void VMAC_Base::HashEndianCorrectedBlock(const word64 *data)
+{
+ assert(false);
+ throw 0;
+}
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
+void
+#ifdef __GNUC__
+__attribute__ ((noinline)) // Intel Compiler 9.1 workaround
+#endif
+VMAC_Base::VHASH_Update_SSE2(const word64 *data, size_t blocksRemainingInWord64, int tagPart)
+{
+ const word64 *nhK = m_nhKey();
+ word64 *polyS = m_polyState();
+ word32 L1KeyLength = m_L1KeyLength;
+
+#ifdef __GNUC__
+ word32 temp;
+ __asm__ __volatile__
+ (
+ AS2( mov %%ebx, %0)
+ AS2( mov %1, %%ebx)
+ ".intel_syntax noprefix;"
+#else
+ #if _MSC_VER < 1300 || defined(__INTEL_COMPILER)
+ char isFirstBlock = m_isFirstBlock;
+ AS2( mov ebx, [L1KeyLength])
+ AS2( mov dl, [isFirstBlock])
+ #else
+ AS2( mov ecx, this)
+ AS2( mov ebx, [ecx+m_L1KeyLength])
+ AS2( mov dl, [ecx+m_isFirstBlock])
+ #endif
+ AS2( mov eax, tagPart)
+ AS2( shl eax, 4)
+ AS2( mov edi, nhK)
+ AS2( add edi, eax)
+ AS2( add eax, eax)
+ AS2( add eax, polyS)
+
+ AS2( mov esi, data)
+ AS2( mov ecx, blocksRemainingInWord64)
+#endif
+
+ AS2( shr ebx, 3)
+ AS1( push ebp)
+ AS2( sub esp, 12)
+ ASL(4)
+ AS2( mov ebp, ebx)
+ AS2( cmp ecx, ebx)
+ AS2( cmovl ebp, ecx)
+ AS2( sub ecx, ebp)
+ AS2( lea ebp, [edi+8*ebp]) // end of nhK
+ AS2( movq mm6, [esi])
+ AS2( paddq mm6, [edi])
+ AS2( movq mm5, [esi+8])
+ AS2( paddq mm5, [edi+8])
+ AS2( add esi, 16)
+ AS2( add edi, 16)
+ AS2( movq mm4, mm6)
+ ASS( pshufw mm2, mm6, 1, 0, 3, 2)
+ AS2( pmuludq mm6, mm5)
+ ASS( pshufw mm3, mm5, 1, 0, 3, 2)
+ AS2( pmuludq mm5, mm2)
+ AS2( pmuludq mm2, mm3)
+ AS2( pmuludq mm3, mm4)
+ AS2( pxor mm7, mm7)
+ AS2( movd [esp], mm6)
+ AS2( psrlq mm6, 32)
+ AS2( movd [esp+4], mm5)
+ AS2( psrlq mm5, 32)
+ AS2( cmp edi, ebp)
+ ASJ( je, 1, f)
+ ASL(0)
+ AS2( movq mm0, [esi])
+ AS2( paddq mm0, [edi])
+ AS2( movq mm1, [esi+8])
+ AS2( paddq mm1, [edi+8])
+ AS2( add esi, 16)
+ AS2( add edi, 16)
+ AS2( movq mm4, mm0)
+ AS2( paddq mm5, mm2)
+ ASS( pshufw mm2, mm0, 1, 0, 3, 2)
+ AS2( pmuludq mm0, mm1)
+ AS2( movd [esp+8], mm3)
+ AS2( psrlq mm3, 32)
+ AS2( paddq mm5, mm3)
+ ASS( pshufw mm3, mm1, 1, 0, 3, 2)
+ AS2( pmuludq mm1, mm2)
+ AS2( pmuludq mm2, mm3)
+ AS2( pmuludq mm3, mm4)
+ AS2( movd mm4, [esp])
+ AS2( paddq mm7, mm4)
+ AS2( movd mm4, [esp+4])
+ AS2( paddq mm6, mm4)
+ AS2( movd mm4, [esp+8])
+ AS2( paddq mm6, mm4)
+ AS2( movd [esp], mm0)
+ AS2( psrlq mm0, 32)
+ AS2( paddq mm6, mm0)
+ AS2( movd [esp+4], mm1)
+ AS2( psrlq mm1, 32)
+ AS2( paddq mm5, mm1)
+ AS2( cmp edi, ebp)
+ ASJ( jne, 0, b)
+ ASL(1)
+ AS2( paddq mm5, mm2)
+ AS2( movd [esp+8], mm3)
+ AS2( psrlq mm3, 32)
+ AS2( paddq mm5, mm3)
+ AS2( movd mm4, [esp])
+ AS2( paddq mm7, mm4)
+ AS2( movd mm4, [esp+4])
+ AS2( paddq mm6, mm4)
+ AS2( movd mm4, [esp+8])
+ AS2( paddq mm6, mm4)
+ AS2( lea ebp, [8*ebx])
+ AS2( sub edi, ebp) // reset edi to start of nhK
+
+ AS2( movd [esp], mm7)
+ AS2( psrlq mm7, 32)
+ AS2( paddq mm6, mm7)
+ AS2( movd [esp+4], mm6)
+ AS2( psrlq mm6, 32)
+ AS2( paddq mm5, mm6)
+ AS2( psllq mm5, 2)
+ AS2( psrlq mm5, 2)
+
+#define a0 [eax+2*4]
+#define a1 [eax+3*4]
+#define a2 [eax+0*4]
+#define a3 [eax+1*4]
+#define k0 [eax+2*8+2*4]
+#define k1 [eax+2*8+3*4]
+#define k2 [eax+2*8+0*4]
+#define k3 [eax+2*8+1*4]
+ AS2( test dl, dl)
+ ASJ( jz, 2, f)
+ AS2( movd mm1, k0)
+ AS2( movd mm0, [esp])
+ AS2( paddq mm0, mm1)
+ AS2( movd a0, mm0)
+ AS2( psrlq mm0, 32)
+ AS2( movd mm1, k1)
+ AS2( movd mm2, [esp+4])
+ AS2( paddq mm1, mm2)
+ AS2( paddq mm0, mm1)
+ AS2( movd a1, mm0)
+ AS2( psrlq mm0, 32)
+ AS2( paddq mm5, k2)
+ AS2( paddq mm0, mm5)
+ AS2( movq a2, mm0)
+ AS2( xor edx, edx)
+ ASJ( jmp, 3, f)
+ ASL(2)
+ AS2( movd mm0, a3)
+ AS2( movq mm4, mm0)
+ AS2( pmuludq mm0, k3) // a3*k3
+ AS2( movd mm1, a0)
+ AS2( pmuludq mm1, k2) // a0*k2
+ AS2( movd mm2, a1)
+ AS2( movd mm6, k1)
+ AS2( pmuludq mm2, mm6) // a1*k1
+ AS2( movd mm3, a2)
+ AS2( psllq mm0, 1)
+ AS2( paddq mm0, mm5)
+ AS2( movq mm5, mm3)
+ AS2( movd mm7, k0)
+ AS2( pmuludq mm3, mm7) // a2*k0
+ AS2( pmuludq mm4, mm7) // a3*k0
+ AS2( pmuludq mm5, mm6) // a2*k1
+ AS2( paddq mm0, mm1)
+ AS2( movd mm1, a1)
+ AS2( paddq mm4, mm5)
+ AS2( movq mm5, mm1)
+ AS2( pmuludq mm1, k2) // a1*k2
+ AS2( paddq mm0, mm2)
+ AS2( movd mm2, a0)
+ AS2( paddq mm0, mm3)
+ AS2( movq mm3, mm2)
+ AS2( pmuludq mm2, k3) // a0*k3
+ AS2( pmuludq mm3, mm7) // a0*k0
+ AS2( movd [esp+8], mm0)
+ AS2( psrlq mm0, 32)
+ AS2( pmuludq mm7, mm5) // a1*k0
+ AS2( pmuludq mm5, k3) // a1*k3
+ AS2( paddq mm0, mm1)
+ AS2( movd mm1, a2)
+ AS2( pmuludq mm1, k2) // a2*k2
+ AS2( paddq mm0, mm2)
+ AS2( paddq mm0, mm4)
+ AS2( movq mm4, mm0)
+ AS2( movd mm2, a3)
+ AS2( pmuludq mm2, mm6) // a3*k1
+ AS2( pmuludq mm6, a0) // a0*k1
+ AS2( psrlq mm0, 31)
+ AS2( paddq mm0, mm3)
+ AS2( movd mm3, [esp])
+ AS2( paddq mm0, mm3)
+ AS2( movd mm3, a2)
+ AS2( pmuludq mm3, k3) // a2*k3
+ AS2( paddq mm5, mm1)
+ AS2( movd mm1, a3)
+ AS2( pmuludq mm1, k2) // a3*k2
+ AS2( paddq mm5, mm2)
+ AS2( movd mm2, [esp+4])
+ AS2( psllq mm5, 1)
+ AS2( paddq mm0, mm5)
+ AS2( psllq mm4, 33)
+ AS2( movd a0, mm0)
+ AS2( psrlq mm0, 32)
+ AS2( paddq mm6, mm7)
+ AS2( movd mm7, [esp+8])
+ AS2( paddq mm0, mm6)
+ AS2( paddq mm0, mm2)
+ AS2( paddq mm3, mm1)
+ AS2( psllq mm3, 1)
+ AS2( paddq mm0, mm3)
+ AS2( psrlq mm4, 1)
+ AS2( movd a1, mm0)
+ AS2( psrlq mm0, 32)
+ AS2( por mm4, mm7)
+ AS2( paddq mm0, mm4)
+ AS2( movq a2, mm0)
+#undef a0
+#undef a1
+#undef a2
+#undef a3
+#undef k0
+#undef k1
+#undef k2
+#undef k3
+
+ ASL(3)
+ AS2( test ecx, ecx)
+ ASJ( jnz, 4, b)
+
+ AS2( add esp, 12)
+ AS1( pop ebp)
+ AS1( emms)
+#ifdef __GNUC__
+ ".att_syntax prefix;"
+ AS2( mov %0, %%ebx)
+ : "=m" (temp)
+ : "m" (L1KeyLength), "c" (blocksRemainingInWord64), "S" (data), "D" (nhK+tagPart*2), "d" (m_isFirstBlock), "a" (polyS+tagPart*4)
+ : "memory", "cc"
+ );
+#endif
+}
+#endif
+
+#if VMAC_BOOL_WORD128
+ #define DeclareNH(a) word128 a=0
+ #define MUL64(rh,rl,i1,i2) {word128 p = word128(i1)*(i2); rh = word64(p>>64); rl = word64(p);}
+ #define AccumulateNH(a, b, c) a += word128(b)*(c)
+ #define Multiply128(r, i1, i2) r = word128(word64(i1)) * word64(i2)
+#else
+ #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER)
+ #define MUL32(a, b) __emulu(word32(a), word32(b))
+ #else
+ #define MUL32(a, b) ((word64)((word32)(a)) * (word32)(b))
+ #endif
+ #if defined(CRYPTOPP_X64_ASM_AVAILABLE)
+ #define DeclareNH(a) word64 a##0=0, a##1=0
+ #define MUL64(rh,rl,i1,i2) asm ("mulq %3" : "=a"(rl), "=d"(rh) : "a"(i1), "g"(i2) : "cc");
+ #define AccumulateNH(a, b, c) asm ("mulq %3; addq %%rax, %0; adcq %%rdx, %1" : "+r"(a##0), "+r"(a##1) : "a"(b), "g"(c) : "%rdx", "cc");
+ #define ADD128(rh,rl,ih,il) asm ("addq %3, %1; adcq %2, %0" : "+r"(rh),"+r"(rl) : "r"(ih),"r"(il) : "cc");
+ #elif defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64
+ #define DeclareNH(a) word64 a##0=0, a##1=0
+ #define MUL64(rh,rl,i1,i2) (rl) = _umul128(i1,i2,&(rh));
+ #define AccumulateNH(a, b, c) {\
+ word64 ph, pl;\
+ pl = _umul128(b,c,&ph);\
+ a##0 += pl;\
+ a##1 += ph + (a##0 < pl);}
+ #else
+ #define VMAC_BOOL_32BIT 1
+ #define DeclareNH(a) word64 a##0=0, a##1=0, a##2=0
+ #define MUL64(rh,rl,i1,i2) \
+ { word64 _i1 = (i1), _i2 = (i2); \
+ word64 m1= MUL32(_i1,_i2>>32); \
+ word64 m2= MUL32(_i1>>32,_i2); \
+ rh = MUL32(_i1>>32,_i2>>32); \
+ rl = MUL32(_i1,_i2); \
+ ADD128(rh,rl,(m1 >> 32),(m1 << 32)); \
+ ADD128(rh,rl,(m2 >> 32),(m2 << 32)); \
+ }
+ #define AccumulateNH(a, b, c) {\
+ word64 p = MUL32(b, c);\
+ a##1 += word32((p)>>32);\
+ a##0 += word32(p);\
+ p = MUL32((b)>>32, c);\
+ a##2 += word32((p)>>32);\
+ a##1 += word32(p);\
+ p = MUL32((b)>>32, (c)>>32);\
+ a##2 += p;\
+ p = MUL32(b, (c)>>32);\
+ a##1 += word32(p);\
+ a##2 += word32(p>>32);}
+ #endif
+#endif
+#ifndef VMAC_BOOL_32BIT
+ #define VMAC_BOOL_32BIT 0
+#endif
+#ifndef ADD128
+ #define ADD128(rh,rl,ih,il) \
+ { word64 _il = (il); \
+ (rl) += (_il); \
+ (rh) += (ih) + ((rl) < (_il)); \
+ }
+#endif
+
+#if !(defined(_MSC_VER) && _MSC_VER < 1300)
+template <bool T_128BitTag>
+#endif
+void VMAC_Base::VHASH_Update_Template(const word64 *data, size_t blocksRemainingInWord64)
+{
+ #define INNER_LOOP_ITERATION(j) {\
+ word64 d0 = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, data[i+2*j+0]);\
+ word64 d1 = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, data[i+2*j+1]);\
+ AccumulateNH(nhA, d0+nhK[i+2*j+0], d1+nhK[i+2*j+1]);\
+ if (T_128BitTag)\
+ AccumulateNH(nhB, d0+nhK[i+2*j+2], d1+nhK[i+2*j+3]);\
+ }
+
+#if (defined(_MSC_VER) && _MSC_VER < 1300)
+ bool T_128BitTag = m_is128;
+#endif
+ size_t L1KeyLengthInWord64 = m_L1KeyLength / 8;
+ size_t innerLoopEnd = L1KeyLengthInWord64;
+ const word64 *nhK = m_nhKey();
+ word64 *polyS = m_polyState();
+ bool isFirstBlock = true;
+ size_t i;
+
+ #if !VMAC_BOOL_32BIT
+ #if VMAC_BOOL_WORD128
+ word128 a1, a2;
+ #else
+ word64 ah1, al1, ah2, al2;
+ #endif
+ word64 kh1, kl1, kh2, kl2;
+ kh1=(polyS+0*4+2)[0]; kl1=(polyS+0*4+2)[1];
+ if (T_128BitTag)
+ {
+ kh2=(polyS+1*4+2)[0]; kl2=(polyS+1*4+2)[1];
+ }
+ #endif
+
+ do
+ {
+ DeclareNH(nhA);
+ DeclareNH(nhB);
+
+ i = 0;
+ if (blocksRemainingInWord64 < L1KeyLengthInWord64)
+ {
+ if (blocksRemainingInWord64 % 8)
+ {
+ innerLoopEnd = blocksRemainingInWord64 % 8;
+ for (; i<innerLoopEnd; i+=2)
+ INNER_LOOP_ITERATION(0);
+ }
+ innerLoopEnd = blocksRemainingInWord64;
+ }
+ for (; i<innerLoopEnd; i+=8)
+ {
+ INNER_LOOP_ITERATION(0);
+ INNER_LOOP_ITERATION(1);
+ INNER_LOOP_ITERATION(2);
+ INNER_LOOP_ITERATION(3);
+ }
+ blocksRemainingInWord64 -= innerLoopEnd;
+ data += innerLoopEnd;
+
+ #if VMAC_BOOL_32BIT
+ word32 nh0[2], nh1[2];
+ word64 nh2[2];
+
+ nh0[0] = word32(nhA0);
+ nhA1 += (nhA0 >> 32);
+ nh1[0] = word32(nhA1);
+ nh2[0] = (nhA2 + (nhA1 >> 32)) & m62;
+
+ if (T_128BitTag)
+ {
+ nh0[1] = word32(nhB0);
+ nhB1 += (nhB0 >> 32);
+ nh1[1] = word32(nhB1);
+ nh2[1] = (nhB2 + (nhB1 >> 32)) & m62;
+ }
+
+ #define a0 (((word32 *)(polyS+i*4))[2+NativeByteOrder::ToEnum()])
+ #define a1 (*(((word32 *)(polyS+i*4))+3-NativeByteOrder::ToEnum())) // workaround for GCC 3.2
+ #define a2 (((word32 *)(polyS+i*4))[0+NativeByteOrder::ToEnum()])
+ #define a3 (*(((word32 *)(polyS+i*4))+1-NativeByteOrder::ToEnum()))
+ #define aHi ((polyS+i*4)[0])
+ #define k0 (((word32 *)(polyS+i*4+2))[2+NativeByteOrder::ToEnum()])
+ #define k1 (*(((word32 *)(polyS+i*4+2))+3-NativeByteOrder::ToEnum()))
+ #define k2 (((word32 *)(polyS+i*4+2))[0+NativeByteOrder::ToEnum()])
+ #define k3 (*(((word32 *)(polyS+i*4+2))+1-NativeByteOrder::ToEnum()))
+ #define kHi ((polyS+i*4+2)[0])
+
+ if (isFirstBlock)
+ {
+ isFirstBlock = false;
+ if (m_isFirstBlock)
+ {
+ m_isFirstBlock = false;
+ for (i=0; i<=(size_t)T_128BitTag; i++)
+ {
+ word64 t = (word64)nh0[i] + k0;
+ a0 = (word32)t;
+ t = (t >> 32) + nh1[i] + k1;
+ a1 = (word32)t;
+ aHi = (t >> 32) + nh2[i] + kHi;
+ }
+ continue;
+ }
+ }
+ for (i=0; i<=(size_t)T_128BitTag; i++)
+ {
+ word64 p, t;
+ word32 t2;
+
+ p = MUL32(a3, 2*k3);
+ p += nh2[i];
+ p += MUL32(a0, k2);
+ p += MUL32(a1, k1);
+ p += MUL32(a2, k0);
+ t2 = (word32)p;
+ p >>= 32;
+ p += MUL32(a0, k3);
+ p += MUL32(a1, k2);
+ p += MUL32(a2, k1);
+ p += MUL32(a3, k0);
+ t = (word64(word32(p) & 0x7fffffff) << 32) | t2;
+ p >>= 31;
+ p += nh0[i];
+ p += MUL32(a0, k0);
+ p += MUL32(a1, 2*k3);
+ p += MUL32(a2, 2*k2);
+ p += MUL32(a3, 2*k1);
+ t2 = (word32)p;
+ p >>= 32;
+ p += nh1[i];
+ p += MUL32(a0, k1);
+ p += MUL32(a1, k0);
+ p += MUL32(a2, 2*k3);
+ p += MUL32(a3, 2*k2);
+ a0 = t2;
+ a1 = (word32)p;
+ aHi = (p >> 32) + t;
+ }
+
+ #undef a0
+ #undef a1
+ #undef a2
+ #undef a3
+ #undef aHi
+ #undef k0
+ #undef k1
+ #undef k2
+ #undef k3
+ #undef kHi
+ #else // #if VMAC_BOOL_32BIT
+ if (isFirstBlock)
+ {
+ isFirstBlock = false;
+ if (m_isFirstBlock)
+ {
+ m_isFirstBlock = false;
+ #if VMAC_BOOL_WORD128
+ #define first_poly_step(a, kh, kl, m) a = (m & m126) + ((word128(kh) << 64) | kl)
+
+ first_poly_step(a1, kh1, kl1, nhA);
+ if (T_128BitTag)
+ first_poly_step(a2, kh2, kl2, nhB);
+ #else
+ #define first_poly_step(ah, al, kh, kl, mh, ml) {\
+ mh &= m62;\
+ ADD128(mh, ml, kh, kl); \
+ ah = mh; al = ml;}
+
+ first_poly_step(ah1, al1, kh1, kl1, nhA1, nhA0);
+ if (T_128BitTag)
+ first_poly_step(ah2, al2, kh2, kl2, nhB1, nhB0);
+ #endif
+ continue;
+ }
+ else
+ {
+ #if VMAC_BOOL_WORD128
+ a1 = (word128((polyS+0*4)[0]) << 64) | (polyS+0*4)[1];
+ #else
+ ah1=(polyS+0*4)[0]; al1=(polyS+0*4)[1];
+ #endif
+ if (T_128BitTag)
+ {
+ #if VMAC_BOOL_WORD128
+ a2 = (word128((polyS+1*4)[0]) << 64) | (polyS+1*4)[1];
+ #else
+ ah2=(polyS+1*4)[0]; al2=(polyS+1*4)[1];
+ #endif
+ }
+ }
+ }
+
+ #if VMAC_BOOL_WORD128
+ #define poly_step(a, kh, kl, m) \
+ { word128 t1, t2, t3, t4;\
+ Multiply128(t2, a>>64, kl);\
+ Multiply128(t3, a, kh);\
+ Multiply128(t1, a, kl);\
+ Multiply128(t4, a>>64, 2*kh);\
+ t2 += t3;\
+ t4 += t1;\
+ t2 += t4>>64;\
+ a = (word128(word64(t2)&m63) << 64) | word64(t4);\
+ t2 *= 2;\
+ a += m & m126;\
+ a += t2>>64;}
+
+ poly_step(a1, kh1, kl1, nhA);
+ if (T_128BitTag)
+ poly_step(a2, kh2, kl2, nhB);
+ #else
+ #define poly_step(ah, al, kh, kl, mh, ml) \
+ { word64 t1h, t1l, t2h, t2l, t3h, t3l, z=0; \
+ /* compute ab*cd, put bd into result registers */ \
+ MUL64(t2h,t2l,ah,kl); \
+ MUL64(t3h,t3l,al,kh); \
+ MUL64(t1h,t1l,ah,2*kh); \
+ MUL64(ah,al,al,kl); \
+ /* add together ad + bc */ \
+ ADD128(t2h,t2l,t3h,t3l); \
+ /* add 2 * ac to result */ \
+ ADD128(ah,al,t1h,t1l); \
+ /* now (ah,al), (t2l,2*t2h) need summing */ \
+ /* first add the high registers, carrying into t2h */ \
+ ADD128(t2h,ah,z,t2l); \
+ /* double t2h and add top bit of ah */ \
+ t2h += t2h + (ah >> 63); \
+ ah &= m63; \
+ /* now add the low registers */ \
+ mh &= m62; \
+ ADD128(ah,al,mh,ml); \
+ ADD128(ah,al,z,t2h); \
+ }
+
+ poly_step(ah1, al1, kh1, kl1, nhA1, nhA0);
+ if (T_128BitTag)
+ poly_step(ah2, al2, kh2, kl2, nhB1, nhB0);
+ #endif
+ #endif // #if VMAC_BOOL_32BIT
+ } while (blocksRemainingInWord64);
+
+ #if VMAC_BOOL_WORD128
+ (polyS+0*4)[0]=word64(a1>>64); (polyS+0*4)[1]=word64(a1);
+ if (T_128BitTag)
+ {
+ (polyS+1*4)[0]=word64(a2>>64); (polyS+1*4)[1]=word64(a2);
+ }
+ #elif !VMAC_BOOL_32BIT
+ (polyS+0*4)[0]=ah1; (polyS+0*4)[1]=al1;
+ if (T_128BitTag)
+ {
+ (polyS+1*4)[0]=ah2; (polyS+1*4)[1]=al2;
+ }
+ #endif
+}
+
+inline void VMAC_Base::VHASH_Update(const word64 *data, size_t blocksRemainingInWord64)
+{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+ if (HasSSE2())
+ {
+ VHASH_Update_SSE2(data, blocksRemainingInWord64, 0);
+ if (m_is128)
+ VHASH_Update_SSE2(data, blocksRemainingInWord64, 1);
+ m_isFirstBlock = false;
+ }
+ else
+#endif
+ {
+#if defined(_MSC_VER) && _MSC_VER < 1300
+ VHASH_Update_Template(data, blocksRemainingInWord64);
+#else
+ if (m_is128)
+ VHASH_Update_Template<true>(data, blocksRemainingInWord64);
+ else
+ VHASH_Update_Template<false>(data, blocksRemainingInWord64);
+#endif
+ }
+}
+
+size_t VMAC_Base::HashMultipleBlocks(const word64 *data, size_t length)
+{
+ size_t remaining = ModPowerOf2(length, m_L1KeyLength);
+ VHASH_Update(data, (length-remaining)/8);
+ return remaining;
+}
+
+static word64 L3Hash(const word64 *input, const word64 *l3Key, size_t len)
+{
+ word64 rh, rl, t, z=0;
+ word64 p1 = input[0], p2 = input[1];
+ word64 k1 = l3Key[0], k2 = l3Key[1];
+
+ /* fully reduce (p1,p2)+(len,0) mod p127 */
+ t = p1 >> 63;
+ p1 &= m63;
+ ADD128(p1, p2, len, t);
+ /* At this point, (p1,p2) is at most 2^127+(len<<64) */
+ t = (p1 > m63) + ((p1 == m63) & (p2 == m64));
+ ADD128(p1, p2, z, t);
+ p1 &= m63;
+
+ /* compute (p1,p2)/(2^64-2^32) and (p1,p2)%(2^64-2^32) */
+ t = p1 + (p2 >> 32);
+ t += (t >> 32);
+ t += (word32)t > 0xfffffffeU;
+ p1 += (t >> 32);
+ p2 += (p1 << 32);
+
+ /* compute (p1+k1)%p64 and (p2+k2)%p64 */
+ p1 += k1;
+ p1 += (0 - (p1 < k1)) & 257;
+ p2 += k2;
+ p2 += (0 - (p2 < k2)) & 257;
+
+ /* compute (p1+k1)*(p2+k2)%p64 */
+ MUL64(rh, rl, p1, p2);
+ t = rh >> 56;
+ ADD128(t, rl, z, rh);
+ rh <<= 8;
+ ADD128(t, rl, z, rh);
+ t += t << 8;
+ rl += t;
+ rl += (0 - (rl < t)) & 257;
+ rl += (0 - (rl > p64-1)) & 257;
+ return rl;
+}
+
+void VMAC_Base::TruncatedFinal(byte *mac, size_t size)
+{
+ size_t len = ModPowerOf2(GetBitCountLo()/8, m_L1KeyLength);
+
+ if (len)
+ {
+ memset(m_data()+len, 0, (0-len)%16);
+ VHASH_Update(DataBuf(), ((len+15)/16)*2);
+ len *= 8; // convert to bits
+ }
+ else if (m_isFirstBlock)
+ {
+ // special case for empty string
+ m_polyState()[0] = m_polyState()[2];
+ m_polyState()[1] = m_polyState()[3];
+ if (m_is128)
+ {
+ m_polyState()[4] = m_polyState()[6];
+ m_polyState()[5] = m_polyState()[7];
+ }
+ }
+
+ if (m_is128)
+ {
+ word64 t[2];
+ t[0] = L3Hash(m_polyState(), m_l3Key(), len) + GetWord<word64>(true, BIG_ENDIAN_ORDER, m_pad());
+ t[1] = L3Hash(m_polyState()+4, m_l3Key()+2, len) + GetWord<word64>(true, BIG_ENDIAN_ORDER, m_pad()+8);
+ if (size == 16)
+ {
+ PutWord(false, BIG_ENDIAN_ORDER, mac, t[0]);
+ PutWord(false, BIG_ENDIAN_ORDER, mac+8, t[1]);
+ }
+ else
+ {
+ t[0] = ConditionalByteReverse(BIG_ENDIAN_ORDER, t[0]);
+ t[1] = ConditionalByteReverse(BIG_ENDIAN_ORDER, t[1]);
+ memcpy(mac, t, size);
+ }
+ }
+ else
+ {
+ word64 t = L3Hash(m_polyState(), m_l3Key(), len);
+ t += GetWord<word64>(true, BIG_ENDIAN_ORDER, m_pad() + (m_nonce()[IVSize()-1]&1) * 8);
+ if (size == 8)
+ PutWord(false, BIG_ENDIAN_ORDER, mac, t);
+ else
+ {
+ t = ConditionalByteReverse(BIG_ENDIAN_ORDER, t);
+ memcpy(mac, &t, size);
+ }
+ }
+}
+
+NAMESPACE_END
diff --git a/lib/cryptopp/vmac.h b/lib/cryptopp/vmac.h
new file mode 100644
index 000000000..07240173c
--- /dev/null
+++ b/lib/cryptopp/vmac.h
@@ -0,0 +1,68 @@
+#ifndef CRYPTOPP_VMAC_H
+#define CRYPTOPP_VMAC_H
+
+#include "iterhash.h"
+#include "seckey.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// .
+class VMAC_Base : public IteratedHashBase<word64, MessageAuthenticationCode>
+{
+public:
+ std::string AlgorithmName() const {return std::string("VMAC(") + GetCipher().AlgorithmName() + ")-" + IntToString(DigestSize()*8);}
+ unsigned int IVSize() const {return GetCipher().BlockSize();}
+ unsigned int MinIVLength() const {return 1;}
+ void Resynchronize(const byte *nonce, int length=-1);
+ void GetNextIV(RandomNumberGenerator &rng, byte *IV);
+ unsigned int DigestSize() const {return m_is128 ? 16 : 8;};
+ void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &params);
+ void TruncatedFinal(byte *mac, size_t size);
+ unsigned int BlockSize() const {return m_L1KeyLength;}
+ ByteOrder GetByteOrder() const {return LITTLE_ENDIAN_ORDER;}
+
+protected:
+ virtual BlockCipher & AccessCipher() =0;
+ virtual int DefaultDigestSize() const =0;
+ const BlockCipher & GetCipher() const {return const_cast<VMAC_Base *>(this)->AccessCipher();}
+ void HashEndianCorrectedBlock(const word64 *data);
+ size_t HashMultipleBlocks(const word64 *input, size_t length);
+ void Init() {}
+ word64* StateBuf() {return NULL;}
+ word64* DataBuf() {return (word64 *)m_data();}
+
+ void VHASH_Update_SSE2(const word64 *data, size_t blocksRemainingInWord64, int tagPart);
+#if !(defined(_MSC_VER) && _MSC_VER < 1300) // can't use function template here with VC6
+ template <bool T_128BitTag>
+#endif
+ void VHASH_Update_Template(const word64 *data, size_t blockRemainingInWord128);
+ void VHASH_Update(const word64 *data, size_t blocksRemainingInWord128);
+
+ CRYPTOPP_BLOCK_1(polyState, word64, 4*(m_is128+1))
+ CRYPTOPP_BLOCK_2(nhKey, word64, m_L1KeyLength/sizeof(word64) + 2*m_is128)
+ CRYPTOPP_BLOCK_3(data, byte, m_L1KeyLength)
+ CRYPTOPP_BLOCK_4(l3Key, word64, 2*(m_is128+1))
+ CRYPTOPP_BLOCK_5(nonce, byte, IVSize())
+ CRYPTOPP_BLOCK_6(pad, byte, IVSize())
+ CRYPTOPP_BLOCKS_END(6)
+
+ bool m_is128, m_padCached, m_isFirstBlock;
+ int m_L1KeyLength;
+};
+
+/// <a href="http://www.cryptolounge.org/wiki/VMAC">VMAC</a>
+template <class T_BlockCipher, int T_DigestBitSize = 128>
+class VMAC : public SimpleKeyingInterfaceImpl<VMAC_Base, SameKeyLengthAs<T_BlockCipher, SimpleKeyingInterface::UNIQUE_IV, T_BlockCipher::BLOCKSIZE> >
+{
+public:
+ static std::string StaticAlgorithmName() {return std::string("VMAC(") + T_BlockCipher::StaticAlgorithmName() + ")-" + IntToString(T_DigestBitSize);}
+
+private:
+ BlockCipher & AccessCipher() {return m_cipher;}
+ int DefaultDigestSize() const {return T_DigestBitSize/8;}
+ typename T_BlockCipher::Encryption m_cipher;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/wait.cpp b/lib/cryptopp/wait.cpp
new file mode 100644
index 000000000..198785838
--- /dev/null
+++ b/lib/cryptopp/wait.cpp
@@ -0,0 +1,397 @@
+// wait.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "wait.h"
+#include "misc.h"
+
+#ifdef SOCKETS_AVAILABLE
+
+#ifdef USE_BERKELEY_STYLE_SOCKETS
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+unsigned int WaitObjectContainer::MaxWaitObjects()
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ return MAXIMUM_WAIT_OBJECTS * (MAXIMUM_WAIT_OBJECTS-1);
+#else
+ return FD_SETSIZE;
+#endif
+}
+
+WaitObjectContainer::WaitObjectContainer(WaitObjectsTracer* tracer)
+ : m_tracer(tracer), m_eventTimer(Timer::MILLISECONDS)
+ , m_sameResultCount(0), m_noWaitTimer(Timer::MILLISECONDS)
+{
+ Clear();
+ m_eventTimer.StartTimer();
+}
+
+void WaitObjectContainer::Clear()
+{
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ m_handles.clear();
+#else
+ m_maxFd = 0;
+ FD_ZERO(&m_readfds);
+ FD_ZERO(&m_writefds);
+#endif
+ m_noWait = false;
+ m_firstEventTime = 0;
+}
+
+inline void WaitObjectContainer::SetLastResult(LastResultType result)
+{
+ if (result == m_lastResult)
+ m_sameResultCount++;
+ else
+ {
+ m_lastResult = result;
+ m_sameResultCount = 0;
+ }
+}
+
+void WaitObjectContainer::DetectNoWait(LastResultType result, CallStack const& callStack)
+{
+ if (result == m_lastResult && m_noWaitTimer.ElapsedTime() > 1000)
+ {
+ if (m_sameResultCount > m_noWaitTimer.ElapsedTime())
+ {
+ if (m_tracer)
+ {
+ std::string desc = "No wait loop detected - m_lastResult: ";
+ desc.append(IntToString(m_lastResult)).append(", call stack:");
+ for (CallStack const* cs = &callStack; cs; cs = cs->Prev())
+ desc.append("\n- ").append(cs->Format());
+ m_tracer->TraceNoWaitLoop(desc);
+ }
+ try { throw 0; } catch (...) {} // help debugger break
+ }
+
+ m_noWaitTimer.StartTimer();
+ m_sameResultCount = 0;
+ }
+}
+
+void WaitObjectContainer::SetNoWait(CallStack const& callStack)
+{
+ DetectNoWait(LASTRESULT_NOWAIT, CallStack("WaitObjectContainer::SetNoWait()", &callStack));
+ m_noWait = true;
+}
+
+void WaitObjectContainer::ScheduleEvent(double milliseconds, CallStack const& callStack)
+{
+ if (milliseconds <= 3)
+ DetectNoWait(LASTRESULT_SCHEDULED, CallStack("WaitObjectContainer::ScheduleEvent()", &callStack));
+ double thisEventTime = m_eventTimer.ElapsedTimeAsDouble() + milliseconds;
+ if (!m_firstEventTime || thisEventTime < m_firstEventTime)
+ m_firstEventTime = thisEventTime;
+}
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+
+struct WaitingThreadData
+{
+ bool waitingToWait, terminate;
+ HANDLE startWaiting, stopWaiting;
+ const HANDLE *waitHandles;
+ unsigned int count;
+ HANDLE threadHandle;
+ DWORD threadId;
+ DWORD* error;
+};
+
+WaitObjectContainer::~WaitObjectContainer()
+{
+ try // don't let exceptions escape destructor
+ {
+ if (!m_threads.empty())
+ {
+ HANDLE threadHandles[MAXIMUM_WAIT_OBJECTS];
+ unsigned int i;
+ for (i=0; i<m_threads.size(); i++)
+ {
+ WaitingThreadData &thread = *m_threads[i];
+ while (!thread.waitingToWait) // spin until thread is in the initial "waiting to wait" state
+ Sleep(0);
+ thread.terminate = true;
+ threadHandles[i] = thread.threadHandle;
+ }
+ PulseEvent(m_startWaiting);
+ ::WaitForMultipleObjects((DWORD)m_threads.size(), threadHandles, TRUE, INFINITE);
+ for (i=0; i<m_threads.size(); i++)
+ CloseHandle(threadHandles[i]);
+ CloseHandle(m_startWaiting);
+ CloseHandle(m_stopWaiting);
+ }
+ }
+ catch (...)
+ {
+ }
+}
+
+
+void WaitObjectContainer::AddHandle(HANDLE handle, CallStack const& callStack)
+{
+ DetectNoWait(m_handles.size(), CallStack("WaitObjectContainer::AddHandle()", &callStack));
+ m_handles.push_back(handle);
+}
+
+DWORD WINAPI WaitingThread(LPVOID lParam)
+{
+ std::auto_ptr<WaitingThreadData> pThread((WaitingThreadData *)lParam);
+ WaitingThreadData &thread = *pThread;
+ std::vector<HANDLE> handles;
+
+ while (true)
+ {
+ thread.waitingToWait = true;
+ ::WaitForSingleObject(thread.startWaiting, INFINITE);
+ thread.waitingToWait = false;
+
+ if (thread.terminate)
+ break;
+ if (!thread.count)
+ continue;
+
+ handles.resize(thread.count + 1);
+ handles[0] = thread.stopWaiting;
+ std::copy(thread.waitHandles, thread.waitHandles+thread.count, handles.begin()+1);
+
+ DWORD result = ::WaitForMultipleObjects((DWORD)handles.size(), &handles[0], FALSE, INFINITE);
+
+ if (result == WAIT_OBJECT_0)
+ continue; // another thread finished waiting first, so do nothing
+ SetEvent(thread.stopWaiting);
+ if (!(result > WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + handles.size()))
+ {
+ assert(!"error in WaitingThread"); // break here so we can see which thread has an error
+ *thread.error = ::GetLastError();
+ }
+ }
+
+ return S_OK; // return a value here to avoid compiler warning
+}
+
+void WaitObjectContainer::CreateThreads(unsigned int count)
+{
+ size_t currentCount = m_threads.size();
+ if (currentCount == 0)
+ {
+ m_startWaiting = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_stopWaiting = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ }
+
+ if (currentCount < count)
+ {
+ m_threads.resize(count);
+ for (size_t i=currentCount; i<count; i++)
+ {
+ m_threads[i] = new WaitingThreadData;
+ WaitingThreadData &thread = *m_threads[i];
+ thread.terminate = false;
+ thread.startWaiting = m_startWaiting;
+ thread.stopWaiting = m_stopWaiting;
+ thread.waitingToWait = false;
+ thread.threadHandle = CreateThread(NULL, 0, &WaitingThread, &thread, 0, &thread.threadId);
+ }
+ }
+}
+
+bool WaitObjectContainer::Wait(unsigned long milliseconds)
+{
+ if (m_noWait || (m_handles.empty() && !m_firstEventTime))
+ {
+ SetLastResult(LASTRESULT_NOWAIT);
+ return true;
+ }
+
+ bool timeoutIsScheduledEvent = false;
+
+ if (m_firstEventTime)
+ {
+ double timeToFirstEvent = SaturatingSubtract(m_firstEventTime, m_eventTimer.ElapsedTimeAsDouble());
+
+ if (timeToFirstEvent <= milliseconds)
+ {
+ milliseconds = (unsigned long)timeToFirstEvent;
+ timeoutIsScheduledEvent = true;
+ }
+
+ if (m_handles.empty() || !milliseconds)
+ {
+ if (milliseconds)
+ Sleep(milliseconds);
+ SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
+ return timeoutIsScheduledEvent;
+ }
+ }
+
+ if (m_handles.size() > MAXIMUM_WAIT_OBJECTS)
+ {
+ // too many wait objects for a single WaitForMultipleObjects call, so use multiple threads
+ static const unsigned int WAIT_OBJECTS_PER_THREAD = MAXIMUM_WAIT_OBJECTS-1;
+ unsigned int nThreads = (unsigned int)((m_handles.size() + WAIT_OBJECTS_PER_THREAD - 1) / WAIT_OBJECTS_PER_THREAD);
+ if (nThreads > MAXIMUM_WAIT_OBJECTS) // still too many wait objects, maybe implement recursive threading later?
+ throw Err("WaitObjectContainer: number of wait objects exceeds limit");
+ CreateThreads(nThreads);
+ DWORD error = S_OK;
+
+ for (unsigned int i=0; i<m_threads.size(); i++)
+ {
+ WaitingThreadData &thread = *m_threads[i];
+ while (!thread.waitingToWait) // spin until thread is in the initial "waiting to wait" state
+ Sleep(0);
+ if (i<nThreads)
+ {
+ thread.waitHandles = &m_handles[i*WAIT_OBJECTS_PER_THREAD];
+ thread.count = UnsignedMin(WAIT_OBJECTS_PER_THREAD, m_handles.size() - i*WAIT_OBJECTS_PER_THREAD);
+ thread.error = &error;
+ }
+ else
+ thread.count = 0;
+ }
+
+ ResetEvent(m_stopWaiting);
+ PulseEvent(m_startWaiting);
+
+ DWORD result = ::WaitForSingleObject(m_stopWaiting, milliseconds);
+ if (result == WAIT_OBJECT_0)
+ {
+ if (error == S_OK)
+ return true;
+ else
+ throw Err("WaitObjectContainer: WaitForMultipleObjects in thread failed with error " + IntToString(error));
+ }
+ SetEvent(m_stopWaiting);
+ if (result == WAIT_TIMEOUT)
+ {
+ SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
+ return timeoutIsScheduledEvent;
+ }
+ else
+ throw Err("WaitObjectContainer: WaitForSingleObject failed with error " + IntToString(::GetLastError()));
+ }
+ else
+ {
+#if TRACE_WAIT
+ static Timer t(Timer::MICROSECONDS);
+ static unsigned long lastTime = 0;
+ unsigned long timeBeforeWait = t.ElapsedTime();
+#endif
+ DWORD result = ::WaitForMultipleObjects((DWORD)m_handles.size(), &m_handles[0], FALSE, milliseconds);
+#if TRACE_WAIT
+ if (milliseconds > 0)
+ {
+ unsigned long timeAfterWait = t.ElapsedTime();
+ OutputDebugString(("Handles " + IntToString(m_handles.size()) + ", Woke up by " + IntToString(result-WAIT_OBJECT_0) + ", Busied for " + IntToString(timeBeforeWait-lastTime) + " us, Waited for " + IntToString(timeAfterWait-timeBeforeWait) + " us, max " + IntToString(milliseconds) + "ms\n").c_str());
+ lastTime = timeAfterWait;
+ }
+#endif
+ if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + m_handles.size())
+ {
+ if (result == m_lastResult)
+ m_sameResultCount++;
+ else
+ {
+ m_lastResult = result;
+ m_sameResultCount = 0;
+ }
+ return true;
+ }
+ else if (result == WAIT_TIMEOUT)
+ {
+ SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
+ return timeoutIsScheduledEvent;
+ }
+ else
+ throw Err("WaitObjectContainer: WaitForMultipleObjects failed with error " + IntToString(::GetLastError()));
+ }
+}
+
+#else // #ifdef USE_WINDOWS_STYLE_SOCKETS
+
+void WaitObjectContainer::AddReadFd(int fd, CallStack const& callStack) // TODO: do something with callStack
+{
+ FD_SET(fd, &m_readfds);
+ m_maxFd = STDMAX(m_maxFd, fd);
+}
+
+void WaitObjectContainer::AddWriteFd(int fd, CallStack const& callStack) // TODO: do something with callStack
+{
+ FD_SET(fd, &m_writefds);
+ m_maxFd = STDMAX(m_maxFd, fd);
+}
+
+bool WaitObjectContainer::Wait(unsigned long milliseconds)
+{
+ if (m_noWait || (!m_maxFd && !m_firstEventTime))
+ return true;
+
+ bool timeoutIsScheduledEvent = false;
+
+ if (m_firstEventTime)
+ {
+ double timeToFirstEvent = SaturatingSubtract(m_firstEventTime, m_eventTimer.ElapsedTimeAsDouble());
+ if (timeToFirstEvent <= milliseconds)
+ {
+ milliseconds = (unsigned long)timeToFirstEvent;
+ timeoutIsScheduledEvent = true;
+ }
+ }
+
+ timeval tv, *timeout;
+
+ if (milliseconds == INFINITE_TIME)
+ timeout = NULL;
+ else
+ {
+ tv.tv_sec = milliseconds / 1000;
+ tv.tv_usec = (milliseconds % 1000) * 1000;
+ timeout = &tv;
+ }
+
+ int result = select(m_maxFd+1, &m_readfds, &m_writefds, NULL, timeout);
+
+ if (result > 0)
+ return true;
+ else if (result == 0)
+ return timeoutIsScheduledEvent;
+ else
+ throw Err("WaitObjectContainer: select failed with error " + errno);
+}
+
+#endif
+
+// ********************************************************
+
+std::string CallStack::Format() const
+{
+ return m_info;
+}
+
+std::string CallStackWithNr::Format() const
+{
+ return std::string(m_info) + " / nr: " + IntToString(m_nr);
+}
+
+std::string CallStackWithStr::Format() const
+{
+ return std::string(m_info) + " / " + std::string(m_z);
+}
+
+bool Waitable::Wait(unsigned long milliseconds, CallStack const& callStack)
+{
+ WaitObjectContainer container;
+ GetWaitObjects(container, callStack); // reduce clutter by not adding this func to stack
+ return container.Wait(milliseconds);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/wait.h b/lib/cryptopp/wait.h
new file mode 100644
index 000000000..045afbc18
--- /dev/null
+++ b/lib/cryptopp/wait.h
@@ -0,0 +1,208 @@
+#ifndef CRYPTOPP_WAIT_H
+#define CRYPTOPP_WAIT_H
+
+#include "config.h"
+
+#ifdef SOCKETS_AVAILABLE
+
+#include "misc.h"
+#include "cryptlib.h"
+#include <vector>
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+#include <winsock2.h>
+#else
+#include <sys/types.h>
+#endif
+
+#include "hrtimer.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+class Tracer
+{
+public:
+ Tracer(unsigned int level) : m_level(level) {}
+ virtual ~Tracer() {}
+
+protected:
+ //! Override this in your most-derived tracer to do the actual tracing.
+ virtual void Trace(unsigned int n, std::string const& s) = 0;
+
+ /*! By default, tracers will decide which trace messages to trace according to a trace level
+ mechanism. If your most-derived tracer uses a different mechanism, override this to
+ return false. If this method returns false, the default TraceXxxx(void) methods will all
+ return 0 and must be overridden explicitly by your tracer for trace messages you want. */
+ virtual bool UsingDefaults() const { return true; }
+
+protected:
+ unsigned int m_level;
+
+ void TraceIf(unsigned int n, std::string const&s)
+ { if (n) Trace(n, s); }
+
+ /*! Returns nr if, according to the default log settings mechanism (using log levels),
+ the message should be traced. Returns 0 if the default trace level mechanism is not
+ in use, or if it is in use but the event should not be traced. Provided as a utility
+ method for easier and shorter coding of default TraceXxxx(void) implementations. */
+ unsigned int Tracing(unsigned int nr, unsigned int minLevel) const
+ { return (UsingDefaults() && m_level >= minLevel) ? nr : 0; }
+};
+
+// Your Tracer-derived class should inherit as virtual public from Tracer or another
+// Tracer-derived class, and should pass the log level in its constructor. You can use the
+// following methods to begin and end your Tracer definition.
+
+// This constructor macro initializes Tracer directly even if not derived directly from it;
+// this is intended, virtual base classes are always initialized by the most derived class.
+#define CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED) \
+ public: DERIVED(unsigned int level = 0) : Tracer(level) {}
+
+#define CRYPTOPP_BEGIN_TRACER_CLASS_1(DERIVED, BASE1) \
+ class DERIVED : virtual public BASE1 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)
+
+#define CRYPTOPP_BEGIN_TRACER_CLASS_2(DERIVED, BASE1, BASE2) \
+ class DERIVED : virtual public BASE1, virtual public BASE2 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)
+
+#define CRYPTOPP_END_TRACER_CLASS };
+
+// In your Tracer-derived class, you should define a globally unique event number for each
+// new event defined. This can be done using the following macros.
+
+#define CRYPTOPP_BEGIN_TRACER_EVENTS(UNIQUENR) enum { EVENTBASE = UNIQUENR,
+#define CRYPTOPP_TRACER_EVENT(EVENTNAME) EventNr_##EVENTNAME,
+#define CRYPTOPP_END_TRACER_EVENTS };
+
+// In your own Tracer-derived class, you must define two methods per new trace event type:
+// - unsigned int TraceXxxx() const
+// Your default implementation of this method should return the event number if according
+// to the default trace level system the event should be traced, or 0 if it should not.
+// - void TraceXxxx(string const& s)
+// This method should call TraceIf(TraceXxxx(), s); to do the tracing.
+// For your convenience, a macro to define these two types of methods are defined below.
+// If you use this macro, you should also use the TRACER_EVENTS macros above to associate
+// event names with numbers.
+
+#define CRYPTOPP_TRACER_EVENT_METHODS(EVENTNAME, LOGLEVEL) \
+ virtual unsigned int Trace##EVENTNAME() const { return Tracing(EventNr_##EVENTNAME, LOGLEVEL); } \
+ virtual void Trace##EVENTNAME(std::string const& s) { TraceIf(Trace##EVENTNAME(), s); }
+
+
+/*! A simple unidirectional linked list with m_prev == 0 to indicate the final entry.
+ The aim of this implementation is to provide a very lightweight and practical
+ tracing mechanism with a low performance impact. Functions and methods supporting
+ this call-stack mechanism would take a parameter of the form "CallStack const& callStack",
+ and would pass this parameter to subsequent functions they call using the construct:
+
+ SubFunc(arg1, arg2, CallStack("my func at place such and such", &callStack));
+
+ The advantage of this approach is that it is easy to use and should be very efficient,
+ involving no allocation from the heap, just a linked list of stack objects containing
+ pointers to static ASCIIZ strings (or possibly additional but simple data if derived). */
+class CallStack
+{
+public:
+ CallStack(char const* i, CallStack const* p) : m_info(i), m_prev(p) {}
+ CallStack const* Prev() const { return m_prev; }
+ virtual std::string Format() const;
+
+protected:
+ char const* m_info;
+ CallStack const* m_prev;
+};
+
+/*! An extended CallStack entry type with an additional numeric parameter. */
+class CallStackWithNr : public CallStack
+{
+public:
+ CallStackWithNr(char const* i, word32 n, CallStack const* p) : CallStack(i, p), m_nr(n) {}
+ std::string Format() const;
+
+protected:
+ word32 m_nr;
+};
+
+/*! An extended CallStack entry type with an additional string parameter. */
+class CallStackWithStr : public CallStack
+{
+public:
+ CallStackWithStr(char const* i, char const* z, CallStack const* p) : CallStack(i, p), m_z(z) {}
+ std::string Format() const;
+
+protected:
+ char const* m_z;
+};
+
+CRYPTOPP_BEGIN_TRACER_CLASS_1(WaitObjectsTracer, Tracer)
+ CRYPTOPP_BEGIN_TRACER_EVENTS(0x48752841)
+ CRYPTOPP_TRACER_EVENT(NoWaitLoop)
+ CRYPTOPP_END_TRACER_EVENTS
+ CRYPTOPP_TRACER_EVENT_METHODS(NoWaitLoop, 1)
+CRYPTOPP_END_TRACER_CLASS
+
+struct WaitingThreadData;
+
+//! container of wait objects
+class WaitObjectContainer : public NotCopyable
+{
+public:
+ //! exception thrown by WaitObjectContainer
+ class Err : public Exception
+ {
+ public:
+ Err(const std::string& s) : Exception(IO_ERROR, s) {}
+ };
+
+ static unsigned int MaxWaitObjects();
+
+ WaitObjectContainer(WaitObjectsTracer* tracer = 0);
+
+ void Clear();
+ void SetNoWait(CallStack const& callStack);
+ void ScheduleEvent(double milliseconds, CallStack const& callStack);
+ // returns false if timed out
+ bool Wait(unsigned long milliseconds);
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ ~WaitObjectContainer();
+ void AddHandle(HANDLE handle, CallStack const& callStack);
+#else
+ void AddReadFd(int fd, CallStack const& callStack);
+ void AddWriteFd(int fd, CallStack const& callStack);
+#endif
+
+private:
+ WaitObjectsTracer* m_tracer;
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ void CreateThreads(unsigned int count);
+ std::vector<HANDLE> m_handles;
+ std::vector<WaitingThreadData *> m_threads;
+ HANDLE m_startWaiting;
+ HANDLE m_stopWaiting;
+#else
+ fd_set m_readfds, m_writefds;
+ int m_maxFd;
+#endif
+ bool m_noWait;
+ double m_firstEventTime;
+ Timer m_eventTimer;
+
+#ifdef USE_WINDOWS_STYLE_SOCKETS
+ typedef size_t LastResultType;
+#else
+ typedef int LastResultType;
+#endif
+ enum { LASTRESULT_NOWAIT = -1, LASTRESULT_SCHEDULED = -2, LASTRESULT_TIMEOUT = -3 };
+ LastResultType m_lastResult;
+ unsigned int m_sameResultCount;
+ Timer m_noWaitTimer;
+ void SetLastResult(LastResultType result);
+ void DetectNoWait(LastResultType result, CallStack const& callStack);
+};
+
+NAMESPACE_END
+
+#endif
+
+#endif
diff --git a/lib/cryptopp/winpipes.cpp b/lib/cryptopp/winpipes.cpp
new file mode 100644
index 000000000..1c2e047b0
--- /dev/null
+++ b/lib/cryptopp/winpipes.cpp
@@ -0,0 +1,205 @@
+// winpipes.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "winpipes.h"
+
+#ifdef WINDOWS_PIPES_AVAILABLE
+
+#include "wait.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+WindowsHandle::WindowsHandle(HANDLE h, bool own)
+ : m_h(h), m_own(own)
+{
+}
+
+WindowsHandle::~WindowsHandle()
+{
+ if (m_own)
+ {
+ try
+ {
+ CloseHandle();
+ }
+ catch (...)
+ {
+ }
+ }
+}
+
+bool WindowsHandle::HandleValid() const
+{
+ return m_h && m_h != INVALID_HANDLE_VALUE;
+}
+
+void WindowsHandle::AttachHandle(HANDLE h, bool own)
+{
+ if (m_own)
+ CloseHandle();
+
+ m_h = h;
+ m_own = own;
+ HandleChanged();
+}
+
+HANDLE WindowsHandle::DetachHandle()
+{
+ HANDLE h = m_h;
+ m_h = INVALID_HANDLE_VALUE;
+ HandleChanged();
+ return h;
+}
+
+void WindowsHandle::CloseHandle()
+{
+ if (m_h != INVALID_HANDLE_VALUE)
+ {
+ ::CloseHandle(m_h);
+ m_h = INVALID_HANDLE_VALUE;
+ HandleChanged();
+ }
+}
+
+// ********************************************************
+
+void WindowsPipe::HandleError(const char *operation) const
+{
+ DWORD err = GetLastError();
+ throw Err(GetHandle(), operation, err);
+}
+
+WindowsPipe::Err::Err(HANDLE s, const std::string& operation, int error)
+ : OS_Error(IO_ERROR, "WindowsPipe: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
+ , m_h(s)
+{
+}
+
+// *************************************************************
+
+WindowsPipeReceiver::WindowsPipeReceiver()
+ : m_resultPending(false), m_eofReceived(false)
+{
+ m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
+ CheckAndHandleError("CreateEvent", m_event.HandleValid());
+ memset(&m_overlapped, 0, sizeof(m_overlapped));
+ m_overlapped.hEvent = m_event;
+}
+
+bool WindowsPipeReceiver::Receive(byte* buf, size_t bufLen)
+{
+ assert(!m_resultPending && !m_eofReceived);
+
+ HANDLE h = GetHandle();
+ // don't queue too much at once, or we might use up non-paged memory
+ if (ReadFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &m_lastResult, &m_overlapped))
+ {
+ if (m_lastResult == 0)
+ m_eofReceived = true;
+ }
+ else
+ {
+ switch (GetLastError())
+ {
+ default:
+ CheckAndHandleError("ReadFile", false);
+ case ERROR_BROKEN_PIPE:
+ case ERROR_HANDLE_EOF:
+ m_lastResult = 0;
+ m_eofReceived = true;
+ break;
+ case ERROR_IO_PENDING:
+ m_resultPending = true;
+ }
+ }
+ return !m_resultPending;
+}
+
+void WindowsPipeReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ if (m_resultPending)
+ container.AddHandle(m_event, CallStack("WindowsPipeReceiver::GetWaitObjects() - result pending", &callStack));
+ else if (!m_eofReceived)
+ container.SetNoWait(CallStack("WindowsPipeReceiver::GetWaitObjects() - result ready", &callStack));
+}
+
+unsigned int WindowsPipeReceiver::GetReceiveResult()
+{
+ if (m_resultPending)
+ {
+ HANDLE h = GetHandle();
+ if (GetOverlappedResult(h, &m_overlapped, &m_lastResult, false))
+ {
+ if (m_lastResult == 0)
+ m_eofReceived = true;
+ }
+ else
+ {
+ switch (GetLastError())
+ {
+ default:
+ CheckAndHandleError("GetOverlappedResult", false);
+ case ERROR_BROKEN_PIPE:
+ case ERROR_HANDLE_EOF:
+ m_lastResult = 0;
+ m_eofReceived = true;
+ }
+ }
+ m_resultPending = false;
+ }
+ return m_lastResult;
+}
+
+// *************************************************************
+
+WindowsPipeSender::WindowsPipeSender()
+ : m_resultPending(false), m_lastResult(0)
+{
+ m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
+ CheckAndHandleError("CreateEvent", m_event.HandleValid());
+ memset(&m_overlapped, 0, sizeof(m_overlapped));
+ m_overlapped.hEvent = m_event;
+}
+
+void WindowsPipeSender::Send(const byte* buf, size_t bufLen)
+{
+ DWORD written = 0;
+ HANDLE h = GetHandle();
+ // don't queue too much at once, or we might use up non-paged memory
+ if (WriteFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &written, &m_overlapped))
+ {
+ m_resultPending = false;
+ m_lastResult = written;
+ }
+ else
+ {
+ if (GetLastError() != ERROR_IO_PENDING)
+ CheckAndHandleError("WriteFile", false);
+
+ m_resultPending = true;
+ }
+}
+
+void WindowsPipeSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
+{
+ if (m_resultPending)
+ container.AddHandle(m_event, CallStack("WindowsPipeSender::GetWaitObjects() - result pending", &callStack));
+ else
+ container.SetNoWait(CallStack("WindowsPipeSender::GetWaitObjects() - result ready", &callStack));
+}
+
+unsigned int WindowsPipeSender::GetSendResult()
+{
+ if (m_resultPending)
+ {
+ HANDLE h = GetHandle();
+ BOOL result = GetOverlappedResult(h, &m_overlapped, &m_lastResult, false);
+ CheckAndHandleError("GetOverlappedResult", result);
+ m_resultPending = false;
+ }
+ return m_lastResult;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/cryptopp/winpipes.h b/lib/cryptopp/winpipes.h
new file mode 100644
index 000000000..07225f9f1
--- /dev/null
+++ b/lib/cryptopp/winpipes.h
@@ -0,0 +1,142 @@
+#ifndef CRYPTOPP_WINPIPES_H
+#define CRYPTOPP_WINPIPES_H
+
+#include "config.h"
+
+#ifdef WINDOWS_PIPES_AVAILABLE
+
+#include "network.h"
+#include "queue.h"
+#include <winsock2.h>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! Windows Handle
+class WindowsHandle
+{
+public:
+ WindowsHandle(HANDLE h = INVALID_HANDLE_VALUE, bool own=false);
+ WindowsHandle(const WindowsHandle &h) : m_h(h.m_h), m_own(false) {}
+ virtual ~WindowsHandle();
+
+ bool GetOwnership() const {return m_own;}
+ void SetOwnership(bool own) {m_own = own;}
+
+ operator HANDLE() {return m_h;}
+ HANDLE GetHandle() const {return m_h;}
+ bool HandleValid() const;
+ void AttachHandle(HANDLE h, bool own=false);
+ HANDLE DetachHandle();
+ void CloseHandle();
+
+protected:
+ virtual void HandleChanged() {}
+
+ HANDLE m_h;
+ bool m_own;
+};
+
+//! Windows Pipe
+class WindowsPipe
+{
+public:
+ class Err : public OS_Error
+ {
+ public:
+ Err(HANDLE h, const std::string& operation, int error);
+ HANDLE GetHandle() const {return m_h;}
+
+ private:
+ HANDLE m_h;
+ };
+
+protected:
+ virtual HANDLE GetHandle() const =0;
+ virtual void HandleError(const char *operation) const;
+ void CheckAndHandleError(const char *operation, BOOL result) const
+ {assert(result==TRUE || result==FALSE); if (!result) HandleError(operation);}
+};
+
+//! pipe-based implementation of NetworkReceiver
+class WindowsPipeReceiver : public WindowsPipe, public NetworkReceiver
+{
+public:
+ WindowsPipeReceiver();
+
+ bool MustWaitForResult() {return true;}
+ bool Receive(byte* buf, size_t bufLen);
+ unsigned int GetReceiveResult();
+ bool EofReceived() const {return m_eofReceived;}
+
+ unsigned int GetMaxWaitObjectCount() const {return 1;}
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+
+private:
+ WindowsHandle m_event;
+ OVERLAPPED m_overlapped;
+ bool m_resultPending;
+ DWORD m_lastResult;
+ bool m_eofReceived;
+};
+
+//! pipe-based implementation of NetworkSender
+class WindowsPipeSender : public WindowsPipe, public NetworkSender
+{
+public:
+ WindowsPipeSender();
+
+ bool MustWaitForResult() {return true;}
+ void Send(const byte* buf, size_t bufLen);
+ unsigned int GetSendResult();
+ bool MustWaitForEof() { return false; }
+ void SendEof() {}
+
+ unsigned int GetMaxWaitObjectCount() const {return 1;}
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+
+private:
+ WindowsHandle m_event;
+ OVERLAPPED m_overlapped;
+ bool m_resultPending;
+ DWORD m_lastResult;
+};
+
+//! Windows Pipe Source
+class WindowsPipeSource : public WindowsHandle, public NetworkSource, public WindowsPipeReceiver
+{
+public:
+ WindowsPipeSource(HANDLE h=INVALID_HANDLE_VALUE, bool pumpAll=false, BufferedTransformation *attachment=NULL)
+ : WindowsHandle(h), NetworkSource(attachment)
+ {
+ if (pumpAll)
+ PumpAll();
+ }
+
+ NetworkSource::GetMaxWaitObjectCount;
+ NetworkSource::GetWaitObjects;
+
+private:
+ HANDLE GetHandle() const {return WindowsHandle::GetHandle();}
+ NetworkReceiver & AccessReceiver() {return *this;}
+};
+
+//! Windows Pipe Sink
+class WindowsPipeSink : public WindowsHandle, public NetworkSink, public WindowsPipeSender
+{
+public:
+ WindowsPipeSink(HANDLE h=INVALID_HANDLE_VALUE, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024)
+ : WindowsHandle(h), NetworkSink(maxBufferSize, autoFlushBound) {}
+
+ NetworkSink::GetMaxWaitObjectCount;
+ NetworkSink::GetWaitObjects;
+
+private:
+ HANDLE GetHandle() const {return WindowsHandle::GetHandle();}
+ NetworkSender & AccessSender() {return *this;}
+};
+
+NAMESPACE_END
+
+#endif
+
+#endif
diff --git a/lib/cryptopp/words.h b/lib/cryptopp/words.h
new file mode 100644
index 000000000..d5fda71da
--- /dev/null
+++ b/lib/cryptopp/words.h
@@ -0,0 +1,103 @@
+#ifndef CRYPTOPP_WORDS_H
+#define CRYPTOPP_WORDS_H
+
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+inline size_t CountWords(const word *X, size_t N)
+{
+ while (N && X[N-1]==0)
+ N--;
+ return N;
+}
+
+inline void SetWords(word *r, word a, size_t n)
+{
+ for (size_t i=0; i<n; i++)
+ r[i] = a;
+}
+
+inline void CopyWords(word *r, const word *a, size_t n)
+{
+ if (r != a)
+ memcpy(r, a, n*WORD_SIZE);
+}
+
+inline void XorWords(word *r, const word *a, const word *b, size_t n)
+{
+ for (size_t i=0; i<n; i++)
+ r[i] = a[i] ^ b[i];
+}
+
+inline void XorWords(word *r, const word *a, size_t n)
+{
+ for (size_t i=0; i<n; i++)
+ r[i] ^= a[i];
+}
+
+inline void AndWords(word *r, const word *a, const word *b, size_t n)
+{
+ for (size_t i=0; i<n; i++)
+ r[i] = a[i] & b[i];
+}
+
+inline void AndWords(word *r, const word *a, size_t n)
+{
+ for (size_t i=0; i<n; i++)
+ r[i] &= a[i];
+}
+
+inline word ShiftWordsLeftByBits(word *r, size_t n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (size_t i=0; i<n; i++)
+ {
+ u = r[i];
+ r[i] = (u << shiftBits) | carry;
+ carry = u >> (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+inline word ShiftWordsRightByBits(word *r, size_t n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (size_t i=n; i>0; i--)
+ {
+ u = r[i-1];
+ r[i-1] = (u >> shiftBits) | carry;
+ carry = u << (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+inline void ShiftWordsLeftByWords(word *r, size_t n, size_t shiftWords)
+{
+ shiftWords = STDMIN(shiftWords, n);
+ if (shiftWords)
+ {
+ for (size_t i=n-1; i>=shiftWords; i--)
+ r[i] = r[i-shiftWords];
+ SetWords(r, 0, shiftWords);
+ }
+}
+
+inline void ShiftWordsRightByWords(word *r, size_t n, size_t shiftWords)
+{
+ shiftWords = STDMIN(shiftWords, n);
+ if (shiftWords)
+ {
+ for (size_t i=0; i+shiftWords<n; i++)
+ r[i] = r[i+shiftWords];
+ SetWords(r+n-shiftWords, 0, shiftWords);
+ }
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/lib/expat/ascii.h b/lib/expat/ascii.h
new file mode 100644
index 000000000..d10530b09
--- /dev/null
+++ b/lib/expat/ascii.h
@@ -0,0 +1,92 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#define ASCII_A 0x41
+#define ASCII_B 0x42
+#define ASCII_C 0x43
+#define ASCII_D 0x44
+#define ASCII_E 0x45
+#define ASCII_F 0x46
+#define ASCII_G 0x47
+#define ASCII_H 0x48
+#define ASCII_I 0x49
+#define ASCII_J 0x4A
+#define ASCII_K 0x4B
+#define ASCII_L 0x4C
+#define ASCII_M 0x4D
+#define ASCII_N 0x4E
+#define ASCII_O 0x4F
+#define ASCII_P 0x50
+#define ASCII_Q 0x51
+#define ASCII_R 0x52
+#define ASCII_S 0x53
+#define ASCII_T 0x54
+#define ASCII_U 0x55
+#define ASCII_V 0x56
+#define ASCII_W 0x57
+#define ASCII_X 0x58
+#define ASCII_Y 0x59
+#define ASCII_Z 0x5A
+
+#define ASCII_a 0x61
+#define ASCII_b 0x62
+#define ASCII_c 0x63
+#define ASCII_d 0x64
+#define ASCII_e 0x65
+#define ASCII_f 0x66
+#define ASCII_g 0x67
+#define ASCII_h 0x68
+#define ASCII_i 0x69
+#define ASCII_j 0x6A
+#define ASCII_k 0x6B
+#define ASCII_l 0x6C
+#define ASCII_m 0x6D
+#define ASCII_n 0x6E
+#define ASCII_o 0x6F
+#define ASCII_p 0x70
+#define ASCII_q 0x71
+#define ASCII_r 0x72
+#define ASCII_s 0x73
+#define ASCII_t 0x74
+#define ASCII_u 0x75
+#define ASCII_v 0x76
+#define ASCII_w 0x77
+#define ASCII_x 0x78
+#define ASCII_y 0x79
+#define ASCII_z 0x7A
+
+#define ASCII_0 0x30
+#define ASCII_1 0x31
+#define ASCII_2 0x32
+#define ASCII_3 0x33
+#define ASCII_4 0x34
+#define ASCII_5 0x35
+#define ASCII_6 0x36
+#define ASCII_7 0x37
+#define ASCII_8 0x38
+#define ASCII_9 0x39
+
+#define ASCII_TAB 0x09
+#define ASCII_SPACE 0x20
+#define ASCII_EXCL 0x21
+#define ASCII_QUOT 0x22
+#define ASCII_AMP 0x26
+#define ASCII_APOS 0x27
+#define ASCII_MINUS 0x2D
+#define ASCII_PERIOD 0x2E
+#define ASCII_COLON 0x3A
+#define ASCII_SEMI 0x3B
+#define ASCII_LT 0x3C
+#define ASCII_EQUALS 0x3D
+#define ASCII_GT 0x3E
+#define ASCII_LSQB 0x5B
+#define ASCII_RSQB 0x5D
+#define ASCII_UNDERSCORE 0x5F
+#define ASCII_LPAREN 0x28
+#define ASCII_RPAREN 0x29
+#define ASCII_FF 0x0C
+#define ASCII_SLASH 0x2F
+#define ASCII_HASH 0x23
+#define ASCII_PIPE 0x7C
+#define ASCII_COMMA 0x2C
diff --git a/lib/expat/asciitab.h b/lib/expat/asciitab.h
new file mode 100644
index 000000000..79a15c28c
--- /dev/null
+++ b/lib/expat/asciitab.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/lib/expat/expat.h b/lib/expat/expat.h
new file mode 100644
index 000000000..20a8278f7
--- /dev/null
+++ b/lib/expat/expat.h
@@ -0,0 +1,1014 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef Expat_INCLUDED
+#define Expat_INCLUDED 1
+
+#ifdef __VMS
+/* 0 1 2 3 0 1 2 3
+ 1234567890123456789012345678901 1234567890123456789012345678901 */
+#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler
+#define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler
+#define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler
+#define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg
+#endif
+
+#include <stdlib.h>
+#include "expat_external.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct XML_ParserStruct;
+typedef struct XML_ParserStruct *XML_Parser;
+
+/* Should this be defined using stdbool.h when C99 is available? */
+typedef unsigned char XML_Bool;
+#define XML_TRUE ((XML_Bool) 1)
+#define XML_FALSE ((XML_Bool) 0)
+
+/* The XML_Status enum gives the possible return values for several
+ API functions. The preprocessor #defines are included so this
+ stanza can be added to code that still needs to support older
+ versions of Expat 1.95.x:
+
+ #ifndef XML_STATUS_OK
+ #define XML_STATUS_OK 1
+ #define XML_STATUS_ERROR 0
+ #endif
+
+ Otherwise, the #define hackery is quite ugly and would have been
+ dropped.
+*/
+enum XML_Status {
+ XML_STATUS_ERROR = 0,
+#define XML_STATUS_ERROR XML_STATUS_ERROR
+ XML_STATUS_OK = 1,
+#define XML_STATUS_OK XML_STATUS_OK
+ XML_STATUS_SUSPENDED = 2
+#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED
+};
+
+enum XML_Error {
+ XML_ERROR_NONE,
+ XML_ERROR_NO_MEMORY,
+ XML_ERROR_SYNTAX,
+ XML_ERROR_NO_ELEMENTS,
+ XML_ERROR_INVALID_TOKEN,
+ XML_ERROR_UNCLOSED_TOKEN,
+ XML_ERROR_PARTIAL_CHAR,
+ XML_ERROR_TAG_MISMATCH,
+ XML_ERROR_DUPLICATE_ATTRIBUTE,
+ XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+ XML_ERROR_PARAM_ENTITY_REF,
+ XML_ERROR_UNDEFINED_ENTITY,
+ XML_ERROR_RECURSIVE_ENTITY_REF,
+ XML_ERROR_ASYNC_ENTITY,
+ XML_ERROR_BAD_CHAR_REF,
+ XML_ERROR_BINARY_ENTITY_REF,
+ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+ XML_ERROR_MISPLACED_XML_PI,
+ XML_ERROR_UNKNOWN_ENCODING,
+ XML_ERROR_INCORRECT_ENCODING,
+ XML_ERROR_UNCLOSED_CDATA_SECTION,
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+ XML_ERROR_NOT_STANDALONE,
+ XML_ERROR_UNEXPECTED_STATE,
+ XML_ERROR_ENTITY_DECLARED_IN_PE,
+ XML_ERROR_FEATURE_REQUIRES_XML_DTD,
+ XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING,
+ /* Added in 1.95.7. */
+ XML_ERROR_UNBOUND_PREFIX,
+ /* Added in 1.95.8. */
+ XML_ERROR_UNDECLARING_PREFIX,
+ XML_ERROR_INCOMPLETE_PE,
+ XML_ERROR_XML_DECL,
+ XML_ERROR_TEXT_DECL,
+ XML_ERROR_PUBLICID,
+ XML_ERROR_SUSPENDED,
+ XML_ERROR_NOT_SUSPENDED,
+ XML_ERROR_ABORTED,
+ XML_ERROR_FINISHED,
+ XML_ERROR_SUSPEND_PE,
+ /* Added in 2.0. */
+ XML_ERROR_RESERVED_PREFIX_XML,
+ XML_ERROR_RESERVED_PREFIX_XMLNS,
+ XML_ERROR_RESERVED_NAMESPACE_URI
+};
+
+enum XML_Content_Type {
+ XML_CTYPE_EMPTY = 1,
+ XML_CTYPE_ANY,
+ XML_CTYPE_MIXED,
+ XML_CTYPE_NAME,
+ XML_CTYPE_CHOICE,
+ XML_CTYPE_SEQ
+};
+
+enum XML_Content_Quant {
+ XML_CQUANT_NONE,
+ XML_CQUANT_OPT,
+ XML_CQUANT_REP,
+ XML_CQUANT_PLUS
+};
+
+/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be
+ XML_CQUANT_NONE, and the other fields will be zero or NULL.
+ If type == XML_CTYPE_MIXED, then quant will be NONE or REP and
+ numchildren will contain number of elements that may be mixed in
+ and children point to an array of XML_Content cells that will be
+ all of XML_CTYPE_NAME type with no quantification.
+
+ If type == XML_CTYPE_NAME, then the name points to the name, and
+ the numchildren field will be zero and children will be NULL. The
+ quant fields indicates any quantifiers placed on the name.
+
+ CHOICE and SEQ will have name NULL, the number of children in
+ numchildren and children will point, recursively, to an array
+ of XML_Content cells.
+
+ The EMPTY, ANY, and MIXED types will only occur at top level.
+*/
+
+typedef struct XML_cp XML_Content;
+
+struct XML_cp {
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ XML_Char * name;
+ unsigned int numchildren;
+ XML_Content * children;
+};
+
+
+/* This is called for an element declaration. See above for
+ description of the model argument. It's the caller's responsibility
+ to free model when finished with it.
+*/
+typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
+ const XML_Char *name,
+ XML_Content *model);
+
+XMLPARSEAPI(void)
+XML_SetElementDeclHandler(XML_Parser parser,
+ XML_ElementDeclHandler eldecl);
+
+/* The Attlist declaration handler is called for *each* attribute. So
+ a single Attlist declaration with multiple attributes declared will
+ generate multiple calls to this handler. The "default" parameter
+ may be NULL in the case of the "#IMPLIED" or "#REQUIRED"
+ keyword. The "isrequired" parameter will be true and the default
+ value will be NULL in the case of "#REQUIRED". If "isrequired" is
+ true and default is non-NULL, then this is a "#FIXED" default.
+*/
+typedef void (XMLCALL *XML_AttlistDeclHandler) (
+ void *userData,
+ const XML_Char *elname,
+ const XML_Char *attname,
+ const XML_Char *att_type,
+ const XML_Char *dflt,
+ int isrequired);
+
+XMLPARSEAPI(void)
+XML_SetAttlistDeclHandler(XML_Parser parser,
+ XML_AttlistDeclHandler attdecl);
+
+/* The XML declaration handler is called for *both* XML declarations
+ and text declarations. The way to distinguish is that the version
+ parameter will be NULL for text declarations. The encoding
+ parameter may be NULL for XML declarations. The standalone
+ parameter will be -1, 0, or 1 indicating respectively that there
+ was no standalone parameter in the declaration, that it was given
+ as no, or that it was given as yes.
+*/
+typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData,
+ const XML_Char *version,
+ const XML_Char *encoding,
+ int standalone);
+
+XMLPARSEAPI(void)
+XML_SetXmlDeclHandler(XML_Parser parser,
+ XML_XmlDeclHandler xmldecl);
+
+
+typedef struct {
+ void *(*malloc_fcn)(size_t size);
+ void *(*realloc_fcn)(void *ptr, size_t size);
+ void (*free_fcn)(void *ptr);
+} XML_Memory_Handling_Suite;
+
+/* Constructs a new parser; encoding is the encoding specified by the
+ external protocol or NULL if there is none specified.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor. Element type
+ names and attribute names that belong to a namespace will be
+ expanded; unprefixed attribute names are never expanded; unprefixed
+ element type names are expanded only if there is a default
+ namespace. The expanded name is the concatenation of the namespace
+ URI, the namespace separator character, and the local part of the
+ name. If the namespace separator is '\0' then the namespace URI
+ and the local part will be concatenated without any separator.
+ It is a programming error to use the separator '\0' with namespace
+ triplets (see XML_SetReturnNSTriplet).
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* Constructs a new parser using the memory management suite referred to
+ by memsuite. If memsuite is NULL, then use the standard library memory
+ suite. If namespaceSeparator is non-NULL it creates a parser with
+ namespace processing as described above. The character pointed at
+ will serve as the namespace separator.
+
+ All further memory operations used for the created parser will come from
+ the given suite.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate_MM(const XML_Char *encoding,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *namespaceSeparator);
+
+/* Prepare a parser object to be re-used. This is particularly
+ valuable when memory allocation overhead is disproportionatly high,
+ such as when a large number of small documnents need to be parsed.
+ All handlers are cleared from the parser, except for the
+ unknownEncodingHandler. The parser's external state is re-initialized
+ except for the values of ns and ns_triplets.
+
+ Added in Expat 1.95.3.
+*/
+XMLPARSEAPI(XML_Bool)
+XML_ParserReset(XML_Parser parser, const XML_Char *encoding);
+
+/* atts is array of name/value pairs, terminated by 0;
+ names and values are 0 terminated.
+*/
+typedef void (XMLCALL *XML_StartElementHandler) (void *userData,
+ const XML_Char *name,
+ const XML_Char **atts);
+
+typedef void (XMLCALL *XML_EndElementHandler) (void *userData,
+ const XML_Char *name);
+
+
+/* s is not 0 terminated. */
+typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData,
+ const XML_Char *s,
+ int len);
+
+/* target and data are 0 terminated */
+typedef void (XMLCALL *XML_ProcessingInstructionHandler) (
+ void *userData,
+ const XML_Char *target,
+ const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (XMLCALL *XML_CommentHandler) (void *userData,
+ const XML_Char *data);
+
+typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData);
+typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData);
+
+/* This is called for any characters in the XML document for which
+ there is no applicable handler. This includes both characters that
+ are part of markup which is of a kind that is not reported
+ (comments, markup declarations), or characters that are part of a
+ construct which could be reported but for which no handler has been
+ supplied. The characters are passed exactly as they were in the XML
+ document except that they will be encoded in UTF-8 or UTF-16.
+ Line boundaries are not normalized. Note that a byte order mark
+ character is not passed to the default handler. There are no
+ guarantees about how characters are divided between calls to the
+ default handler: for example, a comment might be split between
+ multiple calls.
+*/
+typedef void (XMLCALL *XML_DefaultHandler) (void *userData,
+ const XML_Char *s,
+ int len);
+
+/* This is called for the start of the DOCTYPE declaration, before
+ any DTD or internal subset is parsed.
+*/
+typedef void (XMLCALL *XML_StartDoctypeDeclHandler) (
+ void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset);
+
+/* This is called for the start of the DOCTYPE declaration when the
+ closing > is encountered, but after processing any external
+ subset.
+*/
+typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData);
+
+/* This is called for entity declarations. The is_parameter_entity
+ argument will be non-zero if the entity is a parameter entity, zero
+ otherwise.
+
+ For internal entities (<!ENTITY foo "bar">), value will
+ be non-NULL and systemId, publicID, and notationName will be NULL.
+ The value string is NOT nul-terminated; the length is provided in
+ the value_length argument. Since it is legal to have zero-length
+ values, do not use this argument to test for internal entities.
+
+ For external entities, value will be NULL and systemId will be
+ non-NULL. The publicId argument will be NULL unless a public
+ identifier was provided. The notationName argument will have a
+ non-NULL value only for unparsed entity declarations.
+
+ Note that is_parameter_entity can't be changed to XML_Bool, since
+ that would break binary compatibility.
+*/
+typedef void (XMLCALL *XML_EntityDeclHandler) (
+ void *userData,
+ const XML_Char *entityName,
+ int is_parameter_entity,
+ const XML_Char *value,
+ int value_length,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+XMLPARSEAPI(void)
+XML_SetEntityDeclHandler(XML_Parser parser,
+ XML_EntityDeclHandler handler);
+
+/* OBSOLETE -- OBSOLETE -- OBSOLETE
+ This handler has been superceded by the EntityDeclHandler above.
+ It is provided here for backward compatibility.
+
+ This is called for a declaration of an unparsed (NDATA) entity.
+ The base argument is whatever was set by XML_SetBase. The
+ entityName, systemId and notationName arguments will never be
+ NULL. The other arguments may be.
+*/
+typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) (
+ void *userData,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+/* This is called for a declaration of notation. The base argument is
+ whatever was set by XML_SetBase. The notationName will never be
+ NULL. The other arguments can be.
+*/
+typedef void (XMLCALL *XML_NotationDeclHandler) (
+ void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+ each namespace declaration. The call to the start and end element
+ handlers occur between the calls to the start and end namespace
+ declaration handlers. For an xmlns attribute, prefix will be
+ NULL. For an xmlns="" attribute, uri will be NULL.
+*/
+typedef void (XMLCALL *XML_StartNamespaceDeclHandler) (
+ void *userData,
+ const XML_Char *prefix,
+ const XML_Char *uri);
+
+typedef void (XMLCALL *XML_EndNamespaceDeclHandler) (
+ void *userData,
+ const XML_Char *prefix);
+
+/* This is called if the document is not standalone, that is, it has an
+ external subset or a reference to a parameter entity, but does not
+ have standalone="yes". If this handler returns XML_STATUS_ERROR,
+ then processing will not continue, and the parser will return a
+ XML_ERROR_NOT_STANDALONE error.
+ If parameter entity parsing is enabled, then in addition to the
+ conditions above this handler will only be called if the referenced
+ entity was actually read.
+*/
+typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData);
+
+/* This is called for a reference to an external parsed general
+ entity. The referenced entity is not automatically parsed. The
+ application can parse it immediately or later using
+ XML_ExternalEntityParserCreate.
+
+ The parser argument is the parser parsing the entity containing the
+ reference; it can be passed as the parser argument to
+ XML_ExternalEntityParserCreate. The systemId argument is the
+ system identifier as specified in the entity declaration; it will
+ not be NULL.
+
+ The base argument is the system identifier that should be used as
+ the base for resolving systemId if systemId was relative; this is
+ set by XML_SetBase; it may be NULL.
+
+ The publicId argument is the public identifier as specified in the
+ entity declaration, or NULL if none was specified; the whitespace
+ in the public identifier will have been normalized as required by
+ the XML spec.
+
+ The context argument specifies the parsing context in the format
+ expected by the context argument to XML_ExternalEntityParserCreate;
+ context is valid only until the handler returns, so if the
+ referenced entity is to be parsed later, it must be copied.
+ context is NULL only when the entity is a parameter entity.
+
+ The handler should return XML_STATUS_ERROR if processing should not
+ continue because of a fatal error in the handling of the external
+ entity. In this case the calling parser will return an
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING error.
+
+ Note that unlike other handlers the first argument is the parser,
+ not userData.
+*/
+typedef int (XMLCALL *XML_ExternalEntityRefHandler) (
+ XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* This is called in two situations:
+ 1) An entity reference is encountered for which no declaration
+ has been read *and* this is not an error.
+ 2) An internal entity reference is read, but not expanded, because
+ XML_SetDefaultHandler has been called.
+ Note: skipped parameter entities in declarations and skipped general
+ entities in attribute values cannot be reported, because
+ the event would be out of sync with the reporting of the
+ declarations or attribute values
+*/
+typedef void (XMLCALL *XML_SkippedEntityHandler) (
+ void *userData,
+ const XML_Char *entityName,
+ int is_parameter_entity);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler to
+ provide information to the parser about encodings that are unknown
+ to the parser.
+
+ The map[b] member gives information about byte sequences whose
+ first byte is b.
+
+ If map[b] is c where c is >= 0, then b by itself encodes the
+ Unicode scalar value c.
+
+ If map[b] is -1, then the byte sequence is malformed.
+
+ If map[b] is -n, where n >= 2, then b is the first byte of an
+ n-byte sequence that encodes a single Unicode scalar value.
+
+ The data member will be passed as the first argument to the convert
+ function.
+
+ The convert function is used to convert multibyte sequences; s will
+ point to a n-byte sequence where map[(unsigned char)*s] == -n. The
+ convert function must return the Unicode scalar value represented
+ by this byte sequence or -1 if the byte sequence is malformed.
+
+ The convert function may be NULL if the encoding is a single-byte
+ encoding, that is if map[b] >= -1 for all bytes b.
+
+ When the parser is finished with the encoding, then if release is
+ not NULL, it will call release passing it the data member; once
+ release has been called, the convert function will not be called
+ again.
+
+ Expat places certain restrictions on the encodings that are supported
+ using this mechanism.
+
+ 1. Every ASCII character that can appear in a well-formed XML document,
+ other than the characters
+
+ $@\^`{}~
+
+ must be represented by a single byte, and that byte must be the
+ same byte that represents that character in ASCII.
+
+ 2. No character may require more than 4 bytes to encode.
+
+ 3. All characters encoded must have Unicode scalar values <=
+ 0xFFFF, (i.e., characters that would be encoded by surrogates in
+ UTF-16 are not allowed). Note that this restriction doesn't
+ apply to the built-in support for UTF-8 and UTF-16.
+
+ 4. No Unicode character may be encoded by more than one distinct
+ sequence of bytes.
+*/
+typedef struct {
+ int map[256];
+ void *data;
+ int (XMLCALL *convert)(void *data, const char *s);
+ void (XMLCALL *release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+
+ The encodingHandlerData argument is that which was passed as the
+ second argument to XML_SetUnknownEncodingHandler.
+
+ The name argument gives the name of the encoding as specified in
+ the encoding declaration.
+
+ If the callback can provide information about the encoding, it must
+ fill in the XML_Encoding structure, and return XML_STATUS_OK.
+ Otherwise it must return XML_STATUS_ERROR.
+
+ If info does not describe a suitable encoding, then the parser will
+ return an XML_UNKNOWN_ENCODING error.
+*/
+typedef int (XMLCALL *XML_UnknownEncodingHandler) (
+ void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info);
+
+XMLPARSEAPI(void)
+XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartElementHandler(XML_Parser parser,
+ XML_StartElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetEndElementHandler(XML_Parser parser,
+ XML_EndElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler);
+XMLPARSEAPI(void)
+XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+ XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of
+ internal entities. These entity references will be passed to the
+ default handler, or to the skipped entity handler, if one is set.
+*/
+XMLPARSEAPI(void)
+XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of
+ internal entities. The entity reference will not be passed to the
+ default handler.
+*/
+XMLPARSEAPI(void)
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+ XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+ XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler);
+
+/* If a non-NULL value for arg is specified here, then it will be
+ passed as the first argument to the external entity ref handler
+ instead of the parser object.
+*/
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser,
+ void *arg);
+
+XMLPARSEAPI(void)
+XML_SetSkippedEntityHandler(XML_Parser parser,
+ XML_SkippedEntityHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end
+ element, processing instruction or character data. It causes the
+ corresponding markup to be passed to the default handler.
+*/
+XMLPARSEAPI(void)
+XML_DefaultCurrent(XML_Parser parser);
+
+/* If do_nst is non-zero, and namespace processing is in effect, and
+ a name has a prefix (i.e. an explicit namespace qualifier) then
+ that name is returned as a triplet in a single string separated by
+ the separator character specified when the parser was created: URI
+ + sep + local_name + sep + prefix.
+
+ If do_nst is zero, then namespace information is returned in the
+ default manner (URI + sep + local_name) whether or not the name
+ has a prefix.
+
+ Note: Calling XML_SetReturnNSTriplet after XML_Parse or
+ XML_ParseBuffer has no effect.
+*/
+
+XMLPARSEAPI(void)
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst);
+
+/* This value is passed as the userData argument to callbacks. */
+XMLPARSEAPI(void)
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or NULL. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument to
+ XML_ParserCreate. On success XML_SetEncoding returns non-zero,
+ zero otherwise.
+ Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer
+ has no effect and returns XML_STATUS_ERROR.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed as the
+ first argument to callbacks instead of userData. The userData will
+ still be accessible using XML_GetUserData.
+*/
+XMLPARSEAPI(void)
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* If useDTD == XML_TRUE is passed to this function, then the parser
+ will assume that there is an external subset, even if none is
+ specified in the document. In such a case the parser will call the
+ externalEntityRefHandler with a value of NULL for the systemId
+ argument (the publicId and context arguments will be NULL as well).
+ Note: For the purpose of checking WFC: Entity Declared, passing
+ useDTD == XML_TRUE will make the parser behave as if the document
+ had a DTD with an external subset.
+ Note: If this function is called, then this must be done before
+ the first call to XML_Parse or XML_ParseBuffer, since it will
+ have no effect after that. Returns
+ XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING.
+ Note: If the document does not have a DOCTYPE declaration at all,
+ then startDoctypeDeclHandler and endDoctypeDeclHandler will not
+ be called, despite an external subset being parsed.
+ Note: If XML_DTD is not defined when Expat is compiled, returns
+ XML_ERROR_FEATURE_REQUIRES_XML_DTD.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
+
+
+/* Sets the base to be used for resolving relative URIs in system
+ identifiers in declarations. Resolving relative identifiers is
+ left to the application: this value will be passed through as the
+ base argument to the XML_ExternalEntityRefHandler,
+ XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base
+ argument will be copied. Returns XML_STATUS_ERROR if out of memory,
+ XML_STATUS_OK otherwise.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+XMLPARSEAPI(const XML_Char *)
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attribute/value pairs passed in last call
+ to the XML_StartElementHandler that were specified in the start-tag
+ rather than defaulted. Each attribute/value pair counts as 2; thus
+ this correspondds to an index into the atts array passed to the
+ XML_StartElementHandler.
+*/
+XMLPARSEAPI(int)
+XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Returns the index of the ID attribute passed in the last call to
+ XML_StartElementHandler, or -1 if there is no ID attribute. Each
+ attribute/value pair counts as 2; thus this correspondds to an
+ index into the atts array passed to the XML_StartElementHandler.
+*/
+XMLPARSEAPI(int)
+XML_GetIdAttributeIndex(XML_Parser parser);
+
+/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is
+ detected. The last call to XML_Parse must have isFinal true; len
+ may be zero for this call (or any other).
+
+ Though the return values for these functions has always been
+ described as a Boolean value, the implementation, at least for the
+ 1.95.x series, has always returned exactly one of the XML_Status
+ values.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+XMLPARSEAPI(void *)
+XML_GetBuffer(XML_Parser parser, int len);
+
+XMLPARSEAPI(enum XML_Status)
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return.
+ Must be called from within a call-back handler, except when aborting
+ (resumable = 0) an already suspended parser. Some call-backs may
+ still follow because they would otherwise get lost. Examples:
+ - endElementHandler() for empty elements when stopped in
+ startElementHandler(),
+ - endNameSpaceDeclHandler() when stopped in endElementHandler(),
+ and possibly others.
+
+ Can be called from most handlers, including DTD related call-backs,
+ except when parsing an external parameter entity and resumable != 0.
+ Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise.
+ Possible error codes:
+ - XML_ERROR_SUSPENDED: when suspending an already suspended parser.
+ - XML_ERROR_FINISHED: when the parser has already finished.
+ - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE.
+
+ When resumable != 0 (true) then parsing is suspended, that is,
+ XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED.
+ Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer()
+ return XML_STATUS_ERROR with error code XML_ERROR_ABORTED.
+
+ *Note*:
+ This will be applied to the current parser instance only, that is, if
+ there is a parent parser then it will continue parsing when the
+ externalEntityRefHandler() returns. It is up to the implementation of
+ the externalEntityRefHandler() to call XML_StopParser() on the parent
+ parser (recursively), if one wants to stop parsing altogether.
+
+ When suspended, parsing can be resumed by calling XML_ResumeParser().
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_StopParser(XML_Parser parser, XML_Bool resumable);
+
+/* Resumes parsing after it has been suspended with XML_StopParser().
+ Must not be called from within a handler call-back. Returns same
+ status codes as XML_Parse() or XML_ParseBuffer().
+ Additional error code XML_ERROR_NOT_SUSPENDED possible.
+
+ *Note*:
+ This must be called on the most deeply nested child parser instance
+ first, and on its parent parser only after the child parser has finished,
+ to be applied recursively until the document entity's parser is restarted.
+ That is, the parent parser will not resume by itself and it is up to the
+ application to call XML_ResumeParser() on it at the appropriate moment.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_ResumeParser(XML_Parser parser);
+
+enum XML_Parsing {
+ XML_INITIALIZED,
+ XML_PARSING,
+ XML_FINISHED,
+ XML_SUSPENDED
+};
+
+typedef struct {
+ enum XML_Parsing parsing;
+ XML_Bool finalBuffer;
+} XML_ParsingStatus;
+
+/* Returns status of parser with respect to being initialized, parsing,
+ finished, or suspended and processing the final buffer.
+ XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus,
+ XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED
+*/
+XMLPARSEAPI(void)
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status);
+
+/* Creates an XML_Parser object that can parse an external general
+ entity; context is a '\0'-terminated string specifying the parse
+ context; encoding is a '\0'-terminated string giving the name of
+ the externally specified encoding, or NULL if there is no
+ externally specified encoding. The context string consists of a
+ sequence of tokens separated by formfeeds (\f); a token consisting
+ of a name specifies that the general entity of the name is open; a
+ token of the form prefix=uri specifies the namespace for a
+ particular prefix; a token of the form =uri specifies the default
+ namespace. This can be called at any point after the first call to
+ an ExternalEntityRefHandler so longer as the parser has not yet
+ been freed. The new parser is completely independent and may
+ safely be used in a separate thread. The handlers and userData are
+ initialized from the parser argument. Returns NULL if out of memory.
+ Otherwise returns a new XML_Parser object.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ExternalEntityParserCreate(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *encoding);
+
+enum XML_ParamEntityParsing {
+ XML_PARAM_ENTITY_PARSING_NEVER,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+ XML_PARAM_ENTITY_PARSING_ALWAYS
+};
+
+/* Controls parsing of parameter entities (including the external DTD
+ subset). If parsing of parameter entities is enabled, then
+ references to external parameter entities (including the external
+ DTD subset) will be passed to the handler set with
+ XML_SetExternalEntityRefHandler. The context passed will be 0.
+
+ Unlike external general entities, external parameter entities can
+ only be parsed synchronously. If the external parameter entity is
+ to be parsed, it must be parsed during the call to the external
+ entity ref handler: the complete sequence of
+ XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and
+ XML_ParserFree calls must be made during this call. After
+ XML_ExternalEntityParserCreate has been called to create the parser
+ for the external parameter entity (context must be 0 for this
+ call), it is illegal to make any calls on the old parser until
+ XML_ParserFree has been called on the newly created parser.
+ If the library has been compiled without support for parameter
+ entity parsing (ie without XML_DTD being defined), then
+ XML_SetParamEntityParsing will return 0 if parsing of parameter
+ entities is requested; otherwise it will return non-zero.
+ Note: If XML_SetParamEntityParsing is called after XML_Parse or
+ XML_ParseBuffer, then it has no effect and will always return 0.
+*/
+XMLPARSEAPI(int)
+XML_SetParamEntityParsing(XML_Parser parser,
+ enum XML_ParamEntityParsing parsing);
+
+/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
+ XML_GetErrorCode returns information about the error.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse
+ location. They may be called from any callback called to report
+ some parse event; in this case the location is the location of the
+ first of the sequence of characters that generated the event. When
+ called from callbacks generated by declarations in the document
+ prologue, the location identified isn't as neatly defined, but will
+ be within the relevant markup. When called outside of the callback
+ functions, the position indicated will be just past the last parse
+ event (regardless of whether there was an associated callback).
+
+ They may also be called after returning from a call to XML_Parse
+ or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then
+ the location is the location of the character at which the error
+ was detected; otherwise the location is the location of the last
+ parse event, as described above.
+*/
+XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Index) XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+ Returns 0 if the event is in an internal entity.
+*/
+XMLPARSEAPI(int)
+XML_GetCurrentByteCount(XML_Parser parser);
+
+/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets
+ the integer pointed to by offset to the offset within this buffer
+ of the current parse position, and sets the integer pointed to by size
+ to the size of this buffer (the number of input bytes). Otherwise
+ returns a NULL pointer. Also returns a NULL pointer if a parse isn't
+ active.
+
+ NOTE: The character pointer returned should not be used outside
+ the handler that makes the call.
+*/
+XMLPARSEAPI(const char *)
+XML_GetInputContext(XML_Parser parser,
+ int *offset,
+ int *size);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+
+/* Frees the content model passed to the element declaration handler */
+XMLPARSEAPI(void)
+XML_FreeContentModel(XML_Parser parser, XML_Content *model);
+
+/* Exposing the memory handling functions used in Expat */
+XMLPARSEAPI(void *)
+XML_MemMalloc(XML_Parser parser, size_t size);
+
+XMLPARSEAPI(void *)
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size);
+
+XMLPARSEAPI(void)
+XML_MemFree(XML_Parser parser, void *ptr);
+
+/* Frees memory used by the parser. */
+XMLPARSEAPI(void)
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+XMLPARSEAPI(const XML_LChar *)
+XML_ErrorString(enum XML_Error code);
+
+/* Return a string containing the version number of this expat */
+XMLPARSEAPI(const XML_LChar *)
+XML_ExpatVersion(void);
+
+typedef struct {
+ int major;
+ int minor;
+ int micro;
+} XML_Expat_Version;
+
+/* Return an XML_Expat_Version structure containing numeric version
+ number information for this version of expat.
+*/
+XMLPARSEAPI(XML_Expat_Version)
+XML_ExpatVersionInfo(void);
+
+/* Added in Expat 1.95.5. */
+enum XML_FeatureEnum {
+ XML_FEATURE_END = 0,
+ XML_FEATURE_UNICODE,
+ XML_FEATURE_UNICODE_WCHAR_T,
+ XML_FEATURE_DTD,
+ XML_FEATURE_CONTEXT_BYTES,
+ XML_FEATURE_MIN_SIZE,
+ XML_FEATURE_SIZEOF_XML_CHAR,
+ XML_FEATURE_SIZEOF_XML_LCHAR,
+ XML_FEATURE_NS,
+ XML_FEATURE_LARGE_SIZE
+ /* Additional features must be added to the end of this enum. */
+};
+
+typedef struct {
+ enum XML_FeatureEnum feature;
+ const XML_LChar *name;
+ long int value;
+} XML_Feature;
+
+XMLPARSEAPI(const XML_Feature *)
+XML_GetFeatureList(void);
+
+
+/* Expat follows the GNU/Linux convention of odd number minor version for
+ beta/development releases and even number minor version for stable
+ releases. Micro is bumped with each release, and set to 0 with each
+ change to major or minor version.
+*/
+#define XML_MAJOR_VERSION 2
+#define XML_MINOR_VERSION 0
+#define XML_MICRO_VERSION 1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_INCLUDED */
diff --git a/lib/expat/expat_external.h b/lib/expat/expat_external.h
new file mode 100644
index 000000000..2c03284ea
--- /dev/null
+++ b/lib/expat/expat_external.h
@@ -0,0 +1,115 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef Expat_External_INCLUDED
+#define Expat_External_INCLUDED 1
+
+/* External API definitions */
+
+#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
+#define XML_USE_MSC_EXTENSIONS 1
+#endif
+
+/* Expat tries very hard to make the API boundary very specifically
+ defined. There are two macros defined to control this boundary;
+ each of these can be defined before including this header to
+ achieve some different behavior, but doing so it not recommended or
+ tested frequently.
+
+ XMLCALL - The calling convention to use for all calls across the
+ "library boundary." This will default to cdecl, and
+ try really hard to tell the compiler that's what we
+ want.
+
+ XMLIMPORT - Whatever magic is needed to note that a function is
+ to be imported from a dynamically loaded library
+ (.dll, .so, or .sl, depending on your platform).
+
+ The XMLCALL macro was added in Expat 1.95.7. The only one which is
+ expected to be directly useful in client code is XMLCALL.
+
+ Note that on at least some Unix versions, the Expat library must be
+ compiled with the cdecl calling convention as the default since
+ system headers may assume the cdecl convention.
+*/
+#ifndef XMLCALL
+#if defined(_MSC_VER)
+#define XMLCALL __cdecl
+#elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER)
+#define XMLCALL __attribute__((cdecl))
+#else
+/* For any platform which uses this definition and supports more than
+ one calling convention, we need to extend this definition to
+ declare the convention used on that platform, if it's possible to
+ do so.
+
+ If this is the case for your platform, please file a bug report
+ with information on how to identify your platform via the C
+ pre-processor and how to specify the same calling convention as the
+ platform's malloc() implementation.
+*/
+#define XMLCALL
+#endif
+#endif /* not defined XMLCALL */
+
+
+#if !defined(XML_STATIC) && !defined(XMLIMPORT)
+#ifndef XML_BUILDING_EXPAT
+/* using Expat from an application */
+
+#ifdef XML_USE_MSC_EXTENSIONS
+#define XMLIMPORT __declspec(dllimport)
+#endif
+
+#endif
+#endif /* not defined XML_STATIC */
+
+
+/* If we didn't define it above, define it away: */
+#ifndef XMLIMPORT
+#define XMLIMPORT
+#endif
+
+
+#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_UNICODE
+#endif
+
+#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
+#ifdef XML_UNICODE_WCHAR_T
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+#else
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE_WCHAR_T */
+#else /* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE */
+
+#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
+#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
+typedef __int64 XML_Index;
+typedef unsigned __int64 XML_Size;
+#else
+typedef long long XML_Index;
+typedef unsigned long long XML_Size;
+#endif
+#else
+typedef long XML_Index;
+typedef unsigned long XML_Size;
+#endif /* XML_LARGE_SIZE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_External_INCLUDED */
diff --git a/lib/expat/iasciitab.h b/lib/expat/iasciitab.h
new file mode 100644
index 000000000..24a1d5ccc
--- /dev/null
+++ b/lib/expat/iasciitab.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/lib/expat/internal.h b/lib/expat/internal.h
new file mode 100644
index 000000000..dd5454831
--- /dev/null
+++ b/lib/expat/internal.h
@@ -0,0 +1,73 @@
+/* internal.h
+
+ Internal definitions used by Expat. This is not needed to compile
+ client code.
+
+ The following calling convention macros are defined for frequently
+ called functions:
+
+ FASTCALL - Used for those internal functions that have a simple
+ body and a low number of arguments and local variables.
+
+ PTRCALL - Used for functions called though function pointers.
+
+ PTRFASTCALL - Like PTRCALL, but for low number of arguments.
+
+ inline - Used for selected internal functions for which inlining
+ may improve performance on some platforms.
+
+ Note: Use of these macros is based on judgement, not hard rules,
+ and therefore subject to change.
+*/
+
+#if defined(__GNUC__) && defined(__i386__) && !defined(__MINGW32__)
+/* We'll use this version by default only where we know it helps.
+
+ regparm() generates warnings on Solaris boxes. See SF bug #692878.
+
+ Instability reported with egcs on a RedHat Linux 7.3.
+ Let's comment out:
+ #define FASTCALL __attribute__((stdcall, regparm(3)))
+ and let's try this:
+*/
+#define FASTCALL __attribute__((regparm(3)))
+#define PTRFASTCALL __attribute__((regparm(3)))
+#endif
+
+/* Using __fastcall seems to have an unexpected negative effect under
+ MS VC++, especially for function pointers, so we won't use it for
+ now on that platform. It may be reconsidered for a future release
+ if it can be made more effective.
+ Likely reason: __fastcall on Windows is like stdcall, therefore
+ the compiler cannot perform stack optimizations for call clusters.
+*/
+
+/* Make sure all of these are defined if they aren't already. */
+
+#ifndef FASTCALL
+#define FASTCALL
+#endif
+
+#ifndef PTRCALL
+#define PTRCALL
+#endif
+
+#ifndef PTRFASTCALL
+#define PTRFASTCALL
+#endif
+
+#ifndef XML_MIN_SIZE
+#if !defined(__cplusplus) && !defined(inline)
+#ifdef __GNUC__
+#define inline __inline
+#endif /* __GNUC__ */
+#endif
+#endif /* XML_MIN_SIZE */
+
+#ifdef __cplusplus
+#define inline inline
+#else
+#ifndef inline
+#define inline
+#endif
+#endif
diff --git a/lib/expat/latin1tab.h b/lib/expat/latin1tab.h
new file mode 100644
index 000000000..53c25d76b
--- /dev/null
+++ b/lib/expat/latin1tab.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
diff --git a/lib/expat/nametab.h b/lib/expat/nametab.h
new file mode 100644
index 000000000..b05e62c77
--- /dev/null
+++ b/lib/expat/nametab.h
@@ -0,0 +1,150 @@
+static const unsigned namingBitmap[] = {
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
+0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
+0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
+0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
+0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
+0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
+0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
+0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
+0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
+0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
+0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
+0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
+0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
+0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
+0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
+0x40000000, 0xF580C900, 0x00000007, 0x02010800,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
+0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
+0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
+0x00000000, 0x00004C40, 0x00000000, 0x00000000,
+0x00000007, 0x00000000, 0x00000000, 0x00000000,
+0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
+0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
+0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
+0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
+0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
+0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
+0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
+0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
+0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
+0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
+0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
+0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
+0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
+0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
+0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
+0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
+};
+static const unsigned char nmstrtPages[] = {
+0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
+0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+static const unsigned char namePages[] = {
+0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
+0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/lib/expat/utf8tab.h b/lib/expat/utf8tab.h
new file mode 100644
index 000000000..7bb3e7760
--- /dev/null
+++ b/lib/expat/utf8tab.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+
+/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
diff --git a/lib/expat/winconfig.h b/lib/expat/winconfig.h
new file mode 100644
index 000000000..c1b791d62
--- /dev/null
+++ b/lib/expat/winconfig.h
@@ -0,0 +1,30 @@
+/*================================================================
+** Copyright 2000, Clark Cooper
+** All rights reserved.
+**
+** This is free software. You are permitted to copy, distribute, or modify
+** it under the terms of the MIT/X license (contained in the COPYING file
+** with this distribution.)
+*/
+
+#ifndef WINCONFIG_H
+#define WINCONFIG_H
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <memory.h>
+#include <string.h>
+
+#define XML_NS 1
+#define XML_DTD 1
+#define XML_CONTEXT_BYTES 1024
+
+/* we will assume all Windows platforms are little endian */
+#define BYTEORDER 1234
+
+/* Windows has memmove() available. */
+#define HAVE_MEMMOVE
+
+#endif /* ndef WINCONFIG_H */
diff --git a/lib/expat/xmlparse.c b/lib/expat/xmlparse.c
new file mode 100644
index 000000000..115b42127
--- /dev/null
+++ b/lib/expat/xmlparse.c
@@ -0,0 +1,6294 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stddef.h>
+#include <string.h> /* memset(), memcpy() */
+#include <assert.h>
+
+#define XML_BUILDING_EXPAT 1
+
+// 2013_04_09 _X: Quick and dirty "fix" for expat compilation under Linux:
+#define HAVE_MEMMOVE
+
+#ifdef COMPILED_FROM_DSP
+#include "winconfig.h"
+#elif defined(MACOS_CLASSIC)
+#include "macconfig.h"
+#elif defined(__amigaos4__)
+#include "amigaconfig.h"
+#elif defined(__WATCOMC__)
+#include "watcomconfig.h"
+#elif defined(HAVE_EXPAT_CONFIG_H)
+#include <expat_config.h>
+#endif /* ndef COMPILED_FROM_DSP */
+
+#include "ascii.h"
+#include "expat.h"
+
+#ifdef XML_UNICODE
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+#define XmlConvert XmlUtf16Convert
+#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
+#define XmlEncode XmlUtf16Encode
+/* Using pointer subtraction to convert to integer type. */
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
+typedef unsigned short ICHAR;
+#else
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+#define XmlConvert XmlUtf8Convert
+#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
+#define XmlEncode XmlUtf8Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+typedef char ICHAR;
+#endif
+
+
+#ifndef XML_NS
+
+#define XmlInitEncodingNS XmlInitEncoding
+#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
+#undef XmlGetInternalEncodingNS
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS XmlParseXmlDecl
+
+#endif
+
+#ifdef XML_UNICODE
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_T(x) (const wchar_t)x
+#define XML_L(x) L ## x
+#else
+#define XML_T(x) (const unsigned short)x
+#define XML_L(x) x
+#endif
+
+#else
+
+#define XML_T(x) x
+#define XML_L(x) x
+
+#endif
+
+/* Round up n to be a multiple of sz, where sz is a power of 2. */
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+
+/* Handle the case where memmove() doesn't exist. */
+#ifndef HAVE_MEMMOVE
+#ifdef HAVE_BCOPY
+#define memmove(d,s,l) bcopy((s),(d),(l))
+#else
+#error memmove does not exist on this platform, nor is a substitute available
+#endif /* HAVE_BCOPY */
+#endif /* HAVE_MEMMOVE */
+
+#include "internal.h"
+#include "xmltok.h"
+#include "xmlrole.h"
+
+typedef const XML_Char *KEY;
+
+typedef struct {
+ KEY name;
+} NAMED;
+
+typedef struct {
+ NAMED **v;
+ unsigned char power;
+ size_t size;
+ size_t used;
+ const XML_Memory_Handling_Suite *mem;
+} HASH_TABLE;
+
+/* Basic character hash algorithm, taken from Python's string hash:
+ h = h * 1000003 ^ character, the constant being a prime number.
+
+*/
+#ifdef XML_UNICODE
+#define CHAR_HASH(h, c) \
+ (((h) * 0xF4243) ^ (unsigned short)(c))
+#else
+#define CHAR_HASH(h, c) \
+ (((h) * 0xF4243) ^ (unsigned char)(c))
+#endif
+
+/* For probing (after a collision) we need a step size relative prime
+ to the hash table size, which is a power of 2. We use double-hashing,
+ since we can calculate a second hash value cheaply by taking those bits
+ of the first hash value that were discarded (masked out) when the table
+ index was calculated: index = hash & mask, where mask = table->size - 1.
+ We limit the maximum step size to table->size / 4 (mask >> 2) and make
+ it odd, since odd numbers are always relative prime to a power of 2.
+*/
+#define SECOND_HASH(hash, mask, power) \
+ ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
+#define PROBE_STEP(hash, mask, power) \
+ ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
+
+typedef struct {
+ NAMED **p;
+ NAMED **end;
+} HASH_TABLE_ITER;
+
+#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
+#define INIT_DATA_BUF_SIZE 1024
+#define INIT_ATTS_SIZE 16
+#define INIT_ATTS_VERSION 0xFFFFFFFF
+#define INIT_BLOCK_SIZE 1024
+#define INIT_BUFFER_SIZE 1024
+
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+ struct prefix *prefix;
+ struct binding *nextTagBinding;
+ struct binding *prevPrefixBinding;
+ const struct attribute_id *attId;
+ XML_Char *uri;
+ int uriLen;
+ int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+ const XML_Char *name;
+ BINDING *binding;
+} PREFIX;
+
+typedef struct {
+ const XML_Char *str;
+ const XML_Char *localPart;
+ const XML_Char *prefix;
+ int strLen;
+ int uriLen;
+ int prefixLen;
+} TAG_NAME;
+
+/* TAG represents an open element.
+ The name of the element is stored in both the document and API
+ encodings. The memory buffer 'buf' is a separately-allocated
+ memory area which stores the name. During the XML_Parse()/
+ XMLParseBuffer() when the element is open, the memory for the 'raw'
+ version of the name (in the document encoding) is shared with the
+ document buffer. If the element is open across calls to
+ XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
+ contain the 'raw' name as well.
+
+ A parser re-uses these structures, maintaining a list of allocated
+ TAG objects in a free list.
+*/
+typedef struct tag {
+ struct tag *parent; /* parent of this element */
+ const char *rawName; /* tagName in the original encoding */
+ int rawNameLength;
+ TAG_NAME name; /* tagName in the API encoding */
+ char *buf; /* buffer for name components */
+ char *bufEnd; /* end of the buffer */
+ BINDING *bindings;
+} TAG;
+
+typedef struct {
+ const XML_Char *name;
+ const XML_Char *textPtr;
+ int textLen; /* length in XML_Chars */
+ int processed; /* # of processed bytes - when suspended */
+ const XML_Char *systemId;
+ const XML_Char *base;
+ const XML_Char *publicId;
+ const XML_Char *notation;
+ XML_Bool open;
+ XML_Bool is_param;
+ XML_Bool is_internal; /* true if declared in internal subset outside PE */
+} ENTITY;
+
+typedef struct {
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ const XML_Char * name;
+ int firstchild;
+ int lastchild;
+ int childcnt;
+ int nextsib;
+} CONTENT_SCAFFOLD;
+
+#define INIT_SCAFFOLD_ELEMENTS 32
+
+typedef struct block {
+ struct block *next;
+ int size;
+ XML_Char s[1];
+} BLOCK;
+
+typedef struct {
+ BLOCK *blocks;
+ BLOCK *freeBlocks;
+ const XML_Char *end;
+ XML_Char *ptr;
+ XML_Char *start;
+ const XML_Memory_Handling_Suite *mem;
+} STRING_POOL;
+
+/* The XML_Char before the name is used to determine whether
+ an attribute has been specified. */
+typedef struct attribute_id {
+ XML_Char *name;
+ PREFIX *prefix;
+ XML_Bool maybeTokenized;
+ XML_Bool xmlns;
+} ATTRIBUTE_ID;
+
+typedef struct {
+ const ATTRIBUTE_ID *id;
+ XML_Bool isCdata;
+ const XML_Char *value;
+} DEFAULT_ATTRIBUTE;
+
+typedef struct {
+ unsigned long version;
+ unsigned long hash;
+ const XML_Char *uriName;
+} NS_ATT;
+
+typedef struct {
+ const XML_Char *name;
+ PREFIX *prefix;
+ const ATTRIBUTE_ID *idAtt;
+ int nDefaultAtts;
+ int allocDefaultAtts;
+ DEFAULT_ATTRIBUTE *defaultAtts;
+} ELEMENT_TYPE;
+
+typedef struct {
+ HASH_TABLE generalEntities;
+ HASH_TABLE elementTypes;
+ HASH_TABLE attributeIds;
+ HASH_TABLE prefixes;
+ STRING_POOL pool;
+ STRING_POOL entityValuePool;
+ /* false once a parameter entity reference has been skipped */
+ XML_Bool keepProcessing;
+ /* true once an internal or external PE reference has been encountered;
+ this includes the reference to an external subset */
+ XML_Bool hasParamEntityRefs;
+ XML_Bool standalone;
+#ifdef XML_DTD
+ /* indicates if external PE has been read */
+ XML_Bool paramEntityRead;
+ HASH_TABLE paramEntities;
+#endif /* XML_DTD */
+ PREFIX defaultPrefix;
+ /* === scaffolding for building content model === */
+ XML_Bool in_eldecl;
+ CONTENT_SCAFFOLD *scaffold;
+ unsigned contentStringLen;
+ unsigned scaffSize;
+ unsigned scaffCount;
+ int scaffLevel;
+ int *scaffIndex;
+} DTD;
+
+typedef struct open_internal_entity {
+ const char *internalEventPtr;
+ const char *internalEventEndPtr;
+ struct open_internal_entity *next;
+ ENTITY *entity;
+ int startTagLevel;
+ XML_Bool betweenDecl; /* WFC: PE Between Declarations */
+} OPEN_INTERNAL_ENTITY;
+
+typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr);
+
+static Processor prologProcessor;
+static Processor prologInitProcessor;
+static Processor contentProcessor;
+static Processor cdataSectionProcessor;
+#ifdef XML_DTD
+static Processor ignoreSectionProcessor;
+static Processor externalParEntProcessor;
+static Processor externalParEntInitProcessor;
+static Processor entityValueProcessor;
+static Processor entityValueInitProcessor;
+#endif /* XML_DTD */
+static Processor epilogProcessor;
+static Processor errorProcessor;
+static Processor externalEntityInitProcessor;
+static Processor externalEntityInitProcessor2;
+static Processor externalEntityInitProcessor3;
+static Processor externalEntityContentProcessor;
+static Processor internalEntityProcessor;
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next);
+static enum XML_Error
+initializeEncoding(XML_Parser parser);
+static enum XML_Error
+doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
+ const char *end, int tok, const char *next, const char **nextPtr,
+ XML_Bool haveMore);
+static enum XML_Error
+processInternalEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl);
+static enum XML_Error
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+ const char *start, const char *end, const char **endPtr,
+ XML_Bool haveMore);
+static enum XML_Error
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
+ const char *end, const char **nextPtr, XML_Bool haveMore);
+#ifdef XML_DTD
+static enum XML_Error
+doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
+ const char *end, const char **nextPtr, XML_Bool haveMore);
+#endif /* XML_DTD */
+
+static enum XML_Error
+storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
+static enum XML_Error
+addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
+ const XML_Char *uri, BINDING **bindingsPtr);
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
+ XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
+ const char *, const char *, STRING_POOL *);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
+ const char *, const char *, STRING_POOL *);
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+static int
+setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end);
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+
+static const XML_Char * getContext(XML_Parser parser);
+static XML_Bool
+setContext(XML_Parser parser, const XML_Char *context);
+
+static void FASTCALL normalizePublicId(XML_Char *s);
+
+static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
+/* do not call if parentParser != NULL */
+static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
+static void
+dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
+static int
+dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
+static int
+copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
+
+static NAMED *
+lookup(HASH_TABLE *table, KEY name, size_t createSize);
+static void FASTCALL
+hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
+static void FASTCALL hashTableClear(HASH_TABLE *);
+static void FASTCALL hashTableDestroy(HASH_TABLE *);
+static void FASTCALL
+hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
+
+static void FASTCALL
+poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
+static void FASTCALL poolClear(STRING_POOL *);
+static void FASTCALL poolDestroy(STRING_POOL *);
+static XML_Char *
+poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Char *
+poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
+static const XML_Char * FASTCALL
+poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *
+poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
+static const XML_Char * FASTCALL
+poolAppendString(STRING_POOL *pool, const XML_Char *s);
+
+static int FASTCALL nextScaffoldPart(XML_Parser parser);
+static XML_Content * build_model(XML_Parser parser);
+static ELEMENT_TYPE *
+getElementType(XML_Parser parser, const ENCODING *enc,
+ const char *ptr, const char *end);
+
+static XML_Parser
+parserCreate(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep,
+ DTD *dtd);
+static void
+parserInit(XML_Parser parser, const XML_Char *encodingName);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolChop(pool) ((void)--(pool->ptr))
+#define poolLastChar(pool) (((pool)->ptr)[-1])
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendChar(pool, c) \
+ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+ ? 0 \
+ : ((*((pool)->ptr)++ = c), 1))
+
+struct XML_ParserStruct {
+ /* The first member must be userData so that the XML_GetUserData
+ macro works. */
+ void *m_userData;
+ void *m_handlerArg;
+ char *m_buffer;
+ const XML_Memory_Handling_Suite m_mem;
+ /* first character to be parsed */
+ const char *m_bufferPtr;
+ /* past last character to be parsed */
+ char *m_bufferEnd;
+ /* allocated end of buffer */
+ const char *m_bufferLim;
+ XML_Index m_parseEndByteIndex;
+ const char *m_parseEndPtr;
+ XML_Char *m_dataBuf;
+ XML_Char *m_dataBufEnd;
+ XML_StartElementHandler m_startElementHandler;
+ XML_EndElementHandler m_endElementHandler;
+ XML_CharacterDataHandler m_characterDataHandler;
+ XML_ProcessingInstructionHandler m_processingInstructionHandler;
+ XML_CommentHandler m_commentHandler;
+ XML_StartCdataSectionHandler m_startCdataSectionHandler;
+ XML_EndCdataSectionHandler m_endCdataSectionHandler;
+ XML_DefaultHandler m_defaultHandler;
+ XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
+ XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
+ XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
+ XML_NotationDeclHandler m_notationDeclHandler;
+ XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
+ XML_NotStandaloneHandler m_notStandaloneHandler;
+ XML_ExternalEntityRefHandler m_externalEntityRefHandler;
+ XML_Parser m_externalEntityRefHandlerArg;
+ XML_SkippedEntityHandler m_skippedEntityHandler;
+ XML_UnknownEncodingHandler m_unknownEncodingHandler;
+ XML_ElementDeclHandler m_elementDeclHandler;
+ XML_AttlistDeclHandler m_attlistDeclHandler;
+ XML_EntityDeclHandler m_entityDeclHandler;
+ XML_XmlDeclHandler m_xmlDeclHandler;
+ const ENCODING *m_encoding;
+ INIT_ENCODING m_initEncoding;
+ const ENCODING *m_internalEncoding;
+ const XML_Char *m_protocolEncodingName;
+ XML_Bool m_ns;
+ XML_Bool m_ns_triplets;
+ void *m_unknownEncodingMem;
+ void *m_unknownEncodingData;
+ void *m_unknownEncodingHandlerData;
+ void (XMLCALL *m_unknownEncodingRelease)(void *);
+ PROLOG_STATE m_prologState;
+ Processor *m_processor;
+ enum XML_Error m_errorCode;
+ const char *m_eventPtr;
+ const char *m_eventEndPtr;
+ const char *m_positionPtr;
+ OPEN_INTERNAL_ENTITY *m_openInternalEntities;
+ OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
+ XML_Bool m_defaultExpandInternalEntities;
+ int m_tagLevel;
+ ENTITY *m_declEntity;
+ const XML_Char *m_doctypeName;
+ const XML_Char *m_doctypeSysid;
+ const XML_Char *m_doctypePubid;
+ const XML_Char *m_declAttributeType;
+ const XML_Char *m_declNotationName;
+ const XML_Char *m_declNotationPublicId;
+ ELEMENT_TYPE *m_declElementType;
+ ATTRIBUTE_ID *m_declAttributeId;
+ XML_Bool m_declAttributeIsCdata;
+ XML_Bool m_declAttributeIsId;
+ DTD *m_dtd;
+ const XML_Char *m_curBase;
+ TAG *m_tagStack;
+ TAG *m_freeTagList;
+ BINDING *m_inheritedBindings;
+ BINDING *m_freeBindingList;
+ int m_attsSize;
+ int m_nSpecifiedAtts;
+ int m_idAttIndex;
+ ATTRIBUTE *m_atts;
+ NS_ATT *m_nsAtts;
+ unsigned long m_nsAttsVersion;
+ unsigned char m_nsAttsPower;
+ POSITION m_position;
+ STRING_POOL m_tempPool;
+ STRING_POOL m_temp2Pool;
+ char *m_groupConnector;
+ unsigned int m_groupSize;
+ XML_Char m_namespaceSeparator;
+ XML_Parser m_parentParser;
+ XML_ParsingStatus m_parsingStatus;
+#ifdef XML_DTD
+ XML_Bool m_isParamEntity;
+ XML_Bool m_useForeignDTD;
+ enum XML_ParamEntityParsing m_paramEntityParsing;
+#endif
+};
+
+#define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
+#define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
+#define FREE(p) (parser->m_mem.free_fcn((p)))
+
+#define userData (parser->m_userData)
+#define handlerArg (parser->m_handlerArg)
+#define startElementHandler (parser->m_startElementHandler)
+#define endElementHandler (parser->m_endElementHandler)
+#define characterDataHandler (parser->m_characterDataHandler)
+#define processingInstructionHandler \
+ (parser->m_processingInstructionHandler)
+#define commentHandler (parser->m_commentHandler)
+#define startCdataSectionHandler \
+ (parser->m_startCdataSectionHandler)
+#define endCdataSectionHandler (parser->m_endCdataSectionHandler)
+#define defaultHandler (parser->m_defaultHandler)
+#define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
+#define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
+#define unparsedEntityDeclHandler \
+ (parser->m_unparsedEntityDeclHandler)
+#define notationDeclHandler (parser->m_notationDeclHandler)
+#define startNamespaceDeclHandler \
+ (parser->m_startNamespaceDeclHandler)
+#define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
+#define notStandaloneHandler (parser->m_notStandaloneHandler)
+#define externalEntityRefHandler \
+ (parser->m_externalEntityRefHandler)
+#define externalEntityRefHandlerArg \
+ (parser->m_externalEntityRefHandlerArg)
+#define internalEntityRefHandler \
+ (parser->m_internalEntityRefHandler)
+#define skippedEntityHandler (parser->m_skippedEntityHandler)
+#define unknownEncodingHandler (parser->m_unknownEncodingHandler)
+#define elementDeclHandler (parser->m_elementDeclHandler)
+#define attlistDeclHandler (parser->m_attlistDeclHandler)
+#define entityDeclHandler (parser->m_entityDeclHandler)
+#define xmlDeclHandler (parser->m_xmlDeclHandler)
+#define encoding (parser->m_encoding)
+#define initEncoding (parser->m_initEncoding)
+#define internalEncoding (parser->m_internalEncoding)
+#define unknownEncodingMem (parser->m_unknownEncodingMem)
+#define unknownEncodingData (parser->m_unknownEncodingData)
+#define unknownEncodingHandlerData \
+ (parser->m_unknownEncodingHandlerData)
+#define unknownEncodingRelease (parser->m_unknownEncodingRelease)
+#define protocolEncodingName (parser->m_protocolEncodingName)
+#define ns (parser->m_ns)
+#define ns_triplets (parser->m_ns_triplets)
+#define prologState (parser->m_prologState)
+#define processor (parser->m_processor)
+#define errorCode (parser->m_errorCode)
+#define eventPtr (parser->m_eventPtr)
+#define eventEndPtr (parser->m_eventEndPtr)
+#define positionPtr (parser->m_positionPtr)
+#define position (parser->m_position)
+#define openInternalEntities (parser->m_openInternalEntities)
+#define freeInternalEntities (parser->m_freeInternalEntities)
+#define defaultExpandInternalEntities \
+ (parser->m_defaultExpandInternalEntities)
+#define tagLevel (parser->m_tagLevel)
+#define buffer (parser->m_buffer)
+#define bufferPtr (parser->m_bufferPtr)
+#define bufferEnd (parser->m_bufferEnd)
+#define parseEndByteIndex (parser->m_parseEndByteIndex)
+#define parseEndPtr (parser->m_parseEndPtr)
+#define bufferLim (parser->m_bufferLim)
+#define dataBuf (parser->m_dataBuf)
+#define dataBufEnd (parser->m_dataBufEnd)
+#define _dtd (parser->m_dtd)
+#define curBase (parser->m_curBase)
+#define declEntity (parser->m_declEntity)
+#define doctypeName (parser->m_doctypeName)
+#define doctypeSysid (parser->m_doctypeSysid)
+#define doctypePubid (parser->m_doctypePubid)
+#define declAttributeType (parser->m_declAttributeType)
+#define declNotationName (parser->m_declNotationName)
+#define declNotationPublicId (parser->m_declNotationPublicId)
+#define declElementType (parser->m_declElementType)
+#define declAttributeId (parser->m_declAttributeId)
+#define declAttributeIsCdata (parser->m_declAttributeIsCdata)
+#define declAttributeIsId (parser->m_declAttributeIsId)
+#define freeTagList (parser->m_freeTagList)
+#define freeBindingList (parser->m_freeBindingList)
+#define inheritedBindings (parser->m_inheritedBindings)
+#define tagStack (parser->m_tagStack)
+#define atts (parser->m_atts)
+#define attsSize (parser->m_attsSize)
+#define nSpecifiedAtts (parser->m_nSpecifiedAtts)
+#define idAttIndex (parser->m_idAttIndex)
+#define nsAtts (parser->m_nsAtts)
+#define nsAttsVersion (parser->m_nsAttsVersion)
+#define nsAttsPower (parser->m_nsAttsPower)
+#define tempPool (parser->m_tempPool)
+#define temp2Pool (parser->m_temp2Pool)
+#define groupConnector (parser->m_groupConnector)
+#define groupSize (parser->m_groupSize)
+#define namespaceSeparator (parser->m_namespaceSeparator)
+#define parentParser (parser->m_parentParser)
+#define ps_parsing (parser->m_parsingStatus.parsing)
+#define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
+#ifdef XML_DTD
+#define isParamEntity (parser->m_isParamEntity)
+#define useForeignDTD (parser->m_useForeignDTD)
+#define paramEntityParsing (parser->m_paramEntityParsing)
+#endif /* XML_DTD */
+
+XML_Parser XMLCALL
+XML_ParserCreate(const XML_Char *encodingName)
+{
+ return XML_ParserCreate_MM(encodingName, NULL, NULL);
+}
+
+XML_Parser XMLCALL
+XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+{
+ XML_Char tmp[2];
+ *tmp = nsSep;
+ return XML_ParserCreate_MM(encodingName, NULL, tmp);
+}
+
+static const XML_Char implicitContext[] = {
+ ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
+ ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
+ ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
+ ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
+ ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
+ ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
+};
+
+XML_Parser XMLCALL
+XML_ParserCreate_MM(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep)
+{
+ XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
+ if (parser != NULL && ns) {
+ /* implicit context only set for root parser, since child
+ parsers (i.e. external entity parsers) will inherit it
+ */
+ if (!setContext(parser, implicitContext)) {
+ XML_ParserFree(parser);
+ return NULL;
+ }
+ }
+ return parser;
+}
+
+static XML_Parser
+parserCreate(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep,
+ DTD *dtd)
+{
+ XML_Parser parser;
+
+ if (memsuite) {
+ XML_Memory_Handling_Suite *mtemp;
+ parser = (XML_Parser)
+ memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
+ if (parser != NULL) {
+ mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
+ mtemp->malloc_fcn = memsuite->malloc_fcn;
+ mtemp->realloc_fcn = memsuite->realloc_fcn;
+ mtemp->free_fcn = memsuite->free_fcn;
+ }
+ }
+ else {
+ XML_Memory_Handling_Suite *mtemp;
+ parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
+ if (parser != NULL) {
+ mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
+ mtemp->malloc_fcn = malloc;
+ mtemp->realloc_fcn = realloc;
+ mtemp->free_fcn = free;
+ }
+ }
+
+ if (!parser)
+ return parser;
+
+ buffer = NULL;
+ bufferLim = NULL;
+
+ attsSize = INIT_ATTS_SIZE;
+ atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
+ if (atts == NULL) {
+ FREE(parser);
+ return NULL;
+ }
+ dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+ if (dataBuf == NULL) {
+ FREE(atts);
+ FREE(parser);
+ return NULL;
+ }
+ dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+
+ if (dtd)
+ _dtd = dtd;
+ else {
+ _dtd = dtdCreate(&parser->m_mem);
+ if (_dtd == NULL) {
+ FREE(dataBuf);
+ FREE(atts);
+ FREE(parser);
+ return NULL;
+ }
+ }
+
+ freeBindingList = NULL;
+ freeTagList = NULL;
+ freeInternalEntities = NULL;
+
+ groupSize = 0;
+ groupConnector = NULL;
+
+ unknownEncodingHandler = NULL;
+ unknownEncodingHandlerData = NULL;
+
+ namespaceSeparator = ASCII_EXCL;
+ ns = XML_FALSE;
+ ns_triplets = XML_FALSE;
+
+ nsAtts = NULL;
+ nsAttsVersion = 0;
+ nsAttsPower = 0;
+
+ poolInit(&tempPool, &(parser->m_mem));
+ poolInit(&temp2Pool, &(parser->m_mem));
+ parserInit(parser, encodingName);
+
+ if (encodingName && !protocolEncodingName) {
+ XML_ParserFree(parser);
+ return NULL;
+ }
+
+ if (nameSep) {
+ ns = XML_TRUE;
+ internalEncoding = XmlGetInternalEncodingNS();
+ namespaceSeparator = *nameSep;
+ }
+ else {
+ internalEncoding = XmlGetInternalEncoding();
+ }
+
+ return parser;
+}
+
+static void
+parserInit(XML_Parser parser, const XML_Char *encodingName)
+{
+ processor = prologInitProcessor;
+ XmlPrologStateInit(&prologState);
+ protocolEncodingName = (encodingName != NULL
+ ? poolCopyString(&tempPool, encodingName)
+ : NULL);
+ curBase = NULL;
+ XmlInitEncoding(&initEncoding, &encoding, 0);
+ userData = NULL;
+ handlerArg = NULL;
+ startElementHandler = NULL;
+ endElementHandler = NULL;
+ characterDataHandler = NULL;
+ processingInstructionHandler = NULL;
+ commentHandler = NULL;
+ startCdataSectionHandler = NULL;
+ endCdataSectionHandler = NULL;
+ defaultHandler = NULL;
+ startDoctypeDeclHandler = NULL;
+ endDoctypeDeclHandler = NULL;
+ unparsedEntityDeclHandler = NULL;
+ notationDeclHandler = NULL;
+ startNamespaceDeclHandler = NULL;
+ endNamespaceDeclHandler = NULL;
+ notStandaloneHandler = NULL;
+ externalEntityRefHandler = NULL;
+ externalEntityRefHandlerArg = parser;
+ skippedEntityHandler = NULL;
+ elementDeclHandler = NULL;
+ attlistDeclHandler = NULL;
+ entityDeclHandler = NULL;
+ xmlDeclHandler = NULL;
+ bufferPtr = buffer;
+ bufferEnd = buffer;
+ parseEndByteIndex = 0;
+ parseEndPtr = NULL;
+ declElementType = NULL;
+ declAttributeId = NULL;
+ declEntity = NULL;
+ doctypeName = NULL;
+ doctypeSysid = NULL;
+ doctypePubid = NULL;
+ declAttributeType = NULL;
+ declNotationName = NULL;
+ declNotationPublicId = NULL;
+ declAttributeIsCdata = XML_FALSE;
+ declAttributeIsId = XML_FALSE;
+ memset(&position, 0, sizeof(POSITION));
+ errorCode = XML_ERROR_NONE;
+ eventPtr = NULL;
+ eventEndPtr = NULL;
+ positionPtr = NULL;
+ openInternalEntities = NULL;
+ defaultExpandInternalEntities = XML_TRUE;
+ tagLevel = 0;
+ tagStack = NULL;
+ inheritedBindings = NULL;
+ nSpecifiedAtts = 0;
+ unknownEncodingMem = NULL;
+ unknownEncodingRelease = NULL;
+ unknownEncodingData = NULL;
+ parentParser = NULL;
+ ps_parsing = XML_INITIALIZED;
+#ifdef XML_DTD
+ isParamEntity = XML_FALSE;
+ useForeignDTD = XML_FALSE;
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+}
+
+/* moves list of bindings to freeBindingList */
+static void FASTCALL
+moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
+{
+ while (bindings) {
+ BINDING *b = bindings;
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ }
+}
+
+XML_Bool XMLCALL
+XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
+{
+ TAG *tStk;
+ OPEN_INTERNAL_ENTITY *openEntityList;
+ if (parentParser)
+ return XML_FALSE;
+ /* move tagStack to freeTagList */
+ tStk = tagStack;
+ while (tStk) {
+ TAG *tag = tStk;
+ tStk = tStk->parent;
+ tag->parent = freeTagList;
+ moveToFreeBindingList(parser, tag->bindings);
+ tag->bindings = NULL;
+ freeTagList = tag;
+ }
+ /* move openInternalEntities to freeInternalEntities */
+ openEntityList = openInternalEntities;
+ while (openEntityList) {
+ OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
+ openEntityList = openEntity->next;
+ openEntity->next = freeInternalEntities;
+ freeInternalEntities = openEntity;
+ }
+ moveToFreeBindingList(parser, inheritedBindings);
+ FREE(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ poolClear(&tempPool);
+ poolClear(&temp2Pool);
+ parserInit(parser, encodingName);
+ dtdReset(_dtd, &parser->m_mem);
+ return setContext(parser, implicitContext);
+}
+
+enum XML_Status XMLCALL
+XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ /* Block after XML_Parse()/XML_ParseBuffer() has been called.
+ XXX There's no way for the caller to determine which of the
+ XXX possible error cases caused the XML_STATUS_ERROR return.
+ */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return XML_STATUS_ERROR;
+ if (encodingName == NULL)
+ protocolEncodingName = NULL;
+ else {
+ protocolEncodingName = poolCopyString(&tempPool, encodingName);
+ if (!protocolEncodingName)
+ return XML_STATUS_ERROR;
+ }
+ return XML_STATUS_OK;
+}
+
+XML_Parser XMLCALL
+XML_ExternalEntityParserCreate(XML_Parser oldParser,
+ const XML_Char *context,
+ const XML_Char *encodingName)
+{
+ XML_Parser parser = oldParser;
+ DTD *newDtd = NULL;
+ DTD *oldDtd = _dtd;
+ XML_StartElementHandler oldStartElementHandler = startElementHandler;
+ XML_EndElementHandler oldEndElementHandler = endElementHandler;
+ XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler
+ = processingInstructionHandler;
+ XML_CommentHandler oldCommentHandler = commentHandler;
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler
+ = startCdataSectionHandler;
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler
+ = endCdataSectionHandler;
+ XML_DefaultHandler oldDefaultHandler = defaultHandler;
+ XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
+ = unparsedEntityDeclHandler;
+ XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
+ = startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
+ = endNamespaceDeclHandler;
+ XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler
+ = externalEntityRefHandler;
+ XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler
+ = unknownEncodingHandler;
+ XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
+ XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
+ XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
+ XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
+ ELEMENT_TYPE * oldDeclElementType = declElementType;
+
+ void *oldUserData = userData;
+ void *oldHandlerArg = handlerArg;
+ XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+ XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+#ifdef XML_DTD
+ enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
+ int oldInEntityValue = prologState.inEntityValue;
+#endif
+ XML_Bool oldns_triplets = ns_triplets;
+
+#ifdef XML_DTD
+ if (!context)
+ newDtd = oldDtd;
+#endif /* XML_DTD */
+
+ /* Note that the magical uses of the pre-processor to make field
+ access look more like C++ require that `parser' be overwritten
+ here. This makes this function more painful to follow than it
+ would be otherwise.
+ */
+ if (ns) {
+ XML_Char tmp[2];
+ *tmp = namespaceSeparator;
+ parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
+ }
+ else {
+ parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
+ }
+
+ if (!parser)
+ return NULL;
+
+ startElementHandler = oldStartElementHandler;
+ endElementHandler = oldEndElementHandler;
+ characterDataHandler = oldCharacterDataHandler;
+ processingInstructionHandler = oldProcessingInstructionHandler;
+ commentHandler = oldCommentHandler;
+ startCdataSectionHandler = oldStartCdataSectionHandler;
+ endCdataSectionHandler = oldEndCdataSectionHandler;
+ defaultHandler = oldDefaultHandler;
+ unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
+ notationDeclHandler = oldNotationDeclHandler;
+ startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+ endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+ notStandaloneHandler = oldNotStandaloneHandler;
+ externalEntityRefHandler = oldExternalEntityRefHandler;
+ skippedEntityHandler = oldSkippedEntityHandler;
+ unknownEncodingHandler = oldUnknownEncodingHandler;
+ elementDeclHandler = oldElementDeclHandler;
+ attlistDeclHandler = oldAttlistDeclHandler;
+ entityDeclHandler = oldEntityDeclHandler;
+ xmlDeclHandler = oldXmlDeclHandler;
+ declElementType = oldDeclElementType;
+ userData = oldUserData;
+ if (oldUserData == oldHandlerArg)
+ handlerArg = userData;
+ else
+ handlerArg = parser;
+ if (oldExternalEntityRefHandlerArg != oldParser)
+ externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+ defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ ns_triplets = oldns_triplets;
+ parentParser = oldParser;
+#ifdef XML_DTD
+ paramEntityParsing = oldParamEntityParsing;
+ prologState.inEntityValue = oldInEntityValue;
+ if (context) {
+#endif /* XML_DTD */
+ if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
+ || !setContext(parser, context)) {
+ XML_ParserFree(parser);
+ return NULL;
+ }
+ processor = externalEntityInitProcessor;
+#ifdef XML_DTD
+ }
+ else {
+ /* The DTD instance referenced by _dtd is shared between the document's
+ root parser and external PE parsers, therefore one does not need to
+ call setContext. In addition, one also *must* not call setContext,
+ because this would overwrite existing prefix->binding pointers in
+ _dtd with ones that get destroyed with the external PE parser.
+ This would leave those prefixes with dangling pointers.
+ */
+ isParamEntity = XML_TRUE;
+ XmlPrologStateInitExternalEntity(&prologState);
+ processor = externalParEntInitProcessor;
+ }
+#endif /* XML_DTD */
+ return parser;
+}
+
+static void FASTCALL
+destroyBindings(BINDING *bindings, XML_Parser parser)
+{
+ for (;;) {
+ BINDING *b = bindings;
+ if (!b)
+ break;
+ bindings = b->nextTagBinding;
+ FREE(b->uri);
+ FREE(b);
+ }
+}
+
+void XMLCALL
+XML_ParserFree(XML_Parser parser)
+{
+ TAG *tagList;
+ OPEN_INTERNAL_ENTITY *entityList;
+ if (parser == NULL)
+ return;
+ /* free tagStack and freeTagList */
+ tagList = tagStack;
+ for (;;) {
+ TAG *p;
+ if (tagList == NULL) {
+ if (freeTagList == NULL)
+ break;
+ tagList = freeTagList;
+ freeTagList = NULL;
+ }
+ p = tagList;
+ tagList = tagList->parent;
+ FREE(p->buf);
+ destroyBindings(p->bindings, parser);
+ FREE(p);
+ }
+ /* free openInternalEntities and freeInternalEntities */
+ entityList = openInternalEntities;
+ for (;;) {
+ OPEN_INTERNAL_ENTITY *openEntity;
+ if (entityList == NULL) {
+ if (freeInternalEntities == NULL)
+ break;
+ entityList = freeInternalEntities;
+ freeInternalEntities = NULL;
+ }
+ openEntity = entityList;
+ entityList = entityList->next;
+ FREE(openEntity);
+ }
+
+ destroyBindings(freeBindingList, parser);
+ destroyBindings(inheritedBindings, parser);
+ poolDestroy(&tempPool);
+ poolDestroy(&temp2Pool);
+#ifdef XML_DTD
+ /* external parameter entity parsers share the DTD structure
+ parser->m_dtd with the root parser, so we must not destroy it
+ */
+ if (!isParamEntity && _dtd)
+#else
+ if (_dtd)
+#endif /* XML_DTD */
+ dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
+ FREE((void *)atts);
+ FREE(groupConnector);
+ FREE(buffer);
+ FREE(dataBuf);
+ FREE(nsAtts);
+ FREE(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ FREE(parser);
+}
+
+void XMLCALL
+XML_UseParserAsHandlerArg(XML_Parser parser)
+{
+ handlerArg = parser;
+}
+
+enum XML_Error XMLCALL
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
+{
+#ifdef XML_DTD
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
+ useForeignDTD = useDTD;
+ return XML_ERROR_NONE;
+#else
+ return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
+#endif
+}
+
+void XMLCALL
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
+{
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return;
+ ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
+}
+
+void XMLCALL
+XML_SetUserData(XML_Parser parser, void *p)
+{
+ if (handlerArg == userData)
+ handlerArg = userData = p;
+ else
+ userData = p;
+}
+
+enum XML_Status XMLCALL
+XML_SetBase(XML_Parser parser, const XML_Char *p)
+{
+ if (p) {
+ p = poolCopyString(&_dtd->pool, p);
+ if (!p)
+ return XML_STATUS_ERROR;
+ curBase = p;
+ }
+ else
+ curBase = NULL;
+ return XML_STATUS_OK;
+}
+
+const XML_Char * XMLCALL
+XML_GetBase(XML_Parser parser)
+{
+ return curBase;
+}
+
+int XMLCALL
+XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+ return nSpecifiedAtts;
+}
+
+int XMLCALL
+XML_GetIdAttributeIndex(XML_Parser parser)
+{
+ return idAttIndex;
+}
+
+void XMLCALL
+XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end)
+{
+ startElementHandler = start;
+ endElementHandler = end;
+}
+
+void XMLCALL
+XML_SetStartElementHandler(XML_Parser parser,
+ XML_StartElementHandler start) {
+ startElementHandler = start;
+}
+
+void XMLCALL
+XML_SetEndElementHandler(XML_Parser parser,
+ XML_EndElementHandler end) {
+ endElementHandler = end;
+}
+
+void XMLCALL
+XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler)
+{
+ characterDataHandler = handler;
+}
+
+void XMLCALL
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler)
+{
+ processingInstructionHandler = handler;
+}
+
+void XMLCALL
+XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler)
+{
+ commentHandler = handler;
+}
+
+void XMLCALL
+XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end)
+{
+ startCdataSectionHandler = start;
+ endCdataSectionHandler = end;
+}
+
+void XMLCALL
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start) {
+ startCdataSectionHandler = start;
+}
+
+void XMLCALL
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+ XML_EndCdataSectionHandler end) {
+ endCdataSectionHandler = end;
+}
+
+void XMLCALL
+XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = XML_FALSE;
+}
+
+void XMLCALL
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = XML_TRUE;
+}
+
+void XMLCALL
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end)
+{
+ startDoctypeDeclHandler = start;
+ endDoctypeDeclHandler = end;
+}
+
+void XMLCALL
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start) {
+ startDoctypeDeclHandler = start;
+}
+
+void XMLCALL
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+ XML_EndDoctypeDeclHandler end) {
+ endDoctypeDeclHandler = end;
+}
+
+void XMLCALL
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler)
+{
+ unparsedEntityDeclHandler = handler;
+}
+
+void XMLCALL
+XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler)
+{
+ notationDeclHandler = handler;
+}
+
+void XMLCALL
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end)
+{
+ startNamespaceDeclHandler = start;
+ endNamespaceDeclHandler = end;
+}
+
+void XMLCALL
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start) {
+ startNamespaceDeclHandler = start;
+}
+
+void XMLCALL
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+ XML_EndNamespaceDeclHandler end) {
+ endNamespaceDeclHandler = end;
+}
+
+void XMLCALL
+XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler)
+{
+ notStandaloneHandler = handler;
+}
+
+void XMLCALL
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler)
+{
+ externalEntityRefHandler = handler;
+}
+
+void XMLCALL
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+ if (arg)
+ externalEntityRefHandlerArg = (XML_Parser)arg;
+ else
+ externalEntityRefHandlerArg = parser;
+}
+
+void XMLCALL
+XML_SetSkippedEntityHandler(XML_Parser parser,
+ XML_SkippedEntityHandler handler)
+{
+ skippedEntityHandler = handler;
+}
+
+void XMLCALL
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *data)
+{
+ unknownEncodingHandler = handler;
+ unknownEncodingHandlerData = data;
+}
+
+void XMLCALL
+XML_SetElementDeclHandler(XML_Parser parser,
+ XML_ElementDeclHandler eldecl)
+{
+ elementDeclHandler = eldecl;
+}
+
+void XMLCALL
+XML_SetAttlistDeclHandler(XML_Parser parser,
+ XML_AttlistDeclHandler attdecl)
+{
+ attlistDeclHandler = attdecl;
+}
+
+void XMLCALL
+XML_SetEntityDeclHandler(XML_Parser parser,
+ XML_EntityDeclHandler handler)
+{
+ entityDeclHandler = handler;
+}
+
+void XMLCALL
+XML_SetXmlDeclHandler(XML_Parser parser,
+ XML_XmlDeclHandler handler) {
+ xmlDeclHandler = handler;
+}
+
+int XMLCALL
+XML_SetParamEntityParsing(XML_Parser parser,
+ enum XML_ParamEntityParsing peParsing)
+{
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return 0;
+#ifdef XML_DTD
+ paramEntityParsing = peParsing;
+ return 1;
+#else
+ return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+}
+
+enum XML_Status XMLCALL
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+{
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ errorCode = XML_ERROR_SUSPENDED;
+ return XML_STATUS_ERROR;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return XML_STATUS_ERROR;
+ default:
+ ps_parsing = XML_PARSING;
+ }
+
+ if (len == 0) {
+ ps_finalBuffer = (XML_Bool)isFinal;
+ if (!isFinal)
+ return XML_STATUS_OK;
+ positionPtr = bufferPtr;
+ parseEndPtr = bufferEnd;
+
+ /* If data are left over from last buffer, and we now know that these
+ data are the final chunk of input, then we have to check them again
+ to detect errors based on that fact.
+ */
+ errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
+
+ if (errorCode == XML_ERROR_NONE) {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ positionPtr = bufferPtr;
+ return XML_STATUS_SUSPENDED;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ ps_parsing = XML_FINISHED;
+ /* fall through */
+ default:
+ return XML_STATUS_OK;
+ }
+ }
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+#ifndef XML_CONTEXT_BYTES
+ else if (bufferPtr == bufferEnd) {
+ const char *end;
+ int nLeftOver;
+ enum XML_Error result;
+ parseEndByteIndex += len;
+ positionPtr = s;
+ ps_finalBuffer = (XML_Bool)isFinal;
+
+ errorCode = processor(parser, s, parseEndPtr = s + len, &end);
+
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ else {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ result = XML_STATUS_SUSPENDED;
+ break;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ result = XML_STATUS_OK;
+ if (isFinal) {
+ ps_parsing = XML_FINISHED;
+ return result;
+ }
+ }
+ }
+
+ XmlUpdatePosition(encoding, positionPtr, end, &position);
+ nLeftOver = s + len - end;
+ if (nLeftOver) {
+ if (buffer == NULL || nLeftOver > bufferLim - buffer) {
+ /* FIXME avoid integer overflow */
+ char *temp;
+ temp = (buffer == NULL
+ ? (char *)MALLOC(len * 2)
+ : (char *)REALLOC(buffer, len * 2));
+ if (temp == NULL) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return XML_STATUS_ERROR;
+ }
+ buffer = temp;
+ if (!buffer) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = NULL;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ bufferLim = buffer + len * 2;
+ }
+ memcpy(buffer, end, nLeftOver);
+ }
+ bufferPtr = buffer;
+ bufferEnd = buffer + nLeftOver;
+ positionPtr = bufferPtr;
+ parseEndPtr = bufferEnd;
+ eventPtr = bufferPtr;
+ eventEndPtr = bufferPtr;
+ return result;
+ }
+#endif /* not defined XML_CONTEXT_BYTES */
+ else {
+ void *buff = XML_GetBuffer(parser, len);
+ if (buff == NULL)
+ return XML_STATUS_ERROR;
+ else {
+ memcpy(buff, s, len);
+ return XML_ParseBuffer(parser, len, isFinal);
+ }
+ }
+}
+
+enum XML_Status XMLCALL
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+{
+ const char *start;
+ enum XML_Status result = XML_STATUS_OK;
+
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ errorCode = XML_ERROR_SUSPENDED;
+ return XML_STATUS_ERROR;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return XML_STATUS_ERROR;
+ default:
+ ps_parsing = XML_PARSING;
+ }
+
+ start = bufferPtr;
+ positionPtr = start;
+ bufferEnd += len;
+ parseEndPtr = bufferEnd;
+ parseEndByteIndex += len;
+ ps_finalBuffer = (XML_Bool)isFinal;
+
+ errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
+
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ else {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ result = XML_STATUS_SUSPENDED;
+ break;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ if (isFinal) {
+ ps_parsing = XML_FINISHED;
+ return result;
+ }
+ default: ; /* should not happen */
+ }
+ }
+
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ positionPtr = bufferPtr;
+ return result;
+}
+
+void * XMLCALL
+XML_GetBuffer(XML_Parser parser, int len)
+{
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ errorCode = XML_ERROR_SUSPENDED;
+ return NULL;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return NULL;
+ default: ;
+ }
+
+ if (len > bufferLim - bufferEnd) {
+ /* FIXME avoid integer overflow */
+ int neededSize = len + (int)(bufferEnd - bufferPtr);
+#ifdef XML_CONTEXT_BYTES
+ int keep = (int)(bufferPtr - buffer);
+
+ if (keep > XML_CONTEXT_BYTES)
+ keep = XML_CONTEXT_BYTES;
+ neededSize += keep;
+#endif /* defined XML_CONTEXT_BYTES */
+ if (neededSize <= bufferLim - buffer) {
+#ifdef XML_CONTEXT_BYTES
+ if (keep < bufferPtr - buffer) {
+ int offset = (int)(bufferPtr - buffer) - keep;
+ memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
+ bufferEnd -= offset;
+ bufferPtr -= offset;
+ }
+#else
+ memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+ bufferEnd = buffer + (bufferEnd - bufferPtr);
+ bufferPtr = buffer;
+#endif /* not defined XML_CONTEXT_BYTES */
+ }
+ else {
+ char *newBuf;
+ int bufferSize = (int)(bufferLim - bufferPtr);
+ if (bufferSize == 0)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+ bufferSize *= 2;
+ } while (bufferSize < neededSize);
+ newBuf = (char *)MALLOC(bufferSize);
+ if (newBuf == 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
+ bufferLim = newBuf + bufferSize;
+#ifdef XML_CONTEXT_BYTES
+ if (bufferPtr) {
+ int keep = (int)(bufferPtr - buffer);
+ if (keep > XML_CONTEXT_BYTES)
+ keep = XML_CONTEXT_BYTES;
+ memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
+ FREE(buffer);
+ buffer = newBuf;
+ bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
+ bufferPtr = buffer + keep;
+ }
+ else {
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+ }
+#else
+ if (bufferPtr) {
+ memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+ FREE(buffer);
+ }
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+#endif /* not defined XML_CONTEXT_BYTES */
+ }
+ }
+ return bufferEnd;
+}
+
+enum XML_Status XMLCALL
+XML_StopParser(XML_Parser parser, XML_Bool resumable)
+{
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ if (resumable) {
+ errorCode = XML_ERROR_SUSPENDED;
+ return XML_STATUS_ERROR;
+ }
+ ps_parsing = XML_FINISHED;
+ break;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return XML_STATUS_ERROR;
+ default:
+ if (resumable) {
+#ifdef XML_DTD
+ if (isParamEntity) {
+ errorCode = XML_ERROR_SUSPEND_PE;
+ return XML_STATUS_ERROR;
+ }
+#endif
+ ps_parsing = XML_SUSPENDED;
+ }
+ else
+ ps_parsing = XML_FINISHED;
+ }
+ return XML_STATUS_OK;
+}
+
+enum XML_Status XMLCALL
+XML_ResumeParser(XML_Parser parser)
+{
+ enum XML_Status result = XML_STATUS_OK;
+
+ if (ps_parsing != XML_SUSPENDED) {
+ errorCode = XML_ERROR_NOT_SUSPENDED;
+ return XML_STATUS_ERROR;
+ }
+ ps_parsing = XML_PARSING;
+
+ errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
+
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ else {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ result = XML_STATUS_SUSPENDED;
+ break;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ if (ps_finalBuffer) {
+ ps_parsing = XML_FINISHED;
+ return result;
+ }
+ default: ;
+ }
+ }
+
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ positionPtr = bufferPtr;
+ return result;
+}
+
+void XMLCALL
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
+{
+ assert(status != NULL);
+ *status = parser->m_parsingStatus;
+}
+
+enum XML_Error XMLCALL
+XML_GetErrorCode(XML_Parser parser)
+{
+ return errorCode;
+}
+
+XML_Index XMLCALL
+XML_GetCurrentByteIndex(XML_Parser parser)
+{
+ if (eventPtr)
+ return parseEndByteIndex - (parseEndPtr - eventPtr);
+ return -1;
+}
+
+int XMLCALL
+XML_GetCurrentByteCount(XML_Parser parser)
+{
+ if (eventEndPtr && eventPtr)
+ return (int)(eventEndPtr - eventPtr);
+ return 0;
+}
+
+const char * XMLCALL
+XML_GetInputContext(XML_Parser parser, int *offset, int *size)
+{
+#ifdef XML_CONTEXT_BYTES
+ if (eventPtr && buffer) {
+ *offset = (int)(eventPtr - buffer);
+ *size = (int)(bufferEnd - buffer);
+ return buffer;
+ }
+#endif /* defined XML_CONTEXT_BYTES */
+ return (char *) 0;
+}
+
+XML_Size XMLCALL
+XML_GetCurrentLineNumber(XML_Parser parser)
+{
+ if (eventPtr && eventPtr >= positionPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.lineNumber + 1;
+}
+
+XML_Size XMLCALL
+XML_GetCurrentColumnNumber(XML_Parser parser)
+{
+ if (eventPtr && eventPtr >= positionPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.columnNumber;
+}
+
+void XMLCALL
+XML_FreeContentModel(XML_Parser parser, XML_Content *model)
+{
+ FREE(model);
+}
+
+void * XMLCALL
+XML_MemMalloc(XML_Parser parser, size_t size)
+{
+ return MALLOC(size);
+}
+
+void * XMLCALL
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
+{
+ return REALLOC(ptr, size);
+}
+
+void XMLCALL
+XML_MemFree(XML_Parser parser, void *ptr)
+{
+ FREE(ptr);
+}
+
+void XMLCALL
+XML_DefaultCurrent(XML_Parser parser)
+{
+ if (defaultHandler) {
+ if (openInternalEntities)
+ reportDefault(parser,
+ internalEncoding,
+ openInternalEntities->internalEventPtr,
+ openInternalEntities->internalEventEndPtr);
+ else
+ reportDefault(parser, encoding, eventPtr, eventEndPtr);
+ }
+}
+
+const XML_LChar * XMLCALL
+XML_ErrorString(enum XML_Error code)
+{
+ static const XML_LChar* const message[] = {
+ 0,
+ XML_L("out of memory"),
+ XML_L("syntax error"),
+ XML_L("no element found"),
+ XML_L("not well-formed (invalid token)"),
+ XML_L("unclosed token"),
+ XML_L("partial character"),
+ XML_L("mismatched tag"),
+ XML_L("duplicate attribute"),
+ XML_L("junk after document element"),
+ XML_L("illegal parameter entity reference"),
+ XML_L("undefined entity"),
+ XML_L("recursive entity reference"),
+ XML_L("asynchronous entity"),
+ XML_L("reference to invalid character number"),
+ XML_L("reference to binary entity"),
+ XML_L("reference to external entity in attribute"),
+ XML_L("XML or text declaration not at start of entity"),
+ XML_L("unknown encoding"),
+ XML_L("encoding specified in XML declaration is incorrect"),
+ XML_L("unclosed CDATA section"),
+ XML_L("error in processing external entity reference"),
+ XML_L("document is not standalone"),
+ XML_L("unexpected parser state - please send a bug report"),
+ XML_L("entity declared in parameter entity"),
+ XML_L("requested feature requires XML_DTD support in Expat"),
+ XML_L("cannot change setting once parsing has begun"),
+ XML_L("unbound prefix"),
+ XML_L("must not undeclare prefix"),
+ XML_L("incomplete markup in parameter entity"),
+ XML_L("XML declaration not well-formed"),
+ XML_L("text declaration not well-formed"),
+ XML_L("illegal character(s) in public id"),
+ XML_L("parser suspended"),
+ XML_L("parser not suspended"),
+ XML_L("parsing aborted"),
+ XML_L("parsing finished"),
+ XML_L("cannot suspend in external parameter entity"),
+ XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
+ XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
+ XML_L("prefix must not be bound to one of the reserved namespace names")
+ };
+ if (code > 0 && code < sizeof(message)/sizeof(message[0]))
+ return message[code];
+ return NULL;
+}
+
+const XML_LChar * XMLCALL
+XML_ExpatVersion(void) {
+
+ /* V1 is used to string-ize the version number. However, it would
+ string-ize the actual version macro *names* unless we get them
+ substituted before being passed to V1. CPP is defined to expand
+ a macro, then rescan for more expansions. Thus, we use V2 to expand
+ the version macros, then CPP will expand the resulting V1() macro
+ with the correct numerals. */
+ /* ### I'm assuming cpp is portable in this respect... */
+
+#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
+#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
+
+ return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
+
+#undef V1
+#undef V2
+}
+
+XML_Expat_Version XMLCALL
+XML_ExpatVersionInfo(void)
+{
+ XML_Expat_Version version;
+
+ version.major = XML_MAJOR_VERSION;
+ version.minor = XML_MINOR_VERSION;
+ version.micro = XML_MICRO_VERSION;
+
+ return version;
+}
+
+const XML_Feature * XMLCALL
+XML_GetFeatureList(void)
+{
+ static const XML_Feature features[] = {
+ {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
+ sizeof(XML_Char)},
+ {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
+ sizeof(XML_LChar)},
+#ifdef XML_UNICODE
+ {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
+#endif
+#ifdef XML_UNICODE_WCHAR_T
+ {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
+#endif
+#ifdef XML_DTD
+ {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
+#endif
+#ifdef XML_CONTEXT_BYTES
+ {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
+ XML_CONTEXT_BYTES},
+#endif
+#ifdef XML_MIN_SIZE
+ {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
+#endif
+#ifdef XML_NS
+ {XML_FEATURE_NS, XML_L("XML_NS"), 0},
+#endif
+#ifdef XML_LARGE_SIZE
+ {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
+#endif
+ {XML_FEATURE_END, NULL, 0}
+ };
+
+ return features;
+}
+
+/* Initially tag->rawName always points into the parse buffer;
+ for those TAG instances opened while the current parse buffer was
+ processed, and not yet closed, we need to store tag->rawName in a more
+ permanent location, since the parse buffer is about to be discarded.
+*/
+static XML_Bool
+storeRawNames(XML_Parser parser)
+{
+ TAG *tag = tagStack;
+ while (tag) {
+ int bufSize;
+ int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
+ char *rawNameBuf = tag->buf + nameLen;
+ /* Stop if already stored. Since tagStack is a stack, we can stop
+ at the first entry that has already been copied; everything
+ below it in the stack is already been accounted for in a
+ previous call to this function.
+ */
+ if (tag->rawName == rawNameBuf)
+ break;
+ /* For re-use purposes we need to ensure that the
+ size of tag->buf is a multiple of sizeof(XML_Char).
+ */
+ bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
+ if (bufSize > tag->bufEnd - tag->buf) {
+ char *temp = (char *)REALLOC(tag->buf, bufSize);
+ if (temp == NULL)
+ return XML_FALSE;
+ /* if tag->name.str points to tag->buf (only when namespace
+ processing is off) then we have to update it
+ */
+ if (tag->name.str == (XML_Char *)tag->buf)
+ tag->name.str = (XML_Char *)temp;
+ /* if tag->name.localPart is set (when namespace processing is on)
+ then update it as well, since it will always point into tag->buf
+ */
+ if (tag->name.localPart)
+ tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
+ (XML_Char *)tag->buf);
+ tag->buf = temp;
+ tag->bufEnd = temp + bufSize;
+ rawNameBuf = temp + nameLen;
+ }
+ memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
+ tag->rawName = rawNameBuf;
+ tag = tag->parent;
+ }
+ return XML_TRUE;
+}
+
+static enum XML_Error PTRCALL
+contentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doContent(parser, 0, encoding, start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+ if (result == XML_ERROR_NONE) {
+ if (!storeRawNames(parser))
+ return XML_ERROR_NO_MEMORY;
+ }
+ return result;
+}
+
+static enum XML_Error PTRCALL
+externalEntityInitProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = externalEntityInitProcessor2;
+ return externalEntityInitProcessor2(parser, start, end, endPtr);
+}
+
+static enum XML_Error PTRCALL
+externalEntityInitProcessor2(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next = start; /* XmlContentTok doesn't always set the last arg */
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_BOM:
+ /* If we are at the end of the buffer, this would cause the next stage,
+ i.e. externalEntityInitProcessor3, to pass control directly to
+ doContent (by detecting XML_TOK_NONE) without processing any xml text
+ declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
+ */
+ if (next == end && !ps_finalBuffer) {
+ *endPtr = next;
+ return XML_ERROR_NONE;
+ }
+ start = next;
+ break;
+ case XML_TOK_PARTIAL:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityInitProcessor3;
+ return externalEntityInitProcessor3(parser, start, end, endPtr);
+}
+
+static enum XML_Error PTRCALL
+externalEntityInitProcessor3(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ int tok;
+ const char *next = start; /* XmlContentTok doesn't always set the last arg */
+ eventPtr = start;
+ tok = XmlContentTok(encoding, start, end, &next);
+ eventEndPtr = next;
+
+ switch (tok) {
+ case XML_TOK_XML_DECL:
+ {
+ enum XML_Error result;
+ result = processXmlDecl(parser, 1, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *endPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default:
+ start = next;
+ }
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityContentProcessor;
+ tagLevel = 1;
+ return externalEntityContentProcessor(parser, start, end, endPtr);
+}
+
+static enum XML_Error PTRCALL
+externalEntityContentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doContent(parser, 1, encoding, start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+ if (result == XML_ERROR_NONE) {
+ if (!storeRawNames(parser))
+ return XML_ERROR_NO_MEMORY;
+ }
+ return result;
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+ int startTagLevel,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+ /* save one level of indirection */
+ DTD * const dtd = _dtd;
+
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+
+ for (;;) {
+ const char *next = s; /* XmlContentTok doesn't always set the last arg */
+ int tok = XmlContentTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ *eventEndPP = end;
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ /* We are at the end of the final buffer, should we check for
+ XML_SUSPENDED, XML_FINISHED?
+ */
+ if (startTagLevel == 0)
+ return XML_ERROR_NO_ELEMENTS;
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ *nextPtr = end;
+ return XML_ERROR_NONE;
+ case XML_TOK_NONE:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (startTagLevel > 0) {
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_NO_ELEMENTS;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (characterDataHandler)
+ characterDataHandler(handlerArg, &ch, 1);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ name = poolStoreString(&dtd->pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
+ poolDiscard(&dtd->pool);
+ /* First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal,
+ otherwise call the skipped entity or default handler.
+ */
+ if (!dtd->hasParamEntityRefs || dtd->standalone) {
+ if (!entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (!entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ }
+ else if (!entity) {
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, name, 0);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->notation)
+ return XML_ERROR_BINARY_ENTITY_REF;
+ if (entity->textPtr) {
+ enum XML_Error result;
+ if (!defaultExpandInternalEntities) {
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, entity->name, 0);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ result = processInternalEntity(parser, entity, XML_FALSE);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ else if (externalEntityRefHandler) {
+ const XML_Char *context;
+ entity->open = XML_TRUE;
+ context = getContext(parser);
+ entity->open = XML_FALSE;
+ if (!context)
+ return XML_ERROR_NO_MEMORY;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ context,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ poolDiscard(&tempPool);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ case XML_TOK_START_TAG_NO_ATTS:
+ /* fall through */
+ case XML_TOK_START_TAG_WITH_ATTS:
+ {
+ TAG *tag;
+ enum XML_Error result;
+ XML_Char *toPtr;
+ if (freeTagList) {
+ tag = freeTagList;
+ freeTagList = freeTagList->parent;
+ }
+ else {
+ tag = (TAG *)MALLOC(sizeof(TAG));
+ if (!tag)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
+ if (!tag->buf) {
+ FREE(tag);
+ return XML_ERROR_NO_MEMORY;
+ }
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+ }
+ tag->bindings = NULL;
+ tag->parent = tagStack;
+ tagStack = tag;
+ tag->name.localPart = NULL;
+ tag->name.prefix = NULL;
+ tag->rawName = s + enc->minBytesPerChar;
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+ ++tagLevel;
+ {
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+ const char *fromPtr = tag->rawName;
+ toPtr = (XML_Char *)tag->buf;
+ for (;;) {
+ int bufSize;
+ int convLen;
+ XmlConvert(enc,
+ &fromPtr, rawNameEnd,
+ (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+ convLen = (int)(toPtr - (XML_Char *)tag->buf);
+ if (fromPtr == rawNameEnd) {
+ tag->name.strLen = convLen;
+ break;
+ }
+ bufSize = (int)(tag->bufEnd - tag->buf) << 1;
+ {
+ char *temp = (char *)REALLOC(tag->buf, bufSize);
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = temp;
+ tag->bufEnd = temp + bufSize;
+ toPtr = (XML_Char *)temp + convLen;
+ }
+ }
+ }
+ tag->name.str = (XML_Char *)tag->buf;
+ *toPtr = XML_T('\0');
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+ if (result)
+ return result;
+ if (startElementHandler)
+ startElementHandler(handlerArg, tag->name.str,
+ (const XML_Char **)atts);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ poolClear(&tempPool);
+ break;
+ }
+ case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+ /* fall through */
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+ {
+ const char *rawName = s + enc->minBytesPerChar;
+ enum XML_Error result;
+ BINDING *bindings = NULL;
+ XML_Bool noElmHandlers = XML_TRUE;
+ TAG_NAME name;
+ name.str = poolStoreString(&tempPool, enc, rawName,
+ rawName + XmlNameLength(enc, rawName));
+ if (!name.str)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ result = storeAtts(parser, enc, s, &name, &bindings);
+ if (result)
+ return result;
+ poolFinish(&tempPool);
+ if (startElementHandler) {
+ startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+ noElmHandlers = XML_FALSE;
+ }
+ if (endElementHandler) {
+ if (startElementHandler)
+ *eventPP = *eventEndPP;
+ endElementHandler(handlerArg, name.str);
+ noElmHandlers = XML_FALSE;
+ }
+ if (noElmHandlers && defaultHandler)
+ reportDefault(parser, enc, s, next);
+ poolClear(&tempPool);
+ while (bindings) {
+ BINDING *b = bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ }
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ break;
+ case XML_TOK_END_TAG:
+ if (tagLevel == startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ else {
+ int len;
+ const char *rawName;
+ TAG *tag = tagStack;
+ tagStack = tag->parent;
+ tag->parent = freeTagList;
+ freeTagList = tag;
+ rawName = s + enc->minBytesPerChar*2;
+ len = XmlNameLength(enc, rawName);
+ if (len != tag->rawNameLength
+ || memcmp(tag->rawName, rawName, len) != 0) {
+ *eventPP = rawName;
+ return XML_ERROR_TAG_MISMATCH;
+ }
+ --tagLevel;
+ if (endElementHandler) {
+ const XML_Char *localPart;
+ const XML_Char *prefix;
+ XML_Char *uri;
+ localPart = tag->name.localPart;
+ if (ns && localPart) {
+ /* localPart and prefix may have been overwritten in
+ tag->name.str, since this points to the binding->uri
+ buffer which gets re-used; so we have to add them again
+ */
+ uri = (XML_Char *)tag->name.str + tag->name.uriLen;
+ /* don't need to check for space - already done in storeAtts() */
+ while (*localPart) *uri++ = *localPart++;
+ prefix = (XML_Char *)tag->name.prefix;
+ if (ns_triplets && prefix) {
+ *uri++ = namespaceSeparator;
+ while (*prefix) *uri++ = *prefix++;
+ }
+ *uri = XML_T('\0');
+ }
+ endElementHandler(handlerArg, tag->name.str);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ while (tag->bindings) {
+ BINDING *b = tag->bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ tag->bindings = tag->bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ }
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ int n = XmlCharRefNumber(enc, s);
+ if (n < 0)
+ return XML_ERROR_BAD_CHAR_REF;
+ if (characterDataHandler) {
+ XML_Char buf[XML_ENCODE_MAX];
+ characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_CDATA_SECT_OPEN:
+ {
+ enum XML_Error result;
+ if (startCdataSectionHandler)
+ startCdataSectionHandler(handlerArg);
+#if 0
+ /* Suppose you doing a transformation on a document that involves
+ changing only the character data. You set up a defaultHandler
+ and a characterDataHandler. The defaultHandler simply copies
+ characters through. The characterDataHandler does the
+ transformation and writes the characters out escaping them as
+ necessary. This case will fail to work if we leave out the
+ following two lines (because & and < inside CDATA sections will
+ be incorrectly escaped).
+
+ However, now we have a start/endCdataSectionHandler, so it seems
+ easier to let the user deal with this.
+ */
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (!next) {
+ processor = cdataSectionProcessor;
+ return result;
+ }
+ }
+ break;
+ case XML_TOK_TRAILING_RSQB:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ characterDataHandler(handlerArg, dataBuf,
+ (int)(dataPtr - (ICHAR *)dataBuf));
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (int)((XML_Char *)end - (XML_Char *)s));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ /* We are at the end of the final buffer, should we check for
+ XML_SUSPENDED, XML_FINISHED?
+ */
+ if (startTagLevel == 0) {
+ *eventPP = end;
+ return XML_ERROR_NO_ELEMENTS;
+ }
+ if (tagLevel != startTagLevel) {
+ *eventPP = end;
+ return XML_ERROR_ASYNC_ENTITY;
+ }
+ *nextPtr = end;
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_CHARS:
+ {
+ XML_CharacterDataHandler charDataHandler = characterDataHandler;
+ if (charDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ charDataHandler(handlerArg, dataBuf,
+ (int)(dataPtr - (ICHAR *)dataBuf));
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ charDataHandler(handlerArg,
+ (XML_Char *)s,
+ (int)((XML_Char *)next - (XML_Char *)s));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ default:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ *eventPP = s = next;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default: ;
+ }
+ }
+ /* not reached */
+}
+
+/* Precondition: all arguments must be non-NULL;
+ Purpose:
+ - normalize attributes
+ - check attributes for well-formedness
+ - generate namespace aware attribute names (URI, prefix)
+ - build list of attributes for startElementHandler
+ - default attributes
+ - process namespace declarations (check and report them)
+ - generate namespace aware element name (URI, prefix)
+*/
+static enum XML_Error
+storeAtts(XML_Parser parser, const ENCODING *enc,
+ const char *attStr, TAG_NAME *tagNamePtr,
+ BINDING **bindingsPtr)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ ELEMENT_TYPE *elementType;
+ int nDefaultAtts;
+ const XML_Char **appAtts; /* the attribute list for the application */
+ int attIndex = 0;
+ int prefixLen;
+ int i;
+ int n;
+ XML_Char *uri;
+ int nPrefixes = 0;
+ BINDING *binding;
+ const XML_Char *localPart;
+
+ /* lookup the element type name */
+ elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
+ if (!elementType) {
+ const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
+ sizeof(ELEMENT_TYPE));
+ if (!elementType)
+ return XML_ERROR_NO_MEMORY;
+ if (ns && !setElementTypePrefix(parser, elementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ nDefaultAtts = elementType->nDefaultAtts;
+
+ /* get the attributes from the tokenizer */
+ n = XmlGetAttributes(enc, attStr, attsSize, atts);
+ if (n + nDefaultAtts > attsSize) {
+ int oldAttsSize = attsSize;
+ ATTRIBUTE *temp;
+ attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+ temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ atts = temp;
+ if (n > oldAttsSize)
+ XmlGetAttributes(enc, attStr, n, atts);
+ }
+
+ appAtts = (const XML_Char **)atts;
+ for (i = 0; i < n; i++) {
+ /* add the name and value to the attribute list */
+ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
+ atts[i].name
+ + XmlNameLength(enc, atts[i].name));
+ if (!attId)
+ return XML_ERROR_NO_MEMORY;
+ /* Detect duplicate attributes by their QNames. This does not work when
+ namespace processing is turned on and different prefixes for the same
+ namespace are used. For this case we have a check further down.
+ */
+ if ((attId->name)[-1]) {
+ if (enc == encoding)
+ eventPtr = atts[i].name;
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;
+ }
+ (attId->name)[-1] = 1;
+ appAtts[attIndex++] = attId->name;
+ if (!atts[i].normalized) {
+ enum XML_Error result;
+ XML_Bool isCdata = XML_TRUE;
+
+ /* figure out whether declared as other than CDATA */
+ if (attId->maybeTokenized) {
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ if (attId == elementType->defaultAtts[j].id) {
+ isCdata = elementType->defaultAtts[j].isCdata;
+ break;
+ }
+ }
+ }
+
+ /* normalize the attribute value */
+ result = storeAttributeValue(parser, enc, isCdata,
+ atts[i].valuePtr, atts[i].valueEnd,
+ &tempPool);
+ if (result)
+ return result;
+ appAtts[attIndex] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ else {
+ /* the value did not need normalizing */
+ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
+ atts[i].valueEnd);
+ if (appAtts[attIndex] == 0)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ /* handle prefixed attribute names */
+ if (attId->prefix) {
+ if (attId->xmlns) {
+ /* deal with namespace declarations here */
+ enum XML_Error result = addBinding(parser, attId->prefix, attId,
+ appAtts[attIndex], bindingsPtr);
+ if (result)
+ return result;
+ --attIndex;
+ }
+ else {
+ /* deal with other prefixed names later */
+ attIndex++;
+ nPrefixes++;
+ (attId->name)[-1] = 2;
+ }
+ }
+ else
+ attIndex++;
+ }
+
+ /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
+ nSpecifiedAtts = attIndex;
+ if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
+ for (i = 0; i < attIndex; i += 2)
+ if (appAtts[i] == elementType->idAtt->name) {
+ idAttIndex = i;
+ break;
+ }
+ }
+ else
+ idAttIndex = -1;
+
+ /* do attribute defaulting */
+ for (i = 0; i < nDefaultAtts; i++) {
+ const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
+ if (!(da->id->name)[-1] && da->value) {
+ if (da->id->prefix) {
+ if (da->id->xmlns) {
+ enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
+ da->value, bindingsPtr);
+ if (result)
+ return result;
+ }
+ else {
+ (da->id->name)[-1] = 2;
+ nPrefixes++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ else {
+ (da->id->name)[-1] = 1;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ }
+ appAtts[attIndex] = 0;
+
+ /* expand prefixed attribute names, check for duplicates,
+ and clear flags that say whether attributes were specified */
+ i = 0;
+ if (nPrefixes) {
+ int j; /* hash table index */
+ unsigned long version = nsAttsVersion;
+ int nsAttsSize = (int)1 << nsAttsPower;
+ /* size of hash table must be at least 2 * (# of prefixed attributes) */
+ if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
+ NS_ATT *temp;
+ /* hash table size must also be a power of 2 and >= 8 */
+ while (nPrefixes >> nsAttsPower++);
+ if (nsAttsPower < 3)
+ nsAttsPower = 3;
+ nsAttsSize = (int)1 << nsAttsPower;
+ temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
+ if (!temp)
+ return XML_ERROR_NO_MEMORY;
+ nsAtts = temp;
+ version = 0; /* force re-initialization of nsAtts hash table */
+ }
+ /* using a version flag saves us from initializing nsAtts every time */
+ if (!version) { /* initialize version flags when version wraps around */
+ version = INIT_ATTS_VERSION;
+ for (j = nsAttsSize; j != 0; )
+ nsAtts[--j].version = version;
+ }
+ nsAttsVersion = --version;
+
+ /* expand prefixed names and check for duplicates */
+ for (; i < attIndex; i += 2) {
+ const XML_Char *s = appAtts[i];
+ if (s[-1] == 2) { /* prefixed */
+ ATTRIBUTE_ID *id;
+ const BINDING *b;
+ unsigned long uriHash = 0;
+ ((XML_Char *)s)[-1] = 0; /* clear flag */
+ id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
+ b = id->prefix->binding;
+ if (!b)
+ return XML_ERROR_UNBOUND_PREFIX;
+
+ /* as we expand the name we also calculate its hash value */
+ for (j = 0; j < b->uriLen; j++) {
+ const XML_Char c = b->uri[j];
+ if (!poolAppendChar(&tempPool, c))
+ return XML_ERROR_NO_MEMORY;
+ uriHash = CHAR_HASH(uriHash, c);
+ }
+ while (*s++ != XML_T(ASCII_COLON))
+ ;
+ do { /* copies null terminator */
+ const XML_Char c = *s;
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ uriHash = CHAR_HASH(uriHash, c);
+ } while (*s++);
+
+ { /* Check hash table for duplicate of expanded name (uriName).
+ Derived from code in lookup(HASH_TABLE *table, ...).
+ */
+ unsigned char step = 0;
+ unsigned long mask = nsAttsSize - 1;
+ j = uriHash & mask; /* index into hash table */
+ while (nsAtts[j].version == version) {
+ /* for speed we compare stored hash values first */
+ if (uriHash == nsAtts[j].hash) {
+ const XML_Char *s1 = poolStart(&tempPool);
+ const XML_Char *s2 = nsAtts[j].uriName;
+ /* s1 is null terminated, but not s2 */
+ for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
+ if (*s1 == 0)
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;
+ }
+ if (!step)
+ step = PROBE_STEP(uriHash, mask, nsAttsPower);
+ j < step ? (j += nsAttsSize - step) : (j -= step);
+ }
+ }
+
+ if (ns_triplets) { /* append namespace separator and prefix */
+ tempPool.ptr[-1] = namespaceSeparator;
+ s = b->prefix->name;
+ do {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+ }
+
+ /* store expanded name in attribute list */
+ s = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ appAtts[i] = s;
+
+ /* fill empty slot with new version, uriName and hash value */
+ nsAtts[j].version = version;
+ nsAtts[j].hash = uriHash;
+ nsAtts[j].uriName = s;
+
+ if (!--nPrefixes) {
+ i += 2;
+ break;
+ }
+ }
+ else /* not prefixed */
+ ((XML_Char *)s)[-1] = 0; /* clear flag */
+ }
+ }
+ /* clear flags for the remaining attributes */
+ for (; i < attIndex; i += 2)
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+ binding->attId->name[-1] = 0;
+
+ if (!ns)
+ return XML_ERROR_NONE;
+
+ /* expand the element type name */
+ if (elementType->prefix) {
+ binding = elementType->prefix->binding;
+ if (!binding)
+ return XML_ERROR_UNBOUND_PREFIX;
+ localPart = tagNamePtr->str;
+ while (*localPart++ != XML_T(ASCII_COLON))
+ ;
+ }
+ else if (dtd->defaultPrefix.binding) {
+ binding = dtd->defaultPrefix.binding;
+ localPart = tagNamePtr->str;
+ }
+ else
+ return XML_ERROR_NONE;
+ prefixLen = 0;
+ if (ns_triplets && binding->prefix->name) {
+ for (; binding->prefix->name[prefixLen++];)
+ ; /* prefixLen includes null terminator */
+ }
+ tagNamePtr->localPart = localPart;
+ tagNamePtr->uriLen = binding->uriLen;
+ tagNamePtr->prefix = binding->prefix->name;
+ tagNamePtr->prefixLen = prefixLen;
+ for (i = 0; localPart[i++];)
+ ; /* i includes null terminator */
+ n = i + binding->uriLen + prefixLen;
+ if (n > binding->uriAlloc) {
+ TAG *p;
+ uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
+ if (!uri)
+ return XML_ERROR_NO_MEMORY;
+ binding->uriAlloc = n + EXPAND_SPARE;
+ memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
+ for (p = tagStack; p; p = p->parent)
+ if (p->name.str == binding->uri)
+ p->name.str = uri;
+ FREE(binding->uri);
+ binding->uri = uri;
+ }
+ /* if namespaceSeparator != '\0' then uri includes it already */
+ uri = binding->uri + binding->uriLen;
+ memcpy(uri, localPart, i * sizeof(XML_Char));
+ /* we always have a namespace separator between localPart and prefix */
+ if (prefixLen) {
+ uri += i - 1;
+ *uri = namespaceSeparator; /* replace null terminator */
+ memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
+ }
+ tagNamePtr->str = binding->uri;
+ return XML_ERROR_NONE;
+}
+
+/* addBinding() overwrites the value of prefix->binding without checking.
+ Therefore one must keep track of the old value outside of addBinding().
+*/
+static enum XML_Error
+addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
+ const XML_Char *uri, BINDING **bindingsPtr)
+{
+ static const XML_Char xmlNamespace[] = {
+ ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
+ ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
+ ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
+ ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
+ ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
+ ASCII_e, '\0'
+ };
+ static const int xmlLen =
+ (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
+ static const XML_Char xmlnsNamespace[] = {
+ ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
+ ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
+ ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
+ ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
+ ASCII_SLASH, '\0'
+ };
+ static const int xmlnsLen =
+ (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
+
+ XML_Bool mustBeXML = XML_FALSE;
+ XML_Bool isXML = XML_TRUE;
+ XML_Bool isXMLNS = XML_TRUE;
+
+ BINDING *b;
+ int len;
+
+ /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
+ if (*uri == XML_T('\0') && prefix->name)
+ return XML_ERROR_UNDECLARING_PREFIX;
+
+ if (prefix->name
+ && prefix->name[0] == XML_T(ASCII_x)
+ && prefix->name[1] == XML_T(ASCII_m)
+ && prefix->name[2] == XML_T(ASCII_l)) {
+
+ /* Not allowed to bind xmlns */
+ if (prefix->name[3] == XML_T(ASCII_n)
+ && prefix->name[4] == XML_T(ASCII_s)
+ && prefix->name[5] == XML_T('\0'))
+ return XML_ERROR_RESERVED_PREFIX_XMLNS;
+
+ if (prefix->name[3] == XML_T('\0'))
+ mustBeXML = XML_TRUE;
+ }
+
+ for (len = 0; uri[len]; len++) {
+ if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
+ isXML = XML_FALSE;
+
+ if (!mustBeXML && isXMLNS
+ && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
+ isXMLNS = XML_FALSE;
+ }
+ isXML = isXML && len == xmlLen;
+ isXMLNS = isXMLNS && len == xmlnsLen;
+
+ if (mustBeXML != isXML)
+ return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
+ : XML_ERROR_RESERVED_NAMESPACE_URI;
+
+ if (isXMLNS)
+ return XML_ERROR_RESERVED_NAMESPACE_URI;
+
+ if (namespaceSeparator)
+ len++;
+ if (freeBindingList) {
+ b = freeBindingList;
+ if (len > b->uriAlloc) {
+ XML_Char *temp = (XML_Char *)REALLOC(b->uri,
+ sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ b->uri = temp;
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ freeBindingList = b->nextTagBinding;
+ }
+ else {
+ b = (BINDING *)MALLOC(sizeof(BINDING));
+ if (!b)
+ return XML_ERROR_NO_MEMORY;
+ b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (!b->uri) {
+ FREE(b);
+ return XML_ERROR_NO_MEMORY;
+ }
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ b->uriLen = len;
+ memcpy(b->uri, uri, len * sizeof(XML_Char));
+ if (namespaceSeparator)
+ b->uri[len - 1] = namespaceSeparator;
+ b->prefix = prefix;
+ b->attId = attId;
+ b->prevPrefixBinding = prefix->binding;
+ /* NULL binding when default namespace undeclared */
+ if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
+ prefix->binding = NULL;
+ else
+ prefix->binding = b;
+ b->nextTagBinding = *bindingsPtr;
+ *bindingsPtr = b;
+ /* if attId == NULL then we are not starting a namespace scope */
+ if (attId && startNamespaceDeclHandler)
+ startNamespaceDeclHandler(handlerArg, prefix->name,
+ prefix->binding ? uri : 0);
+ return XML_ERROR_NONE;
+}
+
+/* The idea here is to avoid using stack for each CDATA section when
+ the whole file is parsed with one call.
+*/
+static enum XML_Error PTRCALL
+cdataSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doCdataSection(parser, encoding, &start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+ if (result != XML_ERROR_NONE)
+ return result;
+ if (start) {
+ if (parentParser) { /* we are parsing an external entity */
+ processor = externalEntityContentProcessor;
+ return externalEntityContentProcessor(parser, start, end, endPtr);
+ }
+ else {
+ processor = contentProcessor;
+ return contentProcessor(parser, start, end, endPtr);
+ }
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null if the section is closed, and to null if
+ the section is not yet closed.
+*/
+static enum XML_Error
+doCdataSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = NULL;
+
+ for (;;) {
+ const char *next;
+ int tok = XmlCdataSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_CDATA_SECT_CLOSE:
+ if (endCdataSectionHandler)
+ endCdataSectionHandler(handlerArg);
+#if 0
+ /* see comment under XML_TOK_CDATA_SECT_OPEN */
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ *nextPtr = next;
+ if (ps_parsing == XML_FINISHED)
+ return XML_ERROR_ABORTED;
+ else
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_DATA_CHARS:
+ {
+ XML_CharacterDataHandler charDataHandler = characterDataHandler;
+ if (charDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = next;
+ charDataHandler(handlerArg, dataBuf,
+ (int)(dataPtr - (ICHAR *)dataBuf));
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ charDataHandler(handlerArg,
+ (XML_Char *)s,
+ (int)((XML_Char *)next - (XML_Char *)s));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_CDATA_SECTION;
+ default:
+ *eventPP = next;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+
+ *eventPP = s = next;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default: ;
+ }
+ }
+ /* not reached */
+}
+
+#ifdef XML_DTD
+
+/* The idea here is to avoid using stack for each IGNORE section when
+ the whole file is parsed with one call.
+*/
+static enum XML_Error PTRCALL
+ignoreSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+ if (result != XML_ERROR_NONE)
+ return result;
+ if (start) {
+ processor = prologProcessor;
+ return prologProcessor(parser, start, end, endPtr);
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null
+ if the section is not yet closed.
+*/
+static enum XML_Error
+doIgnoreSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+ const char *next;
+ int tok;
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = NULL;
+ tok = XmlIgnoreSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_IGNORE_SECT:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ *nextPtr = next;
+ if (ps_parsing == XML_FINISHED)
+ return XML_ERROR_ABORTED;
+ else
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
+ default:
+ *eventPP = next;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ /* not reached */
+}
+
+#endif /* XML_DTD */
+
+static enum XML_Error
+initializeEncoding(XML_Parser parser)
+{
+ const char *s;
+#ifdef XML_UNICODE
+ char encodingBuf[128];
+ if (!protocolEncodingName)
+ s = NULL;
+ else {
+ int i;
+ for (i = 0; protocolEncodingName[i]; i++) {
+ if (i == sizeof(encodingBuf) - 1
+ || (protocolEncodingName[i] & ~0x7f) != 0) {
+ encodingBuf[0] = '\0';
+ break;
+ }
+ encodingBuf[i] = (char)protocolEncodingName[i];
+ }
+ encodingBuf[i] = '\0';
+ s = encodingBuf;
+ }
+#else
+ s = protocolEncodingName;
+#endif
+ if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
+ return XML_ERROR_NONE;
+ return handleUnknownEncoding(parser, protocolEncodingName);
+}
+
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next)
+{
+ const char *encodingName = NULL;
+ const XML_Char *storedEncName = NULL;
+ const ENCODING *newEncoding = NULL;
+ const char *version = NULL;
+ const char *versionend;
+ const XML_Char *storedversion = NULL;
+ int standalone = -1;
+ if (!(ns
+ ? XmlParseXmlDeclNS
+ : XmlParseXmlDecl)(isGeneralTextEntity,
+ encoding,
+ s,
+ next,
+ &eventPtr,
+ &version,
+ &versionend,
+ &encodingName,
+ &newEncoding,
+ &standalone)) {
+ if (isGeneralTextEntity)
+ return XML_ERROR_TEXT_DECL;
+ else
+ return XML_ERROR_XML_DECL;
+ }
+ if (!isGeneralTextEntity && standalone == 1) {
+ _dtd->standalone = XML_TRUE;
+#ifdef XML_DTD
+ if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif /* XML_DTD */
+ }
+ if (xmlDeclHandler) {
+ if (encodingName != NULL) {
+ storedEncName = poolStoreString(&temp2Pool,
+ encoding,
+ encodingName,
+ encodingName
+ + XmlNameLength(encoding, encodingName));
+ if (!storedEncName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&temp2Pool);
+ }
+ if (version) {
+ storedversion = poolStoreString(&temp2Pool,
+ encoding,
+ version,
+ versionend - encoding->minBytesPerChar);
+ if (!storedversion)
+ return XML_ERROR_NO_MEMORY;
+ }
+ xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ if (protocolEncodingName == NULL) {
+ if (newEncoding) {
+ if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+ eventPtr = encodingName;
+ return XML_ERROR_INCORRECT_ENCODING;
+ }
+ encoding = newEncoding;
+ }
+ else if (encodingName) {
+ enum XML_Error result;
+ if (!storedEncName) {
+ storedEncName = poolStoreString(
+ &temp2Pool, encoding, encodingName,
+ encodingName + XmlNameLength(encoding, encodingName));
+ if (!storedEncName)
+ return XML_ERROR_NO_MEMORY;
+ }
+ result = handleUnknownEncoding(parser, storedEncName);
+ poolClear(&temp2Pool);
+ if (result == XML_ERROR_UNKNOWN_ENCODING)
+ eventPtr = encodingName;
+ return result;
+ }
+ }
+
+ if (storedEncName || storedversion)
+ poolClear(&temp2Pool);
+
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (unknownEncodingHandler) {
+ XML_Encoding info;
+ int i;
+ for (i = 0; i < 256; i++)
+ info.map[i] = -1;
+ info.convert = NULL;
+ info.data = NULL;
+ info.release = NULL;
+ if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
+ &info)) {
+ ENCODING *enc;
+ unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
+ if (!unknownEncodingMem) {
+ if (info.release)
+ info.release(info.data);
+ return XML_ERROR_NO_MEMORY;
+ }
+ enc = (ns
+ ? XmlInitUnknownEncodingNS
+ : XmlInitUnknownEncoding)(unknownEncodingMem,
+ info.map,
+ info.convert,
+ info.data);
+ if (enc) {
+ unknownEncodingData = info.data;
+ unknownEncodingRelease = info.release;
+ encoding = enc;
+ return XML_ERROR_NONE;
+ }
+ }
+ if (info.release != NULL)
+ info.release(info.data);
+ }
+ return XML_ERROR_UNKNOWN_ENCODING;
+}
+
+static enum XML_Error PTRCALL
+prologInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = prologProcessor;
+ return prologProcessor(parser, s, end, nextPtr);
+}
+
+#ifdef XML_DTD
+
+static enum XML_Error PTRCALL
+externalParEntInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+
+ /* we know now that XML_Parse(Buffer) has been called,
+ so we consider the external parameter entity read */
+ _dtd->paramEntityRead = XML_TRUE;
+
+ if (prologState.inEntityValue) {
+ processor = entityValueInitProcessor;
+ return entityValueInitProcessor(parser, s, end, nextPtr);
+ }
+ else {
+ processor = externalParEntProcessor;
+ return externalParEntProcessor(parser, s, end, nextPtr);
+ }
+}
+
+static enum XML_Error PTRCALL
+entityValueInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ int tok;
+ const char *start = s;
+ const char *next = start;
+ eventPtr = start;
+
+ for (;;) {
+ tok = XmlPrologTok(encoding, start, end, &next);
+ eventEndPtr = next;
+ if (tok <= 0) {
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE: /* start == end */
+ default:
+ break;
+ }
+ /* found end of entity value - can store it now */
+ return storeEntityValue(parser, encoding, s, end);
+ }
+ else if (tok == XML_TOK_XML_DECL) {
+ enum XML_Error result;
+ result = processXmlDecl(parser, 0, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default:
+ *nextPtr = next;
+ }
+ /* stop scanning for text declaration - we found one */
+ processor = entityValueProcessor;
+ return entityValueProcessor(parser, next, end, nextPtr);
+ }
+ /* If we are at the end of the buffer, this would cause XmlPrologTok to
+ return XML_TOK_NONE on the next call, which would then cause the
+ function to exit with *nextPtr set to s - that is what we want for other
+ tokens, but not for the BOM - we would rather like to skip it;
+ then, when this routine is entered the next time, XmlPrologTok will
+ return XML_TOK_INVALID, since the BOM is still in the buffer
+ */
+ else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ }
+ start = next;
+ eventPtr = start;
+ }
+}
+
+static enum XML_Error PTRCALL
+externalParEntProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *next = s;
+ int tok;
+
+ tok = XmlPrologTok(encoding, s, end, &next);
+ if (tok <= 0) {
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE: /* start == end */
+ default:
+ break;
+ }
+ }
+ /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
+ However, when parsing an external subset, doProlog will not accept a BOM
+ as valid, and report a syntax error, so we have to skip the BOM
+ */
+ else if (tok == XML_TOK_BOM) {
+ s = next;
+ tok = XmlPrologTok(encoding, s, end, &next);
+ }
+
+ processor = prologProcessor;
+ return doProlog(parser, encoding, s, end, tok, next,
+ nextPtr, (XML_Bool)!ps_finalBuffer);
+}
+
+static enum XML_Error PTRCALL
+entityValueProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *start = s;
+ const char *next = s;
+ const ENCODING *enc = encoding;
+ int tok;
+
+ for (;;) {
+ tok = XmlPrologTok(enc, start, end, &next);
+ if (tok <= 0) {
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE: /* start == end */
+ default:
+ break;
+ }
+ /* found end of entity value - can store it now */
+ return storeEntityValue(parser, enc, s, end);
+ }
+ start = next;
+ }
+}
+
+#endif /* XML_DTD */
+
+static enum XML_Error PTRCALL
+prologProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *next = s;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ return doProlog(parser, encoding, s, end, tok, next,
+ nextPtr, (XML_Bool)!ps_finalBuffer);
+}
+
+static enum XML_Error
+doProlog(XML_Parser parser,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ int tok,
+ const char *next,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+#ifdef XML_DTD
+ static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
+#endif /* XML_DTD */
+ static const XML_Char atypeCDATA[] =
+ { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+ static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
+ static const XML_Char atypeIDREF[] =
+ { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
+ static const XML_Char atypeIDREFS[] =
+ { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+ static const XML_Char atypeENTITY[] =
+ { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
+ static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
+ ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
+ static const XML_Char atypeNMTOKEN[] = {
+ ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
+ static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
+ ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
+ static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
+ ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
+ static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
+ static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
+
+ /* save one level of indirection */
+ DTD * const dtd = _dtd;
+
+ const char **eventPP;
+ const char **eventEndPP;
+ enum XML_Content_Quant quant;
+
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+
+ for (;;) {
+ int role;
+ XML_Bool handleDefault = XML_TRUE;
+ *eventPP = s;
+ *eventEndPP = next;
+ if (tok <= 0) {
+ if (haveMore && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE:
+#ifdef XML_DTD
+ /* for internal PE NOT referenced between declarations */
+ if (enc != encoding && !openInternalEntities->betweenDecl) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ /* WFC: PE Between Declarations - must check that PE contains
+ complete markup, not only for external PEs, but also for
+ internal PEs if the reference occurs between declarations.
+ */
+ if (isParamEntity || enc != encoding) {
+ if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
+ == XML_ROLE_ERROR)
+ return XML_ERROR_INCOMPLETE_PE;
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+#endif /* XML_DTD */
+ return XML_ERROR_NO_ELEMENTS;
+ default:
+ tok = -tok;
+ next = end;
+ break;
+ }
+ }
+ role = XmlTokenRole(&prologState, tok, s, next, enc);
+ switch (role) {
+ case XML_ROLE_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 0, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = encoding;
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_NAME:
+ if (startDoctypeDeclHandler) {
+ doctypeName = poolStoreString(&tempPool, enc, s, next);
+ if (!doctypeName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ doctypePubid = NULL;
+ handleDefault = XML_FALSE;
+ }
+ doctypeSysid = NULL; /* always initialize to NULL */
+ break;
+ case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
+ if (startDoctypeDeclHandler) {
+ startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
+ doctypePubid, 1);
+ doctypeName = NULL;
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ break;
+#ifdef XML_DTD
+ case XML_ROLE_TEXT_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 1, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = encoding;
+ handleDefault = XML_FALSE;
+ }
+ break;
+#endif /* XML_DTD */
+ case XML_ROLE_DOCTYPE_PUBLIC_ID:
+#ifdef XML_DTD
+ useForeignDTD = XML_FALSE;
+ declEntity = (ENTITY *)lookup(&dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+#endif /* XML_DTD */
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (startDoctypeDeclHandler) {
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_PUBLICID;
+ doctypePubid = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!doctypePubid)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId((XML_Char *)doctypePubid);
+ poolFinish(&tempPool);
+ handleDefault = XML_FALSE;
+ goto alreadyChecked;
+ }
+ /* fall through */
+ case XML_ROLE_ENTITY_PUBLIC_ID:
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_PUBLICID;
+ alreadyChecked:
+ if (dtd->keepProcessing && declEntity) {
+ XML_Char *tem = poolStoreString(&dtd->pool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declEntity->publicId = tem;
+ poolFinish(&dtd->pool);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_CLOSE:
+ if (doctypeName) {
+ startDoctypeDeclHandler(handlerArg, doctypeName,
+ doctypeSysid, doctypePubid, 0);
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ /* doctypeSysid will be non-NULL in the case of a previous
+ XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
+ was not set, indicating an external subset
+ */
+#ifdef XML_DTD
+ if (doctypeSysid || useForeignDTD) {
+ XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (paramEntityParsing && externalEntityRefHandler) {
+ ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!entity)
+ return XML_ERROR_NO_MEMORY;
+ if (useForeignDTD)
+ entity->base = curBase;
+ dtd->paramEntityRead = XML_FALSE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ if (dtd->paramEntityRead) {
+ if (!dtd->standalone &&
+ notStandaloneHandler &&
+ !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ }
+ /* if we didn't read the foreign DTD then this means that there
+ is no external subset and we must reset dtd->hasParamEntityRefs
+ */
+ else if (!doctypeSysid)
+ dtd->hasParamEntityRefs = hadParamEntityRefs;
+ /* end of DTD - no need to update dtd->keepProcessing */
+ }
+ useForeignDTD = XML_FALSE;
+ }
+#endif /* XML_DTD */
+ if (endDoctypeDeclHandler) {
+ endDoctypeDeclHandler(handlerArg);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_INSTANCE_START:
+#ifdef XML_DTD
+ /* if there is no DOCTYPE declaration then now is the
+ last chance to read the foreign DTD
+ */
+ if (useForeignDTD) {
+ XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (paramEntityParsing && externalEntityRefHandler) {
+ ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!entity)
+ return XML_ERROR_NO_MEMORY;
+ entity->base = curBase;
+ dtd->paramEntityRead = XML_FALSE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ if (dtd->paramEntityRead) {
+ if (!dtd->standalone &&
+ notStandaloneHandler &&
+ !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ }
+ /* if we didn't read the foreign DTD then this means that there
+ is no external subset and we must reset dtd->hasParamEntityRefs
+ */
+ else
+ dtd->hasParamEntityRefs = hadParamEntityRefs;
+ /* end of DTD - no need to update dtd->keepProcessing */
+ }
+ }
+#endif /* XML_DTD */
+ processor = contentProcessor;
+ return contentProcessor(parser, s, end, nextPtr);
+ case XML_ROLE_ATTLIST_ELEMENT_NAME:
+ declElementType = getElementType(parser, enc, s, next);
+ if (!declElementType)
+ return XML_ERROR_NO_MEMORY;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_NAME:
+ declAttributeId = getAttributeId(parser, enc, s, next);
+ if (!declAttributeId)
+ return XML_ERROR_NO_MEMORY;
+ declAttributeIsCdata = XML_FALSE;
+ declAttributeType = NULL;
+ declAttributeIsId = XML_FALSE;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
+ declAttributeIsCdata = XML_TRUE;
+ declAttributeType = atypeCDATA;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_ID:
+ declAttributeIsId = XML_TRUE;
+ declAttributeType = atypeID;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
+ declAttributeType = atypeIDREF;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
+ declAttributeType = atypeIDREFS;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
+ declAttributeType = atypeENTITY;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
+ declAttributeType = atypeENTITIES;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
+ declAttributeType = atypeNMTOKEN;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
+ declAttributeType = atypeNMTOKENS;
+ checkAttListDeclHandler:
+ if (dtd->keepProcessing && attlistDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
+ case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
+ if (dtd->keepProcessing && attlistDeclHandler) {
+ const XML_Char *prefix;
+ if (declAttributeType) {
+ prefix = enumValueSep;
+ }
+ else {
+ prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
+ ? notationPrefix
+ : enumValueStart);
+ }
+ if (!poolAppendString(&tempPool, prefix))
+ return XML_ERROR_NO_MEMORY;
+ if (!poolAppend(&tempPool, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
+ case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
+ if (dtd->keepProcessing) {
+ if (!defineAttribute(declElementType, declAttributeId,
+ declAttributeIsCdata, declAttributeIsId,
+ 0, parser))
+ return XML_ERROR_NO_MEMORY;
+ if (attlistDeclHandler && declAttributeType) {
+ if (*declAttributeType == XML_T(ASCII_LPAREN)
+ || (*declAttributeType == XML_T(ASCII_N)
+ && declAttributeType[1] == XML_T(ASCII_O))) {
+ /* Enumerated or Notation type */
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
+ || !poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ poolFinish(&tempPool);
+ }
+ *eventEndPP = s;
+ attlistDeclHandler(handlerArg, declElementType->name,
+ declAttributeId->name, declAttributeType,
+ 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ }
+ break;
+ case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+ case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+ if (dtd->keepProcessing) {
+ const XML_Char *attVal;
+ enum XML_Error result =
+ storeAttributeValue(parser, enc, declAttributeIsCdata,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar,
+ &dtd->pool);
+ if (result)
+ return result;
+ attVal = poolStart(&dtd->pool);
+ poolFinish(&dtd->pool);
+ /* ID attributes aren't allowed to have a default */
+ if (!defineAttribute(declElementType, declAttributeId,
+ declAttributeIsCdata, XML_FALSE, attVal, parser))
+ return XML_ERROR_NO_MEMORY;
+ if (attlistDeclHandler && declAttributeType) {
+ if (*declAttributeType == XML_T(ASCII_LPAREN)
+ || (*declAttributeType == XML_T(ASCII_N)
+ && declAttributeType[1] == XML_T(ASCII_O))) {
+ /* Enumerated or Notation type */
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
+ || !poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ poolFinish(&tempPool);
+ }
+ *eventEndPP = s;
+ attlistDeclHandler(handlerArg, declElementType->name,
+ declAttributeId->name, declAttributeType,
+ attVal,
+ role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ }
+ break;
+ case XML_ROLE_ENTITY_VALUE:
+ if (dtd->keepProcessing) {
+ enum XML_Error result = storeEntityValue(parser, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (declEntity) {
+ declEntity->textPtr = poolStart(&dtd->entityValuePool);
+ declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
+ poolFinish(&dtd->entityValuePool);
+ if (entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->is_param,
+ declEntity->textPtr,
+ declEntity->textLen,
+ curBase, 0, 0, 0);
+ handleDefault = XML_FALSE;
+ }
+ }
+ else
+ poolDiscard(&dtd->entityValuePool);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_SYSTEM_ID:
+#ifdef XML_DTD
+ useForeignDTD = XML_FALSE;
+#endif /* XML_DTD */
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (startDoctypeDeclHandler) {
+ doctypeSysid = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (doctypeSysid == NULL)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+#ifdef XML_DTD
+ else
+ /* use externalSubsetName to make doctypeSysid non-NULL
+ for the case where no startDoctypeDeclHandler is set */
+ doctypeSysid = externalSubsetName;
+#endif /* XML_DTD */
+ if (!dtd->standalone
+#ifdef XML_DTD
+ && !paramEntityParsing
+#endif /* XML_DTD */
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+#ifndef XML_DTD
+ break;
+#else /* XML_DTD */
+ if (!declEntity) {
+ declEntity = (ENTITY *)lookup(&dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ declEntity->publicId = NULL;
+ }
+ /* fall through */
+#endif /* XML_DTD */
+ case XML_ROLE_ENTITY_SYSTEM_ID:
+ if (dtd->keepProcessing && declEntity) {
+ declEntity->systemId = poolStoreString(&dtd->pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!declEntity->systemId)
+ return XML_ERROR_NO_MEMORY;
+ declEntity->base = curBase;
+ poolFinish(&dtd->pool);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_ENTITY_COMPLETE:
+ if (dtd->keepProcessing && declEntity && entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->is_param,
+ 0,0,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ 0);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_ENTITY_NOTATION_NAME:
+ if (dtd->keepProcessing && declEntity) {
+ declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
+ if (!declEntity->notation)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&dtd->pool);
+ if (unparsedEntityDeclHandler) {
+ *eventEndPP = s;
+ unparsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ handleDefault = XML_FALSE;
+ }
+ else if (entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ 0,0,0,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ handleDefault = XML_FALSE;
+ }
+ }
+ break;
+ case XML_ROLE_GENERAL_ENTITY_NAME:
+ {
+ if (XmlPredefinedEntityName(enc, s, next)) {
+ declEntity = NULL;
+ break;
+ }
+ if (dtd->keepProcessing) {
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
+ sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+ else {
+ poolFinish(&dtd->pool);
+ declEntity->publicId = NULL;
+ declEntity->is_param = XML_FALSE;
+ /* if we have a parent parser or are reading an internal parameter
+ entity, then the entity declaration is not considered "internal"
+ */
+ declEntity->is_internal = !(parentParser || openInternalEntities);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ }
+ else {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+ }
+ break;
+ case XML_ROLE_PARAM_ENTITY_NAME:
+#ifdef XML_DTD
+ if (dtd->keepProcessing) {
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ declEntity = (ENTITY *)lookup(&dtd->paramEntities,
+ name, sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+ else {
+ poolFinish(&dtd->pool);
+ declEntity->publicId = NULL;
+ declEntity->is_param = XML_TRUE;
+ /* if we have a parent parser or are reading an internal parameter
+ entity, then the entity declaration is not considered "internal"
+ */
+ declEntity->is_internal = !(parentParser || openInternalEntities);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ }
+ else {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+#else /* not XML_DTD */
+ declEntity = NULL;
+#endif /* XML_DTD */
+ break;
+ case XML_ROLE_NOTATION_NAME:
+ declNotationPublicId = NULL;
+ declNotationName = NULL;
+ if (notationDeclHandler) {
+ declNotationName = poolStoreString(&tempPool, enc, s, next);
+ if (!declNotationName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_NOTATION_PUBLIC_ID:
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_PUBLICID;
+ if (declNotationName) { /* means notationDeclHandler != NULL */
+ XML_Char *tem = poolStoreString(&tempPool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declNotationPublicId = tem;
+ poolFinish(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_NOTATION_SYSTEM_ID:
+ if (declNotationName && notationDeclHandler) {
+ const XML_Char *systemId
+ = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!systemId)
+ return XML_ERROR_NO_MEMORY;
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ systemId,
+ declNotationPublicId);
+ handleDefault = XML_FALSE;
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_NOTATION_NO_SYSTEM_ID:
+ if (declNotationPublicId && notationDeclHandler) {
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ 0,
+ declNotationPublicId);
+ handleDefault = XML_FALSE;
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_ERROR:
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ /* PE references in internal subset are
+ not allowed within declarations. */
+ return XML_ERROR_PARAM_ENTITY_REF;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ default:
+ return XML_ERROR_SYNTAX;
+ }
+#ifdef XML_DTD
+ case XML_ROLE_IGNORE_SECT:
+ {
+ enum XML_Error result;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ handleDefault = XML_FALSE;
+ result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (!next) {
+ processor = ignoreSectionProcessor;
+ return result;
+ }
+ }
+ break;
+#endif /* XML_DTD */
+ case XML_ROLE_GROUP_OPEN:
+ if (prologState.level >= groupSize) {
+ if (groupSize) {
+ char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ groupConnector = temp;
+ if (dtd->scaffIndex) {
+ int *temp = (int *)REALLOC(dtd->scaffIndex,
+ groupSize * sizeof(int));
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffIndex = temp;
+ }
+ }
+ else {
+ groupConnector = (char *)MALLOC(groupSize = 32);
+ if (!groupConnector)
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ groupConnector[prologState.level] = 0;
+ if (dtd->in_eldecl) {
+ int myindex = nextScaffoldPart(parser);
+ if (myindex < 0)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffIndex[dtd->scaffLevel] = myindex;
+ dtd->scaffLevel++;
+ dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_GROUP_SEQUENCE:
+ if (groupConnector[prologState.level] == ASCII_PIPE)
+ return XML_ERROR_SYNTAX;
+ groupConnector[prologState.level] = ASCII_COMMA;
+ if (dtd->in_eldecl && elementDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_GROUP_CHOICE:
+ if (groupConnector[prologState.level] == ASCII_COMMA)
+ return XML_ERROR_SYNTAX;
+ if (dtd->in_eldecl
+ && !groupConnector[prologState.level]
+ && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
+ != XML_CTYPE_MIXED)
+ ) {
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
+ = XML_CTYPE_CHOICE;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ groupConnector[prologState.level] = ASCII_PIPE;
+ break;
+ case XML_ROLE_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+ case XML_ROLE_INNER_PARAM_ENTITY_REF:
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (!paramEntityParsing)
+ dtd->keepProcessing = dtd->standalone;
+ else {
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&dtd->pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
+ poolDiscard(&dtd->pool);
+ /* first, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal,
+ otherwise call the skipped entity handler
+ */
+ if (prologState.documentEntity &&
+ (dtd->standalone
+ ? !openInternalEntities
+ : !dtd->hasParamEntityRefs)) {
+ if (!entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (!entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ }
+ else if (!entity) {
+ dtd->keepProcessing = dtd->standalone;
+ /* cannot report skipped entities in declarations */
+ if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
+ skippedEntityHandler(handlerArg, name, 1);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->textPtr) {
+ enum XML_Error result;
+ XML_Bool betweenDecl =
+ (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
+ result = processInternalEntity(parser, entity, betweenDecl);
+ if (result != XML_ERROR_NONE)
+ return result;
+ handleDefault = XML_FALSE;
+ break;
+ }
+ if (externalEntityRefHandler) {
+ dtd->paramEntityRead = XML_FALSE;
+ entity->open = XML_TRUE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ entity->open = XML_FALSE;
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ }
+ entity->open = XML_FALSE;
+ handleDefault = XML_FALSE;
+ if (!dtd->paramEntityRead) {
+ dtd->keepProcessing = dtd->standalone;
+ break;
+ }
+ }
+ else {
+ dtd->keepProcessing = dtd->standalone;
+ break;
+ }
+ }
+#endif /* XML_DTD */
+ if (!dtd->standalone &&
+ notStandaloneHandler &&
+ !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ break;
+
+ /* Element declaration stuff */
+
+ case XML_ROLE_ELEMENT_NAME:
+ if (elementDeclHandler) {
+ declElementType = getElementType(parser, enc, s, next);
+ if (!declElementType)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffLevel = 0;
+ dtd->scaffCount = 0;
+ dtd->in_eldecl = XML_TRUE;
+ handleDefault = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_ANY:
+ case XML_ROLE_CONTENT_EMPTY:
+ if (dtd->in_eldecl) {
+ if (elementDeclHandler) {
+ XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
+ if (!content)
+ return XML_ERROR_NO_MEMORY;
+ content->quant = XML_CQUANT_NONE;
+ content->name = NULL;
+ content->numchildren = 0;
+ content->children = NULL;
+ content->type = ((role == XML_ROLE_CONTENT_ANY) ?
+ XML_CTYPE_ANY :
+ XML_CTYPE_EMPTY);
+ *eventEndPP = s;
+ elementDeclHandler(handlerArg, declElementType->name, content);
+ handleDefault = XML_FALSE;
+ }
+ dtd->in_eldecl = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_PCDATA:
+ if (dtd->in_eldecl) {
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
+ = XML_CTYPE_MIXED;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_ELEMENT:
+ quant = XML_CQUANT_NONE;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_OPT:
+ quant = XML_CQUANT_OPT;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_REP:
+ quant = XML_CQUANT_REP;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_PLUS:
+ quant = XML_CQUANT_PLUS;
+ elementContent:
+ if (dtd->in_eldecl) {
+ ELEMENT_TYPE *el;
+ const XML_Char *name;
+ int nameLen;
+ const char *nxt = (quant == XML_CQUANT_NONE
+ ? next
+ : next - enc->minBytesPerChar);
+ int myindex = nextScaffoldPart(parser);
+ if (myindex < 0)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffold[myindex].type = XML_CTYPE_NAME;
+ dtd->scaffold[myindex].quant = quant;
+ el = getElementType(parser, enc, s, nxt);
+ if (!el)
+ return XML_ERROR_NO_MEMORY;
+ name = el->name;
+ dtd->scaffold[myindex].name = name;
+ nameLen = 0;
+ for (; name[nameLen++]; );
+ dtd->contentStringLen += nameLen;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_GROUP_CLOSE:
+ quant = XML_CQUANT_NONE;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_OPT:
+ quant = XML_CQUANT_OPT;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_REP:
+ quant = XML_CQUANT_REP;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_PLUS:
+ quant = XML_CQUANT_PLUS;
+ closeGroup:
+ if (dtd->in_eldecl) {
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ dtd->scaffLevel--;
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
+ if (dtd->scaffLevel == 0) {
+ if (!handleDefault) {
+ XML_Content *model = build_model(parser);
+ if (!model)
+ return XML_ERROR_NO_MEMORY;
+ *eventEndPP = s;
+ elementDeclHandler(handlerArg, declElementType->name, model);
+ }
+ dtd->in_eldecl = XML_FALSE;
+ dtd->contentStringLen = 0;
+ }
+ }
+ break;
+ /* End element declaration stuff */
+
+ case XML_ROLE_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_NONE:
+ switch (tok) {
+ case XML_TOK_BOM:
+ handleDefault = XML_FALSE;
+ break;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_NONE:
+ if (startDoctypeDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ENTITY_NONE:
+ if (dtd->keepProcessing && entityDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_NOTATION_NONE:
+ if (notationDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ATTLIST_NONE:
+ if (dtd->keepProcessing && attlistDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ELEMENT_NONE:
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ } /* end of big switch */
+
+ if (handleDefault && defaultHandler)
+ reportDefault(parser, enc, s, next);
+
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default:
+ s = next;
+ tok = XmlPrologTok(enc, s, end, &next);
+ }
+ }
+ /* not reached */
+}
+
+static enum XML_Error PTRCALL
+epilogProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ processor = epilogProcessor;
+ eventPtr = s;
+ for (;;) {
+ const char *next = NULL;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ eventEndPtr = next;
+ switch (tok) {
+ /* report partial linebreak - it might be the last token */
+ case -XML_TOK_PROLOG_S:
+ if (defaultHandler) {
+ reportDefault(parser, encoding, s, next);
+ if (ps_parsing == XML_FINISHED)
+ return XML_ERROR_ABORTED;
+ }
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_TOK_NONE:
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ case XML_TOK_PROLOG_S:
+ if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (!ps_finalBuffer) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (!ps_finalBuffer) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ default:
+ return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+ }
+ eventPtr = s = next;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default: ;
+ }
+ }
+}
+
+static enum XML_Error
+processInternalEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl)
+{
+ const char *textStart, *textEnd;
+ const char *next;
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY *openEntity;
+
+ if (freeInternalEntities) {
+ openEntity = freeInternalEntities;
+ freeInternalEntities = openEntity->next;
+ }
+ else {
+ openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
+ if (!openEntity)
+ return XML_ERROR_NO_MEMORY;
+ }
+ entity->open = XML_TRUE;
+ entity->processed = 0;
+ openEntity->next = openInternalEntities;
+ openInternalEntities = openEntity;
+ openEntity->entity = entity;
+ openEntity->startTagLevel = tagLevel;
+ openEntity->betweenDecl = betweenDecl;
+ openEntity->internalEventPtr = NULL;
+ openEntity->internalEventEndPtr = NULL;
+ textStart = (char *)entity->textPtr;
+ textEnd = (char *)(entity->textPtr + entity->textLen);
+
+#ifdef XML_DTD
+ if (entity->is_param) {
+ int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
+ result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
+ next, &next, XML_FALSE);
+ }
+ else
+#endif /* XML_DTD */
+ result = doContent(parser, tagLevel, internalEncoding, textStart,
+ textEnd, &next, XML_FALSE);
+
+ if (result == XML_ERROR_NONE) {
+ if (textEnd != next && ps_parsing == XML_SUSPENDED) {
+ entity->processed = (int)(next - textStart);
+ processor = internalEntityProcessor;
+ }
+ else {
+ entity->open = XML_FALSE;
+ openInternalEntities = openEntity->next;
+ /* put openEntity back in list of free instances */
+ openEntity->next = freeInternalEntities;
+ freeInternalEntities = openEntity;
+ }
+ }
+ return result;
+}
+
+static enum XML_Error PTRCALL
+internalEntityProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ ENTITY *entity;
+ const char *textStart, *textEnd;
+ const char *next;
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
+ if (!openEntity)
+ return XML_ERROR_UNEXPECTED_STATE;
+
+ entity = openEntity->entity;
+ textStart = ((char *)entity->textPtr) + entity->processed;
+ textEnd = (char *)(entity->textPtr + entity->textLen);
+
+#ifdef XML_DTD
+ if (entity->is_param) {
+ int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
+ result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
+ next, &next, XML_FALSE);
+ }
+ else
+#endif /* XML_DTD */
+ result = doContent(parser, openEntity->startTagLevel, internalEncoding,
+ textStart, textEnd, &next, XML_FALSE);
+
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
+ entity->processed = (int)(next - (char *)entity->textPtr);
+ return result;
+ }
+ else {
+ entity->open = XML_FALSE;
+ openInternalEntities = openEntity->next;
+ /* put openEntity back in list of free instances */
+ openEntity->next = freeInternalEntities;
+ freeInternalEntities = openEntity;
+ }
+
+#ifdef XML_DTD
+ if (entity->is_param) {
+ int tok;
+ processor = prologProcessor;
+ tok = XmlPrologTok(encoding, s, end, &next);
+ return doProlog(parser, encoding, s, end, tok, next, nextPtr,
+ (XML_Bool)!ps_finalBuffer);
+ }
+ else
+#endif /* XML_DTD */
+ {
+ processor = contentProcessor;
+ /* see externalEntityContentProcessor vs contentProcessor */
+ return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
+ nextPtr, (XML_Bool)!ps_finalBuffer);
+ }
+}
+
+static enum XML_Error PTRCALL
+errorProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ (void)s;
+ (void)end;
+ (void)nextPtr;
+
+ return errorCode;
+}
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
+ end, pool);
+ if (result)
+ return result;
+ if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+ poolChop(pool);
+ if (!poolAppendChar(pool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ for (;;) {
+ const char *next;
+ int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+ switch (tok) {
+ case XML_TOK_NONE:
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, ptr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ if (!isCdata
+ && n == 0x20 /* space */
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (!poolAppendChar(pool, buf[i]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, ptr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = ptr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_ATTRIBUTE_VALUE_S:
+ case XML_TOK_DATA_NEWLINE:
+ if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ if (!poolAppendChar(pool, 0x20))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ char checkEntityDecl;
+ XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (!poolAppendChar(pool, ch))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ name = poolStoreString(&temp2Pool, enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
+ poolDiscard(&temp2Pool);
+ /* First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal.
+ */
+ if (pool == &dtd->pool) /* are we called from prolog? */
+ checkEntityDecl =
+#ifdef XML_DTD
+ prologState.documentEntity &&
+#endif /* XML_DTD */
+ (dtd->standalone
+ ? !openInternalEntities
+ : !dtd->hasParamEntityRefs);
+ else /* if (pool == &tempPool): we are called from content */
+ checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
+ if (checkEntityDecl) {
+ if (!entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (!entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ }
+ else if (!entity) {
+ /* Cannot report skipped entity here - see comments on
+ skippedEntityHandler.
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, name, 0);
+ */
+ /* Cannot call the default handler because this would be
+ out of sync with the call to the startElementHandler.
+ if ((pool == &tempPool) && defaultHandler)
+ reportDefault(parser, enc, ptr, next);
+ */
+ break;
+ }
+ if (entity->open) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ if (entity->notation) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BINARY_ENTITY_REF;
+ }
+ if (!entity->textPtr) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+ }
+ else {
+ enum XML_Error result;
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;
+ entity->open = XML_TRUE;
+ result = appendAttributeValue(parser, internalEncoding, isCdata,
+ (char *)entity->textPtr,
+ (char *)textEnd, pool);
+ entity->open = XML_FALSE;
+ if (result)
+ return result;
+ }
+ }
+ break;
+ default:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ ptr = next;
+ }
+ /* not reached */
+}
+
+static enum XML_Error
+storeEntityValue(XML_Parser parser,
+ const ENCODING *enc,
+ const char *entityTextPtr,
+ const char *entityTextEnd)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ STRING_POOL *pool = &(dtd->entityValuePool);
+ enum XML_Error result = XML_ERROR_NONE;
+#ifdef XML_DTD
+ int oldInEntityValue = prologState.inEntityValue;
+ prologState.inEntityValue = 1;
+#endif /* XML_DTD */
+ /* never return Null for the value argument in EntityDeclHandler,
+ since this would indicate an external entity; therefore we
+ have to make sure that entityValuePool.start is not null */
+ if (!pool->blocks) {
+ if (!poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ for (;;) {
+ const char *next;
+ int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+ if (isParamEntity || enc != encoding) {
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&tempPool, enc,
+ entityTextPtr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
+ poolDiscard(&tempPool);
+ if (!entity) {
+ /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
+ /* cannot report skipped entity here - see comments on
+ skippedEntityHandler
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, name, 0);
+ */
+ dtd->keepProcessing = dtd->standalone;
+ goto endEntityValue;
+ }
+ if (entity->open) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_RECURSIVE_ENTITY_REF;
+ goto endEntityValue;
+ }
+ if (entity->systemId) {
+ if (externalEntityRefHandler) {
+ dtd->paramEntityRead = XML_FALSE;
+ entity->open = XML_TRUE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ entity->open = XML_FALSE;
+ result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ goto endEntityValue;
+ }
+ entity->open = XML_FALSE;
+ if (!dtd->paramEntityRead)
+ dtd->keepProcessing = dtd->standalone;
+ }
+ else
+ dtd->keepProcessing = dtd->standalone;
+ }
+ else {
+ entity->open = XML_TRUE;
+ result = storeEntityValue(parser,
+ internalEncoding,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr
+ + entity->textLen));
+ entity->open = XML_FALSE;
+ if (result)
+ goto endEntityValue;
+ }
+ break;
+ }
+#endif /* XML_DTD */
+ /* In the internal subset, PE references are not legal
+ within markup declarations, e.g entity values in this case. */
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_PARAM_ENTITY_REF;
+ goto endEntityValue;
+ case XML_TOK_NONE:
+ result = XML_ERROR_NONE;
+ goto endEntityValue;
+ case XML_TOK_ENTITY_REF:
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, entityTextPtr, next)) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = entityTextPtr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_DATA_NEWLINE:
+ if (pool->end == pool->ptr && !poolGrow(pool)) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ *(pool->ptr)++ = 0xA;
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, entityTextPtr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_BAD_CHAR_REF;
+ goto endEntityValue;
+ }
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_BAD_CHAR_REF;
+ goto endEntityValue;
+ }
+ for (i = 0; i < n; i++) {
+ if (pool->end == pool->ptr && !poolGrow(pool)) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ *(pool->ptr)++ = buf[i];
+ }
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_INVALID_TOKEN;
+ goto endEntityValue;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ result = XML_ERROR_INVALID_TOKEN;
+ goto endEntityValue;
+ default:
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_UNEXPECTED_STATE;
+ goto endEntityValue;
+ }
+ entityTextPtr = next;
+ }
+endEntityValue:
+#ifdef XML_DTD
+ prologState.inEntityValue = oldInEntityValue;
+#endif /* XML_DTD */
+ return result;
+}
+
+static void FASTCALL
+normalizeLines(XML_Char *s)
+{
+ XML_Char *p;
+ for (;; s++) {
+ if (*s == XML_T('\0'))
+ return;
+ if (*s == 0xD)
+ break;
+ }
+ p = s;
+ do {
+ if (*s == 0xD) {
+ *p++ = 0xA;
+ if (*++s == 0xA)
+ s++;
+ }
+ else
+ *p++ = *s++;
+ } while (*s);
+ *p = XML_T('\0');
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end)
+{
+ const XML_Char *target;
+ XML_Char *data;
+ const char *tem;
+ if (!processingInstructionHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ start += enc->minBytesPerChar * 2;
+ tem = start + XmlNameLength(enc, start);
+ target = poolStoreString(&tempPool, enc, start, tem);
+ if (!target)
+ return 0;
+ poolFinish(&tempPool);
+ data = poolStoreString(&tempPool, enc,
+ XmlSkipS(enc, tem),
+ end - enc->minBytesPerChar*2);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ processingInstructionHandler(handlerArg, target, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static int
+reportComment(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end)
+{
+ XML_Char *data;
+ if (!commentHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ data = poolStoreString(&tempPool,
+ enc,
+ start + enc->minBytesPerChar * 4,
+ end - enc->minBytesPerChar * 3);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ commentHandler(handlerArg, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc,
+ const char *s, const char *end)
+{
+ if (MUST_CONVERT(enc, s)) {
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ do {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
+ *eventPP = s;
+ } while (s != end);
+ }
+ else
+ defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
+}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
+ XML_Bool isId, const XML_Char *value, XML_Parser parser)
+{
+ DEFAULT_ATTRIBUTE *att;
+ if (value || isId) {
+ /* The handling of default attributes gets messed up if we have
+ a default which duplicates a non-default. */
+ int i;
+ for (i = 0; i < type->nDefaultAtts; i++)
+ if (attId == type->defaultAtts[i].id)
+ return 1;
+ if (isId && !type->idAtt && !attId->xmlns)
+ type->idAtt = attId;
+ }
+ if (type->nDefaultAtts == type->allocDefaultAtts) {
+ if (type->allocDefaultAtts == 0) {
+ type->allocDefaultAtts = 8;
+ type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
+ * sizeof(DEFAULT_ATTRIBUTE));
+ if (!type->defaultAtts)
+ return 0;
+ }
+ else {
+ DEFAULT_ATTRIBUTE *temp;
+ int count = type->allocDefaultAtts * 2;
+ temp = (DEFAULT_ATTRIBUTE *)
+ REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
+ if (temp == NULL)
+ return 0;
+ type->allocDefaultAtts = count;
+ type->defaultAtts = temp;
+ }
+ }
+ att = type->defaultAtts + type->nDefaultAtts;
+ att->id = attId;
+ att->value = value;
+ att->isCdata = isCdata;
+ if (!isCdata)
+ attId->maybeTokenized = XML_TRUE;
+ type->nDefaultAtts += 1;
+ return 1;
+}
+
+static int
+setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ const XML_Char *name;
+ for (name = elementType->name; *name; name++) {
+ if (*name == XML_T(ASCII_COLON)) {
+ PREFIX *prefix;
+ const XML_Char *s;
+ for (s = elementType->name; s != name; s++) {
+ if (!poolAppendChar(&dtd->pool, *s))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
+ sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&dtd->pool))
+ poolFinish(&dtd->pool);
+ else
+ poolDiscard(&dtd->pool);
+ elementType->prefix = prefix;
+
+ }
+ }
+ return 1;
+}
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ ATTRIBUTE_ID *id;
+ const XML_Char *name;
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ return NULL;
+ name = poolStoreString(&dtd->pool, enc, start, end);
+ if (!name)
+ return NULL;
+ /* skip quotation mark - its storage will be re-used (like in name[-1]) */
+ ++name;
+ id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
+ if (!id)
+ return NULL;
+ if (id->name != name)
+ poolDiscard(&dtd->pool);
+ else {
+ poolFinish(&dtd->pool);
+ if (!ns)
+ ;
+ else if (name[0] == XML_T(ASCII_x)
+ && name[1] == XML_T(ASCII_m)
+ && name[2] == XML_T(ASCII_l)
+ && name[3] == XML_T(ASCII_n)
+ && name[4] == XML_T(ASCII_s)
+ && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
+ if (name[5] == XML_T('\0'))
+ id->prefix = &dtd->defaultPrefix;
+ else
+ id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
+ id->xmlns = XML_TRUE;
+ }
+ else {
+ int i;
+ for (i = 0; name[i]; i++) {
+ /* attributes without prefix are *not* in the default namespace */
+ if (name[i] == XML_T(ASCII_COLON)) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!poolAppendChar(&dtd->pool, name[j]))
+ return NULL;
+ }
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ return NULL;
+ id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
+ sizeof(PREFIX));
+ if (id->prefix->name == poolStart(&dtd->pool))
+ poolFinish(&dtd->pool);
+ else
+ poolDiscard(&dtd->pool);
+ break;
+ }
+ }
+ }
+ }
+ return id;
+}
+
+#define CONTEXT_SEP XML_T(ASCII_FF)
+
+static const XML_Char *
+getContext(XML_Parser parser)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ HASH_TABLE_ITER iter;
+ XML_Bool needSep = XML_FALSE;
+
+ if (dtd->defaultPrefix.binding) {
+ int i;
+ int len;
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
+ return NULL;
+ len = dtd->defaultPrefix.binding->uriLen;
+ if (namespaceSeparator)
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
+ return NULL;
+ needSep = XML_TRUE;
+ }
+
+ hashTableIterInit(&iter, &(dtd->prefixes));
+ for (;;) {
+ int i;
+ int len;
+ const XML_Char *s;
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+ if (!prefix)
+ break;
+ if (!prefix->binding)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return NULL;
+ for (s = prefix->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return NULL;
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
+ return NULL;
+ len = prefix->binding->uriLen;
+ if (namespaceSeparator)
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+ return NULL;
+ needSep = XML_TRUE;
+ }
+
+
+ hashTableIterInit(&iter, &(dtd->generalEntities));
+ for (;;) {
+ const XML_Char *s;
+ ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (!e->open)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return NULL;
+ for (s = e->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ needSep = XML_TRUE;
+ }
+
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return NULL;
+ return tempPool.start;
+}
+
+static XML_Bool
+setContext(XML_Parser parser, const XML_Char *context)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ const XML_Char *s = context;
+
+ while (*context != XML_T('\0')) {
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+ ENTITY *e;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_FALSE;
+ e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
+ if (e)
+ e->open = XML_TRUE;
+ if (*s != XML_T('\0'))
+ s++;
+ context = s;
+ poolDiscard(&tempPool);
+ }
+ else if (*s == XML_T(ASCII_EQUALS)) {
+ PREFIX *prefix;
+ if (poolLength(&tempPool) == 0)
+ prefix = &dtd->defaultPrefix;
+ else {
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_FALSE;
+ prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
+ sizeof(PREFIX));
+ if (!prefix)
+ return XML_FALSE;
+ if (prefix->name == poolStart(&tempPool)) {
+ prefix->name = poolCopyString(&dtd->pool, prefix->name);
+ if (!prefix->name)
+ return XML_FALSE;
+ }
+ poolDiscard(&tempPool);
+ }
+ for (context = s + 1;
+ *context != CONTEXT_SEP && *context != XML_T('\0');
+ context++)
+ if (!poolAppendChar(&tempPool, *context))
+ return XML_FALSE;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_FALSE;
+ if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
+ &inheritedBindings) != XML_ERROR_NONE)
+ return XML_FALSE;
+ poolDiscard(&tempPool);
+ if (*context != XML_T('\0'))
+ ++context;
+ s = context;
+ }
+ else {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_FALSE;
+ s++;
+ }
+ }
+ return XML_TRUE;
+}
+
+static void FASTCALL
+normalizePublicId(XML_Char *publicId)
+{
+ XML_Char *p = publicId;
+ XML_Char *s;
+ for (s = publicId; *s; s++) {
+ switch (*s) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ if (p != publicId && p[-1] != 0x20)
+ *p++ = 0x20;
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ if (p != publicId && p[-1] == 0x20)
+ --p;
+ *p = XML_T('\0');
+}
+
+static DTD *
+dtdCreate(const XML_Memory_Handling_Suite *ms)
+{
+ DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
+ if (p == NULL)
+ return p;
+ poolInit(&(p->pool), ms);
+ poolInit(&(p->entityValuePool), ms);
+ hashTableInit(&(p->generalEntities), ms);
+ hashTableInit(&(p->elementTypes), ms);
+ hashTableInit(&(p->attributeIds), ms);
+ hashTableInit(&(p->prefixes), ms);
+#ifdef XML_DTD
+ p->paramEntityRead = XML_FALSE;
+ hashTableInit(&(p->paramEntities), ms);
+#endif /* XML_DTD */
+ p->defaultPrefix.name = NULL;
+ p->defaultPrefix.binding = NULL;
+
+ p->in_eldecl = XML_FALSE;
+ p->scaffIndex = NULL;
+ p->scaffold = NULL;
+ p->scaffLevel = 0;
+ p->scaffSize = 0;
+ p->scaffCount = 0;
+ p->contentStringLen = 0;
+
+ p->keepProcessing = XML_TRUE;
+ p->hasParamEntityRefs = XML_FALSE;
+ p->standalone = XML_FALSE;
+ return p;
+}
+
+static void
+dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
+{
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ ms->free_fcn(e->defaultAtts);
+ }
+ hashTableClear(&(p->generalEntities));
+#ifdef XML_DTD
+ p->paramEntityRead = XML_FALSE;
+ hashTableClear(&(p->paramEntities));
+#endif /* XML_DTD */
+ hashTableClear(&(p->elementTypes));
+ hashTableClear(&(p->attributeIds));
+ hashTableClear(&(p->prefixes));
+ poolClear(&(p->pool));
+ poolClear(&(p->entityValuePool));
+ p->defaultPrefix.name = NULL;
+ p->defaultPrefix.binding = NULL;
+
+ p->in_eldecl = XML_FALSE;
+
+ ms->free_fcn(p->scaffIndex);
+ p->scaffIndex = NULL;
+ ms->free_fcn(p->scaffold);
+ p->scaffold = NULL;
+
+ p->scaffLevel = 0;
+ p->scaffSize = 0;
+ p->scaffCount = 0;
+ p->contentStringLen = 0;
+
+ p->keepProcessing = XML_TRUE;
+ p->hasParamEntityRefs = XML_FALSE;
+ p->standalone = XML_FALSE;
+}
+
+static void
+dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
+{
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ ms->free_fcn(e->defaultAtts);
+ }
+ hashTableDestroy(&(p->generalEntities));
+#ifdef XML_DTD
+ hashTableDestroy(&(p->paramEntities));
+#endif /* XML_DTD */
+ hashTableDestroy(&(p->elementTypes));
+ hashTableDestroy(&(p->attributeIds));
+ hashTableDestroy(&(p->prefixes));
+ poolDestroy(&(p->pool));
+ poolDestroy(&(p->entityValuePool));
+ if (isDocEntity) {
+ ms->free_fcn(p->scaffIndex);
+ ms->free_fcn(p->scaffold);
+ }
+ ms->free_fcn(p);
+}
+
+/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
+ The new DTD has already been initialized.
+*/
+static int
+dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
+{
+ HASH_TABLE_ITER iter;
+
+ /* Copy the prefix table. */
+
+ hashTableIterInit(&iter, &(oldDtd->prefixes));
+ for (;;) {
+ const XML_Char *name;
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+ if (!oldP)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldP->name);
+ if (!name)
+ return 0;
+ if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+ return 0;
+ }
+
+ hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+ /* Copy the attribute id table. */
+
+ for (;;) {
+ ATTRIBUTE_ID *newA;
+ const XML_Char *name;
+ const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+ if (!oldA)
+ break;
+ /* Remember to allocate the scratch byte before the name. */
+ if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+ return 0;
+ name = poolCopyString(&(newDtd->pool), oldA->name);
+ if (!name)
+ return 0;
+ ++name;
+ newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
+ sizeof(ATTRIBUTE_ID));
+ if (!newA)
+ return 0;
+ newA->maybeTokenized = oldA->maybeTokenized;
+ if (oldA->prefix) {
+ newA->xmlns = oldA->xmlns;
+ if (oldA->prefix == &oldDtd->defaultPrefix)
+ newA->prefix = &newDtd->defaultPrefix;
+ else
+ newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
+ oldA->prefix->name, 0);
+ }
+ }
+
+ /* Copy the element type table. */
+
+ hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+ for (;;) {
+ int i;
+ ELEMENT_TYPE *newE;
+ const XML_Char *name;
+ const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
+ sizeof(ELEMENT_TYPE));
+ if (!newE)
+ return 0;
+ if (oldE->nDefaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
+ ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (!newE->defaultAtts) {
+ ms->free_fcn(newE);
+ return 0;
+ }
+ }
+ if (oldE->idAtt)
+ newE->idAtt = (ATTRIBUTE_ID *)
+ lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
+ newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+ if (oldE->prefix)
+ newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
+ oldE->prefix->name, 0);
+ for (i = 0; i < newE->nDefaultAtts; i++) {
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
+ lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+ if (oldE->defaultAtts[i].value) {
+ newE->defaultAtts[i].value
+ = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+ if (!newE->defaultAtts[i].value)
+ return 0;
+ }
+ else
+ newE->defaultAtts[i].value = NULL;
+ }
+ }
+
+ /* Copy the entity tables. */
+ if (!copyEntityTable(&(newDtd->generalEntities),
+ &(newDtd->pool),
+ &(oldDtd->generalEntities)))
+ return 0;
+
+#ifdef XML_DTD
+ if (!copyEntityTable(&(newDtd->paramEntities),
+ &(newDtd->pool),
+ &(oldDtd->paramEntities)))
+ return 0;
+ newDtd->paramEntityRead = oldDtd->paramEntityRead;
+#endif /* XML_DTD */
+
+ newDtd->keepProcessing = oldDtd->keepProcessing;
+ newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
+ newDtd->standalone = oldDtd->standalone;
+
+ /* Don't want deep copying for scaffolding */
+ newDtd->in_eldecl = oldDtd->in_eldecl;
+ newDtd->scaffold = oldDtd->scaffold;
+ newDtd->contentStringLen = oldDtd->contentStringLen;
+ newDtd->scaffSize = oldDtd->scaffSize;
+ newDtd->scaffLevel = oldDtd->scaffLevel;
+ newDtd->scaffIndex = oldDtd->scaffIndex;
+
+ return 1;
+} /* End dtdCopy */
+
+static int
+copyEntityTable(HASH_TABLE *newTable,
+ STRING_POOL *newPool,
+ const HASH_TABLE *oldTable)
+{
+ HASH_TABLE_ITER iter;
+ const XML_Char *cachedOldBase = NULL;
+ const XML_Char *cachedNewBase = NULL;
+
+ hashTableIterInit(&iter, oldTable);
+
+ for (;;) {
+ ENTITY *newE;
+ const XML_Char *name;
+ const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(newPool, oldE->name);
+ if (!name)
+ return 0;
+ newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
+ if (!newE)
+ return 0;
+ if (oldE->systemId) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
+ if (!tem)
+ return 0;
+ newE->systemId = tem;
+ if (oldE->base) {
+ if (oldE->base == cachedOldBase)
+ newE->base = cachedNewBase;
+ else {
+ cachedOldBase = oldE->base;
+ tem = poolCopyString(newPool, cachedOldBase);
+ if (!tem)
+ return 0;
+ cachedNewBase = newE->base = tem;
+ }
+ }
+ if (oldE->publicId) {
+ tem = poolCopyString(newPool, oldE->publicId);
+ if (!tem)
+ return 0;
+ newE->publicId = tem;
+ }
+ }
+ else {
+ const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
+ oldE->textLen);
+ if (!tem)
+ return 0;
+ newE->textPtr = tem;
+ newE->textLen = oldE->textLen;
+ }
+ if (oldE->notation) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->notation);
+ if (!tem)
+ return 0;
+ newE->notation = tem;
+ }
+ newE->is_param = oldE->is_param;
+ newE->is_internal = oldE->is_internal;
+ }
+ return 1;
+}
+
+#define INIT_POWER 6
+
+static XML_Bool FASTCALL
+keyeq(KEY s1, KEY s2)
+{
+ for (; *s1 == *s2; s1++, s2++)
+ if (*s1 == 0)
+ return XML_TRUE;
+ return XML_FALSE;
+}
+
+static unsigned long FASTCALL
+hash(KEY s)
+{
+ unsigned long h = 0;
+ while (*s)
+ h = CHAR_HASH(h, *s++);
+ return h;
+}
+
+static NAMED *
+lookup(HASH_TABLE *table, KEY name, size_t createSize)
+{
+ size_t i;
+ if (table->size == 0) {
+ size_t tsize;
+ if (!createSize)
+ return NULL;
+ table->power = INIT_POWER;
+ /* table->size is a power of 2 */
+ table->size = (size_t)1 << INIT_POWER;
+ tsize = table->size * sizeof(NAMED *);
+ table->v = (NAMED **)table->mem->malloc_fcn(tsize);
+ if (!table->v) {
+ table->size = 0;
+ return NULL;
+ }
+ memset(table->v, 0, tsize);
+ i = hash(name) & ((unsigned long)table->size - 1);
+ }
+ else {
+ unsigned long h = hash(name);
+ unsigned long mask = (unsigned long)table->size - 1;
+ unsigned char step = 0;
+ i = h & mask;
+ while (table->v[i]) {
+ if (keyeq(name, table->v[i]->name))
+ return table->v[i];
+ if (!step)
+ step = PROBE_STEP(h, mask, table->power);
+ i < step ? (i += table->size - step) : (i -= step);
+ }
+ if (!createSize)
+ return NULL;
+
+ /* check for overflow (table is half full) */
+ if (table->used >> (table->power - 1)) {
+ unsigned char newPower = table->power + 1;
+ size_t newSize = (size_t)1 << newPower;
+ unsigned long newMask = (unsigned long)newSize - 1;
+ size_t tsize = newSize * sizeof(NAMED *);
+ NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
+ if (!newV)
+ return NULL;
+ memset(newV, 0, tsize);
+ for (i = 0; i < table->size; i++)
+ if (table->v[i]) {
+ unsigned long newHash = hash(table->v[i]->name);
+ size_t j = newHash & newMask;
+ step = 0;
+ while (newV[j]) {
+ if (!step)
+ step = PROBE_STEP(newHash, newMask, newPower);
+ j < step ? (j += newSize - step) : (j -= step);
+ }
+ newV[j] = table->v[i];
+ }
+ table->mem->free_fcn(table->v);
+ table->v = newV;
+ table->power = newPower;
+ table->size = newSize;
+ i = h & newMask;
+ step = 0;
+ while (table->v[i]) {
+ if (!step)
+ step = PROBE_STEP(h, newMask, newPower);
+ i < step ? (i += newSize - step) : (i -= step);
+ }
+ }
+ }
+ table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
+ if (!table->v[i])
+ return NULL;
+ memset(table->v[i], 0, createSize);
+ table->v[i]->name = name;
+ (table->used)++;
+ return table->v[i];
+}
+
+static void FASTCALL
+hashTableClear(HASH_TABLE *table)
+{
+ size_t i;
+ for (i = 0; i < table->size; i++) {
+ table->mem->free_fcn(table->v[i]);
+ table->v[i] = NULL;
+ }
+ table->used = 0;
+}
+
+static void FASTCALL
+hashTableDestroy(HASH_TABLE *table)
+{
+ size_t i;
+ for (i = 0; i < table->size; i++)
+ table->mem->free_fcn(table->v[i]);
+ table->mem->free_fcn(table->v);
+}
+
+static void FASTCALL
+hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
+{
+ p->power = 0;
+ p->size = 0;
+ p->used = 0;
+ p->v = NULL;
+ p->mem = ms;
+}
+
+static void FASTCALL
+hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+{
+ iter->p = table->v;
+ iter->end = iter->p + table->size;
+}
+
+static NAMED * FASTCALL
+hashTableIterNext(HASH_TABLE_ITER *iter)
+{
+ while (iter->p != iter->end) {
+ NAMED *tem = *(iter->p)++;
+ if (tem)
+ return tem;
+ }
+ return NULL;
+}
+
+static void FASTCALL
+poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
+{
+ pool->blocks = NULL;
+ pool->freeBlocks = NULL;
+ pool->start = NULL;
+ pool->ptr = NULL;
+ pool->end = NULL;
+ pool->mem = ms;
+}
+
+static void FASTCALL
+poolClear(STRING_POOL *pool)
+{
+ if (!pool->freeBlocks)
+ pool->freeBlocks = pool->blocks;
+ else {
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ p->next = pool->freeBlocks;
+ pool->freeBlocks = p;
+ p = tem;
+ }
+ }
+ pool->blocks = NULL;
+ pool->start = NULL;
+ pool->ptr = NULL;
+ pool->end = NULL;
+}
+
+static void FASTCALL
+poolDestroy(STRING_POOL *pool)
+{
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ pool->mem->free_fcn(p);
+ p = tem;
+ }
+ p = pool->freeBlocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ pool->mem->free_fcn(p);
+ p = tem;
+ }
+}
+
+static XML_Char *
+poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return NULL;
+ for (;;) {
+ XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+ if (ptr == end)
+ break;
+ if (!poolGrow(pool))
+ return NULL;
+ }
+ return pool->start;
+}
+
+static const XML_Char * FASTCALL
+poolCopyString(STRING_POOL *pool, const XML_Char *s)
+{
+ do {
+ if (!poolAppendChar(pool, *s))
+ return NULL;
+ } while (*s++);
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static const XML_Char *
+poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return NULL;
+ for (; n > 0; --n, s++) {
+ if (!poolAppendChar(pool, *s))
+ return NULL;
+ }
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static const XML_Char * FASTCALL
+poolAppendString(STRING_POOL *pool, const XML_Char *s)
+{
+ while (*s) {
+ if (!poolAppendChar(pool, *s))
+ return NULL;
+ s++;
+ }
+ return pool->start;
+}
+
+static XML_Char *
+poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!poolAppend(pool, enc, ptr, end))
+ return NULL;
+ if (pool->ptr == pool->end && !poolGrow(pool))
+ return NULL;
+ *(pool->ptr)++ = 0;
+ return pool->start;
+}
+
+static XML_Bool FASTCALL
+poolGrow(STRING_POOL *pool)
+{
+ if (pool->freeBlocks) {
+ if (pool->start == 0) {
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = pool->freeBlocks->next;
+ pool->blocks->next = NULL;
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ pool->ptr = pool->start;
+ return XML_TRUE;
+ }
+ if (pool->end - pool->start < pool->freeBlocks->size) {
+ BLOCK *tem = pool->freeBlocks->next;
+ pool->freeBlocks->next = pool->blocks;
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = tem;
+ memcpy(pool->blocks->s, pool->start,
+ (pool->end - pool->start) * sizeof(XML_Char));
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ return XML_TRUE;
+ }
+ }
+ if (pool->blocks && pool->start == pool->blocks->s) {
+ int blockSize = (int)(pool->end - pool->start)*2;
+ pool->blocks = (BLOCK *)
+ pool->mem->realloc_fcn(pool->blocks,
+ (offsetof(BLOCK, s)
+ + blockSize * sizeof(XML_Char)));
+ if (pool->blocks == NULL)
+ return XML_FALSE;
+ pool->blocks->size = blockSize;
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + blockSize;
+ }
+ else {
+ BLOCK *tem;
+ int blockSize = (int)(pool->end - pool->start);
+ if (blockSize < INIT_BLOCK_SIZE)
+ blockSize = INIT_BLOCK_SIZE;
+ else
+ blockSize *= 2;
+ tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
+ + blockSize * sizeof(XML_Char));
+ if (!tem)
+ return XML_FALSE;
+ tem->size = blockSize;
+ tem->next = pool->blocks;
+ pool->blocks = tem;
+ if (pool->ptr != pool->start)
+ memcpy(tem->s, pool->start,
+ (pool->ptr - pool->start) * sizeof(XML_Char));
+ pool->ptr = tem->s + (pool->ptr - pool->start);
+ pool->start = tem->s;
+ pool->end = tem->s + blockSize;
+ }
+ return XML_TRUE;
+}
+
+static int FASTCALL
+nextScaffoldPart(XML_Parser parser)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ CONTENT_SCAFFOLD * me;
+ int next;
+
+ if (!dtd->scaffIndex) {
+ dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
+ if (!dtd->scaffIndex)
+ return -1;
+ dtd->scaffIndex[0] = 0;
+ }
+
+ if (dtd->scaffCount >= dtd->scaffSize) {
+ CONTENT_SCAFFOLD *temp;
+ if (dtd->scaffold) {
+ temp = (CONTENT_SCAFFOLD *)
+ REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
+ if (temp == NULL)
+ return -1;
+ dtd->scaffSize *= 2;
+ }
+ else {
+ temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
+ * sizeof(CONTENT_SCAFFOLD));
+ if (temp == NULL)
+ return -1;
+ dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
+ }
+ dtd->scaffold = temp;
+ }
+ next = dtd->scaffCount++;
+ me = &dtd->scaffold[next];
+ if (dtd->scaffLevel) {
+ CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
+ if (parent->lastchild) {
+ dtd->scaffold[parent->lastchild].nextsib = next;
+ }
+ if (!parent->childcnt)
+ parent->firstchild = next;
+ parent->lastchild = next;
+ parent->childcnt++;
+ }
+ me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
+ return next;
+}
+
+static void
+build_node(XML_Parser parser,
+ int src_node,
+ XML_Content *dest,
+ XML_Content **contpos,
+ XML_Char **strpos)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ dest->type = dtd->scaffold[src_node].type;
+ dest->quant = dtd->scaffold[src_node].quant;
+ if (dest->type == XML_CTYPE_NAME) {
+ const XML_Char *src;
+ dest->name = *strpos;
+ src = dtd->scaffold[src_node].name;
+ for (;;) {
+ *(*strpos)++ = *src;
+ if (!*src)
+ break;
+ src++;
+ }
+ dest->numchildren = 0;
+ dest->children = NULL;
+ }
+ else {
+ unsigned int i;
+ int cn;
+ dest->numchildren = dtd->scaffold[src_node].childcnt;
+ dest->children = *contpos;
+ *contpos += dest->numchildren;
+ for (i = 0, cn = dtd->scaffold[src_node].firstchild;
+ i < dest->numchildren;
+ i++, cn = dtd->scaffold[cn].nextsib) {
+ build_node(parser, cn, &(dest->children[i]), contpos, strpos);
+ }
+ dest->name = NULL;
+ }
+}
+
+static XML_Content *
+build_model (XML_Parser parser)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ XML_Content *ret;
+ XML_Content *cpos;
+ XML_Char * str;
+ int allocsize = (dtd->scaffCount * sizeof(XML_Content)
+ + (dtd->contentStringLen * sizeof(XML_Char)));
+
+ ret = (XML_Content *)MALLOC(allocsize);
+ if (!ret)
+ return NULL;
+
+ str = (XML_Char *) (&ret[dtd->scaffCount]);
+ cpos = &ret[1];
+
+ build_node(parser, 0, ret, &cpos, &str);
+ return ret;
+}
+
+static ELEMENT_TYPE *
+getElementType(XML_Parser parser,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
+ ELEMENT_TYPE *ret;
+
+ if (!name)
+ return NULL;
+ ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
+ if (!ret)
+ return NULL;
+ if (ret->name != name)
+ poolDiscard(&dtd->pool);
+ else {
+ poolFinish(&dtd->pool);
+ if (!setElementTypePrefix(parser, ret))
+ return NULL;
+ }
+ return ret;
+}
diff --git a/lib/expat/xmlrole.c b/lib/expat/xmlrole.c
new file mode 100644
index 000000000..55cba6429
--- /dev/null
+++ b/lib/expat/xmlrole.c
@@ -0,0 +1,1482 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stddef.h>
+
+#ifdef COMPILED_FROM_DSP
+#include "winconfig.h"
+#elif defined(MACOS_CLASSIC)
+#include "macconfig.h"
+#elif defined(__amigaos4__)
+#include "amigaconfig.h"
+#elif defined(__WATCOMC__)
+#include "watcomconfig.h"
+#else
+#ifdef HAVE_EXPAT_CONFIG_H
+#include <expat_config.h>
+#endif
+#endif /* ndef COMPILED_FROM_DSP */
+
+#include "expat_external.h"
+#include "internal.h"
+#include "xmlrole.h"
+#include "ascii.h"
+
+/* Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals
+
+*/
+
+static const char KW_ANY[] = {
+ ASCII_A, ASCII_N, ASCII_Y, '\0' };
+static const char KW_ATTLIST[] = {
+ ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' };
+static const char KW_CDATA[] = {
+ ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_DOCTYPE[] = {
+ ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' };
+static const char KW_ELEMENT[] = {
+ ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' };
+static const char KW_EMPTY[] = {
+ ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' };
+static const char KW_ENTITIES[] = {
+ ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S,
+ '\0' };
+static const char KW_ENTITY[] = {
+ ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
+static const char KW_FIXED[] = {
+ ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' };
+static const char KW_ID[] = {
+ ASCII_I, ASCII_D, '\0' };
+static const char KW_IDREF[] = {
+ ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
+static const char KW_IDREFS[] = {
+ ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+#ifdef XML_DTD
+static const char KW_IGNORE[] = {
+ ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' };
+#endif
+static const char KW_IMPLIED[] = {
+ ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' };
+#ifdef XML_DTD
+static const char KW_INCLUDE[] = {
+ ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' };
+#endif
+static const char KW_NDATA[] = {
+ ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_NMTOKEN[] = {
+ ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
+static const char KW_NMTOKENS[] = {
+ ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S,
+ '\0' };
+static const char KW_NOTATION[] =
+ { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N,
+ '\0' };
+static const char KW_PCDATA[] = {
+ ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_PUBLIC[] = {
+ ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' };
+static const char KW_REQUIRED[] = {
+ ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D,
+ '\0' };
+static const char KW_SYSTEM[] = {
+ ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' };
+
+#ifndef MIN_BYTES_PER_CHAR
+#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+#endif
+
+#ifdef XML_DTD
+#define setTopLevel(state) \
+ ((state)->handler = ((state)->documentEntity \
+ ? internalSubset \
+ : externalSubset1))
+#else /* not XML_DTD */
+#define setTopLevel(state) ((state)->handler = internalSubset)
+#endif /* not XML_DTD */
+
+typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+
+static PROLOG_HANDLER
+ prolog0, prolog1, prolog2,
+ doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
+ internalSubset,
+ entity0, entity1, entity2, entity3, entity4, entity5, entity6,
+ entity7, entity8, entity9, entity10,
+ notation0, notation1, notation2, notation3, notation4,
+ attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
+ attlist7, attlist8, attlist9,
+ element0, element1, element2, element3, element4, element5, element6,
+ element7,
+#ifdef XML_DTD
+ externalSubset0, externalSubset1,
+ condSect0, condSect1, condSect2,
+#endif /* XML_DTD */
+ declClose,
+ error;
+
+static int FASTCALL common(PROLOG_STATE *state, int tok);
+
+static int PTRCALL
+prolog0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_XML_DECL:
+ state->handler = prolog1;
+ return XML_ROLE_XML_DECL;
+ case XML_TOK_PI:
+ state->handler = prolog1;
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ state->handler = prolog1;
+ return XML_ROLE_COMMENT;
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_DOCTYPE))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+prolog1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ return XML_ROLE_COMMENT;
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_DOCTYPE))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+prolog2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ return XML_ROLE_COMMENT;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = doctype1;
+ return XML_ROLE_DOCTYPE_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = doctype3;
+ return XML_ROLE_DOCTYPE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = doctype2;
+ return XML_ROLE_DOCTYPE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype3;
+ return XML_ROLE_DOCTYPE_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype4;
+ return XML_ROLE_DOCTYPE_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+internalSubset(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ENTITY)) {
+ state->handler = entity0;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ATTLIST)) {
+ state->handler = attlist0;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ELEMENT)) {
+ state->handler = element0;
+ return XML_ROLE_ELEMENT_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_NOTATION)) {
+ state->handler = notation0;
+ return XML_ROLE_NOTATION_NONE;
+ }
+ break;
+ case XML_TOK_PI:
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ return XML_ROLE_COMMENT;
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ROLE_PARAM_ENTITY_REF;
+ case XML_TOK_CLOSE_BRACKET:
+ state->handler = doctype5;
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_NONE:
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static int PTRCALL
+externalSubset0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ state->handler = externalSubset1;
+ if (tok == XML_TOK_XML_DECL)
+ return XML_ROLE_TEXT_DECL;
+ return externalSubset1(state, tok, ptr, end, enc);
+}
+
+static int PTRCALL
+externalSubset1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_COND_SECT_OPEN:
+ state->handler = condSect0;
+ return XML_ROLE_NONE;
+ case XML_TOK_COND_SECT_CLOSE:
+ if (state->includeLevel == 0)
+ break;
+ state->includeLevel -= 1;
+ return XML_ROLE_NONE;
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_BRACKET:
+ break;
+ case XML_TOK_NONE:
+ if (state->includeLevel)
+ break;
+ return XML_ROLE_NONE;
+ default:
+ return internalSubset(state, tok, ptr, end, enc);
+ }
+ return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static int PTRCALL
+entity0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_PERCENT:
+ state->handler = entity1;
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity2;
+ return XML_ROLE_GENERAL_ENTITY_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity7;
+ return XML_ROLE_PARAM_ENTITY_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = entity4;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = entity3;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ENTITY_NONE;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity4;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity5;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_ENTITY_COMPLETE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) {
+ state->handler = entity6;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ENTITY_NONE;
+ return XML_ROLE_ENTITY_NOTATION_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = entity9;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = entity8;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ENTITY_NONE;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity9;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity10;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity10(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_ENTITY_COMPLETE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_NAME:
+ state->handler = notation1;
+ return XML_ROLE_NOTATION_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = notation3;
+ return XML_ROLE_NOTATION_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = notation2;
+ return XML_ROLE_NOTATION_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = notation4;
+ return XML_ROLE_NOTATION_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_NOTATION_NONE;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_NOTATION_NONE;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_NOTATION_NO_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist1;
+ return XML_ROLE_ATTLIST_ELEMENT_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist2;
+ return XML_ROLE_ATTRIBUTE_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ {
+ static const char * const types[] = {
+ KW_CDATA,
+ KW_ID,
+ KW_IDREF,
+ KW_IDREFS,
+ KW_ENTITY,
+ KW_ENTITIES,
+ KW_NMTOKEN,
+ KW_NMTOKENS,
+ };
+ int i;
+ for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
+ if (XmlNameMatchesAscii(enc, ptr, end, types[i])) {
+ state->handler = attlist8;
+ return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) {
+ state->handler = attlist5;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist3;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NMTOKEN:
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist4;
+ return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist3;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist6;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ state->handler = attlist7;
+ return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist6;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+/* default value */
+static int PTRCALL
+attlist8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_IMPLIED)) {
+ state->handler = attlist1;
+ return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_REQUIRED)) {
+ state->handler = attlist1;
+ return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_FIXED)) {
+ state->handler = attlist9;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element1;
+ return XML_ROLE_ELEMENT_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_CONTENT_EMPTY;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_CONTENT_ANY;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = element2;
+ state->level = 1;
+ return XML_ROLE_GROUP_OPEN;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_PCDATA)) {
+ state->handler = element3;
+ return XML_ROLE_CONTENT_PCDATA;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->level = 2;
+ state->handler = element6;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_ELEMENT_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element5;
+ return XML_ROLE_CONTENT_ELEMENT;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_ELEMENT_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->level += 1;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_CLOSE_PAREN_QUESTION:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE_OPT;
+ case XML_TOK_CLOSE_PAREN_PLUS:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE_PLUS;
+ case XML_TOK_COMMA:
+ state->handler = element6;
+ return XML_ROLE_GROUP_SEQUENCE;
+ case XML_TOK_OR:
+ state->handler = element6;
+ return XML_ROLE_GROUP_CHOICE;
+ }
+ return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static int PTRCALL
+condSect0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) {
+ state->handler = condSect1;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) {
+ state->handler = condSect2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+condSect1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ state->includeLevel += 1;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+condSect2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ return XML_ROLE_IGNORE_SECT;
+ }
+ return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static int PTRCALL
+declClose(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return state->role_none;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return state->role_none;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+error(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ (void)state;
+ (void)tok;
+ (void)ptr;
+ (void)end;
+ (void)enc;
+
+ return XML_ROLE_NONE;
+}
+
+static int FASTCALL
+common(PROLOG_STATE *state, int tok)
+{
+#ifdef XML_DTD
+ if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
+ return XML_ROLE_INNER_PARAM_ENTITY_REF;
+#endif
+ state->handler = error;
+ return XML_ROLE_ERROR;
+}
+
+void
+XmlPrologStateInit(PROLOG_STATE *state)
+{
+ state->handler = prolog0;
+#ifdef XML_DTD
+ state->documentEntity = 1;
+ state->includeLevel = 0;
+ state->inEntityValue = 0;
+#endif /* XML_DTD */
+}
+
+#ifdef XML_DTD
+
+void
+XmlPrologStateInitExternalEntity(PROLOG_STATE *state)
+{
+ state->handler = externalSubset0;
+ state->documentEntity = 0;
+ state->includeLevel = 0;
+}
+
+#endif /* XML_DTD */
diff --git a/lib/expat/xmlrole.h b/lib/expat/xmlrole.h
new file mode 100644
index 000000000..4dd9f06f9
--- /dev/null
+++ b/lib/expat/xmlrole.h
@@ -0,0 +1,114 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef XmlRole_INCLUDED
+#define XmlRole_INCLUDED 1
+
+#ifdef __VMS
+/* 0 1 2 3 0 1 2 3
+ 1234567890123456789012345678901 1234567890123456789012345678901 */
+#define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt
+#endif
+
+#include "xmltok.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ XML_ROLE_ERROR = -1,
+ XML_ROLE_NONE = 0,
+ XML_ROLE_XML_DECL,
+ XML_ROLE_INSTANCE_START,
+ XML_ROLE_DOCTYPE_NONE,
+ XML_ROLE_DOCTYPE_NAME,
+ XML_ROLE_DOCTYPE_SYSTEM_ID,
+ XML_ROLE_DOCTYPE_PUBLIC_ID,
+ XML_ROLE_DOCTYPE_INTERNAL_SUBSET,
+ XML_ROLE_DOCTYPE_CLOSE,
+ XML_ROLE_GENERAL_ENTITY_NAME,
+ XML_ROLE_PARAM_ENTITY_NAME,
+ XML_ROLE_ENTITY_NONE,
+ XML_ROLE_ENTITY_VALUE,
+ XML_ROLE_ENTITY_SYSTEM_ID,
+ XML_ROLE_ENTITY_PUBLIC_ID,
+ XML_ROLE_ENTITY_COMPLETE,
+ XML_ROLE_ENTITY_NOTATION_NAME,
+ XML_ROLE_NOTATION_NONE,
+ XML_ROLE_NOTATION_NAME,
+ XML_ROLE_NOTATION_SYSTEM_ID,
+ XML_ROLE_NOTATION_NO_SYSTEM_ID,
+ XML_ROLE_NOTATION_PUBLIC_ID,
+ XML_ROLE_ATTRIBUTE_NAME,
+ XML_ROLE_ATTRIBUTE_TYPE_CDATA,
+ XML_ROLE_ATTRIBUTE_TYPE_ID,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREF,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
+ XML_ROLE_ATTRIBUTE_ENUM_VALUE,
+ XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
+ XML_ROLE_ATTLIST_NONE,
+ XML_ROLE_ATTLIST_ELEMENT_NAME,
+ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
+ XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
+ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
+ XML_ROLE_FIXED_ATTRIBUTE_VALUE,
+ XML_ROLE_ELEMENT_NONE,
+ XML_ROLE_ELEMENT_NAME,
+ XML_ROLE_CONTENT_ANY,
+ XML_ROLE_CONTENT_EMPTY,
+ XML_ROLE_CONTENT_PCDATA,
+ XML_ROLE_GROUP_OPEN,
+ XML_ROLE_GROUP_CLOSE,
+ XML_ROLE_GROUP_CLOSE_REP,
+ XML_ROLE_GROUP_CLOSE_OPT,
+ XML_ROLE_GROUP_CLOSE_PLUS,
+ XML_ROLE_GROUP_CHOICE,
+ XML_ROLE_GROUP_SEQUENCE,
+ XML_ROLE_CONTENT_ELEMENT,
+ XML_ROLE_CONTENT_ELEMENT_REP,
+ XML_ROLE_CONTENT_ELEMENT_OPT,
+ XML_ROLE_CONTENT_ELEMENT_PLUS,
+ XML_ROLE_PI,
+ XML_ROLE_COMMENT,
+#ifdef XML_DTD
+ XML_ROLE_TEXT_DECL,
+ XML_ROLE_IGNORE_SECT,
+ XML_ROLE_INNER_PARAM_ENTITY_REF,
+#endif /* XML_DTD */
+ XML_ROLE_PARAM_ENTITY_REF
+};
+
+typedef struct prolog_state {
+ int (PTRCALL *handler) (struct prolog_state *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+ unsigned level;
+ int role_none;
+#ifdef XML_DTD
+ unsigned includeLevel;
+ int documentEntity;
+ int inEntityValue;
+#endif /* XML_DTD */
+} PROLOG_STATE;
+
+void XmlPrologStateInit(PROLOG_STATE *);
+#ifdef XML_DTD
+void XmlPrologStateInitExternalEntity(PROLOG_STATE *);
+#endif /* XML_DTD */
+
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlRole_INCLUDED */
diff --git a/lib/expat/xmltok.c b/lib/expat/xmltok.c
new file mode 100644
index 000000000..c23b348eb
--- /dev/null
+++ b/lib/expat/xmltok.c
@@ -0,0 +1,1684 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stddef.h>
+
+#ifdef COMPILED_FROM_DSP
+#include "winconfig.h"
+#elif defined(MACOS_CLASSIC)
+#include "macconfig.h"
+#elif defined(__amigaos4__)
+#include "amigaconfig.h"
+#elif defined(__WATCOMC__)
+#include "watcomconfig.h"
+#else
+#ifdef HAVE_EXPAT_CONFIG_H
+#include <expat_config.h>
+#endif
+#endif /* ndef COMPILED_FROM_DSP */
+
+#include "expat_external.h"
+#include "internal.h"
+#include "xmltok.h"
+#include "nametab.h"
+
+#ifdef XML_DTD
+#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
+#else
+#define IGNORE_SECTION_TOK_VTABLE /* as nothing */
+#endif
+
+#define VTABLE1 \
+ { PREFIX(prologTok), PREFIX(contentTok), \
+ PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \
+ { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
+ PREFIX(sameName), \
+ PREFIX(nameMatchesAscii), \
+ PREFIX(nameLength), \
+ PREFIX(skipS), \
+ PREFIX(getAtts), \
+ PREFIX(charRefNumber), \
+ PREFIX(predefinedEntityName), \
+ PREFIX(updatePosition), \
+ PREFIX(isPublicId)
+
+#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
+
+#define UCS2_GET_NAMING(pages, hi, lo) \
+ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
+
+/* A 2 byte UTF-8 representation splits the characters 11 bits between
+ the bottom 5 and 6 bits of the bytes. We need 8 bits to index into
+ pages, 3 bits to add to that index and 5 bits to generate the mask.
+*/
+#define UTF8_GET_NAMING2(pages, byte) \
+ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+ + ((((byte)[0]) & 3) << 1) \
+ + ((((byte)[1]) >> 5) & 1)] \
+ & (1 << (((byte)[1]) & 0x1F)))
+
+/* A 3 byte UTF-8 representation splits the characters 16 bits between
+ the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index
+ into pages, 3 bits to add to that index and 5 bits to generate the
+ mask.
+*/
+#define UTF8_GET_NAMING3(pages, byte) \
+ (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
+ + ((((byte)[1]) >> 2) & 0xF)] \
+ << 3) \
+ + ((((byte)[1]) & 3) << 1) \
+ + ((((byte)[2]) >> 5) & 1)] \
+ & (1 << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+ ((n) == 2 \
+ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+ : ((n) == 3 \
+ ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
+ : 0))
+
+/* Detection of invalid UTF-8 sequences is based on Table 3.1B
+ of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
+ with the additional restriction of not allowing the Unicode
+ code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE).
+ Implementation details:
+ (A & 0x80) == 0 means A < 0x80
+ and
+ (A & 0xC0) == 0xC0 means A > 0xBF
+*/
+
+#define UTF8_INVALID2(p) \
+ ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
+
+#define UTF8_INVALID3(p) \
+ (((p)[2] & 0x80) == 0 \
+ || \
+ ((*p) == 0xEF && (p)[1] == 0xBF \
+ ? \
+ (p)[2] > 0xBD \
+ : \
+ ((p)[2] & 0xC0) == 0xC0) \
+ || \
+ ((*p) == 0xE0 \
+ ? \
+ (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \
+ : \
+ ((p)[1] & 0x80) == 0 \
+ || \
+ ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
+
+#define UTF8_INVALID4(p) \
+ (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 \
+ || \
+ ((p)[2] & 0x80) == 0 || ((p)[2] & 0xC0) == 0xC0 \
+ || \
+ ((*p) == 0xF0 \
+ ? \
+ (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \
+ : \
+ ((p)[1] & 0x80) == 0 \
+ || \
+ ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
+
+static int PTRFASTCALL
+isNever(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+ (void)p;
+
+ return 0;
+}
+
+static int PTRFASTCALL
+utf8_isName2(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+
+ return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isName3(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+
+ return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
+}
+
+#define utf8_isName4 isNever
+
+static int PTRFASTCALL
+utf8_isNmstrt2(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+
+ return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isNmstrt3(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+
+ return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
+}
+
+#define utf8_isNmstrt4 isNever
+
+static int PTRFASTCALL
+utf8_isInvalid2(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+
+ return UTF8_INVALID2((const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isInvalid3(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+
+ return UTF8_INVALID3((const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isInvalid4(const ENCODING *enc, const char *p)
+{
+ (void)enc;
+
+ return UTF8_INVALID4((const unsigned char *)p);
+}
+
+struct normal_encoding {
+ ENCODING enc;
+ unsigned char type[256];
+#ifdef XML_MIN_SIZE
+ int (PTRFASTCALL *byteType)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
+ int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
+ int (PTRCALL *charMatches)(const ENCODING *, const char *, int);
+#endif /* XML_MIN_SIZE */
+ int (PTRFASTCALL *isName2)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isName3)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isName4)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
+};
+
+#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *) (enc))
+
+#ifdef XML_MIN_SIZE
+
+#define STANDARD_VTABLE(E) \
+ E ## byteType, \
+ E ## isNameMin, \
+ E ## isNmstrtMin, \
+ E ## byteToAscii, \
+ E ## charMatches,
+
+#else
+
+#define STANDARD_VTABLE(E) /* as nothing */
+
+#endif
+
+#define NORMAL_VTABLE(E) \
+ E ## isName2, \
+ E ## isName3, \
+ E ## isName4, \
+ E ## isNmstrt2, \
+ E ## isNmstrt3, \
+ E ## isNmstrt4, \
+ E ## isInvalid2, \
+ E ## isInvalid3, \
+ E ## isInvalid4
+
+static int FASTCALL checkCharRefNumber(int);
+
+#include "xmltok_impl.h"
+#include "ascii.h"
+
+#ifdef XML_MIN_SIZE
+#define sb_isNameMin isNever
+#define sb_isNmstrtMin isNever
+#endif
+
+#ifdef XML_MIN_SIZE
+#define MINBPC(enc) ((enc)->minBytesPerChar)
+#else
+/* minimum bytes per character */
+#define MINBPC(enc) (((int)(enc) & 0) + 1)
+#endif
+
+#define SB_BYTE_TYPE(enc, p) \
+ (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
+
+#ifdef XML_MIN_SIZE
+static int PTRFASTCALL
+sb_byteType(const ENCODING *enc, const char *p)
+{
+ return SB_BYTE_TYPE(enc, p);
+}
+#define BYTE_TYPE(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->byteType(enc, p))
+#else
+#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define BYTE_TO_ASCII(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
+static int PTRFASTCALL
+sb_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return *p;
+}
+#else
+#define BYTE_TO_ASCII(enc, p) (*(p))
+#endif
+
+#define IS_NAME_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isName ## n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isNmstrt ## n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isInvalid ## n(enc, p))
+
+#ifdef XML_MIN_SIZE
+#define IS_NAME_CHAR_MINBPC(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
+#else
+#define IS_NAME_CHAR_MINBPC(enc, p) ((int)(enc) & 0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) ((int)(enc) & 0)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define CHAR_MATCHES(enc, p, c) \
+ (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
+static int PTRCALL
+sb_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return *p == c;
+}
+#else
+/* c is an ASCII character */
+#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+#endif
+
+#define PREFIX(ident) normal_ ## ident
+#define XML_TOK_IMPL_C
+#include "xmltok_impl.c"
+#undef XML_TOK_IMPL_C
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
+ UTF8_cval1 = 0x00,
+ UTF8_cval2 = 0xc0,
+ UTF8_cval3 = 0xe0,
+ UTF8_cval4 = 0xf0
+};
+
+static void PTRCALL
+utf8_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char *to;
+ const char *from;
+
+ (void)enc;
+
+ if (fromLim - *fromP > toLim - *toP) {
+ /* Avoid copying partial characters. */
+ for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
+ if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
+ break;
+ }
+ for (to = *toP, from = *fromP; from != fromLim; from++, to++)
+ *to = *from;
+ *fromP = from;
+ *toP = to;
+}
+
+static void PTRCALL
+utf8_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ unsigned short *to = *toP;
+ const char *from = *fromP;
+ while (from != fromLim && to != toLim) {
+ switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+ case BT_LEAD2:
+ *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
+ from += 2;
+ break;
+ case BT_LEAD3:
+ *to++ = (unsigned short)(((from[0] & 0xf) << 12)
+ | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
+ from += 3;
+ break;
+ case BT_LEAD4:
+ {
+ unsigned long n;
+ if (to + 1 == toLim)
+ goto after;
+ n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
+ | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+ n -= 0x10000;
+ to[0] = (unsigned short)((n >> 10) | 0xD800);
+ to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+ to += 2;
+ from += 4;
+ }
+ break;
+ default:
+ *to++ = *from++;
+ break;
+ }
+ }
+after:
+ *fromP = from;
+ *toP = to;
+}
+
+#ifdef XML_NS
+static const struct normal_encoding utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+#endif
+
+static const struct normal_encoding utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "iasciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#endif
+
+static const struct normal_encoding internal_utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+static void PTRCALL
+latin1_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ (void)enc;
+
+ for (;;) {
+ unsigned char c;
+ if (*fromP == fromLim)
+ break;
+ c = (unsigned char)**fromP;
+ if (c & 0x80) {
+ if (toLim - *toP < 2)
+ break;
+ *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
+ *(*toP)++ = (char)((c & 0x3f) | 0x80);
+ (*fromP)++;
+ }
+ else {
+ if (*toP == toLim)
+ break;
+ *(*toP)++ = *(*fromP)++;
+ }
+ }
+}
+
+static void PTRCALL
+latin1_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ (void)enc;
+
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = (unsigned char)*(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding latin1_encoding_ns = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding latin1_encoding = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static void PTRCALL
+ascii_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ (void)enc;
+
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = *(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding ascii_encoding_ns = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding ascii_encoding = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static int PTRFASTCALL
+unicode_byte_type(char hi, char lo)
+{
+ switch ((unsigned char)hi) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ return BT_LEAD4;
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return BT_TRAIL;
+ case 0xFF:
+ switch ((unsigned char)lo) {
+ case 0xFF:
+ case 0xFE:
+ return BT_NONXML;
+ }
+ break;
+ }
+ return BT_NONASCII;
+}
+
+#define DEFINE_UTF16_TO_UTF8(E) \
+static void PTRCALL \
+E ## toUtf8(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ char **toP, const char *toLim) \
+{ \
+ const char *from; \
+ \
+ (void)enc; \
+ \
+ for (from = *fromP; from != fromLim; from += 2) { \
+ int plane; \
+ unsigned char lo2; \
+ unsigned char lo = GET_LO(from); \
+ unsigned char hi = GET_HI(from); \
+ switch (hi) { \
+ case 0: \
+ if (lo < 0x80) { \
+ if (*toP == toLim) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = lo; \
+ break; \
+ } \
+ /* fall through */ \
+ case 0x1: case 0x2: case 0x3: \
+ case 0x4: case 0x5: case 0x6: case 0x7: \
+ if (toLim - *toP < 2) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ default: \
+ if (toLim - *toP < 3) { \
+ *fromP = from; \
+ return; \
+ } \
+ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+ if (toLim - *toP < 4) { \
+ *fromP = from; \
+ return; \
+ } \
+ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+ *(*toP)++ = (((char)((plane >> 2) & 0xff)) | UTF8_cval4); \
+ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+ from += 2; \
+ lo2 = GET_LO(from); \
+ *(*toP)++ = (((lo & 0x3) << 4) \
+ | ((GET_HI(from) & 0x3) << 2) \
+ | (lo2 >> 6) \
+ | 0x80); \
+ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+ break; \
+ } \
+ } \
+ *fromP = from; \
+}
+
+#define DEFINE_UTF16_TO_UTF16(E) \
+static void PTRCALL \
+E ## toUtf16(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ unsigned short **toP, const unsigned short *toLim) \
+{ \
+ (void)enc; \
+ \
+ /* Avoid copying first half only of surrogate */ \
+ if (fromLim - *fromP > ((toLim - *toP) << 1) \
+ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
+ fromLim -= 2; \
+ for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
+ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+}
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[0])
+#define GET_HI(ptr) ((unsigned char)(ptr)[1])
+
+DEFINE_UTF16_TO_UTF8(little2_)
+DEFINE_UTF16_TO_UTF16(little2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[1])
+#define GET_HI(ptr) ((unsigned char)(ptr)[0])
+
+DEFINE_UTF16_TO_UTF8(big2_)
+DEFINE_UTF16_TO_UTF16(big2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+ : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+
+#ifdef XML_MIN_SIZE
+
+static int PTRFASTCALL
+little2_byteType(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TYPE(enc, p);
+}
+
+static int PTRFASTCALL
+little2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TO_ASCII(enc, p);
+}
+
+static int PTRCALL
+little2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return LITTLE2_CHAR_MATCHES(enc, p, c);
+}
+
+static int PTRFASTCALL
+little2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static int PTRFASTCALL
+little2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) little2_ ## ident
+#define MINBPC(enc) (((int)(enc) & 0) + 2)
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) ((int)(enc) & 0)
+#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) ((int)(enc) & 0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#define XML_TOK_IMPL_C
+#include "xmltok_impl.c"
+#undef XML_TOK_IMPL_C
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding little2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 1234
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding little2_encoding = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 1234
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#if BYTEORDER != 4321
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_little2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_little2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+ : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+
+#ifdef XML_MIN_SIZE
+
+static int PTRFASTCALL
+big2_byteType(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TYPE(enc, p);
+}
+
+static int PTRFASTCALL
+big2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TO_ASCII(enc, p);
+}
+
+static int PTRCALL
+big2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return BIG2_CHAR_MATCHES(enc, p, c);
+}
+
+static int PTRFASTCALL
+big2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static int PTRFASTCALL
+big2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) big2_ ## ident
+#define MINBPC(enc) (((int)(enc) & 0) + 2)
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) ((int)(enc) & 0)
+#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) ((int)(enc) & 0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#define XML_TOK_IMPL_C
+#include "xmltok_impl.c"
+#undef XML_TOK_IMPL_C
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding big2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 4321
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding big2_encoding = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 4321
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#if BYTEORDER != 1234
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_big2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_big2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+#undef PREFIX
+
+static int FASTCALL
+streqci(const char *s1, const char *s2)
+{
+ for (;;) {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (ASCII_a <= c1 && c1 <= ASCII_z)
+ c1 += ASCII_A - ASCII_a;
+ if (ASCII_a <= c2 && c2 <= ASCII_z)
+ c2 += ASCII_A - ASCII_a;
+ if (c1 != c2)
+ return 0;
+ if (!c1)
+ break;
+ }
+ return 1;
+}
+
+static void PTRCALL
+initUpdatePosition(const ENCODING *enc, const char *ptr,
+ const char *end, POSITION *pos)
+{
+ (void)enc;
+
+ normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
+}
+
+static int
+toAscii(const ENCODING *enc, const char *ptr, const char *end)
+{
+ char buf[1];
+ char *p = buf;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
+ if (p == buf)
+ return -1;
+ else
+ return buf[0];
+}
+
+static int FASTCALL
+isSpace(int c)
+{
+ switch (c) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ case 0x9:
+ return 1;
+ }
+ return 0;
+}
+
+/* Return 1 if there's just optional white space or there's an S
+ followed by name=val.
+*/
+static int
+parsePseudoAttribute(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **namePtr,
+ const char **nameEndPtr,
+ const char **valPtr,
+ const char **nextTokPtr)
+{
+ int c;
+ char open;
+ if (ptr == end) {
+ *namePtr = NULL;
+ return 1;
+ }
+ if (!isSpace(toAscii(enc, ptr, end))) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(toAscii(enc, ptr, end)));
+ if (ptr == end) {
+ *namePtr = NULL;
+ return 1;
+ }
+ *namePtr = ptr;
+ for (;;) {
+ c = toAscii(enc, ptr, end);
+ if (c == -1) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ if (c == ASCII_EQUALS) {
+ *nameEndPtr = ptr;
+ break;
+ }
+ if (isSpace(c)) {
+ *nameEndPtr = ptr;
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(c = toAscii(enc, ptr, end)));
+ if (c != ASCII_EQUALS) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ ptr += enc->minBytesPerChar;
+ }
+ if (ptr == *namePtr) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ while (isSpace(c)) {
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ }
+ if (c != ASCII_QUOT && c != ASCII_APOS) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ open = (char)c;
+ ptr += enc->minBytesPerChar;
+ *valPtr = ptr;
+ for (;; ptr += enc->minBytesPerChar) {
+ c = toAscii(enc, ptr, end);
+ if (c == open)
+ break;
+ if (!(ASCII_a <= c && c <= ASCII_z)
+ && !(ASCII_A <= c && c <= ASCII_Z)
+ && !(ASCII_0 <= c && c <= ASCII_9)
+ && c != ASCII_PERIOD
+ && c != ASCII_MINUS
+ && c != ASCII_UNDERSCORE) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ }
+ *nextTokPtr = ptr + enc->minBytesPerChar;
+ return 1;
+}
+
+static const char KW_version[] = {
+ ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'
+};
+
+static const char KW_encoding[] = {
+ ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'
+};
+
+static const char KW_standalone[] = {
+ ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o,
+ ASCII_n, ASCII_e, '\0'
+};
+
+static const char KW_yes[] = {
+ ASCII_y, ASCII_e, ASCII_s, '\0'
+};
+
+static const char KW_no[] = {
+ ASCII_n, ASCII_o, '\0'
+};
+
+static int
+doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
+ const char *,
+ const char *),
+ int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ const char *val = NULL;
+ const char *name = NULL;
+ const char *nameEnd = NULL;
+ ptr += 5 * enc->minBytesPerChar;
+ end -= 2 * enc->minBytesPerChar;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
+ || !name) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
+ if (!isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ }
+ else {
+ if (versionPtr)
+ *versionPtr = val;
+ if (versionEndPtr)
+ *versionEndPtr = ptr;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name) {
+ if (isGeneralTextEntity) {
+ /* a TextDecl must have an EncodingDecl */
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
+ int c = toAscii(enc, val, end);
+ if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) {
+ *badPtr = val;
+ return 0;
+ }
+ if (encodingName)
+ *encodingName = val;
+ if (encoding)
+ *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name)
+ return 1;
+ }
+ if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
+ || isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
+ if (standalone)
+ *standalone = 1;
+ }
+ else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
+ if (standalone)
+ *standalone = 0;
+ }
+ else {
+ *badPtr = val;
+ return 0;
+ }
+ while (isSpace(toAscii(enc, ptr, end)))
+ ptr += enc->minBytesPerChar;
+ if (ptr != end) {
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+}
+
+static int FASTCALL
+checkCharRefNumber(int result)
+{
+ switch (result >> 8) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return -1;
+ case 0:
+ if (latin1_encoding.type[result] == BT_NONXML)
+ return -1;
+ break;
+ case 0xFF:
+ if (result == 0xFFFE || result == 0xFFFF)
+ return -1;
+ break;
+ }
+ return result;
+}
+
+int FASTCALL
+XmlUtf8Encode(int c, char *buf)
+{
+ enum {
+ /* minN is minimum legal resulting value for N byte sequence */
+ min2 = 0x80,
+ min3 = 0x800,
+ min4 = 0x10000
+ };
+
+ if (c < 0)
+ return 0;
+ if (c < min2) {
+ buf[0] = (char)(c | UTF8_cval1);
+ return 1;
+ }
+ if (c < min3) {
+ buf[0] = (char)((c >> 6) | UTF8_cval2);
+ buf[1] = (char)((c & 0x3f) | 0x80);
+ return 2;
+ }
+ if (c < min4) {
+ buf[0] = (char)((c >> 12) | UTF8_cval3);
+ buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
+ buf[2] = (char)((c & 0x3f) | 0x80);
+ return 3;
+ }
+ if (c < 0x110000) {
+ buf[0] = (char)((c >> 18) | UTF8_cval4);
+ buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
+ buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
+ buf[3] = (char)((c & 0x3f) | 0x80);
+ return 4;
+ }
+ return 0;
+}
+
+int FASTCALL
+XmlUtf16Encode(int charNum, unsigned short *buf)
+{
+ if (charNum < 0)
+ return 0;
+ if (charNum < 0x10000) {
+ buf[0] = (unsigned short)charNum;
+ return 1;
+ }
+ if (charNum < 0x110000) {
+ charNum -= 0x10000;
+ buf[0] = (unsigned short)((charNum >> 10) + 0xD800);
+ buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00);
+ return 2;
+ }
+ return 0;
+}
+
+struct unknown_encoding {
+ struct normal_encoding normal;
+ CONVERTER convert;
+ void *userData;
+ unsigned short utf16[256];
+ char utf8[256][4];
+};
+
+#define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *) (enc))
+
+int
+XmlSizeOfUnknownEncoding(void)
+{
+ return sizeof(struct unknown_encoding);
+}
+
+static int PTRFASTCALL
+unknown_isName(const ENCODING *enc, const char *p)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ int c = uenc->convert(uenc->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
+}
+
+static int PTRFASTCALL
+unknown_isNmstrt(const ENCODING *enc, const char *p)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ int c = uenc->convert(uenc->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
+}
+
+static int PTRFASTCALL
+unknown_isInvalid(const ENCODING *enc, const char *p)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ int c = uenc->convert(uenc->userData, p);
+ return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+}
+
+static void PTRCALL
+unknown_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ char buf[XML_UTF8_ENCODE_MAX];
+ for (;;) {
+ const char *utf8;
+ int n;
+ if (*fromP == fromLim)
+ break;
+ utf8 = uenc->utf8[(unsigned char)**fromP];
+ n = *utf8++;
+ if (n == 0) {
+ int c = uenc->convert(uenc->userData, *fromP);
+ n = XmlUtf8Encode(c, buf);
+ if (n > toLim - *toP)
+ break;
+ utf8 = buf;
+ *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2));
+ }
+ else {
+ if (n > toLim - *toP)
+ break;
+ (*fromP)++;
+ }
+ do {
+ *(*toP)++ = *utf8++;
+ } while (--n != 0);
+ }
+}
+
+static void PTRCALL
+unknown_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ while (*fromP != fromLim && *toP != toLim) {
+ unsigned short c = uenc->utf16[(unsigned char)**fromP];
+ if (c == 0) {
+ c = (unsigned short)
+ uenc->convert(uenc->userData, *fromP);
+ *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2));
+ }
+ else
+ (*fromP)++;
+ *(*toP)++ = c;
+ }
+}
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData)
+{
+ int i;
+ struct unknown_encoding *e = (struct unknown_encoding *)mem;
+ for (i = 0; i < (int)sizeof(struct normal_encoding); i++)
+ ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+ for (i = 0; i < 128; i++)
+ if (latin1_encoding.type[i] != BT_OTHER
+ && latin1_encoding.type[i] != BT_NONXML
+ && table[i] != i)
+ return 0;
+ for (i = 0; i < 256; i++) {
+ int c = table[i];
+ if (c == -1) {
+ e->normal.type[i] = BT_MALFORM;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else if (c < 0) {
+ if (c < -4)
+ return 0;
+ e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2));
+ e->utf8[i][0] = 0;
+ e->utf16[i] = 0;
+ }
+ else if (c < 0x80) {
+ if (latin1_encoding.type[c] != BT_OTHER
+ && latin1_encoding.type[c] != BT_NONXML
+ && c != i)
+ return 0;
+ e->normal.type[i] = latin1_encoding.type[c];
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = (char)c;
+ e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c);
+ }
+ else if (checkCharRefNumber(c) < 0) {
+ e->normal.type[i] = BT_NONXML;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else {
+ if (c > 0xFFFF)
+ return 0;
+ if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NMSTRT;
+ else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NAME;
+ else
+ e->normal.type[i] = BT_OTHER;
+ e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
+ e->utf16[i] = (unsigned short)c;
+ }
+ }
+ e->userData = userData;
+ e->convert = convert;
+ if (convert) {
+ e->normal.isName2 = unknown_isName;
+ e->normal.isName3 = unknown_isName;
+ e->normal.isName4 = unknown_isName;
+ e->normal.isNmstrt2 = unknown_isNmstrt;
+ e->normal.isNmstrt3 = unknown_isNmstrt;
+ e->normal.isNmstrt4 = unknown_isNmstrt;
+ e->normal.isInvalid2 = unknown_isInvalid;
+ e->normal.isInvalid3 = unknown_isInvalid;
+ e->normal.isInvalid4 = unknown_isInvalid;
+ }
+ e->normal.enc.utf8Convert = unknown_toUtf8;
+ e->normal.enc.utf16Convert = unknown_toUtf16;
+ return &(e->normal.enc);
+}
+
+/* If this enumeration is changed, getEncodingIndex and encodings
+must also be changed. */
+enum {
+ UNKNOWN_ENC = -1,
+ ISO_8859_1_ENC = 0,
+ US_ASCII_ENC,
+ UTF_8_ENC,
+ UTF_16_ENC,
+ UTF_16BE_ENC,
+ UTF_16LE_ENC,
+ /* must match encodingNames up to here */
+ NO_ENC
+};
+
+static const char KW_ISO_8859_1[] = {
+ ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9,
+ ASCII_MINUS, ASCII_1, '\0'
+};
+static const char KW_US_ASCII[] = {
+ ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I,
+ '\0'
+};
+static const char KW_UTF_8[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'
+};
+static const char KW_UTF_16[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'
+};
+static const char KW_UTF_16BE[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E,
+ '\0'
+};
+static const char KW_UTF_16LE[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E,
+ '\0'
+};
+
+static int FASTCALL
+getEncodingIndex(const char *name)
+{
+ static const char * const encodingNames[] = {
+ KW_ISO_8859_1,
+ KW_US_ASCII,
+ KW_UTF_8,
+ KW_UTF_16,
+ KW_UTF_16BE,
+ KW_UTF_16LE,
+ };
+ int i;
+ if (name == NULL)
+ return NO_ENC;
+ for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++)
+ if (streqci(name, encodingNames[i]))
+ return i;
+ return UNKNOWN_ENC;
+}
+
+/* For binary compatibility, we store the index of the encoding
+ specified at initialization in the isUtf16 member.
+*/
+
+#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
+#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
+
+/* This is what detects the encoding. encodingTable maps from
+ encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of
+ the external (protocol) specified encoding; state is
+ XML_CONTENT_STATE if we're parsing an external text entity, and
+ XML_PROLOG_STATE otherwise.
+*/
+
+
+static int
+initScan(const ENCODING * const *encodingTable,
+ const INIT_ENCODING *enc,
+ int state,
+ const char *ptr,
+ const char *end,
+ const char **nextTokPtr)
+{
+ const ENCODING **encPtr;
+
+ if (ptr == end)
+ return XML_TOK_NONE;
+ encPtr = enc->encPtr;
+ if (ptr + 1 == end) {
+ /* only a single byte available for auto-detection */
+#ifndef XML_DTD /* FIXME */
+ /* a well-formed document entity must have more than one byte */
+ if (state != XML_CONTENT_STATE)
+ return XML_TOK_PARTIAL;
+#endif
+ /* so we're parsing an external text entity... */
+ /* if UTF-16 was externally specified, then we need at least 2 bytes */
+ switch (INIT_ENC_INDEX(enc)) {
+ case UTF_16_ENC:
+ case UTF_16LE_ENC:
+ case UTF_16BE_ENC:
+ return XML_TOK_PARTIAL;
+ }
+ switch ((unsigned char)*ptr) {
+ case 0xFE:
+ case 0xFF:
+ case 0xEF: /* possibly first byte of UTF-8 BOM */
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ /* fall through */
+ case 0x00:
+ case 0x3C:
+ return XML_TOK_PARTIAL;
+ }
+ }
+ else {
+ switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
+ case 0xFEFF:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XML_TOK_BOM;
+ /* 00 3C is handled in the default case */
+ case 0x3C00:
+ if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
+ || INIT_ENC_INDEX(enc) == UTF_16_ENC)
+ && state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ case 0xFFFE:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XML_TOK_BOM;
+ case 0xEFBB:
+ /* Maybe a UTF-8 BOM (EF BB BF) */
+ /* If there's an explicitly specified (external) encoding
+ of ISO-8859-1 or some flavour of UTF-16
+ and this is an external text entity,
+ don't look for the BOM,
+ because it might be a legal data.
+ */
+ if (state == XML_CONTENT_STATE) {
+ int e = INIT_ENC_INDEX(enc);
+ if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC
+ || e == UTF_16LE_ENC || e == UTF_16_ENC)
+ break;
+ }
+ if (ptr + 2 == end)
+ return XML_TOK_PARTIAL;
+ if ((unsigned char)ptr[2] == 0xBF) {
+ *nextTokPtr = ptr + 3;
+ *encPtr = encodingTable[UTF_8_ENC];
+ return XML_TOK_BOM;
+ }
+ break;
+ default:
+ if (ptr[0] == '\0') {
+ /* 0 isn't a legal data character. Furthermore a document
+ entity can only start with ASCII characters. So the only
+ way this can fail to be big-endian UTF-16 if it it's an
+ external parsed general entity that's labelled as
+ UTF-16LE.
+ */
+ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
+ break;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ else if (ptr[1] == '\0') {
+ /* We could recover here in the case:
+ - parsing an external entity
+ - second byte is 0
+ - no externally specified encoding
+ - no encoding declaration
+ by assuming UTF-16LE. But we don't, because this would mean when
+ presented just with a single byte, we couldn't reliably determine
+ whether we needed further bytes.
+ */
+ if (state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ break;
+ }
+ }
+ *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+}
+
+
+#define NS(x) x
+#define ns(x) x
+#define XML_TOK_NS_C
+#include "xmltok_ns.c"
+#undef XML_TOK_NS_C
+#undef NS
+#undef ns
+
+#ifdef XML_NS
+
+#define NS(x) x ## NS
+#define ns(x) x ## _ns
+
+#define XML_TOK_NS_C
+#include "xmltok_ns.c"
+#undef XML_TOK_NS_C
+
+#undef NS
+#undef ns
+
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData)
+{
+ ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
+ if (enc)
+ ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
+ return enc;
+}
+
+#endif /* XML_NS */
diff --git a/lib/expat/xmltok.h b/lib/expat/xmltok.h
new file mode 100644
index 000000000..ca867aa6b
--- /dev/null
+++ b/lib/expat/xmltok.h
@@ -0,0 +1,316 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef XmlTok_INCLUDED
+#define XmlTok_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following token may be returned by XmlContentTok */
+#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be
+ start of illegal ]]> sequence */
+/* The following tokens may be returned by both XmlPrologTok and
+ XmlContentTok.
+*/
+#define XML_TOK_NONE -4 /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
+ might be part of CRLF sequence */
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_INVALID 0
+
+/* The following tokens are returned by XmlContentTok; some are also
+ returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok.
+*/
+#define XML_TOK_START_TAG_WITH_ATTS 1
+#define XML_TOK_START_TAG_NO_ATTS 2
+#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
+#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
+#define XML_TOK_END_TAG 5
+#define XML_TOK_DATA_CHARS 6
+#define XML_TOK_DATA_NEWLINE 7
+#define XML_TOK_CDATA_SECT_OPEN 8
+#define XML_TOK_ENTITY_REF 9
+#define XML_TOK_CHAR_REF 10 /* numeric character reference */
+
+/* The following tokens may be returned by both XmlPrologTok and
+ XmlContentTok.
+*/
+#define XML_TOK_PI 11 /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_COMMENT 13
+#define XML_TOK_BOM 14 /* Byte order mark */
+
+/* The following tokens are returned only by XmlPrologTok */
+#define XML_TOK_PROLOG_S 15
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_NAME 18
+#define XML_TOK_NMTOKEN 19
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
+#define XML_TOK_PERCENT 22
+#define XML_TOK_OPEN_PAREN 23
+#define XML_TOK_CLOSE_PAREN 24
+#define XML_TOK_OPEN_BRACKET 25
+#define XML_TOK_CLOSE_BRACKET 26
+#define XML_TOK_LITERAL 27
+#define XML_TOK_PARAM_ENTITY_REF 28
+#define XML_TOK_INSTANCE_START 29
+
+/* The following occur only in element type declarations */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_COMMA 38
+
+/* The following token is returned only by XmlAttributeValueTok */
+#define XML_TOK_ATTRIBUTE_VALUE_S 39
+
+/* The following token is returned only by XmlCdataSectionTok */
+#define XML_TOK_CDATA_SECT_CLOSE 40
+
+/* With namespace processing this is returned by XmlPrologTok for a
+ name with a colon.
+*/
+#define XML_TOK_PREFIXED_NAME 41
+
+#ifdef XML_DTD
+#define XML_TOK_IGNORE_SECT 42
+#endif /* XML_DTD */
+
+#ifdef XML_DTD
+#define XML_N_STATES 4
+#else /* not XML_DTD */
+#define XML_N_STATES 3
+#endif /* not XML_DTD */
+
+#define XML_PROLOG_STATE 0
+#define XML_CONTENT_STATE 1
+#define XML_CDATA_SECTION_STATE 2
+#ifdef XML_DTD
+#define XML_IGNORE_SECTION_STATE 3
+#endif /* XML_DTD */
+
+#define XML_N_LITERAL_TYPES 2
+#define XML_ATTRIBUTE_VALUE_LITERAL 0
+#define XML_ENTITY_VALUE_LITERAL 1
+
+/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
+#define XML_UTF8_ENCODE_MAX 4
+/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
+#define XML_UTF16_ENCODE_MAX 2
+
+typedef struct position {
+ /* first line and first column are 0 not 1 */
+ XML_Size lineNumber;
+ XML_Size columnNumber;
+} POSITION;
+
+typedef struct {
+ const char *name;
+ const char *valuePtr;
+ const char *valueEnd;
+ char normalized;
+} ATTRIBUTE;
+
+struct encoding;
+typedef struct encoding ENCODING;
+
+typedef int (PTRCALL *SCANNER)(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+
+struct encoding {
+ SCANNER scanners[XML_N_STATES];
+ SCANNER literalScanners[XML_N_LITERAL_TYPES];
+ int (PTRCALL *sameName)(const ENCODING *,
+ const char *,
+ const char *);
+ int (PTRCALL *nameMatchesAscii)(const ENCODING *,
+ const char *,
+ const char *,
+ const char *);
+ int (PTRFASTCALL *nameLength)(const ENCODING *, const char *);
+ const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *);
+ int (PTRCALL *getAtts)(const ENCODING *enc,
+ const char *ptr,
+ int attsMax,
+ ATTRIBUTE *atts);
+ int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr);
+ int (PTRCALL *predefinedEntityName)(const ENCODING *,
+ const char *,
+ const char *);
+ void (PTRCALL *updatePosition)(const ENCODING *,
+ const char *ptr,
+ const char *end,
+ POSITION *);
+ int (PTRCALL *isPublicId)(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr);
+ void (PTRCALL *utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ char **toP,
+ const char *toLim);
+ void (PTRCALL *utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
+ int minBytesPerChar;
+ char isUtf8;
+ char isUtf16;
+};
+
+/* Scan the string starting at ptr until the end of the next complete
+ token, but do not scan past eptr. Return an integer giving the
+ type of token.
+
+ Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
+
+ Return XML_TOK_PARTIAL when the string does not contain a complete
+ token; nextTokPtr will not be set.
+
+ Return XML_TOK_INVALID when the string does not start a valid
+ token; nextTokPtr will be set to point to the character which made
+ the token invalid.
+
+ Otherwise the string starts with a valid token; nextTokPtr will be
+ set to point to the character following the end of that token.
+
+ Each data character counts as a single token, but adjacent data
+ characters may be returned together. Similarly for characters in
+ the prolog outside literals, comments and processing instructions.
+*/
+
+
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
+
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+
+#ifdef XML_DTD
+
+#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
+
+#endif /* XML_DTD */
+
+/* This is used for performing a 2nd-level tokenization on the content
+ of a literal that has already been returned by XmlTok.
+*/
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
+
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
+
+#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
+ (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
+
+#define XmlNameLength(enc, ptr) \
+ (((enc)->nameLength)(enc, ptr))
+
+#define XmlSkipS(enc, ptr) \
+ (((enc)->skipS)(enc, ptr))
+
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+ (((enc)->getAtts)(enc, ptr, attsMax, atts))
+
+#define XmlCharRefNumber(enc, ptr) \
+ (((enc)->charRefNumber)(enc, ptr))
+
+#define XmlPredefinedEntityName(enc, ptr, end) \
+ (((enc)->predefinedEntityName)(enc, ptr, end))
+
+#define XmlUpdatePosition(enc, ptr, end, pos) \
+ (((enc)->updatePosition)(enc, ptr, end, pos))
+
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
+ (((enc)->isPublicId)(enc, ptr, end, badPtr))
+
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
+
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
+
+typedef struct {
+ ENCODING initEnc;
+ const ENCODING **encPtr;
+} INIT_ENCODING;
+
+int XmlParseXmlDecl(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+
+int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING *XmlGetUtf8InternalEncoding(void);
+const ENCODING *XmlGetUtf16InternalEncoding(void);
+int FASTCALL XmlUtf8Encode(int charNumber, char *buf);
+int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf);
+int XmlSizeOfUnknownEncoding(void);
+
+
+typedef int (XMLCALL *CONVERTER) (void *userData, const char *p);
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData);
+
+int XmlParseXmlDeclNS(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+
+int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING *XmlGetUtf8InternalEncodingNS(void);
+const ENCODING *XmlGetUtf16InternalEncodingNS(void);
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlTok_INCLUDED */
diff --git a/lib/expat/xmltok_impl.c b/lib/expat/xmltok_impl.c
new file mode 100644
index 000000000..5fa578a43
--- /dev/null
+++ b/lib/expat/xmltok_impl.c
@@ -0,0 +1,1800 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* This file is included! */
+#ifdef XML_TOK_IMPL_C
+
+#ifndef IS_INVALID_CHAR
+#define IS_INVALID_CHAR(enc, ptr, n) ((int)(enc) & 0)
+#endif
+
+#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define INVALID_CASES(ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+ case BT_NONXML: \
+ case BT_MALFORM: \
+ case BT_TRAIL: \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID;
+
+#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NAME_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ case BT_DIGIT: \
+ case BT_NAME: \
+ case BT_MINUS: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+#ifndef PREFIX
+#define PREFIX(ident) ident
+#endif
+
+/* ptr points to character following "<!-" */
+
+static int PTRCALL
+PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_MINUS:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMENT;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static int PTRCALL
+PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COND_SECT_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_PERCNT:
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ /* don't allow <!ENTITY% foo "whatever"> */
+ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
+ case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* fall through */
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DECL_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr,
+ const char *end, int *tokPtr)
+{
+ int upper = 0;
+
+ (void)enc;
+
+ *tokPtr = XML_TOK_PI;
+ if (end - ptr != MINBPC(enc)*3)
+ return 1;
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_x:
+ break;
+ case ASCII_X:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_m:
+ break;
+ case ASCII_M:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_l:
+ break;
+ case ASCII_L:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ if (upper)
+ return 0;
+ *tokPtr = XML_TOK_XML_DECL;
+ return 1;
+}
+
+/* ptr points to character following "<?" */
+
+static int PTRCALL
+PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ int tok;
+ const char *target = ptr;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUEST:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+ case BT_QUEST:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A,
+ ASCII_T, ASCII_A, ASCII_LSQB };
+ int i;
+
+ (void)enc;
+
+ /* CDATA[ */
+ if (end - ptr < 6 * MINBPC(enc))
+ return XML_TOK_PARTIAL;
+ for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+ if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static int PTRCALL
+PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CDATA_SECT_CLOSE;
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ case BT_RSQB:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "</" */
+
+static int PTRCALL
+PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ break;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+#ifdef XML_NS
+ case BT_COLON:
+ /* no need to check qname syntax here,
+ since end-tag must match exactly */
+ ptr += MINBPC(enc);
+ break;
+#endif
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static int PTRCALL
+PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static int PTRCALL
+PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (CHAR_MATCHES(enc, ptr, ASCII_x))
+ return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static int PTRCALL
+PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_NUM:
+ return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static int PTRCALL
+PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon = 0;
+#endif
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ for (;;) {
+ int t;
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == BT_EQUALS)
+ break;
+ switch (t) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_EQUALS:
+ {
+ int open;
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ open = BYTE_TYPE(enc, ptr);
+ if (open == BT_QUOT || open == BT_APOS)
+ break;
+ switch (open) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ ptr += MINBPC(enc);
+ /* in attribute value */
+ for (;;) {
+ int t;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == open)
+ break;
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_AMP:
+ {
+ int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+ if (tok <= 0) {
+ if (tok == XML_TOK_INVALID)
+ *nextTokPtr = ptr;
+ return tok;
+ }
+ break;
+ }
+ case BT_LT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ break;
+ case BT_SOL:
+ goto sol;
+ case BT_GT:
+ goto gt;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* ptr points to closing quote */
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ continue;
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_WITH_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+ }
+ break;
+ }
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static int PTRCALL
+PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon;
+#endif
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_EXCL:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc),
+ end, nextTokPtr);
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_SOL:
+ return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ /* we have a start-tag */
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ {
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT:
+ goto gt;
+ case BT_SOL:
+ goto sol;
+ case BT_S: case BT_CR: case BT_LF:
+ ptr += MINBPC(enc);
+ continue;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+ }
+ return XML_TOK_PARTIAL;
+ }
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_NO_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LT:
+ return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_AMP:
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_RSQB:
+ if (ptr + MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ if (ptr + 2*MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_AMP:
+ case BT_LT:
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "%" */
+
+static int PTRCALL
+PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return -XML_TOK_PERCENT;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_PERCENT;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_PARAM_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_POUND_NAME;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return -XML_TOK_POUND_NAME;
+}
+
+static int PTRCALL
+PREFIX(scanLit)(int open, const ENCODING *enc,
+ const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ while (ptr != end) {
+ int t = BYTE_TYPE(enc, ptr);
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUOT:
+ case BT_APOS:
+ ptr += MINBPC(enc);
+ if (t != open)
+ break;
+ if (ptr == end)
+ return -XML_TOK_LITERAL;
+ *nextTokPtr = ptr;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ case BT_GT: case BT_PERCNT: case BT_LSQB:
+ return XML_TOK_LITERAL;
+ default:
+ return XML_TOK_INVALID;
+ }
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_QUOT:
+ return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_APOS:
+ return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LT:
+ {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_EXCL:
+ return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_NMSTRT:
+ case BT_HEX:
+ case BT_NONASCII:
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ *nextTokPtr = ptr - MINBPC(enc);
+ return XML_TOK_INSTANCE_START;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ case BT_CR:
+ if (ptr + MINBPC(enc) == end) {
+ *nextTokPtr = end;
+ /* indicate that this might be part of a CR/LF pair */
+ return -XML_TOK_PROLOG_S;
+ }
+ /* fall through */
+ case BT_S: case BT_LF:
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ break;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_LF:
+ break;
+ case BT_CR:
+ /* don't split CR/LF pair */
+ if (ptr + MINBPC(enc) != end)
+ break;
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ case BT_PERCNT:
+ return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_COMMA:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMA;
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_BRACKET;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return -XML_TOK_CLOSE_BRACKET;
+ if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) {
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_COND_SECT_CLOSE;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_BRACKET;
+ case BT_LPAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_PAREN;
+ case BT_RPAR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return -XML_TOK_CLOSE_PAREN;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_AST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_ASTERISK;
+ case BT_QUEST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_QUESTION;
+ case BT_PLUS:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_PLUS;
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_GT: case BT_COMMA: case BT_VERBAR:
+ case BT_RPAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_PAREN;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_VERBAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OR;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DECL_CLOSE;
+ case BT_NUM:
+ return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NAME; \
+ break; \
+ } \
+ if (IS_NAME_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NMTOKEN; \
+ break; \
+ } \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NMSTRT:
+ case BT_HEX:
+ tok = XML_TOK_NAME;
+ ptr += MINBPC(enc);
+ break;
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ tok = XML_TOK_NMTOKEN;
+ ptr += MINBPC(enc);
+ break;
+ case BT_NONASCII:
+ if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NAME;
+ break;
+ }
+ if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT: case BT_RPAR: case BT_COMMA:
+ case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return tok;
+#ifdef XML_NS
+ case BT_COLON:
+ ptr += MINBPC(enc);
+ switch (tok) {
+ case XML_TOK_NAME:
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ tok = XML_TOK_PREFIXED_NAME;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+ case XML_TOK_PREFIXED_NAME:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+#endif
+ case BT_PLUS:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_PLUS;
+ case BT_AST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_ASTERISK;
+ case BT_QUEST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_QUESTION;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return -tok;
+}
+
+static int PTRCALL
+PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LT:
+ /* this is for inside entity references */
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_S:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ATTRIBUTE_VALUE_S;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+static int PTRCALL
+PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_PERCNT:
+ if (ptr == start) {
+ int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc),
+ end, nextTokPtr);
+ return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+#ifdef XML_DTD
+
+static int PTRCALL
+PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ int level = 0;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ end = ptr + n;
+ }
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_LT:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) {
+ ++level;
+ ptr += MINBPC(enc);
+ }
+ }
+ break;
+ case BT_RSQB:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr += MINBPC(enc);
+ if (level == 0) {
+ *nextTokPtr = ptr;
+ return XML_TOK_IGNORE_SECT;
+ }
+ --level;
+ }
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+#endif /* XML_DTD */
+
+static int PTRCALL
+PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr)
+{
+ ptr += MINBPC(enc);
+ end -= MINBPC(enc);
+ for (; ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ case BT_MINUS:
+ case BT_APOS:
+ case BT_LPAR:
+ case BT_RPAR:
+ case BT_PLUS:
+ case BT_COMMA:
+ case BT_SOL:
+ case BT_EQUALS:
+ case BT_QUEST:
+ case BT_CR:
+ case BT_LF:
+ case BT_SEMI:
+ case BT_EXCL:
+ case BT_AST:
+ case BT_PERCNT:
+ case BT_NUM:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ break;
+ case BT_S:
+ if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ case BT_NAME:
+ case BT_NMSTRT:
+ if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+ break;
+ default:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 0x24: /* $ */
+ case 0x40: /* @ */
+ break;
+ default:
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+/* This must only be called for a well-formed start-tag or empty
+ element tag. Returns the number of attributes. Pointers to the
+ first attsMax attributes are stored in atts.
+*/
+
+static int PTRCALL
+PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts)
+{
+ enum { other, inName, inValue } state = inName;
+ int nAtts = 0;
+ int open = 0; /* defined when state == inValue;
+ initialization just to shut up compilers */
+
+ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define START_NAME \
+ if (state == other) { \
+ if (nAtts < attsMax) { \
+ atts[nAtts].name = ptr; \
+ atts[nAtts].normalized = 1; \
+ } \
+ state = inName; \
+ }
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+ case BT_HEX:
+ START_NAME
+ break;
+#undef START_NAME
+ case BT_QUOT:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ open = BT_QUOT;
+ }
+ else if (open == BT_QUOT) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_APOS:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ open = BT_APOS;
+ }
+ else if (open == BT_APOS) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_AMP:
+ if (nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_S:
+ if (state == inName)
+ state = other;
+ else if (state == inValue
+ && nAtts < attsMax
+ && atts[nAtts].normalized
+ && (ptr == atts[nAtts].valuePtr
+ || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
+ || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
+ || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_CR: case BT_LF:
+ /* This case ensures that the first attribute name is counted
+ Apart from that we could just change state on the quote. */
+ if (state == inName)
+ state = other;
+ else if (state == inValue && nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_GT:
+ case BT_SOL:
+ if (state != inValue)
+ return nAtts;
+ break;
+ default:
+ break;
+ }
+ }
+ /* not reached */
+}
+
+static int PTRFASTCALL
+PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
+{
+ int result = 0;
+
+ (void)enc;
+
+ /* skip &# */
+ ptr += 2*MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
+ for (ptr += MINBPC(enc);
+ !CHAR_MATCHES(enc, ptr, ASCII_SEMI);
+ ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ switch (c) {
+ case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4:
+ case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9:
+ result <<= 4;
+ result |= (c - ASCII_0);
+ break;
+ case ASCII_A: case ASCII_B: case ASCII_C:
+ case ASCII_D: case ASCII_E: case ASCII_F:
+ result <<= 4;
+ result += 10 + (c - ASCII_A);
+ break;
+ case ASCII_a: case ASCII_b: case ASCII_c:
+ case ASCII_d: case ASCII_e: case ASCII_f:
+ result <<= 4;
+ result += 10 + (c - ASCII_a);
+ break;
+ }
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ else {
+ for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ result *= 10;
+ result += (c - ASCII_0);
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ return checkCharRefNumber(result);
+}
+
+static int PTRCALL
+PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr,
+ const char *end)
+{
+ (void)enc;
+
+ switch ((end - ptr)/MINBPC(enc)) {
+ case 2:
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_l:
+ return ASCII_LT;
+ case ASCII_g:
+ return ASCII_GT;
+ }
+ }
+ break;
+ case 3:
+ if (CHAR_MATCHES(enc, ptr, ASCII_a)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_m)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_p))
+ return ASCII_AMP;
+ }
+ }
+ break;
+ case 4:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_q:
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_u)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_t))
+ return ASCII_QUOT;
+ }
+ }
+ break;
+ case ASCII_a:
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_p)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_s))
+ return ASCII_APOS;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static int PTRCALL
+PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr1)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (*ptr1++ != *ptr2++) \
+ return 0;
+ LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
+#undef LEAD_CASE
+ /* fall through */
+ if (*ptr1++ != *ptr2++)
+ return 0;
+ break;
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 1) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 2) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 3) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ }
+ }
+ }
+ break;
+ default:
+ if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
+ return 1;
+ switch (BYTE_TYPE(enc, ptr2)) {
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+ }
+ /* not reached */
+}
+
+static int PTRCALL
+PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
+ const char *end1, const char *ptr2)
+{
+ (void)enc;
+
+ for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
+ if (ptr1 == end1)
+ return 0;
+ if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+ return 0;
+ }
+ return ptr1 == end1;
+}
+
+static int PTRFASTCALL
+PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
+{
+ const char *start = ptr;
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return (int)(ptr - start);
+ }
+ }
+}
+
+static const char * PTRFASTCALL
+PREFIX(skipS)(const ENCODING *enc, const char *ptr)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LF:
+ case BT_CR:
+ case BT_S:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr;
+ }
+ }
+}
+
+static void PTRCALL
+PREFIX(updatePosition)(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ POSITION *pos)
+{
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_LF:
+ pos->columnNumber = (XML_Size)-1;
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ break;
+ case BT_CR:
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ pos->columnNumber = (XML_Size)-1;
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ pos->columnNumber++;
+ }
+}
+
+#undef DO_LEAD_CASE
+#undef MULTIBYTE_CASES
+#undef INVALID_CASES
+#undef CHECK_NAME_CASE
+#undef CHECK_NAME_CASES
+#undef CHECK_NMSTRT_CASE
+#undef CHECK_NMSTRT_CASES
+
+#else /* XML_TOK_IMPL_C */
+
+int xml_tok_impl_c;
+
+#endif /* XML_TOK_IMPL_C */
diff --git a/lib/expat/xmltok_impl.h b/lib/expat/xmltok_impl.h
new file mode 100644
index 000000000..da0ea60a6
--- /dev/null
+++ b/lib/expat/xmltok_impl.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+enum {
+ BT_NONXML,
+ BT_MALFORM,
+ BT_LT,
+ BT_AMP,
+ BT_RSQB,
+ BT_LEAD2,
+ BT_LEAD3,
+ BT_LEAD4,
+ BT_TRAIL,
+ BT_CR,
+ BT_LF,
+ BT_GT,
+ BT_QUOT,
+ BT_APOS,
+ BT_EQUALS,
+ BT_QUEST,
+ BT_EXCL,
+ BT_SOL,
+ BT_SEMI,
+ BT_NUM,
+ BT_LSQB,
+ BT_S,
+ BT_NMSTRT,
+ BT_COLON,
+ BT_HEX,
+ BT_DIGIT,
+ BT_NAME,
+ BT_MINUS,
+ BT_OTHER, /* known not to be a name or name start character */
+ BT_NONASCII, /* might be a name or name start character */
+ BT_PERCNT,
+ BT_LPAR,
+ BT_RPAR,
+ BT_AST,
+ BT_PLUS,
+ BT_COMMA,
+ BT_VERBAR
+};
+
+#include <stddef.h>
diff --git a/lib/expat/xmltok_ns.c b/lib/expat/xmltok_ns.c
new file mode 100644
index 000000000..5afdfbe5c
--- /dev/null
+++ b/lib/expat/xmltok_ns.c
@@ -0,0 +1,119 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* This file is included! */
+#ifdef XML_TOK_NS_C
+
+const ENCODING *
+NS(XmlGetUtf8InternalEncoding)(void)
+{
+ return &ns(internal_utf8_encoding).enc;
+}
+
+const ENCODING *
+NS(XmlGetUtf16InternalEncoding)(void)
+{
+#if BYTEORDER == 1234
+ return &ns(internal_little2_encoding).enc;
+#elif BYTEORDER == 4321
+ return &ns(internal_big2_encoding).enc;
+#else
+ const short n = 1;
+ return (*(const char *)&n
+ ? &ns(internal_little2_encoding).enc
+ : &ns(internal_big2_encoding).enc);
+#endif
+}
+
+static const ENCODING * const NS(encodings)[] = {
+ &ns(latin1_encoding).enc,
+ &ns(ascii_encoding).enc,
+ &ns(utf8_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(little2_encoding).enc,
+ &ns(utf8_encoding).enc /* NO_ENC */
+};
+
+static int PTRCALL
+NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc,
+ XML_PROLOG_STATE, ptr, end, nextTokPtr);
+}
+
+static int PTRCALL
+NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc,
+ XML_CONTENT_STATE, ptr, end, nextTokPtr);
+}
+
+int
+NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr,
+ const char *name)
+{
+ int i = getEncodingIndex(name);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ SET_INIT_ENC_INDEX(p, i);
+ p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+ p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+ p->initEnc.updatePosition = initUpdatePosition;
+ p->encPtr = encPtr;
+ *encPtr = &(p->initEnc);
+ return 1;
+}
+
+static const ENCODING *
+NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
+{
+#define ENCODING_MAX 128
+ char buf[ENCODING_MAX];
+ char *p = buf;
+ int i;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
+ if (ptr != end)
+ return 0;
+ *p = 0;
+ if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2)
+ return enc;
+ i = getEncodingIndex(buf);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ return NS(encodings)[i];
+}
+
+int
+NS(XmlParseXmlDecl)(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ return doParseXmlDecl(NS(findEncoding),
+ isGeneralTextEntity,
+ enc,
+ ptr,
+ end,
+ badPtr,
+ versionPtr,
+ versionEndPtr,
+ encodingName,
+ encoding,
+ standalone);
+}
+
+#else /* XML_TOK_NS_C */
+
+int xml_tok_ns_c;
+
+#endif /* XML_TOK_NS_C */
diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp
new file mode 100644
index 000000000..da523e783
--- /dev/null
+++ b/lib/inifile/iniFile.cpp
@@ -0,0 +1,807 @@
+// IniFile.cpp: Implementation of the CIniFile class.
+// Written by: Adam Clauss
+// Email: cabadam@houston.rr.com
+// You may use this class/code as you wish in your programs. Feel free to distribute it, and
+// email suggested changes to me.
+//
+// Rewritten by: Shane Hill
+// Date: 21/08/2001
+// Email: Shane.Hill@dsto.defence.gov.au
+// Reason: Remove dependancy on MFC. Code should compile on any
+// platform.
+//////////////////////////////////////////////////////////////////////
+
+/*
+!! MODIFIED BY FAKETRUTH and xoft !!
+*/
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+// C++ Includes
+#include <fstream>
+
+// C Includes
+#include <ctype.h>
+
+// Local Includes
+#include "iniFile.h"
+
+#if defined(WIN32)
+ #define iniEOL endl
+#else
+ #define iniEOL '\r' << endl
+#endif
+
+#ifndef _WIN32
+ #define sscanf_s(buffer, stringbuffer, ...) (sscanf(buffer, stringbuffer, __VA_ARGS__))
+#endif
+
+using namespace std;
+
+
+
+
+
+cIniFile::cIniFile(void) :
+ m_IsCaseInsensitive(true)
+{
+}
+
+
+
+
+
+bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
+{
+ // Normally you would use ifstream, but the SGI CC compiler has
+ // a few bugs with ifstream. So ... fstream used.
+ fstream f;
+ AString line;
+ AString keyname, valuename, value;
+ AString::size_type pLeft, pRight;
+ bool IsFromExampleRedirect = false;
+
+ f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::in);
+ if (f.fail())
+ {
+ f.clear();
+ if (a_AllowExampleRedirect)
+ {
+ // Retry with the .example.ini file instead of .ini:
+ AString ExPath(a_FileName.substr(0, a_FileName.length() - 4));
+ ExPath.append(".example.ini");
+ f.open((FILE_IO_PREFIX + ExPath).c_str(), ios::in);
+ if (f.fail())
+ {
+ return false;
+ }
+ IsFromExampleRedirect = true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ while (getline(f, line))
+ {
+ // To be compatible with Win32, check for existence of '\r'.
+ // Win32 files have the '\r' and Unix files don't at the end of a line.
+ // Note that the '\r' will be written to INI files from
+ // Unix so that the created INI file can be read under Win32
+ // without change.
+ size_t lineLength = line.length();
+ if (lineLength == 0)
+ {
+ continue;
+ }
+ if (line[lineLength - 1] == '\r')
+ {
+ line = line.substr(0, lineLength - 1);
+ }
+
+ if (line.length() == 0)
+ {
+ continue;
+ }
+
+ // Check that the user hasn't opened a binary file by checking the first
+ // character of each line!
+ if (!isprint(line[0]))
+ {
+ printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]);
+ f.close();
+ return false;
+ }
+ if ((pLeft = line.find_first_of(";#[=")) == AString::npos)
+ {
+ continue;
+ }
+
+ switch (line[pLeft])
+ {
+ case '[':
+ {
+ if (
+ ((pRight = line.find_last_of("]")) != AString::npos) &&
+ (pRight > pLeft)
+ )
+ {
+ keyname = line.substr(pLeft + 1, pRight - pLeft - 1);
+ AddKeyName(keyname);
+ }
+ break;
+ }
+
+ case '=':
+ {
+ valuename = line.substr(0, pLeft);
+ value = line.substr(pLeft + 1);
+ SetValue(keyname, valuename, value);
+ break;
+ }
+
+ case ';':
+ case '#':
+ {
+ if (names.size() == 0)
+ {
+ AddHeaderComment(line.substr(pLeft + 1));
+ }
+ else
+ {
+ AddKeyComment(keyname, line.substr(pLeft + 1));
+ }
+ break;
+ }
+ } // switch (line[pLeft])
+ } // while (getline())
+
+ f.close();
+ if (names.size() == 0)
+ {
+ return false;
+ }
+
+ if (IsFromExampleRedirect)
+ {
+ WriteFile(FILE_IO_PREFIX + a_FileName);
+ }
+ return true;
+}
+
+
+
+
+
+bool cIniFile::WriteFile(const AString & a_FileName) const
+{
+ // Normally you would use ofstream, but the SGI CC compiler has
+ // a few bugs with ofstream. So ... fstream used.
+ fstream f;
+
+ f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::out);
+ if (f.fail())
+ {
+ return false;
+ }
+
+ // Write header comments.
+ size_t NumComments = comments.size();
+ for (size_t commentID = 0; commentID < NumComments; ++commentID)
+ {
+ f << ';' << comments[commentID] << iniEOL;
+ }
+ if (NumComments > 0)
+ {
+ f << iniEOL;
+ }
+
+ // Write keys and values.
+ for (size_t keyID = 0; keyID < keys.size(); ++keyID)
+ {
+ f << '[' << names[keyID] << ']' << iniEOL;
+
+ // Comments.
+ for (size_t commentID = 0; commentID < keys[keyID].comments.size(); ++commentID)
+ {
+ f << ';' << keys[keyID].comments[commentID] << iniEOL;
+ }
+
+ // Values.
+ for (size_t valueID = 0; valueID < keys[keyID].names.size(); ++valueID)
+ {
+ f << keys[keyID].names[valueID] << '=' << keys[keyID].values[valueID] << iniEOL;
+ }
+ f << iniEOL;
+ }
+ f.close();
+
+ return true;
+}
+
+
+
+
+
+int cIniFile::FindKey(const AString & a_KeyName) const
+{
+ AString CaseKeyName = CheckCase(a_KeyName);
+ for (size_t keyID = 0; keyID < names.size(); ++keyID)
+ {
+ if (CheckCase(names[keyID]) == CaseKeyName)
+ {
+ return keyID;
+ }
+ }
+ return noID;
+}
+
+
+
+
+
+int cIniFile::FindValue(const int keyID, const AString & a_ValueName) const
+{
+ if (!keys.size() || (keyID >= (int)keys.size()))
+ {
+ return noID;
+ }
+
+ AString CaseValueName = CheckCase(a_ValueName);
+ for (size_t valueID = 0; valueID < keys[keyID].names.size(); ++valueID)
+ {
+ if (CheckCase(keys[keyID].names[valueID]) == CaseValueName)
+ {
+ return int(valueID);
+ }
+ }
+ return noID;
+}
+
+
+
+
+
+int cIniFile::AddKeyName(const AString & keyname)
+{
+ names.resize(names.size() + 1, keyname);
+ keys.resize(keys.size() + 1);
+ return names.size() - 1;
+}
+
+
+
+
+
+AString cIniFile::GetKeyName(const int keyID) const
+{
+ if (keyID < (int)names.size())
+ {
+ return names[keyID];
+ }
+ else
+ {
+ return "";
+ }
+}
+
+
+
+
+
+int cIniFile::GetNumValues(const int keyID) const
+{
+ if (keyID < (int)keys.size())
+ {
+ return (int)keys[keyID].names.size();
+ }
+ return 0;
+}
+
+
+
+
+
+int cIniFile::GetNumValues(const AString & keyname) const
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return 0;
+ }
+ return (int)keys[keyID].names.size();
+}
+
+
+
+
+
+AString cIniFile::GetValueName(const int keyID, const int valueID) const
+{
+ if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size()))
+ {
+ return keys[keyID].names[valueID];
+ }
+ return "";
+}
+
+
+
+
+
+AString cIniFile::GetValueName(const AString & keyname, const int valueID) const
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return "";
+ }
+ return GetValueName(keyID, valueID);
+}
+
+
+
+
+
+bool cIniFile::SetValue(const int keyID, const int valueID, const AString & value)
+{
+ if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size()))
+ {
+ keys[keyID].values[valueID] = value;
+ }
+ return false;
+}
+
+
+
+
+
+bool cIniFile::SetValue(const AString & keyname, const AString & valuename, const AString & value, bool const create)
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ if (create)
+ {
+ keyID = int(AddKeyName(keyname));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ int valueID = FindValue(int(keyID), valuename);
+ if (valueID == noID)
+ {
+ if (!create)
+ {
+ return false;
+ }
+ keys[keyID].names.resize(keys[keyID].names.size() + 1, valuename);
+ keys[keyID].values.resize(keys[keyID].values.size() + 1, value);
+ }
+ else
+ {
+ if (!create)
+ {
+ keys[keyID].values[valueID] = value;
+ }
+ else
+ {
+ keys[keyID].names.resize(keys[keyID].names.size() + 1, valuename);
+ keys[keyID].values.resize(keys[keyID].values.size() + 1, value);
+ }
+ }
+
+ return true;
+}
+
+
+
+
+
+bool cIniFile::SetValueI(const AString & keyname, const AString & valuename, const int value, bool const create)
+{
+ AString Data;
+ Printf(Data, "%d", value);
+ return SetValue(keyname, valuename, Data, create);
+}
+
+
+
+
+
+bool cIniFile::SetValueF(const AString & keyname, const AString & valuename, double const value, bool const create)
+{
+ AString Data;
+ Printf(Data, "%f", value);
+ return SetValue(keyname, valuename, Data, create);
+}
+
+
+
+
+
+bool cIniFile::SetValueV(const AString & keyname, const AString & valuename, char * format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ AString Data;
+ AppendVPrintf(Data, format, args);
+ va_end(args);
+ return SetValue(keyname, valuename, Data);
+}
+
+
+
+
+
+AString cIniFile::GetValue(const int keyID, const int valueID, const AString & defValue) const
+{
+ if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size()))
+ {
+ return keys[keyID].values[valueID];
+ }
+ return defValue;
+}
+
+
+
+
+
+AString cIniFile::GetValue(const AString & keyname, const AString & valuename, const AString & defValue) const
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return defValue;
+ }
+
+ int valueID = FindValue(int(keyID), valuename);
+ if (valueID == noID)
+ {
+ return defValue;
+ }
+
+ return keys[keyID].values[valueID];
+}
+
+
+
+
+
+int cIniFile::GetValueI(const AString & keyname, const AString & valuename, const int defValue) const
+{
+ AString Data;
+ Printf(Data, "%d", defValue);
+ return atoi(GetValue(keyname, valuename, Data).c_str());
+}
+
+
+
+
+
+double cIniFile::GetValueF(const AString & keyname, const AString & valuename, double const defValue) const
+{
+ AString Data;
+ Printf(Data, "%f", defValue);
+ return atof(GetValue(keyname, valuename, Data).c_str());
+}
+
+
+
+
+
+AString cIniFile::GetValueSet(const AString & keyname, const AString & valuename, const AString & defValue)
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ SetValue(keyname, valuename, defValue);
+ return defValue;
+ }
+
+ int valueID = FindValue(int(keyID), valuename);
+ if (valueID == noID)
+ {
+ SetValue(keyname, valuename, defValue);
+ return defValue;
+ }
+
+ return keys[keyID].values[valueID];
+}
+
+
+
+
+
+double cIniFile::GetValueSetF(const AString & keyname, const AString & valuename, const double defValue)
+{
+ AString Data;
+ Printf(Data, "%f", defValue);
+ return atof(GetValueSet(keyname, valuename, Data).c_str());
+}
+
+
+
+
+
+int cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const int defValue)
+{
+ AString Data;
+ Printf(Data, "%d", defValue);
+ return atoi(GetValueSet(keyname, valuename, Data).c_str());
+}
+
+
+
+
+
+bool cIniFile::DeleteValueByID(const int keyID, const int valueID)
+{
+ if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size()))
+ {
+ // This looks strange, but is neccessary.
+ vector<AString>::iterator npos = keys[keyID].names.begin() + valueID;
+ vector<AString>::iterator vpos = keys[keyID].values.begin() + valueID;
+ keys[keyID].names.erase(npos, npos + 1);
+ keys[keyID].values.erase(vpos, vpos + 1);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+bool cIniFile::DeleteValue(const AString & keyname, const AString & valuename)
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return false;
+ }
+
+ int valueID = FindValue(int(keyID), valuename);
+ if (valueID == noID)
+ {
+ return false;
+ }
+
+ return DeleteValueByID(keyID, valueID);
+}
+
+
+
+
+
+bool cIniFile::DeleteKey(const AString & keyname)
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return false;
+ }
+
+ vector<AString>::iterator npos = names.begin() + keyID;
+ vector<key>::iterator kpos = keys.begin() + keyID;
+ names.erase(npos, npos + 1);
+ keys.erase(kpos, kpos + 1);
+
+ return true;
+}
+
+
+
+
+
+void cIniFile::Clear(void)
+{
+ names.clear();
+ keys.clear();
+ comments.clear();
+}
+
+
+
+
+
+void cIniFile::AddHeaderComment(const AString & comment)
+{
+ comments.push_back(comment);
+ // comments.resize(comments.size() + 1, comment);
+}
+
+
+
+
+
+AString cIniFile::GetHeaderComment(const int commentID) const
+{
+ if (commentID < (int)comments.size())
+ {
+ return comments[commentID];
+ }
+ return "";
+}
+
+
+
+
+
+bool cIniFile::DeleteHeaderComment(int commentID)
+{
+ if (commentID < (int)comments.size())
+ {
+ vector<AString>::iterator cpos = comments.begin() + commentID;
+ comments.erase(cpos, cpos + 1);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+int cIniFile::GetNumKeyComments(const int keyID) const
+{
+ if (keyID < (int)keys.size())
+ {
+ return keys[keyID].comments.size();
+ }
+ return 0;
+}
+
+
+
+
+
+int cIniFile::GetNumKeyComments(const AString & keyname) const
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return 0;
+ }
+ return (int)keys[keyID].comments.size();
+}
+
+
+
+
+
+bool cIniFile::AddKeyComment(const int keyID, const AString & comment)
+{
+ if (keyID < (int)keys.size())
+ {
+ keys[keyID].comments.resize(keys[keyID].comments.size() + 1, comment);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+bool cIniFile::AddKeyComment(const AString & keyname, const AString & comment)
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return false;
+ }
+ return AddKeyComment(keyID, comment);
+}
+
+
+
+
+
+AString cIniFile::GetKeyComment(const int keyID, const int commentID) const
+{
+ if ((keyID < (int)keys.size()) && (commentID < (int)keys[keyID].comments.size()))
+ {
+ return keys[keyID].comments[commentID];
+ }
+ return "";
+}
+
+
+
+
+
+AString cIniFile::GetKeyComment(const AString & keyname, const int commentID) const
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return "";
+ }
+ return GetKeyComment(int(keyID), commentID);
+}
+
+
+
+
+
+bool cIniFile::DeleteKeyComment(const int keyID, const int commentID)
+{
+ if ((keyID < (int)keys.size()) && (commentID < (int)keys[keyID].comments.size()))
+ {
+ vector<AString>::iterator cpos = keys[keyID].comments.begin() + commentID;
+ keys[keyID].comments.erase(cpos, cpos + 1);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+bool cIniFile::DeleteKeyComment(const AString & keyname, const int commentID)
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return false;
+ }
+ return DeleteKeyComment(int(keyID), commentID);
+}
+
+
+
+
+
+bool cIniFile::DeleteKeyComments(const int keyID)
+{
+ if (keyID < (int)keys.size())
+ {
+ keys[keyID].comments.clear();
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+bool cIniFile::DeleteKeyComments(const AString & keyname)
+{
+ int keyID = FindKey(keyname);
+ if (keyID == noID)
+ {
+ return false;
+ }
+ return DeleteKeyComments(int(keyID));
+}
+
+
+
+
+
+AString cIniFile::CheckCase(const AString & s) const
+{
+ if (!m_IsCaseInsensitive)
+ {
+ return s;
+ }
+ AString res(s);
+ size_t len = res.length();
+ for (size_t i = 0; i < len; i++)
+ {
+ res[i] = tolower(res[i]);
+ }
+ return res;
+}
+
+
+
+
diff --git a/lib/inifile/iniFile.h b/lib/inifile/iniFile.h
new file mode 100644
index 000000000..83d961fc6
--- /dev/null
+++ b/lib/inifile/iniFile.h
@@ -0,0 +1,205 @@
+// IniFile.cpp: Implementation of the CIniFile class.
+// Written by: Adam Clauss
+// Email: cabadam@tamu.edu
+// You may use this class/code as you wish in your programs. Feel free to distribute it, and
+// email suggested changes to me.
+//
+// Rewritten by: Shane Hill
+// Date: 21/08/2001
+// Email: Shane.Hill@dsto.defence.gov.au
+// Reason: Remove dependancy on MFC. Code should compile on any
+// platform. Tested on Windows/Linux/Irix
+//////////////////////////////////////////////////////////////////////
+
+/*
+!! MODIFIED BY FAKETRUTH and madmaxoft!!
+*/
+
+#ifndef CIniFile_H
+#define CIniFile_H
+
+
+
+
+
+#define MAX_KEYNAME 128
+#define MAX_VALUENAME 128
+#define MAX_VALUEDATA 2048
+
+
+
+
+
+// tolua_begin
+
+class cIniFile
+{
+private:
+ bool m_IsCaseInsensitive;
+
+ struct key
+ {
+ std::vector<AString> names;
+ std::vector<AString> values;
+ std::vector<AString> comments;
+ } ;
+
+ std::vector<key> keys;
+ std::vector<AString> names;
+ std::vector<AString> comments;
+
+ /// If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is
+ AString CheckCase(const AString & s) const;
+
+public:
+ enum errors
+ {
+ noID = -1,
+ };
+
+ /// Creates a new instance with no data
+ cIniFile(void);
+
+ // Sets whether or not keynames and valuenames should be case sensitive.
+ // The default is case insensitive.
+ void CaseSensitive (void) { m_IsCaseInsensitive = false; }
+ void CaseInsensitive(void) { m_IsCaseInsensitive = true; }
+
+ /** Reads the contents of the specified ini file
+ If the file doesn't exist and a_AllowExampleRedirect is true, tries to read <basename>.example.ini, and
+ writes its contents as <basename>.ini, if successful.
+ Returns true if successful, false otherwise.
+ */
+ bool ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect = true);
+
+ /// Writes data stored in class to the specified ini file
+ bool WriteFile(const AString & a_FileName) const;
+
+ /// Deletes all stored ini data (but doesn't touch the file)
+ void Clear(void);
+
+ /// Returns index of specified key, or noID if not found
+ int FindKey(const AString & keyname) const;
+
+ /// Returns index of specified value, in the specified key, or noID if not found
+ int FindValue(const int keyID, const AString & valuename) const;
+
+ /// Returns number of keys currently in the ini
+ int GetNumKeys(void) const { return (int)keys.size(); }
+
+ /// Add a key name
+ int AddKeyName(const AString & keyname);
+
+ // Returns key names by index.
+ AString GetKeyName(const int keyID) const;
+
+ // Returns number of values stored for specified key.
+ int GetNumValues(const AString & keyname) const;
+ int GetNumValues(const int keyID) const;
+
+ // Returns value name by index for a given keyname or keyID.
+ AString GetValueName(const AString & keyname, const int valueID) const;
+ AString GetValueName(const int keyID, const int valueID) const;
+
+ // Gets value of [keyname] valuename =.
+ // Overloaded to return string, int, and double.
+ // Returns defValue if key/value not found.
+ AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const;
+ AString GetValue (const int keyID, const int valueID, const AString & defValue = "") const;
+ double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const;
+ int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const;
+ bool GetValueB(const AString & keyname, const AString & valuename, const bool defValue = false) const
+ {
+ return (GetValueI(keyname, valuename, defValue ? 1 : 0) != 0);
+ }
+
+ // Gets the value; if not found, write the default to the INI file
+ AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "");
+ double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0);
+ int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0);
+ bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false)
+ {
+ return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) != 0);
+ }
+
+ // Sets value of [keyname] valuename =.
+ // Specify the optional paramter as false (0) if you do not want it to create
+ // the key if it doesn't exist. Returns true if data entered, false otherwise.
+ // Overloaded to accept string, int, and double.
+ bool SetValue( const int keyID, const int valueID, const AString & value);
+ bool SetValue( const AString & keyname, const AString & valuename, const AString & value, const bool create = true);
+ bool SetValueI( const AString & keyname, const AString & valuename, const int value, const bool create = true);
+ bool SetValueB( const AString & keyname, const AString & valuename, const bool value, const bool create = true)
+ {
+ return SetValueI( keyname, valuename, int(value), create);
+ }
+ bool SetValueF( const AString & keyname, const AString & valuename, const double value, const bool create = true);
+
+ // tolua_end
+
+ bool SetValueV( const AString & keyname, const AString & valuename, char *format, ...);
+
+ // tolua_begin
+
+ // Deletes specified value.
+ // Returns true if value existed and deleted, false otherwise.
+ bool DeleteValueByID(const int keyID, const int valueID);
+ bool DeleteValue(const AString & keyname, const AString & valuename);
+
+ // Deletes specified key and all values contained within.
+ // Returns true if key existed and deleted, false otherwise.
+ bool DeleteKey(const AString & keyname);
+
+ // Header comment functions.
+ // Header comments are those comments before the first key.
+
+ /// Returns the number of header comments
+ int GetNumHeaderComments(void) {return (int)comments.size();}
+
+ /// Adds a header comment
+ void AddHeaderComment(const AString & comment);
+
+ /// Returns a header comment, or empty string if out of range
+ AString GetHeaderComment(const int commentID) const;
+
+ /// Deletes a header comment. Returns true if successful
+ bool DeleteHeaderComment(int commentID);
+
+ /// Deletes all header comments
+ void DeleteHeaderComments(void) {comments.clear();}
+
+
+ // Key comment functions.
+ // Key comments are those comments within a key. Any comments
+ // defined within value names will be added to this list. Therefore,
+ // these comments will be moved to the top of the key definition when
+ // the CIniFile::WriteFile() is called.
+
+ /// Get number of key comments
+ int GetNumKeyComments(const int keyID) const;
+
+ /// Get number of key comments
+ int GetNumKeyComments(const AString & keyname) const;
+
+ /// Add a key comment
+ bool AddKeyComment(const int keyID, const AString & comment);
+
+ /// Add a key comment
+ bool AddKeyComment(const AString & keyname, const AString & comment);
+
+ /// Return a key comment
+ AString GetKeyComment(const int keyID, const int commentID) const;
+ AString GetKeyComment(const AString & keyname, const int commentID) const;
+
+ // Delete a key comment.
+ bool DeleteKeyComment(const int keyID, const int commentID);
+ bool DeleteKeyComment(const AString & keyname, const int commentID);
+
+ // Delete all comments for a key.
+ bool DeleteKeyComments(const int keyID);
+ bool DeleteKeyComments(const AString & keyname);
+};
+
+// tolua_end
+
+#endif
diff --git a/lib/jsoncpp/include/json/autolink.h b/lib/jsoncpp/include/json/autolink.h
new file mode 100644
index 000000000..37c9258ed
--- /dev/null
+++ b/lib/jsoncpp/include/json/autolink.h
@@ -0,0 +1,19 @@
+#ifndef JSON_AUTOLINK_H_INCLUDED
+# define JSON_AUTOLINK_H_INCLUDED
+
+# include "config.h"
+
+# ifdef JSON_IN_CPPTL
+# include <cpptl/cpptl_autolink.h>
+# endif
+
+# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
+# define CPPTL_AUTOLINK_NAME "json"
+# undef CPPTL_AUTOLINK_DLL
+# ifdef JSON_DLL
+# define CPPTL_AUTOLINK_DLL
+# endif
+# include "autolink.h"
+# endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED
diff --git a/lib/jsoncpp/include/json/config.h b/lib/jsoncpp/include/json/config.h
new file mode 100644
index 000000000..5d334cbc5
--- /dev/null
+++ b/lib/jsoncpp/include/json/config.h
@@ -0,0 +1,43 @@
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//# define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//# define JSON_USE_CPPTL_SMALLMAP 1
+/// If defined, indicates that Json specific container should be used
+/// (hash table & simple deque container with customizable allocator).
+/// THIS FEATURE IS STILL EXPERIMENTAL!
+//# define JSON_VALUE_USE_INTERNAL_MAP 1
+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 1
+
+# ifdef JSON_IN_CPPTL
+# include <cpptl/config.h>
+# ifndef JSON_USE_CPPTL
+# define JSON_USE_CPPTL 1
+# endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+# define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+# define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+# define JSON_API __declspec(dllimport)
+# else
+# define JSON_API
+# endif
+
+#endif // JSON_CONFIG_H_INCLUDED
diff --git a/lib/jsoncpp/include/json/features.h b/lib/jsoncpp/include/json/features.h
new file mode 100644
index 000000000..5a9adec11
--- /dev/null
+++ b/lib/jsoncpp/include/json/features.h
@@ -0,0 +1,42 @@
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+# define CPPTL_JSON_FEATURES_H_INCLUDED
+
+# include "forwards.h"
+
+namespace Json {
+
+ /** \brief Configuration passed to reader and writer.
+ * This configuration object can be used to force the Reader or Writer
+ * to behave in a standard conforming way.
+ */
+ class JSON_API Features
+ {
+ public:
+ /** \brief A configuration that allows all features and assumes all strings are UTF-8.
+ * - C & C++ comments are allowed
+ * - Root object can be any JSON value
+ * - Assumes Value strings are encoded in UTF-8
+ */
+ static Features all();
+
+ /** \brief A configuration that is strictly compatible with the JSON specification.
+ * - Comments are forbidden.
+ * - Root object must be either an array or an object value.
+ * - Assumes Value strings are encoded in UTF-8
+ */
+ static Features strictMode();
+
+ /** \brief Initialize the configuration like JsonConfig::allFeatures;
+ */
+ Features();
+
+ /// \c true if comments are allowed. Default: \c true.
+ bool allowComments_;
+
+ /// \c true if root must be either an array or an object value. Default: \c false.
+ bool strictRoot_;
+ };
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
diff --git a/lib/jsoncpp/include/json/forwards.h b/lib/jsoncpp/include/json/forwards.h
new file mode 100644
index 000000000..d0ce8300c
--- /dev/null
+++ b/lib/jsoncpp/include/json/forwards.h
@@ -0,0 +1,39 @@
+#ifndef JSON_FORWARDS_H_INCLUDED
+# define JSON_FORWARDS_H_INCLUDED
+
+# include "config.h"
+
+namespace Json {
+
+ // writer.h
+ class FastWriter;
+ class StyledWriter;
+
+ // reader.h
+ class Reader;
+
+ // features.h
+ class Features;
+
+ // value.h
+ typedef int Int;
+ typedef unsigned int UInt;
+ class StaticString;
+ class Path;
+ class PathArgument;
+ class Value;
+ class ValueIteratorBase;
+ class ValueIterator;
+ class ValueConstIterator;
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ class ValueAllocator;
+ class ValueMapAllocator;
+ class ValueInternalLink;
+ class ValueInternalArray;
+ class ValueInternalMap;
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+} // namespace Json
+
+
+#endif // JSON_FORWARDS_H_INCLUDED
diff --git a/lib/jsoncpp/include/json/json.h b/lib/jsoncpp/include/json/json.h
new file mode 100644
index 000000000..c71ed65ab
--- /dev/null
+++ b/lib/jsoncpp/include/json/json.h
@@ -0,0 +1,10 @@
+#ifndef JSON_JSON_H_INCLUDED
+# define JSON_JSON_H_INCLUDED
+
+# include "autolink.h"
+# include "value.h"
+# include "reader.h"
+# include "writer.h"
+# include "features.h"
+
+#endif // JSON_JSON_H_INCLUDED
diff --git a/lib/jsoncpp/include/json/reader.h b/lib/jsoncpp/include/json/reader.h
new file mode 100644
index 000000000..ee1d6a244
--- /dev/null
+++ b/lib/jsoncpp/include/json/reader.h
@@ -0,0 +1,196 @@
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+# define CPPTL_JSON_READER_H_INCLUDED
+
+# include "features.h"
+# include "value.h"
+# include <deque>
+# include <stack>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+ /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
+ *
+ */
+ class JSON_API Reader
+ {
+ public:
+ typedef char Char;
+ typedef const Char *Location;
+
+ /** \brief Constructs a Reader allowing all features
+ * for parsing.
+ */
+ Reader();
+
+ /** \brief Constructs a Reader allowing the specified feature set
+ * for parsing.
+ */
+ Reader( const Features &features );
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+ * \param document UTF-8 encoded string containing the document to read.
+ * \param root [out] Contains the root value of the document if it was
+ * successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing them back during
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an error occurred.
+ */
+ bool parse( const std::string &document,
+ Value &root,
+ bool collectComments = true );
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+ * \param document UTF-8 encoded string containing the document to read.
+ * \param root [out] Contains the root value of the document if it was
+ * successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing them back during
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an error occurred.
+ */
+ bool parse( const char *beginDoc, const char *endDoc,
+ Value &root,
+ bool collectComments = true );
+
+ /// \brief Parse from input stream.
+ /// \see Json::operator>>(std::istream&, Json::Value&).
+ bool parse( std::istream &is,
+ Value &root,
+ bool collectComments = true );
+
+ /** \brief Returns a user friendly string that list errors in the parsed document.
+ * \return Formatted error message with the list of errors with their location in
+ * the parsed document. An empty string is returned if no error occurred
+ * during parsing.
+ */
+ std::string getFormatedErrorMessages() const;
+
+ private:
+ enum TokenType
+ {
+ tokenEndOfStream = 0,
+ tokenObjectBegin,
+ tokenObjectEnd,
+ tokenArrayBegin,
+ tokenArrayEnd,
+ tokenString,
+ tokenNumber,
+ tokenTrue,
+ tokenFalse,
+ tokenNull,
+ tokenArraySeparator,
+ tokenMemberSeparator,
+ tokenComment,
+ tokenError
+ };
+
+ class Token
+ {
+ public:
+ TokenType type_;
+ Location start_;
+ Location end_;
+ };
+
+ class ErrorInfo
+ {
+ public:
+ Token token_;
+ std::string message_;
+ Location extra_;
+ };
+
+ typedef std::deque<ErrorInfo> Errors;
+
+ bool expectToken( TokenType type, Token &token, const char *message );
+ bool readToken( Token &token );
+ void skipSpaces();
+ bool match( Location pattern,
+ int patternLength );
+ bool readComment();
+ bool readCStyleComment();
+ bool readCppStyleComment();
+ bool readString();
+ void readNumber();
+ bool readValue();
+ bool readObject( Token &token );
+ bool readArray( Token &token );
+ bool decodeNumber( Token &token );
+ bool decodeString( Token &token );
+ bool decodeString( Token &token, std::string &decoded );
+ bool decodeDouble( Token &token );
+ bool decodeUnicodeCodePoint( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode );
+ bool decodeUnicodeEscapeSequence( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode );
+ bool addError( const std::string &message,
+ Token &token,
+ Location extra = 0 );
+ bool recoverFromError( TokenType skipUntilToken );
+ bool addErrorAndRecover( const std::string &message,
+ Token &token,
+ TokenType skipUntilToken );
+ void skipUntilSpace();
+ Value &currentValue();
+ Char getNextChar();
+ void getLocationLineAndColumn( Location location,
+ int &line,
+ int &column ) const;
+ std::string getLocationLineAndColumn( Location location ) const;
+ void addComment( Location begin,
+ Location end,
+ CommentPlacement placement );
+ void skipCommentTokens( Token &token );
+
+ typedef std::stack<Value *> Nodes;
+ Nodes nodes_;
+ Errors errors_;
+ std::string document_;
+ Location begin_;
+ Location end_;
+ Location current_;
+ Location lastValueEnd_;
+ Value *lastValue_;
+ std::string commentsBefore_;
+ Features features_;
+ bool collectComments_;
+ };
+
+ /** \brief Read from 'sin' into 'root'.
+
+ Always keep comments from the input JSON.
+
+ This can be used to read a file into a particular sub-object.
+ For example:
+ \code
+ Json::Value root;
+ cin >> root["dir"]["file"];
+ cout << root;
+ \endcode
+ Result:
+ \verbatim
+ {
+ "dir": {
+ "file": {
+ // The input stream JSON would be nested here.
+ }
+ }
+ }
+ \endverbatim
+ \throw std::exception on parse error.
+ \see Json::operator<<()
+ */
+ std::istream& operator>>( std::istream&, Value& );
+
+} // namespace Json
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
diff --git a/lib/jsoncpp/include/json/value.h b/lib/jsoncpp/include/json/value.h
new file mode 100644
index 000000000..58bfd88e7
--- /dev/null
+++ b/lib/jsoncpp/include/json/value.h
@@ -0,0 +1,1069 @@
+#ifndef CPPTL_JSON_H_INCLUDED
+# define CPPTL_JSON_H_INCLUDED
+
+# include "forwards.h"
+# include <string>
+# include <vector>
+
+# ifndef JSON_USE_CPPTL_SMALLMAP
+# include <map>
+# else
+# include <cpptl/smallmap.h>
+# endif
+# ifdef JSON_USE_CPPTL
+# include <cpptl/forwards.h>
+# endif
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+ /** \brief Type of the value held by a Value object.
+ */
+ enum ValueType
+ {
+ nullValue = 0, ///< 'null' value
+ intValue, ///< signed integer value
+ uintValue, ///< unsigned integer value
+ realValue, ///< double value
+ stringValue, ///< UTF-8 string value
+ booleanValue, ///< bool value
+ arrayValue, ///< array value (ordered list)
+ objectValue ///< object value (collection of name/value pairs).
+ };
+
+ enum CommentPlacement
+ {
+ commentBefore = 0, ///< a comment placed on the line before a value
+ commentAfterOnSameLine, ///< a comment just after a value on the same line
+ commentAfter, ///< a comment on the line after a value (only make sense for root value)
+ numberOfCommentPlacement
+ };
+
+//# ifdef JSON_USE_CPPTL
+// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+ /** \brief Lightweight wrapper to tag static string.
+ *
+ * Value constructor and objectValue member assignement takes advantage of the
+ * StaticString and avoid the cost of string duplication when storing the
+ * string or the member name.
+ *
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+ class JSON_API StaticString
+ {
+ public:
+ explicit StaticString( const char *czstring )
+ : str_( czstring )
+ {
+ }
+
+ operator const char *() const
+ {
+ return str_;
+ }
+
+ const char *c_str() const
+ {
+ return str_;
+ }
+
+ private:
+ const char *str_;
+ };
+
+ /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+ *
+ * This class is a discriminated union wrapper that can represents a:
+ * - signed integer [range: Value::minInt - Value::maxInt]
+ * - unsigned integer (range: 0 - Value::maxUInt)
+ * - double
+ * - UTF-8 string
+ * - boolean
+ * - 'null'
+ * - an ordered list of Value
+ * - collection of name/value pairs (javascript object)
+ *
+ * The type of the held value is represented by a #ValueType and
+ * can be obtained using type().
+ *
+ * values of an #objectValue or #arrayValue can be accessed using operator[]() methods.
+ * Non const methods will automatically create the a #nullValue element
+ * if it does not exist.
+ * The sequence of an #arrayValue will be automatically resize and initialized
+ * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+ *
+ * The get() methods can be used to obtanis default value in the case the required element
+ * does not exist.
+ *
+ * It is possible to iterate over the list of a #objectValue values using
+ * the getMemberNames() method.
+ */
+ class JSON_API Value
+ {
+ friend class ValueIteratorBase;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ friend class ValueInternalLink;
+ friend class ValueInternalMap;
+# endif
+ public:
+ typedef std::vector<std::string> Members;
+ typedef ValueIterator iterator;
+ typedef ValueConstIterator const_iterator;
+ typedef Json::UInt UInt;
+ typedef Json::Int Int;
+ typedef UInt ArrayIndex;
+
+ static const Value null;
+ static const Int minInt;
+ static const Int maxInt;
+ static const UInt maxUInt;
+
+ private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+ class CZString
+ {
+ public:
+ enum DuplicationPolicy
+ {
+ noDuplication = 0,
+ duplicate,
+ duplicateOnCopy
+ };
+ CZString( int index );
+ CZString( const char *cstr, DuplicationPolicy allocate );
+ CZString( const CZString &other );
+ ~CZString();
+ CZString &operator =( const CZString &other );
+ bool operator<( const CZString &other ) const;
+ bool operator==( const CZString &other ) const;
+ int index() const;
+ const char *c_str() const;
+ bool isStaticString() const;
+ private:
+ void swap( CZString &other );
+ const char *cstr_;
+ int index_;
+ };
+
+ public:
+# ifndef JSON_USE_CPPTL_SMALLMAP
+ typedef std::map<CZString, Value> ObjectValues;
+# else
+ typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+# endif // ifndef JSON_USE_CPPTL_SMALLMAP
+# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+ public:
+ /** \brief Create a default Value of the given type.
+
+ This is a very useful constructor.
+ To create an empty array, pass arrayValue.
+ To create an empty object, pass objectValue.
+ Another Value can then be set to this one by assignment.
+ This is useful since clear() and resize() will not alter types.
+
+ Examples:
+ \code
+ Json::Value null_value; // null
+ Json::Value arr_value(Json::arrayValue); // []
+ Json::Value obj_value(Json::objectValue); // {}
+ \endcode
+ */
+ Value( ValueType type = nullValue );
+ Value( Int value );
+ Value( UInt value );
+ Value( double value );
+ Value( const char *value );
+ Value( const char *beginValue, const char *endValue );
+ /** \brief Constructs a value from a static string.
+
+ * Like other value string constructor but do not duplicate the string for
+ * internal storage. The given string must remain alive after the call to this
+ * constructor.
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * \endcode
+ */
+ Value( const StaticString &value );
+ Value( const std::string &value );
+# ifdef JSON_USE_CPPTL
+ Value( const CppTL::ConstString &value );
+# endif
+ Value( bool value );
+ Value( const Value &other );
+ ~Value();
+
+ Value &operator=( const Value &other );
+ /// Swap values.
+ /// \note Currently, comments are intentionally not swapped, for
+ /// both logic and efficiency.
+ void swap( Value &other );
+
+ ValueType type() const;
+
+ bool operator <( const Value &other ) const;
+ bool operator <=( const Value &other ) const;
+ bool operator >=( const Value &other ) const;
+ bool operator >( const Value &other ) const;
+
+ bool operator ==( const Value &other ) const;
+ bool operator !=( const Value &other ) const;
+
+ int compare( const Value &other );
+
+ const char *asCString() const;
+ std::string asString() const;
+# ifdef JSON_USE_CPPTL
+ CppTL::ConstString asConstString() const;
+# endif
+ Int asInt() const;
+ UInt asUInt() const;
+ double asDouble() const;
+ bool asBool() const;
+
+ bool isNull() const;
+ bool isBool() const;
+ bool isInt() const;
+ bool isUInt() const;
+ bool isIntegral() const;
+ bool isDouble() const;
+ bool isNumeric() const;
+ bool isString() const;
+ bool isArray() const;
+ bool isObject() const;
+
+ bool isConvertibleTo( ValueType other ) const;
+
+ /// Number of values in array or object
+ UInt size() const;
+
+ /// \brief Return true if empty array, empty object, or null;
+ /// otherwise, false.
+ bool empty() const;
+
+ /// Return isNull()
+ bool operator!() const;
+
+ /// Remove all object members and array elements.
+ /// \pre type() is arrayValue, objectValue, or nullValue
+ /// \post type() is unchanged
+ void clear();
+
+ /// Resize the array to size elements.
+ /// New elements are initialized to null.
+ /// May only be called on nullValue or arrayValue.
+ /// \pre type() is arrayValue or nullValue
+ /// \post type() is arrayValue
+ void resize( UInt size );
+
+ /// Access an array element (zero based index ).
+ /// If the array contains less than index element, then null value are inserted
+ /// in the array so that its size is index+1.
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ Value &operator[]( UInt index );
+ /// Access an array element (zero based index )
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ const Value &operator[]( UInt index ) const;
+ /// If the array contains at least index+1 elements, returns the element value,
+ /// otherwise returns defaultValue.
+ Value get( UInt index,
+ const Value &defaultValue ) const;
+ /// Return true if index < size().
+ bool isValidIndex( UInt index ) const;
+ /// \brief Append value to array at the end.
+ ///
+ /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+ Value &append( const Value &value );
+
+ /// Access an object value by name, create a null member if it does not exist.
+ Value &operator[]( const char *key );
+ /// Access an object value by name, returns null if there is no member with that name.
+ const Value &operator[]( const char *key ) const;
+ /// Access an object value by name, create a null member if it does not exist.
+ Value &operator[]( const std::string &key );
+ /// Access an object value by name, returns null if there is no member with that name.
+ const Value &operator[]( const std::string &key ) const;
+ /** \brief Access an object value by name, create a null member if it does not exist.
+
+ * If the object as no entry for that name, then the member name used to store
+ * the new entry is not duplicated.
+ * Example of use:
+ * \code
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+ Value &operator[]( const StaticString &key );
+# ifdef JSON_USE_CPPTL
+ /// Access an object value by name, create a null member if it does not exist.
+ Value &operator[]( const CppTL::ConstString &key );
+ /// Access an object value by name, returns null if there is no member with that name.
+ const Value &operator[]( const CppTL::ConstString &key ) const;
+# endif
+ /// Return the member named key if it exist, defaultValue otherwise.
+ Value get( const char *key,
+ const Value &defaultValue ) const;
+ /// Return the member named key if it exist, defaultValue otherwise.
+ Value get( const std::string &key,
+ const Value &defaultValue ) const;
+# ifdef JSON_USE_CPPTL
+ /// Return the member named key if it exist, defaultValue otherwise.
+ Value get( const CppTL::ConstString &key,
+ const Value &defaultValue ) const;
+# endif
+ /// \brief Remove and return the named member.
+ ///
+ /// Do nothing if it did not exist.
+ /// \return the removed Value, or null.
+ /// \pre type() is objectValue or nullValue
+ /// \post type() is unchanged
+ Value removeMember( const char* key );
+ /// Same as removeMember(const char*)
+ Value removeMember( const std::string &key );
+
+ /// Return true if the object has a member named key.
+ bool isMember( const char *key ) const;
+ /// Return true if the object has a member named key.
+ bool isMember( const std::string &key ) const;
+# ifdef JSON_USE_CPPTL
+ /// Return true if the object has a member named key.
+ bool isMember( const CppTL::ConstString &key ) const;
+# endif
+
+ /// \brief Return a list of the member names.
+ ///
+ /// If null, return an empty list.
+ /// \pre type() is objectValue or nullValue
+ /// \post if type() was nullValue, it remains nullValue
+ Members getMemberNames() const;
+
+//# ifdef JSON_USE_CPPTL
+// EnumMemberNames enumMemberNames() const;
+// EnumValues enumValues() const;
+//# endif
+
+ /// Comments must be //... or /* ... */
+ void setComment( const char *comment,
+ CommentPlacement placement );
+ /// Comments must be //... or /* ... */
+ void setComment( const std::string &comment,
+ CommentPlacement placement );
+ bool hasComment( CommentPlacement placement ) const;
+ /// Include delimiters and embedded newlines.
+ std::string getComment( CommentPlacement placement ) const;
+
+ std::string toStyledString() const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ iterator begin();
+ iterator end();
+
+ private:
+ Value &resolveReference( const char *key,
+ bool isStatic );
+
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ inline bool isItemAvailable() const
+ {
+ return itemIsUsed_ == 0;
+ }
+
+ inline void setItemUsed( bool isUsed = true )
+ {
+ itemIsUsed_ = isUsed ? 1 : 0;
+ }
+
+ inline bool isMemberNameStatic() const
+ {
+ return memberNameIsStatic_ == 0;
+ }
+
+ inline void setMemberNameIsStatic( bool isStatic )
+ {
+ memberNameIsStatic_ = isStatic ? 1 : 0;
+ }
+# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+ private:
+ struct CommentInfo
+ {
+ CommentInfo();
+ ~CommentInfo();
+
+ void setComment( const char *text );
+
+ char *comment_;
+ };
+
+ //struct MemberNamesTransform
+ //{
+ // typedef const char *result_type;
+ // const char *operator()( const CZString &name ) const
+ // {
+ // return name.c_str();
+ // }
+ //};
+
+ union ValueHolder
+ {
+ Int int_;
+ UInt uint_;
+ double real_;
+ bool bool_;
+ char *string_;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ ValueInternalArray *array_;
+ ValueInternalMap *map_;
+#else
+ ObjectValues *map_;
+# endif
+ } value_;
+ ValueType type_ : 8;
+ int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container.
+ int memberNameIsStatic_ : 1; // used by the ValueInternalMap container.
+# endif
+ CommentInfo *comments_;
+ };
+
+
+ /** \brief Experimental and untested: represents an element of the "path" to access a node.
+ */
+ class PathArgument
+ {
+ public:
+ friend class Path;
+
+ PathArgument();
+ PathArgument( UInt index );
+ PathArgument( const char *key );
+ PathArgument( const std::string &key );
+
+ private:
+ enum Kind
+ {
+ kindNone = 0,
+ kindIndex,
+ kindKey
+ };
+ std::string key_;
+ UInt index_;
+ Kind kind_;
+ };
+
+ /** \brief Experimental and untested: represents a "path" to access a node.
+ *
+ * Syntax:
+ * - "." => root node
+ * - ".[n]" => elements at index 'n' of root node (an array value)
+ * - ".name" => member named 'name' of root node (an object value)
+ * - ".name1.name2.name3"
+ * - ".[0][1][2].name1[3]"
+ * - ".%" => member name is provided as parameter
+ * - ".[%]" => index is provied as parameter
+ */
+ class Path
+ {
+ public:
+ Path( const std::string &path,
+ const PathArgument &a1 = PathArgument(),
+ const PathArgument &a2 = PathArgument(),
+ const PathArgument &a3 = PathArgument(),
+ const PathArgument &a4 = PathArgument(),
+ const PathArgument &a5 = PathArgument() );
+
+ const Value &resolve( const Value &root ) const;
+ Value resolve( const Value &root,
+ const Value &defaultValue ) const;
+ /// Creates the "path" to access the specified node and returns a reference on the node.
+ Value &make( Value &root ) const;
+
+ private:
+ typedef std::vector<const PathArgument *> InArgs;
+ typedef std::vector<PathArgument> Args;
+
+ void makePath( const std::string &path,
+ const InArgs &in );
+ void addPathInArg( const std::string &path,
+ const InArgs &in,
+ InArgs::const_iterator &itInArg,
+ PathArgument::Kind kind );
+ void invalidPath( const std::string &path,
+ int location );
+
+ Args args_;
+ };
+
+ /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
+ *
+ * - makeMemberName() and releaseMemberName() are called to respectively duplicate and
+ * free an Json::objectValue member name.
+ * - duplicateStringValue() and releaseStringValue() are called similarly to
+ * duplicate and free a Json::stringValue value.
+ */
+ class ValueAllocator
+ {
+ public:
+ enum { unknown = (unsigned)-1 };
+
+ virtual ~ValueAllocator();
+
+ virtual char *makeMemberName( const char *memberName ) = 0;
+ virtual void releaseMemberName( char *memberName ) = 0;
+ virtual char *duplicateStringValue( const char *value,
+ unsigned int length = unknown ) = 0;
+ virtual void releaseStringValue( char *value ) = 0;
+ };
+
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ /** \brief Allocator to customize Value internal map.
+ * Below is an example of a simple implementation (default implementation actually
+ * use memory pool for speed).
+ * \code
+ class DefaultValueMapAllocator : public ValueMapAllocator
+ {
+ public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ return new ValueInternalMap();
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ return new ValueInternalMap( other );
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ delete map;
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ return new ValueInternalLink();
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ delete link;
+ }
+ };
+ * \endcode
+ */
+ class JSON_API ValueMapAllocator
+ {
+ public:
+ virtual ~ValueMapAllocator();
+ virtual ValueInternalMap *newMap() = 0;
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
+ virtual void destructMap( ValueInternalMap *map ) = 0;
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
+ virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
+ virtual ValueInternalLink *allocateMapLink() = 0;
+ virtual void releaseMapLink( ValueInternalLink *link ) = 0;
+ };
+
+ /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
+ * \internal previous_ & next_ allows for bidirectional traversal.
+ */
+ class JSON_API ValueInternalLink
+ {
+ public:
+ enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
+ enum InternalFlags {
+ flagAvailable = 0,
+ flagUsed = 1
+ };
+
+ ValueInternalLink();
+
+ ~ValueInternalLink();
+
+ Value items_[itemPerLink];
+ char *keys_[itemPerLink];
+ ValueInternalLink *previous_;
+ ValueInternalLink *next_;
+ };
+
+
+ /** \brief A linked page based hash-table implementation used internally by Value.
+ * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
+ * list in each bucket to handle collision. There is an addional twist in that
+ * each node of the collision linked list is a page containing a fixed amount of
+ * value. This provides a better compromise between memory usage and speed.
+ *
+ * Each bucket is made up of a chained list of ValueInternalLink. The last
+ * link of a given bucket can be found in the 'previous_' field of the following bucket.
+ * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
+ * Only the last link of a bucket may contains 'available' item. The last link always
+ * contains at least one element unless is it the bucket one very first link.
+ */
+ class JSON_API ValueInternalMap
+ {
+ friend class ValueIteratorBase;
+ friend class Value;
+ public:
+ typedef unsigned int HashKey;
+ typedef unsigned int BucketIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+ struct IteratorState
+ {
+ IteratorState()
+ : map_(0)
+ , link_(0)
+ , itemIndex_(0)
+ , bucketIndex_(0)
+ {
+ }
+ ValueInternalMap *map_;
+ ValueInternalLink *link_;
+ BucketIndex itemIndex_;
+ BucketIndex bucketIndex_;
+ };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+ ValueInternalMap();
+ ValueInternalMap( const ValueInternalMap &other );
+ ValueInternalMap &operator =( const ValueInternalMap &other );
+ ~ValueInternalMap();
+
+ void swap( ValueInternalMap &other );
+
+ BucketIndex size() const;
+
+ void clear();
+
+ bool reserveDelta( BucketIndex growth );
+
+ bool reserve( BucketIndex newItemCount );
+
+ const Value *find( const char *key ) const;
+
+ Value *find( const char *key );
+
+ Value &resolveReference( const char *key,
+ bool isStatic );
+
+ void remove( const char *key );
+
+ void doActualRemove( ValueInternalLink *link,
+ BucketIndex index,
+ BucketIndex bucketIndex );
+
+ ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
+
+ Value &setNewItem( const char *key,
+ bool isStatic,
+ ValueInternalLink *link,
+ BucketIndex index );
+
+ Value &unsafeAdd( const char *key,
+ bool isStatic,
+ HashKey hashedKey );
+
+ HashKey hash( const char *key ) const;
+
+ int compare( const ValueInternalMap &other ) const;
+
+ private:
+ void makeBeginIterator( IteratorState &it ) const;
+ void makeEndIterator( IteratorState &it ) const;
+ static bool equals( const IteratorState &x, const IteratorState &other );
+ static void increment( IteratorState &iterator );
+ static void incrementBucket( IteratorState &iterator );
+ static void decrement( IteratorState &iterator );
+ static const char *key( const IteratorState &iterator );
+ static const char *key( const IteratorState &iterator, bool &isStatic );
+ static Value &value( const IteratorState &iterator );
+ static int distance( const IteratorState &x, const IteratorState &y );
+
+ private:
+ ValueInternalLink *buckets_;
+ ValueInternalLink *tailLink_;
+ BucketIndex bucketsSize_;
+ BucketIndex itemCount_;
+ };
+
+ /** \brief A simplified deque implementation used internally by Value.
+ * \internal
+ * It is based on a list of fixed "page", each page contains a fixed number of items.
+ * Instead of using a linked-list, a array of pointer is used for fast item look-up.
+ * Look-up for an element is as follow:
+ * - compute page index: pageIndex = itemIndex / itemsPerPage
+ * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
+ *
+ * Insertion is amortized constant time (only the array containing the index of pointers
+ * need to be reallocated when items are appended).
+ */
+ class JSON_API ValueInternalArray
+ {
+ friend class Value;
+ friend class ValueIteratorBase;
+ public:
+ enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo.
+ typedef Value::ArrayIndex ArrayIndex;
+ typedef unsigned int PageIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+ struct IteratorState // Must be a POD
+ {
+ IteratorState()
+ : array_(0)
+ , currentPageIndex_(0)
+ , currentItemIndex_(0)
+ {
+ }
+ ValueInternalArray *array_;
+ Value **currentPageIndex_;
+ unsigned int currentItemIndex_;
+ };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+ ValueInternalArray();
+ ValueInternalArray( const ValueInternalArray &other );
+ ValueInternalArray &operator =( const ValueInternalArray &other );
+ ~ValueInternalArray();
+ void swap( ValueInternalArray &other );
+
+ void clear();
+ void resize( ArrayIndex newSize );
+
+ Value &resolveReference( ArrayIndex index );
+
+ Value *find( ArrayIndex index ) const;
+
+ ArrayIndex size() const;
+
+ int compare( const ValueInternalArray &other ) const;
+
+ private:
+ static bool equals( const IteratorState &x, const IteratorState &other );
+ static void increment( IteratorState &iterator );
+ static void decrement( IteratorState &iterator );
+ static Value &dereference( const IteratorState &iterator );
+ static Value &unsafeDereference( const IteratorState &iterator );
+ static int distance( const IteratorState &x, const IteratorState &y );
+ static ArrayIndex indexOf( const IteratorState &iterator );
+ void makeBeginIterator( IteratorState &it ) const;
+ void makeEndIterator( IteratorState &it ) const;
+ void makeIterator( IteratorState &it, ArrayIndex index ) const;
+
+ void makeIndexValid( ArrayIndex index );
+
+ Value **pages_;
+ ArrayIndex size_;
+ PageIndex pageCount_;
+ };
+
+ /** \brief Experimental: do not use. Allocator to customize Value internal array.
+ * Below is an example of a simple implementation (actual implementation use
+ * memory pool).
+ \code
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ return new ValueInternalArray();
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ return new ValueInternalArray( other );
+ }
+
+ virtual void destruct( ValueInternalArray *array )
+ {
+ delete array;
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ free( value );
+ }
+};
+ \endcode
+ */
+ class JSON_API ValueArrayAllocator
+ {
+ public:
+ virtual ~ValueArrayAllocator();
+ virtual ValueInternalArray *newArray() = 0;
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
+ virtual void destructArray( ValueInternalArray *array ) = 0;
+ /** \brief Reallocate array page index.
+ * Reallocates an array of pointer on each page.
+ * \param indexes [input] pointer on the current index. May be \c NULL.
+ * [output] pointer on the new index of at least
+ * \a minNewIndexCount pages.
+ * \param indexCount [input] current number of pages in the index.
+ * [output] number of page the reallocated index can handle.
+ * \b MUST be >= \a minNewIndexCount.
+ * \param minNewIndexCount Minimum number of page the new index must be able to
+ * handle.
+ */
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount ) = 0;
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount ) = 0;
+ virtual Value *allocateArrayPage() = 0;
+ virtual void releaseArrayPage( Value *value ) = 0;
+ };
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+
+ /** \brief base class for Value iterators.
+ *
+ */
+ class ValueIteratorBase
+ {
+ public:
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef ValueIteratorBase SelfType;
+
+ ValueIteratorBase();
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
+#else
+ ValueIteratorBase( const ValueInternalArray::IteratorState &state );
+ ValueIteratorBase( const ValueInternalMap::IteratorState &state );
+#endif
+
+ bool operator ==( const SelfType &other ) const
+ {
+ return isEqual( other );
+ }
+
+ bool operator !=( const SelfType &other ) const
+ {
+ return !isEqual( other );
+ }
+
+ difference_type operator -( const SelfType &other ) const
+ {
+ return computeDistance( other );
+ }
+
+ /// Return either the index or the member name of the referenced value as a Value.
+ Value key() const;
+
+ /// Return the index of the referenced Value. -1 if it is not an arrayValue.
+ UInt index() const;
+
+ /// Return the member name of the referenced Value. "" if it is not an objectValue.
+ const char *memberName() const;
+
+ protected:
+ Value &deref() const;
+
+ void increment();
+
+ void decrement();
+
+ difference_type computeDistance( const SelfType &other ) const;
+
+ bool isEqual( const SelfType &other ) const;
+
+ void copy( const SelfType &other );
+
+ private:
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ Value::ObjectValues::iterator current_;
+ // Indicates that iterator is for a null value.
+ bool isNull_;
+#else
+ union
+ {
+ ValueInternalArray::IteratorState array_;
+ ValueInternalMap::IteratorState map_;
+ } iterator_;
+ bool isArray_;
+#endif
+ };
+
+ /** \brief const iterator for object and array value.
+ *
+ */
+ class ValueConstIterator : public ValueIteratorBase
+ {
+ friend class Value;
+ public:
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef const Value &reference;
+ typedef const Value *pointer;
+ typedef ValueConstIterator SelfType;
+
+ ValueConstIterator();
+ private:
+ /*! \internal Use by Value to create an iterator.
+ */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
+#else
+ ValueConstIterator( const ValueInternalArray::IteratorState &state );
+ ValueConstIterator( const ValueInternalMap::IteratorState &state );
+#endif
+ public:
+ SelfType &operator =( const ValueIteratorBase &other );
+
+ SelfType operator++( int )
+ {
+ SelfType temp( *this );
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--( int )
+ {
+ SelfType temp( *this );
+ --*this;
+ return temp;
+ }
+
+ SelfType &operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ SelfType &operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ reference operator *() const
+ {
+ return deref();
+ }
+ };
+
+
+ /** \brief Iterator for object and array value.
+ */
+ class ValueIterator : public ValueIteratorBase
+ {
+ friend class Value;
+ public:
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef Value &reference;
+ typedef Value *pointer;
+ typedef ValueIterator SelfType;
+
+ ValueIterator();
+ ValueIterator( const ValueConstIterator &other );
+ ValueIterator( const ValueIterator &other );
+ private:
+ /*! \internal Use by Value to create an iterator.
+ */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ explicit ValueIterator( const Value::ObjectValues::iterator &current );
+#else
+ ValueIterator( const ValueInternalArray::IteratorState &state );
+ ValueIterator( const ValueInternalMap::IteratorState &state );
+#endif
+ public:
+
+ SelfType &operator =( const SelfType &other );
+
+ SelfType operator++( int )
+ {
+ SelfType temp( *this );
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--( int )
+ {
+ SelfType temp( *this );
+ --*this;
+ return temp;
+ }
+
+ SelfType &operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ SelfType &operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ reference operator *() const
+ {
+ return deref();
+ }
+ };
+
+
+} // namespace Json
+
+
+#endif // CPPTL_JSON_H_INCLUDED
diff --git a/lib/jsoncpp/include/json/writer.h b/lib/jsoncpp/include/json/writer.h
new file mode 100644
index 000000000..5f4b83be4
--- /dev/null
+++ b/lib/jsoncpp/include/json/writer.h
@@ -0,0 +1,174 @@
+#ifndef JSON_WRITER_H_INCLUDED
+# define JSON_WRITER_H_INCLUDED
+
+# include "value.h"
+# include <vector>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+ class Value;
+
+ /** \brief Abstract class for writers.
+ */
+ class JSON_API Writer
+ {
+ public:
+ virtual ~Writer();
+
+ virtual std::string write( const Value &root ) = 0;
+ };
+
+ /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
+ *
+ * The JSON document is written in a single line. It is not intended for 'human' consumption,
+ * but may be usefull to support feature such as RPC where bandwith is limited.
+ * \sa Reader, Value
+ */
+ class JSON_API FastWriter : public Writer
+ {
+ public:
+ FastWriter();
+ virtual ~FastWriter(){}
+
+ void enableYAMLCompatibility();
+
+ public: // overridden from Writer
+ virtual std::string write( const Value &root );
+
+ private:
+ void writeValue( const Value &value );
+
+ std::string document_;
+ bool yamlCompatiblityEnabled_;
+ };
+
+ /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value types,
+ * and all the values fit on one lines, then print the array on a single line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their #CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ */
+ class JSON_API StyledWriter: public Writer
+ {
+ public:
+ StyledWriter();
+ virtual ~StyledWriter(){}
+
+ public: // overridden from Writer
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param root Value to serialize.
+ * \return String containing the JSON document that represents the root value.
+ */
+ virtual std::string write( const Value &root );
+
+ private:
+ void writeValue( const Value &value );
+ void writeArrayValue( const Value &value );
+ bool isMultineArray( const Value &value );
+ void pushValue( const std::string &value );
+ void writeIndent();
+ void writeWithIndent( const std::string &value );
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue( const Value &root );
+ void writeCommentAfterValueOnSameLine( const Value &root );
+ bool hasCommentForValue( const Value &value );
+ static std::string normalizeEOL( const std::string &text );
+
+ typedef std::vector<std::string> ChildValues;
+
+ ChildValues childValues_;
+ std::string document_;
+ std::string indentString_;
+ int rightMargin_;
+ int indentSize_;
+ bool addChildValues_;
+ };
+
+ /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
+ to a stream rather than to a string.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value types,
+ * and all the values fit on one lines, then print the array on a single line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their #CommentPlacement.
+ *
+ * \param indentation Each level will be indented by this amount extra.
+ * \sa Reader, Value, Value::setComment()
+ */
+ class JSON_API StyledStreamWriter
+ {
+ public:
+ StyledStreamWriter( std::string indentation="\t" );
+ ~StyledStreamWriter(){}
+
+ public:
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param out Stream to write to. (Can be ostringstream, e.g.)
+ * \param root Value to serialize.
+ * \note There is no point in deriving from Writer, since write() should not return a value.
+ */
+ void write( std::ostream &out, const Value &root );
+
+ private:
+ void writeValue( const Value &value );
+ void writeArrayValue( const Value &value );
+ bool isMultineArray( const Value &value );
+ void pushValue( const std::string &value );
+ void writeIndent();
+ void writeWithIndent( const std::string &value );
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue( const Value &root );
+ void writeCommentAfterValueOnSameLine( const Value &root );
+ bool hasCommentForValue( const Value &value );
+ static std::string normalizeEOL( const std::string &text );
+
+ typedef std::vector<std::string> ChildValues;
+
+ ChildValues childValues_;
+ std::ostream* document_;
+ std::string indentString_;
+ int rightMargin_;
+ std::string indentation_;
+ bool addChildValues_;
+ };
+
+ std::string JSON_API valueToString( Int value );
+ std::string JSON_API valueToString( UInt value );
+ std::string JSON_API valueToString( double value );
+ std::string JSON_API valueToString( bool value );
+ std::string JSON_API valueToQuotedString( const char *value );
+
+ /// \brief Output using the StyledStreamWriter.
+ /// \see Json::operator>>()
+ std::ostream& operator<<( std::ostream&, const Value &root );
+
+} // namespace Json
+
+
+
+#endif // JSON_WRITER_H_INCLUDED
diff --git a/lib/jsoncpp/src/lib_json/json_batchallocator.h b/lib/jsoncpp/src/lib_json/json_batchallocator.h
new file mode 100644
index 000000000..87ea5ed80
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/json_batchallocator.h
@@ -0,0 +1,125 @@
+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+# include <stdlib.h>
+# include <assert.h>
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+namespace Json {
+
+/* Fast memory allocator.
+ *
+ * This memory allocator allocates memory for a batch of object (specified by
+ * the page size, the number of object in each page).
+ *
+ * It does not allow the destruction of a single object. All the allocated objects
+ * can be destroyed at once. The memory can be either released or reused for future
+ * allocation.
+ *
+ * The in-place new operator must be used to construct the object using the pointer
+ * returned by allocate.
+ */
+template<typename AllocatedType
+ ,const unsigned int objectPerAllocation>
+class BatchAllocator
+{
+public:
+ typedef AllocatedType Type;
+
+ BatchAllocator( unsigned int objectsPerPage = 255 )
+ : freeHead_( 0 )
+ , objectsPerPage_( objectsPerPage )
+ {
+// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
+ assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
+ assert( objectsPerPage >= 16 );
+ batches_ = allocateBatch( 0 ); // allocated a dummy page
+ currentBatch_ = batches_;
+ }
+
+ ~BatchAllocator()
+ {
+ for ( BatchInfo *batch = batches_; batch; )
+ {
+ BatchInfo *nextBatch = batch->next_;
+ free( batch );
+ batch = nextBatch;
+ }
+ }
+
+ /// allocate space for an array of objectPerAllocation object.
+ /// @warning it is the responsability of the caller to call objects constructors.
+ AllocatedType *allocate()
+ {
+ if ( freeHead_ ) // returns node from free list.
+ {
+ AllocatedType *object = freeHead_;
+ freeHead_ = *(AllocatedType **)object;
+ return object;
+ }
+ if ( currentBatch_->used_ == currentBatch_->end_ )
+ {
+ currentBatch_ = currentBatch_->next_;
+ while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
+ currentBatch_ = currentBatch_->next_;
+
+ if ( !currentBatch_ ) // no free batch found, allocate a new one
+ {
+ currentBatch_ = allocateBatch( objectsPerPage_ );
+ currentBatch_->next_ = batches_; // insert at the head of the list
+ batches_ = currentBatch_;
+ }
+ }
+ AllocatedType *allocated = currentBatch_->used_;
+ currentBatch_->used_ += objectPerAllocation;
+ return allocated;
+ }
+
+ /// Release the object.
+ /// @warning it is the responsability of the caller to actually destruct the object.
+ void release( AllocatedType *object )
+ {
+ assert( object != 0 );
+ *(AllocatedType **)object = freeHead_;
+ freeHead_ = object;
+ }
+
+private:
+ struct BatchInfo
+ {
+ BatchInfo *next_;
+ AllocatedType *used_;
+ AllocatedType *end_;
+ AllocatedType buffer_[objectPerAllocation];
+ };
+
+ // disabled copy constructor and assignement operator.
+ BatchAllocator( const BatchAllocator & );
+ void operator =( const BatchAllocator &);
+
+ static BatchInfo *allocateBatch( unsigned int objectsPerPage )
+ {
+ const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
+ + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
+ BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
+ batch->next_ = 0;
+ batch->used_ = batch->buffer_;
+ batch->end_ = batch->buffer_ + objectsPerPage;
+ return batch;
+ }
+
+ BatchInfo *batches_;
+ BatchInfo *currentBatch_;
+ /// Head of a single linked list within the allocated space of freeed object
+ AllocatedType *freeHead_;
+ unsigned int objectsPerPage_;
+};
+
+
+} // namespace Json
+
+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
+
+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
diff --git a/lib/jsoncpp/src/lib_json/json_internalarray.inl b/lib/jsoncpp/src/lib_json/json_internalarray.inl
new file mode 100644
index 000000000..9b985d258
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/json_internalarray.inl
@@ -0,0 +1,448 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueArrayAllocator::~ValueArrayAllocator()
+{
+}
+
+// //////////////////////////////////////////////////////////////////
+// class DefaultValueArrayAllocator
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ return new ValueInternalArray();
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ return new ValueInternalArray( other );
+ }
+
+ virtual void destructArray( ValueInternalArray *array )
+ {
+ delete array;
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ free( value );
+ }
+};
+
+#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ ValueInternalArray *array = arraysAllocator_.allocate();
+ new (array) ValueInternalArray(); // placement new
+ return array;
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ ValueInternalArray *array = arraysAllocator_.allocate();
+ new (array) ValueInternalArray( other ); // placement new
+ return array;
+ }
+
+ virtual void destructArray( ValueInternalArray *array )
+ {
+ if ( array )
+ {
+ array->~ValueInternalArray();
+ arraysAllocator_.release( array );
+ }
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( pagesAllocator_.allocate() );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ pagesAllocator_.release( value );
+ }
+private:
+ BatchAllocator<ValueInternalArray,1> arraysAllocator_;
+ BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
+};
+#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+static ValueArrayAllocator *&arrayAllocator()
+{
+ static DefaultValueArrayAllocator defaultAllocator;
+ static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
+ return arrayAllocator;
+}
+
+static struct DummyArrayAllocatorInitializer {
+ DummyArrayAllocatorInitializer()
+ {
+ arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
+ }
+} dummyArrayAllocatorInitializer;
+
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+bool
+ValueInternalArray::equals( const IteratorState &x,
+ const IteratorState &other )
+{
+ return x.array_ == other.array_
+ && x.currentItemIndex_ == other.currentItemIndex_
+ && x.currentPageIndex_ == other.currentPageIndex_;
+}
+
+
+void
+ValueInternalArray::increment( IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ &&
+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+ != it.array_->size_,
+ "ValueInternalArray::increment(): moving iterator beyond end" );
+ ++(it.currentItemIndex_);
+ if ( it.currentItemIndex_ == itemsPerPage )
+ {
+ it.currentItemIndex_ = 0;
+ ++(it.currentPageIndex_);
+ }
+}
+
+
+void
+ValueInternalArray::decrement( IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
+ && it.currentItemIndex_ == 0,
+ "ValueInternalArray::decrement(): moving iterator beyond end" );
+ if ( it.currentItemIndex_ == 0 )
+ {
+ it.currentItemIndex_ = itemsPerPage-1;
+ --(it.currentPageIndex_);
+ }
+ else
+ {
+ --(it.currentItemIndex_);
+ }
+}
+
+
+Value &
+ValueInternalArray::unsafeDereference( const IteratorState &it )
+{
+ return (*(it.currentPageIndex_))[it.currentItemIndex_];
+}
+
+
+Value &
+ValueInternalArray::dereference( const IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ &&
+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+ < it.array_->size_,
+ "ValueInternalArray::dereference(): dereferencing invalid iterator" );
+ return unsafeDereference( it );
+}
+
+void
+ValueInternalArray::makeBeginIterator( IteratorState &it ) const
+{
+ it.array_ = const_cast<ValueInternalArray *>( this );
+ it.currentItemIndex_ = 0;
+ it.currentPageIndex_ = pages_;
+}
+
+
+void
+ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
+{
+ it.array_ = const_cast<ValueInternalArray *>( this );
+ it.currentItemIndex_ = index % itemsPerPage;
+ it.currentPageIndex_ = pages_ + index / itemsPerPage;
+}
+
+
+void
+ValueInternalArray::makeEndIterator( IteratorState &it ) const
+{
+ makeIterator( it, size_ );
+}
+
+
+ValueInternalArray::ValueInternalArray()
+ : pages_( 0 )
+ , size_( 0 )
+ , pageCount_( 0 )
+{
+}
+
+
+ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
+ : pages_( 0 )
+ , pageCount_( 0 )
+ , size_( other.size_ )
+{
+ PageIndex minNewPages = other.size_ / itemsPerPage;
+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
+ "ValueInternalArray::reserve(): bad reallocation" );
+ IteratorState itOther;
+ other.makeBeginIterator( itOther );
+ Value *value;
+ for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
+ {
+ if ( index % itemsPerPage == 0 )
+ {
+ PageIndex pageIndex = index / itemsPerPage;
+ value = arrayAllocator()->allocateArrayPage();
+ pages_[pageIndex] = value;
+ }
+ new (value) Value( dereference( itOther ) );
+ }
+}
+
+
+ValueInternalArray &
+ValueInternalArray::operator =( const ValueInternalArray &other )
+{
+ ValueInternalArray temp( other );
+ swap( temp );
+ return *this;
+}
+
+
+ValueInternalArray::~ValueInternalArray()
+{
+ // destroy all constructed items
+ IteratorState it;
+ IteratorState itEnd;
+ makeBeginIterator( it);
+ makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ value->~Value();
+ }
+ // release all pages
+ PageIndex lastPageIndex = size_ / itemsPerPage;
+ for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+ // release pages index
+ arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
+}
+
+
+void
+ValueInternalArray::swap( ValueInternalArray &other )
+{
+ Value **tempPages = pages_;
+ pages_ = other.pages_;
+ other.pages_ = tempPages;
+ ArrayIndex tempSize = size_;
+ size_ = other.size_;
+ other.size_ = tempSize;
+ PageIndex tempPageCount = pageCount_;
+ pageCount_ = other.pageCount_;
+ other.pageCount_ = tempPageCount;
+}
+
+void
+ValueInternalArray::clear()
+{
+ ValueInternalArray dummy;
+ swap( dummy );
+}
+
+
+void
+ValueInternalArray::resize( ArrayIndex newSize )
+{
+ if ( newSize == 0 )
+ clear();
+ else if ( newSize < size_ )
+ {
+ IteratorState it;
+ IteratorState itEnd;
+ makeIterator( it, newSize );
+ makeIterator( itEnd, size_ );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ value->~Value();
+ }
+ PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
+ PageIndex lastPageIndex = size_ / itemsPerPage;
+ for ( ; pageIndex < lastPageIndex; ++pageIndex )
+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+ size_ = newSize;
+ }
+ else if ( newSize > size_ )
+ resolveReference( newSize );
+}
+
+
+void
+ValueInternalArray::makeIndexValid( ArrayIndex index )
+{
+ // Need to enlarge page index ?
+ if ( index >= pageCount_ * itemsPerPage )
+ {
+ PageIndex minNewPages = (index + 1) / itemsPerPage;
+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
+ }
+
+ // Need to allocate new pages ?
+ ArrayIndex nextPageIndex =
+ (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
+ : size_;
+ if ( nextPageIndex <= index )
+ {
+ PageIndex pageIndex = nextPageIndex / itemsPerPage;
+ PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
+ for ( ; pageToAllocate-- > 0; ++pageIndex )
+ pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
+ }
+
+ // Initialize all new entries
+ IteratorState it;
+ IteratorState itEnd;
+ makeIterator( it, size_ );
+ size_ = index + 1;
+ makeIterator( itEnd, size_ );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ new (value) Value(); // Construct a default value using placement new
+ }
+}
+
+Value &
+ValueInternalArray::resolveReference( ArrayIndex index )
+{
+ if ( index >= size_ )
+ makeIndexValid( index );
+ return pages_[index/itemsPerPage][index%itemsPerPage];
+}
+
+Value *
+ValueInternalArray::find( ArrayIndex index ) const
+{
+ if ( index >= size_ )
+ return 0;
+ return &(pages_[index/itemsPerPage][index%itemsPerPage]);
+}
+
+ValueInternalArray::ArrayIndex
+ValueInternalArray::size() const
+{
+ return size_;
+}
+
+int
+ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
+{
+ return indexOf(y) - indexOf(x);
+}
+
+
+ValueInternalArray::ArrayIndex
+ValueInternalArray::indexOf( const IteratorState &iterator )
+{
+ if ( !iterator.array_ )
+ return ArrayIndex(-1);
+ return ArrayIndex(
+ (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
+ + iterator.currentItemIndex_ );
+}
+
+
+int
+ValueInternalArray::compare( const ValueInternalArray &other ) const
+{
+ int sizeDiff( size_ - other.size_ );
+ if ( sizeDiff != 0 )
+ return sizeDiff;
+
+ for ( ArrayIndex index =0; index < size_; ++index )
+ {
+ int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
+ other.pages_[index/itemsPerPage][index%itemsPerPage] );
+ if ( diff != 0 )
+ return diff;
+ }
+ return 0;
+}
diff --git a/lib/jsoncpp/src/lib_json/json_internalmap.inl b/lib/jsoncpp/src/lib_json/json_internalmap.inl
new file mode 100644
index 000000000..19771488d
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/json_internalmap.inl
@@ -0,0 +1,607 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalMap
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
+ * This optimization is used by the fast allocator.
+ */
+ValueInternalLink::ValueInternalLink()
+ : previous_( 0 )
+ , next_( 0 )
+{
+}
+
+ValueInternalLink::~ValueInternalLink()
+{
+ for ( int index =0; index < itemPerLink; ++index )
+ {
+ if ( !items_[index].isItemAvailable() )
+ {
+ if ( !items_[index].isMemberNameStatic() )
+ free( keys_[index] );
+ }
+ else
+ break;
+ }
+}
+
+
+
+ValueMapAllocator::~ValueMapAllocator()
+{
+}
+
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ return new ValueInternalMap();
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ return new ValueInternalMap( other );
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ delete map;
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ return new ValueInternalLink();
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ delete link;
+ }
+};
+#else
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ ValueInternalMap *map = mapsAllocator_.allocate();
+ new (map) ValueInternalMap(); // placement new
+ return map;
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ ValueInternalMap *map = mapsAllocator_.allocate();
+ new (map) ValueInternalMap( other ); // placement new
+ return map;
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ if ( map )
+ {
+ map->~ValueInternalMap();
+ mapsAllocator_.release( map );
+ }
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ ValueInternalLink *link = linksAllocator_.allocate();
+ memset( link, 0, sizeof(ValueInternalLink) );
+ return link;
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ link->~ValueInternalLink();
+ linksAllocator_.release( link );
+ }
+private:
+ BatchAllocator<ValueInternalMap,1> mapsAllocator_;
+ BatchAllocator<ValueInternalLink,1> linksAllocator_;
+};
+#endif
+
+static ValueMapAllocator *&mapAllocator()
+{
+ static DefaultValueMapAllocator defaultAllocator;
+ static ValueMapAllocator *mapAllocator = &defaultAllocator;
+ return mapAllocator;
+}
+
+static struct DummyMapAllocatorInitializer {
+ DummyMapAllocatorInitializer()
+ {
+ mapAllocator(); // ensure mapAllocator() statics are initialized before main().
+ }
+} dummyMapAllocatorInitializer;
+
+
+
+// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
+
+/*
+use linked list hash map.
+buckets array is a container.
+linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
+value have extra state: valid, available, deleted
+*/
+
+
+ValueInternalMap::ValueInternalMap()
+ : buckets_( 0 )
+ , tailLink_( 0 )
+ , bucketsSize_( 0 )
+ , itemCount_( 0 )
+{
+}
+
+
+ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
+ : buckets_( 0 )
+ , tailLink_( 0 )
+ , bucketsSize_( 0 )
+ , itemCount_( 0 )
+{
+ reserve( other.itemCount_ );
+ IteratorState it;
+ IteratorState itEnd;
+ other.makeBeginIterator( it );
+ other.makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ bool isStatic;
+ const char *memberName = key( it, isStatic );
+ const Value &aValue = value( it );
+ resolveReference(memberName, isStatic) = aValue;
+ }
+}
+
+
+ValueInternalMap &
+ValueInternalMap::operator =( const ValueInternalMap &other )
+{
+ ValueInternalMap dummy( other );
+ swap( dummy );
+ return *this;
+}
+
+
+ValueInternalMap::~ValueInternalMap()
+{
+ if ( buckets_ )
+ {
+ for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
+ {
+ ValueInternalLink *link = buckets_[bucketIndex].next_;
+ while ( link )
+ {
+ ValueInternalLink *linkToRelease = link;
+ link = link->next_;
+ mapAllocator()->releaseMapLink( linkToRelease );
+ }
+ }
+ mapAllocator()->releaseMapBuckets( buckets_ );
+ }
+}
+
+
+void
+ValueInternalMap::swap( ValueInternalMap &other )
+{
+ ValueInternalLink *tempBuckets = buckets_;
+ buckets_ = other.buckets_;
+ other.buckets_ = tempBuckets;
+ ValueInternalLink *tempTailLink = tailLink_;
+ tailLink_ = other.tailLink_;
+ other.tailLink_ = tempTailLink;
+ BucketIndex tempBucketsSize = bucketsSize_;
+ bucketsSize_ = other.bucketsSize_;
+ other.bucketsSize_ = tempBucketsSize;
+ BucketIndex tempItemCount = itemCount_;
+ itemCount_ = other.itemCount_;
+ other.itemCount_ = tempItemCount;
+}
+
+
+void
+ValueInternalMap::clear()
+{
+ ValueInternalMap dummy;
+ swap( dummy );
+}
+
+
+ValueInternalMap::BucketIndex
+ValueInternalMap::size() const
+{
+ return itemCount_;
+}
+
+bool
+ValueInternalMap::reserveDelta( BucketIndex growth )
+{
+ return reserve( itemCount_ + growth );
+}
+
+bool
+ValueInternalMap::reserve( BucketIndex newItemCount )
+{
+ if ( !buckets_ && newItemCount > 0 )
+ {
+ buckets_ = mapAllocator()->allocateMapBuckets( 1 );
+ bucketsSize_ = 1;
+ tailLink_ = &buckets_[0];
+ }
+// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
+ return true;
+}
+
+
+const Value *
+ValueInternalMap::find( const char *key ) const
+{
+ if ( !bucketsSize_ )
+ return 0;
+ HashKey hashedKey = hash( key );
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ for ( const ValueInternalLink *current = &buckets_[bucketIndex];
+ current != 0;
+ current = current->next_ )
+ {
+ for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( current->items_[index].isItemAvailable() )
+ return 0;
+ if ( strcmp( key, current->keys_[index] ) == 0 )
+ return &current->items_[index];
+ }
+ }
+ return 0;
+}
+
+
+Value *
+ValueInternalMap::find( const char *key )
+{
+ const ValueInternalMap *constThis = this;
+ return const_cast<Value *>( constThis->find( key ) );
+}
+
+
+Value &
+ValueInternalMap::resolveReference( const char *key,
+ bool isStatic )
+{
+ HashKey hashedKey = hash( key );
+ if ( bucketsSize_ )
+ {
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ ValueInternalLink **previous = 0;
+ BucketIndex index;
+ for ( ValueInternalLink *current = &buckets_[bucketIndex];
+ current != 0;
+ previous = &current->next_, current = current->next_ )
+ {
+ for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( current->items_[index].isItemAvailable() )
+ return setNewItem( key, isStatic, current, index );
+ if ( strcmp( key, current->keys_[index] ) == 0 )
+ return current->items_[index];
+ }
+ }
+ }
+
+ reserveDelta( 1 );
+ return unsafeAdd( key, isStatic, hashedKey );
+}
+
+
+void
+ValueInternalMap::remove( const char *key )
+{
+ HashKey hashedKey = hash( key );
+ if ( !bucketsSize_ )
+ return;
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ for ( ValueInternalLink *link = &buckets_[bucketIndex];
+ link != 0;
+ link = link->next_ )
+ {
+ BucketIndex index;
+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( link->items_[index].isItemAvailable() )
+ return;
+ if ( strcmp( key, link->keys_[index] ) == 0 )
+ {
+ doActualRemove( link, index, bucketIndex );
+ return;
+ }
+ }
+ }
+}
+
+void
+ValueInternalMap::doActualRemove( ValueInternalLink *link,
+ BucketIndex index,
+ BucketIndex bucketIndex )
+{
+ // find last item of the bucket and swap it with the 'removed' one.
+ // set removed items flags to 'available'.
+ // if last page only contains 'available' items, then desallocate it (it's empty)
+ ValueInternalLink *&lastLink = getLastLinkInBucket( index );
+ BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
+ for ( ;
+ lastItemIndex < ValueInternalLink::itemPerLink;
+ ++lastItemIndex ) // may be optimized with dicotomic search
+ {
+ if ( lastLink->items_[lastItemIndex].isItemAvailable() )
+ break;
+ }
+
+ BucketIndex lastUsedIndex = lastItemIndex - 1;
+ Value *valueToDelete = &link->items_[index];
+ Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
+ if ( valueToDelete != valueToPreserve )
+ valueToDelete->swap( *valueToPreserve );
+ if ( lastUsedIndex == 0 ) // page is now empty
+ { // remove it from bucket linked list and delete it.
+ ValueInternalLink *linkPreviousToLast = lastLink->previous_;
+ if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
+ {
+ mapAllocator()->releaseMapLink( lastLink );
+ linkPreviousToLast->next_ = 0;
+ lastLink = linkPreviousToLast;
+ }
+ }
+ else
+ {
+ Value dummy;
+ valueToPreserve->swap( dummy ); // restore deleted to default Value.
+ valueToPreserve->setItemUsed( false );
+ }
+ --itemCount_;
+}
+
+
+ValueInternalLink *&
+ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
+{
+ if ( bucketIndex == bucketsSize_ - 1 )
+ return tailLink_;
+ ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
+ if ( !previous )
+ previous = &buckets_[bucketIndex];
+ return previous;
+}
+
+
+Value &
+ValueInternalMap::setNewItem( const char *key,
+ bool isStatic,
+ ValueInternalLink *link,
+ BucketIndex index )
+{
+ char *duplicatedKey = valueAllocator()->makeMemberName( key );
+ ++itemCount_;
+ link->keys_[index] = duplicatedKey;
+ link->items_[index].setItemUsed();
+ link->items_[index].setMemberNameIsStatic( isStatic );
+ return link->items_[index]; // items already default constructed.
+}
+
+
+Value &
+ValueInternalMap::unsafeAdd( const char *key,
+ bool isStatic,
+ HashKey hashedKey )
+{
+ JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
+ ValueInternalLink *link = previousLink;
+ BucketIndex index;
+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( link->items_[index].isItemAvailable() )
+ break;
+ }
+ if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
+ {
+ ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
+ index = 0;
+ link->next_ = newLink;
+ previousLink = newLink;
+ link = newLink;
+ }
+ return setNewItem( key, isStatic, link, index );
+}
+
+
+ValueInternalMap::HashKey
+ValueInternalMap::hash( const char *key ) const
+{
+ HashKey hash = 0;
+ while ( *key )
+ hash += *key++ * 37;
+ return hash;
+}
+
+
+int
+ValueInternalMap::compare( const ValueInternalMap &other ) const
+{
+ int sizeDiff( itemCount_ - other.itemCount_ );
+ if ( sizeDiff != 0 )
+ return sizeDiff;
+ // Strict order guaranty is required. Compare all keys FIRST, then compare values.
+ IteratorState it;
+ IteratorState itEnd;
+ makeBeginIterator( it );
+ makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ if ( !other.find( key( it ) ) )
+ return 1;
+ }
+
+ // All keys are equals, let's compare values
+ makeBeginIterator( it );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ const Value *otherValue = other.find( key( it ) );
+ int valueDiff = value(it).compare( *otherValue );
+ if ( valueDiff != 0 )
+ return valueDiff;
+ }
+ return 0;
+}
+
+
+void
+ValueInternalMap::makeBeginIterator( IteratorState &it ) const
+{
+ it.map_ = const_cast<ValueInternalMap *>( this );
+ it.bucketIndex_ = 0;
+ it.itemIndex_ = 0;
+ it.link_ = buckets_;
+}
+
+
+void
+ValueInternalMap::makeEndIterator( IteratorState &it ) const
+{
+ it.map_ = const_cast<ValueInternalMap *>( this );
+ it.bucketIndex_ = bucketsSize_;
+ it.itemIndex_ = 0;
+ it.link_ = 0;
+}
+
+
+bool
+ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
+{
+ return x.map_ == other.map_
+ && x.bucketIndex_ == other.bucketIndex_
+ && x.link_ == other.link_
+ && x.itemIndex_ == other.itemIndex_;
+}
+
+
+void
+ValueInternalMap::incrementBucket( IteratorState &iterator )
+{
+ ++iterator.bucketIndex_;
+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
+ if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
+ iterator.link_ = 0;
+ else
+ iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
+ iterator.itemIndex_ = 0;
+}
+
+
+void
+ValueInternalMap::increment( IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
+ ++iterator.itemIndex_;
+ if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
+ {
+ JSON_ASSERT_MESSAGE( iterator.link_ != 0,
+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
+ iterator.link_ = iterator.link_->next_;
+ if ( iterator.link_ == 0 )
+ incrementBucket( iterator );
+ }
+ else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
+ {
+ incrementBucket( iterator );
+ }
+}
+
+
+void
+ValueInternalMap::decrement( IteratorState &iterator )
+{
+ if ( iterator.itemIndex_ == 0 )
+ {
+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
+ if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
+ {
+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
+ --(iterator.bucketIndex_);
+ }
+ iterator.link_ = iterator.link_->previous_;
+ iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
+ }
+}
+
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
+ return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+
+Value &
+ValueInternalMap::value( const IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ return iterator.link_->items_[iterator.itemIndex_];
+}
+
+
+int
+ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
+{
+ int offset = 0;
+ IteratorState it = x;
+ while ( !equals( it, y ) )
+ increment( it );
+ return offset;
+}
diff --git a/lib/jsoncpp/src/lib_json/json_reader.cpp b/lib/jsoncpp/src/lib_json/json_reader.cpp
new file mode 100644
index 000000000..e9d6b88d2
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/json_reader.cpp
@@ -0,0 +1,885 @@
+#include "../../include/json/reader.h"
+#include "../../include/json/value.h"
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+ : allowComments_( true )
+ , strictRoot_( false )
+{
+}
+
+
+Features
+Features::all()
+{
+ return Features();
+}
+
+
+Features
+Features::strictMode()
+{
+ Features features;
+ features.allowComments_ = false;
+ features.strictRoot_ = true;
+ return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+
+static inline bool
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
+{
+ return c == c1 || c == c2 || c == c3 || c == c4;
+}
+
+static inline bool
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
+{
+ return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
+}
+
+
+static bool
+containsNewLine( Reader::Location begin,
+ Reader::Location end )
+{
+ for ( ;begin < end; ++begin )
+ if ( *begin == '\n' || *begin == '\r' )
+ return true;
+ return false;
+}
+
+static std::string codePointToUTF8(unsigned int cp)
+{
+ std::string result;
+
+ // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+ if (cp <= 0x7f)
+ {
+ result.resize(1);
+ result[0] = static_cast<char>(cp);
+ }
+ else if (cp <= 0x7FF)
+ {
+ result.resize(2);
+ result[1] = static_cast<char>(0x80 | (0x3f & cp));
+ result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+ }
+ else if (cp <= 0xFFFF)
+ {
+ result.resize(3);
+ result[2] = static_cast<char>(0x80 | (0x3f & cp));
+ result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
+ result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+ }
+ else if (cp <= 0x10FFFF)
+ {
+ result.resize(4);
+ result[3] = static_cast<char>(0x80 | (0x3f & cp));
+ result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+ result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+ }
+
+ return result;
+}
+
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+ : features_( Features::all() )
+{
+}
+
+
+Reader::Reader( const Features &features )
+ : features_( features )
+{
+}
+
+
+bool
+Reader::parse( const std::string &document,
+ Value &root,
+ bool collectComments )
+{
+ document_ = document;
+ const char *begin = document_.c_str();
+ const char *end = begin + document_.length();
+ return parse( begin, end, root, collectComments );
+}
+
+
+bool
+Reader::parse( std::istream& sin,
+ Value &root,
+ bool collectComments )
+{
+ //std::istream_iterator<char> begin(sin);
+ //std::istream_iterator<char> end;
+ // Those would allow streamed input from a file, if parse() were a
+ // template function.
+
+ // Since std::string is reference-counted, this at least does not
+ // create an extra copy.
+ std::string doc;
+ std::getline(sin, doc, (char)EOF);
+ return parse( doc, root, collectComments );
+}
+
+bool
+Reader::parse( const char *beginDoc, const char *endDoc,
+ Value &root,
+ bool collectComments )
+{
+ if ( !features_.allowComments_ )
+ {
+ collectComments = false;
+ }
+
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = 0;
+ lastValue_ = 0;
+ commentsBefore_ = "";
+ errors_.clear();
+ while ( !nodes_.empty() )
+ nodes_.pop();
+ nodes_.push( &root );
+
+ bool successful = readValue();
+ Token token;
+ skipCommentTokens( token );
+ if ( collectComments_ && !commentsBefore_.empty() )
+ root.setComment( commentsBefore_, commentAfter );
+ if ( features_.strictRoot_ )
+ {
+ if ( !root.isArray() && !root.isObject() )
+ {
+ // Set error location to start of doc, ideally should be first token found in doc
+ token.type_ = tokenError;
+ token.start_ = beginDoc;
+ token.end_ = endDoc;
+ addError( "A valid JSON document must be either an array or an object value.",
+ token );
+ return false;
+ }
+ }
+ return successful;
+}
+
+
+bool
+Reader::readValue()
+{
+ Token token;
+ skipCommentTokens( token );
+ bool successful = true;
+
+ if ( collectComments_ && !commentsBefore_.empty() )
+ {
+ currentValue().setComment( commentsBefore_, commentBefore );
+ commentsBefore_ = "";
+ }
+
+
+ switch ( token.type_ )
+ {
+ case tokenObjectBegin:
+ successful = readObject( token );
+ break;
+ case tokenArrayBegin:
+ successful = readArray( token );
+ break;
+ case tokenNumber:
+ successful = decodeNumber( token );
+ break;
+ case tokenString:
+ successful = decodeString( token );
+ break;
+ case tokenTrue:
+ currentValue() = true;
+ break;
+ case tokenFalse:
+ currentValue() = false;
+ break;
+ case tokenNull:
+ currentValue() = Value();
+ break;
+ default:
+ return addError( "Syntax error: value, object or array expected.", token );
+ }
+
+ if ( collectComments_ )
+ {
+ lastValueEnd_ = current_;
+ lastValue_ = &currentValue();
+ }
+
+ return successful;
+}
+
+
+void
+Reader::skipCommentTokens( Token &token )
+{
+ if ( features_.allowComments_ )
+ {
+ do
+ {
+ readToken( token );
+ }
+ while ( token.type_ == tokenComment );
+ }
+ else
+ {
+ readToken( token );
+ }
+}
+
+
+bool
+Reader::expectToken( TokenType type, Token &token, const char *message )
+{
+ readToken( token );
+ if ( token.type_ != type )
+ return addError( message, token );
+ return true;
+}
+
+
+bool
+Reader::readToken( Token &token )
+{
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
+ bool ok = true;
+ switch ( c )
+ {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ token.type_ = tokenNumber;
+ readNumber();
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match( "rue", 3 );
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match( "alse", 4 );
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match( "ull", 3 );
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if ( !ok )
+ token.type_ = tokenError;
+ token.end_ = current_;
+ return true;
+}
+
+
+void
+Reader::skipSpaces()
+{
+ while ( current_ != end_ )
+ {
+ Char c = *current_;
+ if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
+ ++current_;
+ else
+ break;
+ }
+}
+
+
+bool
+Reader::match( Location pattern,
+ int patternLength )
+{
+ if ( end_ - current_ < patternLength )
+ return false;
+ int index = patternLength;
+ while ( index-- )
+ if ( current_[index] != pattern[index] )
+ return false;
+ current_ += patternLength;
+ return true;
+}
+
+
+bool
+Reader::readComment()
+{
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
+ bool successful = false;
+ if ( c == '*' )
+ successful = readCStyleComment();
+ else if ( c == '/' )
+ successful = readCppStyleComment();
+ if ( !successful )
+ return false;
+
+ if ( collectComments_ )
+ {
+ CommentPlacement placement = commentBefore;
+ if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
+ {
+ if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
+ placement = commentAfterOnSameLine;
+ }
+
+ addComment( commentBegin, current_, placement );
+ }
+ return true;
+}
+
+
+void
+Reader::addComment( Location begin,
+ Location end,
+ CommentPlacement placement )
+{
+ assert( collectComments_ );
+ if ( placement == commentAfterOnSameLine )
+ {
+ assert( lastValue_ != 0 );
+ lastValue_->setComment( std::string( begin, end ), placement );
+ }
+ else
+ {
+ if ( !commentsBefore_.empty() )
+ commentsBefore_ += "\n";
+ commentsBefore_ += std::string( begin, end );
+ }
+}
+
+
+bool
+Reader::readCStyleComment()
+{
+ while ( current_ != end_ )
+ {
+ Char c = getNextChar();
+ if ( c == '*' && *current_ == '/' )
+ break;
+ }
+ return getNextChar() == '/';
+}
+
+
+bool
+Reader::readCppStyleComment()
+{
+ while ( current_ != end_ )
+ {
+ Char c = getNextChar();
+ if ( c == '\r' || c == '\n' )
+ break;
+ }
+ return true;
+}
+
+
+void
+Reader::readNumber()
+{
+ while ( current_ != end_ )
+ {
+ if ( !(*current_ >= '0' && *current_ <= '9') &&
+ !in( *current_, '.', 'e', 'E', '+', '-' ) )
+ break;
+ ++current_;
+ }
+}
+
+bool
+Reader::readString()
+{
+ Char c = 0;
+ while ( current_ != end_ )
+ {
+ c = getNextChar();
+ if ( c == '\\' )
+ getNextChar();
+ else if ( c == '"' )
+ break;
+ }
+ return c == '"';
+}
+
+
+bool
+Reader::readObject( Token &tokenStart )
+{
+ Token tokenName;
+ std::string name;
+ currentValue() = Value( objectValue );
+ while ( readToken( tokenName ) )
+ {
+ bool initialTokenOk = true;
+ while ( tokenName.type_ == tokenComment && initialTokenOk )
+ initialTokenOk = readToken( tokenName );
+ if ( !initialTokenOk )
+ break;
+ if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
+ return true;
+ if ( tokenName.type_ != tokenString )
+ break;
+
+ name = "";
+ if ( !decodeString( tokenName, name ) )
+ return recoverFromError( tokenObjectEnd );
+
+ Token colon;
+ if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
+ {
+ return addErrorAndRecover( "Missing ':' after object member name",
+ colon,
+ tokenObjectEnd );
+ }
+ Value &value = currentValue()[ name ];
+ nodes_.push( &value );
+ bool ok = readValue();
+ nodes_.pop();
+ if ( !ok ) // error already set
+ return recoverFromError( tokenObjectEnd );
+
+ Token comma;
+ if ( !readToken( comma )
+ || ( comma.type_ != tokenObjectEnd &&
+ comma.type_ != tokenArraySeparator &&
+ comma.type_ != tokenComment ) )
+ {
+ return addErrorAndRecover( "Missing ',' or '}' in object declaration",
+ comma,
+ tokenObjectEnd );
+ }
+ bool finalizeTokenOk = true;
+ while ( comma.type_ == tokenComment &&
+ finalizeTokenOk )
+ finalizeTokenOk = readToken( comma );
+ if ( comma.type_ == tokenObjectEnd )
+ return true;
+ }
+ return addErrorAndRecover( "Missing '}' or object member name",
+ tokenName,
+ tokenObjectEnd );
+}
+
+
+bool
+Reader::readArray( Token &tokenStart )
+{
+ currentValue() = Value( arrayValue );
+ skipSpaces();
+ if ( *current_ == ']' ) // empty array
+ {
+ Token endArray;
+ readToken( endArray );
+ return true;
+ }
+ int index = 0;
+ while ( true )
+ {
+ Value &value = currentValue()[ index++ ];
+ nodes_.push( &value );
+ bool ok = readValue();
+ nodes_.pop();
+ if ( !ok ) // error already set
+ return recoverFromError( tokenArrayEnd );
+
+ Token token;
+ // Accept Comment after last item in the array.
+ ok = readToken( token );
+ while ( token.type_ == tokenComment && ok )
+ {
+ ok = readToken( token );
+ }
+ bool badTokenType = ( token.type_ == tokenArraySeparator &&
+ token.type_ == tokenArrayEnd );
+ if ( !ok || badTokenType )
+ {
+ return addErrorAndRecover( "Missing ',' or ']' in array declaration",
+ token,
+ tokenArrayEnd );
+ }
+ if ( token.type_ == tokenArrayEnd )
+ break;
+ }
+ return true;
+}
+
+
+bool
+Reader::decodeNumber( Token &token )
+{
+ bool isDouble = false;
+ for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
+ {
+ isDouble = isDouble
+ || in( *inspect, '.', 'e', 'E', '+' )
+ || ( *inspect == '-' && inspect != token.start_ );
+ }
+ if ( isDouble )
+ return decodeDouble( token );
+ Location current = token.start_;
+ bool isNegative = *current == '-';
+ if ( isNegative )
+ ++current;
+ Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt)
+ : Value::maxUInt) / 10;
+ Value::UInt value = 0;
+ while ( current < token.end_ )
+ {
+ Char c = *current++;
+ if ( c < '0' || c > '9' )
+ return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+ if ( value >= threshold )
+ return decodeDouble( token );
+ value = value * 10 + Value::UInt(c - '0');
+ }
+ if ( isNegative )
+ currentValue() = -Value::Int( value );
+ else if ( value <= Value::UInt(Value::maxInt) )
+ currentValue() = Value::Int( value );
+ else
+ currentValue() = value;
+ return true;
+}
+
+
+bool
+Reader::decodeDouble( Token &token )
+{
+ double value = 0;
+ const int bufferSize = 32;
+ int count;
+ int length = int(token.end_ - token.start_);
+ if ( length <= bufferSize )
+ {
+ Char buffer[bufferSize];
+ memcpy( buffer, token.start_, length );
+ buffer[length] = 0;
+ count = sscanf( buffer, "%lf", &value );
+ }
+ else
+ {
+ std::string buffer( token.start_, token.end_ );
+ count = sscanf( buffer.c_str(), "%lf", &value );
+ }
+
+ if ( count != 1 )
+ return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+ currentValue() = value;
+ return true;
+}
+
+
+bool
+Reader::decodeString( Token &token )
+{
+ std::string decoded;
+ if ( !decodeString( token, decoded ) )
+ return false;
+ currentValue() = decoded;
+ return true;
+}
+
+
+bool
+Reader::decodeString( Token &token, std::string &decoded )
+{
+ decoded.reserve( token.end_ - token.start_ - 2 );
+ Location current = token.start_ + 1; // skip '"'
+ Location end = token.end_ - 1; // do not include '"'
+ while ( current != end )
+ {
+ Char c = *current++;
+ if ( c == '"' )
+ break;
+ else if ( c == '\\' )
+ {
+ if ( current == end )
+ return addError( "Empty escape sequence in string", token, current );
+ Char escape = *current++;
+ switch ( escape )
+ {
+ case '"': decoded += '"'; break;
+ case '/': decoded += '/'; break;
+ case '\\': decoded += '\\'; break;
+ case 'b': decoded += '\b'; break;
+ case 'f': decoded += '\f'; break;
+ case 'n': decoded += '\n'; break;
+ case 'r': decoded += '\r'; break;
+ case 't': decoded += '\t'; break;
+ case 'u':
+ {
+ unsigned int unicode;
+ if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
+ return false;
+ decoded += codePointToUTF8(unicode);
+ }
+ break;
+ default:
+ return addError( "Bad escape sequence in string", token, current );
+ }
+ }
+ else
+ {
+ decoded += c;
+ }
+ }
+ return true;
+}
+
+bool
+Reader::decodeUnicodeCodePoint( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode )
+{
+
+ if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
+ return false;
+ if (unicode >= 0xD800 && unicode <= 0xDBFF)
+ {
+ // surrogate pairs
+ if (end - current < 6)
+ return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
+ unsigned int surrogatePair;
+ if (*(current++) == '\\' && *(current++)== 'u')
+ {
+ if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
+ {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ }
+ else
+ return false;
+ }
+ else
+ return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
+ }
+ return true;
+}
+
+bool
+Reader::decodeUnicodeEscapeSequence( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode )
+{
+ if ( end - current < 4 )
+ return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
+ unicode = 0;
+ for ( int index =0; index < 4; ++index )
+ {
+ Char c = *current++;
+ unicode *= 16;
+ if ( c >= '0' && c <= '9' )
+ unicode += c - '0';
+ else if ( c >= 'a' && c <= 'f' )
+ unicode += c - 'a' + 10;
+ else if ( c >= 'A' && c <= 'F' )
+ unicode += c - 'A' + 10;
+ else
+ return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
+ }
+ return true;
+}
+
+
+bool
+Reader::addError( const std::string &message,
+ Token &token,
+ Location extra )
+{
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = extra;
+ errors_.push_back( info );
+ return false;
+}
+
+
+bool
+Reader::recoverFromError( TokenType skipUntilToken )
+{
+ int errorCount = int(errors_.size());
+ Token skip;
+ while ( true )
+ {
+ if ( !readToken(skip) )
+ errors_.resize( errorCount ); // discard errors caused by recovery
+ if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
+ break;
+ }
+ errors_.resize( errorCount );
+ return false;
+}
+
+
+bool
+Reader::addErrorAndRecover( const std::string &message,
+ Token &token,
+ TokenType skipUntilToken )
+{
+ addError( message, token );
+ return recoverFromError( skipUntilToken );
+}
+
+
+Value &
+Reader::currentValue()
+{
+ return *(nodes_.top());
+}
+
+
+Reader::Char
+Reader::getNextChar()
+{
+ if ( current_ == end_ )
+ return 0;
+ return *current_++;
+}
+
+
+void
+Reader::getLocationLineAndColumn( Location location,
+ int &line,
+ int &column ) const
+{
+ Location current = begin_;
+ Location lastLineStart = current;
+ line = 0;
+ while ( current < location && current != end_ )
+ {
+ Char c = *current++;
+ if ( c == '\r' )
+ {
+ if ( *current == '\n' )
+ ++current;
+ lastLineStart = current;
+ ++line;
+ }
+ else if ( c == '\n' )
+ {
+ lastLineStart = current;
+ ++line;
+ }
+ }
+ // column & line start at 1
+ column = int(location - lastLineStart) + 1;
+ ++line;
+}
+
+
+std::string
+Reader::getLocationLineAndColumn( Location location ) const
+{
+ int line, column;
+ getLocationLineAndColumn( location, line, column );
+ char buffer[18+16+16+1];
+ sprintf( buffer, "Line %d, Column %d", line, column );
+ return buffer;
+}
+
+
+std::string
+Reader::getFormatedErrorMessages() const
+{
+ std::string formattedMessage;
+ for ( Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError )
+ {
+ const ErrorInfo &error = *itError;
+ formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
+ formattedMessage += " " + error.message_ + "\n";
+ if ( error.extra_ )
+ formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
+ }
+ return formattedMessage;
+}
+
+#define JSON_ASSERT( condition ) assert( condition );
+std::istream& operator>>( std::istream &sin, Value &root )
+{
+ Json::Reader reader;
+ bool ok = reader.parse(sin, root, true);
+ JSON_ASSERT( ok );
+ //if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
+ return sin;
+}
+
+
+} // namespace Json
diff --git a/lib/jsoncpp/src/lib_json/json_value.cpp b/lib/jsoncpp/src/lib_json/json_value.cpp
new file mode 100644
index 000000000..ea033c400
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/json_value.cpp
@@ -0,0 +1,1727 @@
+#include <iostream>
+#include "../../include/json/json.h"
+#include "../../include/json/writer.h"
+#include <utility>
+#include <stdexcept>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+# include <cpptl/conststring.h>
+#endif
+#include <cstddef> // size_t
+#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+# include "json_batchallocator.h"
+#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+#define JSON_ASSERT_UNREACHABLE assert( false )
+#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
+#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
+
+namespace Json {
+
+const Value Value::null;
+const Int Value::minInt = Int( ~(UInt(-1)/2) );
+const Int Value::maxInt = Int( UInt(-1)/2 );
+const UInt Value::maxUInt = UInt(-1);
+
+// A "safe" implementation of strdup. Allow null pointer to be passed.
+// Also avoid warning on msvc80.
+//
+//inline char *safeStringDup( const char *czstring )
+//{
+// if ( czstring )
+// {
+// const size_t length = (unsigned int)( strlen(czstring) + 1 );
+// char *newString = static_cast<char *>( malloc( length ) );
+// memcpy( newString, czstring, length );
+// return newString;
+// }
+// return 0;
+//}
+//
+//inline char *safeStringDup( const std::string &str )
+//{
+// if ( !str.empty() )
+// {
+// const size_t length = str.length();
+// char *newString = static_cast<char *>( malloc( length + 1 ) );
+// memcpy( newString, str.c_str(), length );
+// newString[length] = 0;
+// return newString;
+// }
+// return 0;
+//}
+
+ValueAllocator::~ValueAllocator()
+{
+}
+
+class DefaultValueAllocator : public ValueAllocator
+{
+public:
+ virtual ~DefaultValueAllocator()
+ {
+ }
+
+ virtual char *makeMemberName( const char *memberName )
+ {
+ return duplicateStringValue( memberName );
+ }
+
+ virtual void releaseMemberName( char *memberName )
+ {
+ releaseStringValue( memberName );
+ }
+
+ virtual char *duplicateStringValue( const char *value,
+ unsigned int length = unknown )
+ {
+ //@todo invesgate this old optimization
+ //if ( !value || value[0] == 0 )
+ // return 0;
+
+ if ( length == unknown )
+ length = (unsigned int)strlen(value);
+ char *newString = static_cast<char *>( malloc( length + 1 ) );
+ memcpy( newString, value, length );
+ newString[length] = 0;
+ return newString;
+ }
+
+ virtual void releaseStringValue( char *value )
+ {
+ if ( value )
+ free( value );
+ }
+};
+
+static ValueAllocator *&valueAllocator()
+{
+ static DefaultValueAllocator defaultAllocator;
+ static ValueAllocator *valueAllocator = &defaultAllocator;
+ return valueAllocator;
+}
+
+static struct DummyValueAllocatorInitializer {
+ DummyValueAllocatorInitializer()
+ {
+ valueAllocator(); // ensure valueAllocator() statics are initialized before main().
+ }
+} dummyValueAllocatorInitializer;
+
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+# include "json_internalarray.inl"
+# include "json_internalmap.inl"
+#endif // JSON_VALUE_USE_INTERNAL_MAP
+
+# include "json_valueiterator.inl"
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+Value::CommentInfo::CommentInfo()
+ : comment_( 0 )
+{
+}
+
+Value::CommentInfo::~CommentInfo()
+{
+ if ( comment_ )
+ valueAllocator()->releaseStringValue( comment_ );
+}
+
+
+void
+Value::CommentInfo::setComment( const char *text )
+{
+ if ( comment_ )
+ valueAllocator()->releaseStringValue( comment_ );
+ JSON_ASSERT( text );
+ //JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
+ JSON_ASSERT( text[0]=='\0' || text[0]=='/' );
+ // It seems that /**/ style comments are acceptable as well.
+ comment_ = valueAllocator()->duplicateStringValue( text );
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+// Notes: index_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString( int index )
+ : cstr_( 0 )
+ , index_( index )
+{
+}
+
+Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
+ : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
+ : cstr )
+ , index_( allocate )
+{
+}
+
+Value::CZString::CZString( const CZString &other )
+: cstr_( other.index_ != noDuplication && other.cstr_ != 0
+ ? valueAllocator()->makeMemberName( other.cstr_ )
+ : other.cstr_ )
+ , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
+ : other.index_ )
+{
+}
+
+Value::CZString::~CZString()
+{
+ if ( cstr_ && index_ == duplicate )
+ valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
+}
+
+void
+Value::CZString::swap( CZString &other )
+{
+ std::swap( cstr_, other.cstr_ );
+ std::swap( index_, other.index_ );
+}
+
+Value::CZString &
+Value::CZString::operator =( const CZString &other )
+{
+ CZString temp( other );
+ swap( temp );
+ return *this;
+}
+
+bool
+Value::CZString::operator<( const CZString &other ) const
+{
+ if ( cstr_ )
+ return strcmp( cstr_, other.cstr_ ) < 0;
+ return index_ < other.index_;
+}
+
+bool
+Value::CZString::operator==( const CZString &other ) const
+{
+ if ( cstr_ )
+ return strcmp( cstr_, other.cstr_ ) == 0;
+ return index_ == other.index_;
+}
+
+
+int
+Value::CZString::index() const
+{
+ return index_;
+}
+
+
+const char *
+Value::CZString::c_str() const
+{
+ return cstr_;
+}
+
+bool
+Value::CZString::isStaticString() const
+{
+ return index_ == noDuplication;
+}
+
+#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value( ValueType type )
+ : type_( type )
+ , allocated_( 0 )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ switch ( type )
+ {
+ case nullValue:
+ break;
+ case intValue:
+ case uintValue:
+ value_.int_ = 0;
+ break;
+ case realValue:
+ value_.real_ = 0.0;
+ break;
+ case stringValue:
+ value_.string_ = 0;
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues();
+ break;
+#else
+ case arrayValue:
+ value_.array_ = arrayAllocator()->newArray();
+ break;
+ case objectValue:
+ value_.map_ = mapAllocator()->newMap();
+ break;
+#endif
+ case booleanValue:
+ value_.bool_ = false;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+
+Value::Value( Int value )
+ : type_( intValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.int_ = value;
+}
+
+
+Value::Value( UInt value )
+ : type_( uintValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.uint_ = value;
+}
+
+Value::Value( double value )
+ : type_( realValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.real_ = value;
+}
+
+Value::Value( const char *value )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( value );
+}
+
+
+Value::Value( const char *beginValue,
+ const char *endValue )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( beginValue,
+ UInt(endValue - beginValue) );
+}
+
+
+Value::Value( const std::string &value )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
+ (unsigned int)value.length() );
+
+}
+
+Value::Value( const StaticString &value )
+ : type_( stringValue )
+ , allocated_( false )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = const_cast<char *>( value.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value::Value( const CppTL::ConstString &value )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
+}
+# endif
+
+Value::Value( bool value )
+ : type_( booleanValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.bool_ = value;
+}
+
+
+Value::Value( const Value &other )
+ : type_( other.type_ )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ value_ = other.value_;
+ break;
+ case stringValue:
+ if ( other.value_.string_ )
+ {
+ value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
+ allocated_ = true;
+ }
+ else
+ value_.string_ = 0;
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues( *other.value_.map_ );
+ break;
+#else
+ case arrayValue:
+ value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
+ break;
+ case objectValue:
+ value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
+ break;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ if ( other.comments_ )
+ {
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
+ {
+ const CommentInfo &otherComment = other.comments_[comment];
+ if ( otherComment.comment_ )
+ comments_[comment].setComment( otherComment.comment_ );
+ }
+ }
+}
+
+
+Value::~Value()
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if ( allocated_ )
+ valueAllocator()->releaseStringValue( value_.string_ );
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ delete value_.map_;
+ break;
+#else
+ case arrayValue:
+ arrayAllocator()->destructArray( value_.array_ );
+ break;
+ case objectValue:
+ mapAllocator()->destructMap( value_.map_ );
+ break;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+
+ if ( comments_ )
+ delete[] comments_;
+}
+
+Value &
+Value::operator=( const Value &other )
+{
+ Value temp( other );
+ swap( temp );
+ return *this;
+}
+
+void
+Value::swap( Value &other )
+{
+ ValueType temp = type_;
+ type_ = other.type_;
+ other.type_ = temp;
+ std::swap( value_, other.value_ );
+ int temp2 = allocated_;
+ allocated_ = other.allocated_;
+ other.allocated_ = temp2;
+}
+
+ValueType
+Value::type() const
+{
+ return type_;
+}
+
+
+int
+Value::compare( const Value &other )
+{
+ /*
+ int typeDelta = other.type_ - type_;
+ switch ( type_ )
+ {
+ case nullValue:
+
+ return other.type_ == type_;
+ case intValue:
+ if ( other.type_.isNumeric()
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue,
+ break;
+ case arrayValue:
+ delete value_.array_;
+ break;
+ case objectValue:
+ delete value_.map_;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ */
+ return 0; // unreachable
+}
+
+bool
+Value::operator <( const Value &other ) const
+{
+ int typeDelta = type_ - other.type_;
+ if ( typeDelta )
+ return typeDelta < 0 ? true : false;
+ switch ( type_ )
+ {
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ < other.value_.int_;
+ case uintValue:
+ return value_.uint_ < other.value_.uint_;
+ case realValue:
+ return value_.real_ < other.value_.real_;
+ case booleanValue:
+ return value_.bool_ < other.value_.bool_;
+ case stringValue:
+ return ( value_.string_ == 0 && other.value_.string_ )
+ || ( other.value_.string_
+ && value_.string_
+ && strcmp( value_.string_, other.value_.string_ ) < 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ {
+ int delta = int( value_.map_->size() - other.value_.map_->size() );
+ if ( delta )
+ return delta < 0;
+ return (*value_.map_) < (*other.value_.map_);
+ }
+#else
+ case arrayValue:
+ return value_.array_->compare( *(other.value_.array_) ) < 0;
+ case objectValue:
+ return value_.map_->compare( *(other.value_.map_) ) < 0;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable
+}
+
+bool
+Value::operator <=( const Value &other ) const
+{
+ return !(other > *this);
+}
+
+bool
+Value::operator >=( const Value &other ) const
+{
+ return !(*this < other);
+}
+
+bool
+Value::operator >( const Value &other ) const
+{
+ return other < *this;
+}
+
+bool
+Value::operator ==( const Value &other ) const
+{
+ //if ( type_ != other.type_ )
+ // GCC 2.95.3 says:
+ // attempt to take address of bit-field structure member `Json::Value::type_'
+ // Beats me, but a temp solves the problem.
+ int temp = other.type_;
+ if ( type_ != temp )
+ return false;
+ switch ( type_ )
+ {
+ case nullValue:
+ return true;
+ case intValue:
+ return value_.int_ == other.value_.int_;
+ case uintValue:
+ return value_.uint_ == other.value_.uint_;
+ case realValue:
+ return value_.real_ == other.value_.real_;
+ case booleanValue:
+ return value_.bool_ == other.value_.bool_;
+ case stringValue:
+ return ( value_.string_ == other.value_.string_ )
+ || ( other.value_.string_
+ && value_.string_
+ && strcmp( value_.string_, other.value_.string_ ) == 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() == other.value_.map_->size()
+ && (*value_.map_) == (*other.value_.map_);
+#else
+ case arrayValue:
+ return value_.array_->compare( *(other.value_.array_) ) == 0;
+ case objectValue:
+ return value_.map_->compare( *(other.value_.map_) ) == 0;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable
+}
+
+bool
+Value::operator !=( const Value &other ) const
+{
+ return !( *this == other );
+}
+
+const char *
+Value::asCString() const
+{
+ JSON_ASSERT( type_ == stringValue );
+ return value_.string_;
+}
+
+
+std::string
+Value::asString() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return "";
+ case stringValue:
+ return value_.string_ ? value_.string_ : "";
+ case booleanValue:
+ return value_.bool_ ? "true" : "false";
+ case intValue:
+ case uintValue:
+ case realValue:
+ case arrayValue:
+ case objectValue:
+ //JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
+ JSON_ASSERT( false );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return ""; // unreachable
+}
+
+# ifdef JSON_USE_CPPTL
+CppTL::ConstString
+Value::asConstString() const
+{
+ return CppTL::ConstString( asString().c_str() );
+}
+# endif
+
+Value::Int
+Value::asInt() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0;
+ case intValue:
+ return value_.int_;
+ case uintValue:
+ //JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
+ JSON_ASSERT( value_.uint_ < (unsigned)maxInt );
+ return value_.uint_;
+ case realValue:
+ //JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
+ JSON_ASSERT( value_.real_ >= minInt && value_.real_ <= maxInt );
+ return Int( value_.real_ );
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ //JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
+ JSON_ASSERT( false );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+Value::UInt
+Value::asUInt() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0;
+ case intValue:
+ //JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
+ JSON_ASSERT( value_.int_ >= 0 );
+ return value_.int_;
+ case uintValue:
+ return value_.uint_;
+ case realValue:
+ //JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" );
+ JSON_ASSERT( value_.real_ >= 0 && value_.real_ <= maxUInt );
+ return UInt( value_.real_ );
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ //JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
+ JSON_ASSERT( false );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+double
+Value::asDouble() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0.0;
+ case intValue:
+ return value_.int_;
+ case uintValue:
+ return value_.uint_;
+ case realValue:
+ return value_.real_;
+ case booleanValue:
+ return value_.bool_ ? 1.0 : 0.0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ //JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
+ JSON_ASSERT( false );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+bool
+Value::asBool() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return false;
+ case intValue:
+ case uintValue:
+ return value_.int_ != 0;
+ case realValue:
+ return value_.real_ != 0.0;
+ case booleanValue:
+ return value_.bool_;
+ case stringValue:
+ return value_.string_ && value_.string_[0] != 0;
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() != 0;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable;
+}
+
+
+bool
+Value::isConvertibleTo( ValueType other ) const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return true;
+ case intValue:
+ return ( other == nullValue && value_.int_ == 0 )
+ || other == intValue
+ || ( other == uintValue && value_.int_ >= 0 )
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case uintValue:
+ return ( other == nullValue && value_.uint_ == 0 )
+ || ( other == intValue && value_.uint_ <= (unsigned)maxInt )
+ || other == uintValue
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case realValue:
+ return ( other == nullValue && value_.real_ == 0.0 )
+ || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt )
+ || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt )
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case booleanValue:
+ return ( other == nullValue && value_.bool_ == false )
+ || other == intValue
+ || other == uintValue
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case stringValue:
+ return other == stringValue
+ || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) );
+ case arrayValue:
+ return other == arrayValue
+ || ( other == nullValue && value_.map_->size() == 0 );
+ case objectValue:
+ return other == objectValue
+ || ( other == nullValue && value_.map_->size() == 0 );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable;
+}
+
+
+/// Number of values in array or object
+Value::UInt
+Value::size() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ case stringValue:
+ return 0;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue: // size of the array is highest index + 1
+ if ( !value_.map_->empty() )
+ {
+ ObjectValues::const_iterator itLast = value_.map_->end();
+ --itLast;
+ return (*itLast).first.index()+1;
+ }
+ return 0;
+ case objectValue:
+ return Int( value_.map_->size() );
+#else
+ case arrayValue:
+ return Int( value_.array_->size() );
+ case objectValue:
+ return Int( value_.map_->size() );
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+
+bool
+Value::empty() const
+{
+ if ( isNull() || isArray() || isObject() )
+ return size() == 0u;
+ else
+ return false;
+}
+
+
+bool
+Value::operator!() const
+{
+ return isNull();
+}
+
+
+void
+Value::clear()
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
+
+ switch ( type_ )
+ {
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_->clear();
+ break;
+#else
+ case arrayValue:
+ value_.array_->clear();
+ break;
+ case objectValue:
+ value_.map_->clear();
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+void
+Value::resize( UInt newSize )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
+ if ( type_ == nullValue )
+ *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ UInt oldSize = size();
+ if ( newSize == 0 )
+ clear();
+ else if ( newSize > oldSize )
+ (*this)[ newSize - 1 ];
+ else
+ {
+ for ( UInt index = newSize; index < oldSize; ++index )
+ value_.map_->erase( index );
+ assert( size() == newSize );
+ }
+#else
+ value_.array_->resize( newSize );
+#endif
+}
+
+
+Value &
+Value::operator[]( UInt index )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
+ if ( type_ == nullValue )
+ *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString key( index );
+ ObjectValues::iterator it = value_.map_->lower_bound( key );
+ if ( it != value_.map_->end() && (*it).first == key )
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue( key, null );
+ it = value_.map_->insert( it, defaultValue );
+ return (*it).second;
+#else
+ return value_.array_->resolveReference( index );
+#endif
+}
+
+
+const Value &
+Value::operator[]( UInt index ) const
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
+ if ( type_ == nullValue )
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString key( index );
+ ObjectValues::const_iterator it = value_.map_->find( key );
+ if ( it == value_.map_->end() )
+ return null;
+ return (*it).second;
+#else
+ Value *value = value_.array_->find( index );
+ return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const char *key )
+{
+ return resolveReference( key, false );
+}
+
+
+Value &
+Value::resolveReference( const char *key,
+ bool isStatic )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ *this = Value( objectValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey( key, isStatic ? CZString::noDuplication
+ : CZString::duplicateOnCopy );
+ ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
+ if ( it != value_.map_->end() && (*it).first == actualKey )
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue( actualKey, null );
+ it = value_.map_->insert( it, defaultValue );
+ Value &value = (*it).second;
+ return value;
+#else
+ return value_.map_->resolveReference( key, isStatic );
+#endif
+}
+
+
+Value
+Value::get( UInt index,
+ const Value &defaultValue ) const
+{
+ const Value *value = &((*this)[index]);
+ return value == &null ? defaultValue : *value;
+}
+
+
+bool
+Value::isValidIndex( UInt index ) const
+{
+ return index < size();
+}
+
+
+
+const Value &
+Value::operator[]( const char *key ) const
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey( key, CZString::noDuplication );
+ ObjectValues::const_iterator it = value_.map_->find( actualKey );
+ if ( it == value_.map_->end() )
+ return null;
+ return (*it).second;
+#else
+ const Value *value = value_.map_->find( key );
+ return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const std::string &key )
+{
+ return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const std::string &key ) const
+{
+ return (*this)[ key.c_str() ];
+}
+
+Value &
+Value::operator[]( const StaticString &key )
+{
+ return resolveReference( key, true );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value &
+Value::operator[]( const CppTL::ConstString &key )
+{
+ return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const CppTL::ConstString &key ) const
+{
+ return (*this)[ key.c_str() ];
+}
+# endif
+
+
+Value &
+Value::append( const Value &value )
+{
+ return (*this)[size()] = value;
+}
+
+
+Value
+Value::get( const char *key,
+ const Value &defaultValue ) const
+{
+ const Value *value = &((*this)[key]);
+ return value == &null ? defaultValue : *value;
+}
+
+
+Value
+Value::get( const std::string &key,
+ const Value &defaultValue ) const
+{
+ return get( key.c_str(), defaultValue );
+}
+
+Value
+Value::removeMember( const char* key )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey( key, CZString::noDuplication );
+ ObjectValues::iterator it = value_.map_->find( actualKey );
+ if ( it == value_.map_->end() )
+ return null;
+ Value old(it->second);
+ value_.map_->erase(it);
+ return old;
+#else
+ Value *value = value_.map_->find( key );
+ if (value){
+ Value old(*value);
+ value_.map_.remove( key );
+ return old;
+ } else {
+ return null;
+ }
+#endif
+}
+
+Value
+Value::removeMember( const std::string &key )
+{
+ return removeMember( key.c_str() );
+}
+
+# ifdef JSON_USE_CPPTL
+Value
+Value::get( const CppTL::ConstString &key,
+ const Value &defaultValue ) const
+{
+ return get( key.c_str(), defaultValue );
+}
+# endif
+
+bool
+Value::isMember( const char *key ) const
+{
+ const Value *value = &((*this)[key]);
+ return value != &null;
+}
+
+
+bool
+Value::isMember( const std::string &key ) const
+{
+ return isMember( key.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+bool
+Value::isMember( const CppTL::ConstString &key ) const
+{
+ return isMember( key.c_str() );
+}
+#endif
+
+Value::Members
+Value::getMemberNames() const
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ return Value::Members();
+ Members members;
+ members.reserve( value_.map_->size() );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ ObjectValues::const_iterator it = value_.map_->begin();
+ ObjectValues::const_iterator itEnd = value_.map_->end();
+ for ( ; it != itEnd; ++it )
+ members.push_back( std::string( (*it).first.c_str() ) );
+#else
+ ValueInternalMap::IteratorState it;
+ ValueInternalMap::IteratorState itEnd;
+ value_.map_->makeBeginIterator( it );
+ value_.map_->makeEndIterator( itEnd );
+ for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
+ members.push_back( std::string( ValueInternalMap::key( it ) ) );
+#endif
+ return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+//EnumMemberNames
+//Value::enumMemberNames() const
+//{
+// if ( type_ == objectValue )
+// {
+// return CppTL::Enum::any( CppTL::Enum::transform(
+// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+// MemberNamesTransform() ) );
+// }
+// return EnumMemberNames();
+//}
+//
+//
+//EnumValues
+//Value::enumValues() const
+//{
+// if ( type_ == objectValue || type_ == arrayValue )
+// return CppTL::Enum::anyValues( *(value_.map_),
+// CppTL::Type<const Value &>() );
+// return EnumValues();
+//}
+//
+//# endif
+
+
+bool
+Value::isNull() const
+{
+ return type_ == nullValue;
+}
+
+
+bool
+Value::isBool() const
+{
+ return type_ == booleanValue;
+}
+
+
+bool
+Value::isInt() const
+{
+ return type_ == intValue;
+}
+
+
+bool
+Value::isUInt() const
+{
+ return type_ == uintValue;
+}
+
+
+bool
+Value::isIntegral() const
+{
+ return type_ == intValue
+ || type_ == uintValue
+ || type_ == booleanValue;
+}
+
+
+bool
+Value::isDouble() const
+{
+ return type_ == realValue;
+}
+
+
+bool
+Value::isNumeric() const
+{
+ return isIntegral() || isDouble();
+}
+
+
+bool
+Value::isString() const
+{
+ return type_ == stringValue;
+}
+
+
+bool
+Value::isArray() const
+{
+ return type_ == nullValue || type_ == arrayValue;
+}
+
+
+bool
+Value::isObject() const
+{
+ return type_ == nullValue || type_ == objectValue;
+}
+
+
+void
+Value::setComment( const char *comment,
+ CommentPlacement placement )
+{
+ if ( !comments_ )
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ comments_[placement].setComment( comment );
+}
+
+
+void
+Value::setComment( const std::string &comment,
+ CommentPlacement placement )
+{
+ setComment( comment.c_str(), placement );
+}
+
+
+bool
+Value::hasComment( CommentPlacement placement ) const
+{
+ return comments_ != 0 && comments_[placement].comment_ != 0;
+}
+
+std::string
+Value::getComment( CommentPlacement placement ) const
+{
+ if ( hasComment(placement) )
+ return comments_[placement].comment_;
+ return "";
+}
+
+
+std::string
+Value::toStyledString() const
+{
+ StyledWriter writer;
+ return writer.write( *this );
+}
+
+
+Value::const_iterator
+Value::begin() const
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeBeginIterator( it );
+ return const_iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeBeginIterator( it );
+ return const_iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return const_iterator( value_.map_->begin() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+Value::const_iterator
+Value::end() const
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeEndIterator( it );
+ return const_iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeEndIterator( it );
+ return const_iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return const_iterator( value_.map_->end() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+
+Value::iterator
+Value::begin()
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeBeginIterator( it );
+ return iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeBeginIterator( it );
+ return iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return iterator( value_.map_->begin() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return iterator();
+}
+
+Value::iterator
+Value::end()
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeEndIterator( it );
+ return iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeEndIterator( it );
+ return iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return iterator( value_.map_->end() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return iterator();
+}
+
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument()
+ : kind_( kindNone )
+{
+}
+
+
+PathArgument::PathArgument( Value::UInt index )
+ : index_( index )
+ , kind_( kindIndex )
+{
+}
+
+
+PathArgument::PathArgument( const char *key )
+ : key_( key )
+ , kind_( kindKey )
+{
+}
+
+
+PathArgument::PathArgument( const std::string &key )
+ : key_( key.c_str() )
+ , kind_( kindKey )
+{
+}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path( const std::string &path,
+ const PathArgument &a1,
+ const PathArgument &a2,
+ const PathArgument &a3,
+ const PathArgument &a4,
+ const PathArgument &a5 )
+{
+ InArgs in;
+ in.push_back( &a1 );
+ in.push_back( &a2 );
+ in.push_back( &a3 );
+ in.push_back( &a4 );
+ in.push_back( &a5 );
+ makePath( path, in );
+}
+
+
+void
+Path::makePath( const std::string &path,
+ const InArgs &in )
+{
+ const char *current = path.c_str();
+ const char *end = current + path.length();
+ InArgs::const_iterator itInArg = in.begin();
+ while ( current != end )
+ {
+ if ( *current == '[' )
+ {
+ ++current;
+ if ( *current == '%' )
+ addPathInArg( path, in, itInArg, PathArgument::kindIndex );
+ else
+ {
+ Value::UInt index = 0;
+ for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
+ index = index * 10 + Value::UInt(*current - '0');
+ args_.push_back( index );
+ }
+ if ( current == end || *current++ != ']' )
+ invalidPath( path, int(current - path.c_str()) );
+ }
+ else if ( *current == '%' )
+ {
+ addPathInArg( path, in, itInArg, PathArgument::kindKey );
+ ++current;
+ }
+ else if ( *current == '.' )
+ {
+ ++current;
+ }
+ else
+ {
+ const char *beginName = current;
+ while ( current != end && !strchr( "[.", *current ) )
+ ++current;
+ args_.push_back( std::string( beginName, current ) );
+ }
+ }
+}
+
+
+void
+Path::addPathInArg( const std::string &path,
+ const InArgs &in,
+ InArgs::const_iterator &itInArg,
+ PathArgument::Kind kind )
+{
+ if ( itInArg == in.end() )
+ {
+ // Error: missing argument %d
+ }
+ else if ( (*itInArg)->kind_ != kind )
+ {
+ // Error: bad argument type
+ }
+ else
+ {
+ args_.push_back( **itInArg );
+ }
+}
+
+
+void
+Path::invalidPath( const std::string &path,
+ int location )
+{
+ // Error: invalid path.
+}
+
+
+const Value &
+Path::resolve( const Value &root ) const
+{
+ const Value *node = &root;
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+ {
+ const PathArgument &arg = *it;
+ if ( arg.kind_ == PathArgument::kindIndex )
+ {
+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
+ {
+ // Error: unable to resolve path (array value expected at position...
+ }
+ node = &((*node)[arg.index_]);
+ }
+ else if ( arg.kind_ == PathArgument::kindKey )
+ {
+ if ( !node->isObject() )
+ {
+ // Error: unable to resolve path (object value expected at position...)
+ }
+ node = &((*node)[arg.key_]);
+ if ( node == &Value::null )
+ {
+ // Error: unable to resolve path (object has no member named '' at position...)
+ }
+ }
+ }
+ return *node;
+}
+
+
+Value
+Path::resolve( const Value &root,
+ const Value &defaultValue ) const
+{
+ const Value *node = &root;
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+ {
+ const PathArgument &arg = *it;
+ if ( arg.kind_ == PathArgument::kindIndex )
+ {
+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
+ return defaultValue;
+ node = &((*node)[arg.index_]);
+ }
+ else if ( arg.kind_ == PathArgument::kindKey )
+ {
+ if ( !node->isObject() )
+ return defaultValue;
+ node = &((*node)[arg.key_]);
+ if ( node == &Value::null )
+ return defaultValue;
+ }
+ }
+ return *node;
+}
+
+
+Value &
+Path::make( Value &root ) const
+{
+ Value *node = &root;
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+ {
+ const PathArgument &arg = *it;
+ if ( arg.kind_ == PathArgument::kindIndex )
+ {
+ if ( !node->isArray() )
+ {
+ // Error: node is not an array at position ...
+ }
+ node = &((*node)[arg.index_]);
+ }
+ else if ( arg.kind_ == PathArgument::kindKey )
+ {
+ if ( !node->isObject() )
+ {
+ // Error: node is not an object at position...
+ }
+ node = &((*node)[arg.key_]);
+ }
+ }
+ return *node;
+}
+
+
+} // namespace Json
diff --git a/lib/jsoncpp/src/lib_json/json_valueiterator.inl b/lib/jsoncpp/src/lib_json/json_valueiterator.inl
new file mode 100644
index 000000000..736e260ea
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/json_valueiterator.inl
@@ -0,0 +1,292 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ : current_()
+ , isNull_( true )
+{
+}
+#else
+ : isArray_( true )
+ , isNull_( true )
+{
+ iterator_.array_ = ValueInternalArray::IteratorState();
+}
+#endif
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
+ : current_( current )
+ , isNull_( false )
+{
+}
+#else
+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
+ : isArray_( true )
+{
+ iterator_.array_ = state;
+}
+
+
+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
+ : isArray_( false )
+{
+ iterator_.map_ = state;
+}
+#endif
+
+Value &
+ValueIteratorBase::deref() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ return current_->second;
+#else
+ if ( isArray_ )
+ return ValueInternalArray::dereference( iterator_.array_ );
+ return ValueInternalMap::value( iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::increment()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ ++current_;
+#else
+ if ( isArray_ )
+ ValueInternalArray::increment( iterator_.array_ );
+ ValueInternalMap::increment( iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::decrement()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ --current_;
+#else
+ if ( isArray_ )
+ ValueInternalArray::decrement( iterator_.array_ );
+ ValueInternalMap::decrement( iterator_.map_ );
+#endif
+}
+
+
+ValueIteratorBase::difference_type
+ValueIteratorBase::computeDistance( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+# ifdef JSON_USE_CPPTL_SMALLMAP
+ return current_ - other.current_;
+# else
+ // Iterator for null value are initialized using the default
+ // constructor, which initialize current_ to the default
+ // std::map::iterator. As begin() and end() are two instance
+ // of the default std::map::iterator, they can not be compared.
+ // To allow this, we handle this comparison specifically.
+ if ( isNull_ && other.isNull_ )
+ {
+ return 0;
+ }
+
+
+ // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
+ // which is the one used by default).
+ // Using a portable hand-made version for non random iterator instead:
+ // return difference_type( std::distance( current_, other.current_ ) );
+ difference_type myDistance = 0;
+ for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
+ {
+ ++myDistance;
+ }
+ return myDistance;
+# endif
+#else
+ if ( isArray_ )
+ return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
+ return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+bool
+ValueIteratorBase::isEqual( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ if ( isNull_ )
+ {
+ return other.isNull_;
+ }
+ return current_ == other.current_;
+#else
+ if ( isArray_ )
+ return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
+ return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::copy( const SelfType &other )
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ current_ = other.current_;
+#else
+ if ( isArray_ )
+ iterator_.array_ = other.iterator_.array_;
+ iterator_.map_ = other.iterator_.map_;
+#endif
+}
+
+
+Value
+ValueIteratorBase::key() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const Value::CZString czstring = (*current_).first;
+ if ( czstring.c_str() )
+ {
+ if ( czstring.isStaticString() )
+ return Value( StaticString( czstring.c_str() ) );
+ return Value( czstring.c_str() );
+ }
+ return Value( czstring.index() );
+#else
+ if ( isArray_ )
+ return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
+ bool isStatic;
+ const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
+ if ( isStatic )
+ return Value( StaticString( memberName ) );
+ return Value( memberName );
+#endif
+}
+
+
+UInt
+ValueIteratorBase::index() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const Value::CZString czstring = (*current_).first;
+ if ( !czstring.c_str() )
+ return czstring.index();
+ return Value::UInt( -1 );
+#else
+ if ( isArray_ )
+ return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
+ return Value::UInt( -1 );
+#endif
+}
+
+
+const char *
+ValueIteratorBase::memberName() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const char *name = (*current_).first.c_str();
+ return name ? name : "";
+#else
+ if ( !isArray_ )
+ return ValueInternalMap::key( iterator_.map_ );
+ return "";
+#endif
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
+ : ValueIteratorBase( current )
+{
+}
+#else
+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+
+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueConstIterator &
+ValueConstIterator::operator =( const ValueIteratorBase &other )
+{
+ copy( other );
+ return *this;
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
+ : ValueIteratorBase( current )
+{
+}
+#else
+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+
+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueIterator::ValueIterator( const ValueConstIterator &other )
+ : ValueIteratorBase( other )
+{
+}
+
+ValueIterator::ValueIterator( const ValueIterator &other )
+ : ValueIteratorBase( other )
+{
+}
+
+ValueIterator &
+ValueIterator::operator =( const SelfType &other )
+{
+ copy( other );
+ return *this;
+}
diff --git a/lib/jsoncpp/src/lib_json/json_writer.cpp b/lib/jsoncpp/src/lib_json/json_writer.cpp
new file mode 100644
index 000000000..eff3fabeb
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/json_writer.cpp
@@ -0,0 +1,829 @@
+#include "../../include/json/writer.h"
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+static bool isControlCharacter(char ch)
+{
+ return ch > 0 && ch <= 0x1F;
+}
+
+static bool containsControlCharacter( const char* str )
+{
+ while ( *str )
+ {
+ if ( isControlCharacter( *(str++) ) )
+ return true;
+ }
+ return false;
+}
+static void uintToString( unsigned int value,
+ char *&current )
+{
+ *--current = 0;
+ do
+ {
+ *--current = (value % 10) + '0';
+ value /= 10;
+ }
+ while ( value != 0 );
+}
+
+std::string valueToString( Int value )
+{
+ char buffer[32];
+ char *current = buffer + sizeof(buffer);
+ bool isNegative = value < 0;
+ if ( isNegative )
+ value = -value;
+ uintToString( UInt(value), current );
+ if ( isNegative )
+ *--current = '-';
+ assert( current >= buffer );
+ return current;
+}
+
+
+std::string valueToString( UInt value )
+{
+ char buffer[32];
+ char *current = buffer + sizeof(buffer);
+ uintToString( value, current );
+ assert( current >= buffer );
+ return current;
+}
+
+std::string valueToString( double value )
+{
+ char buffer[32];
+#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
+ sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
+#else
+ sprintf(buffer, "%#.16g", value);
+#endif
+ char* ch = buffer + strlen(buffer) - 1;
+ if (*ch != '0') return buffer; // nothing to truncate, so save time
+ while(ch > buffer && *ch == '0'){
+ --ch;
+ }
+ char* last_nonzero = ch;
+ while(ch >= buffer){
+ switch(*ch){
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ --ch;
+ continue;
+ case '.':
+ // Truncate zeroes to save bytes in output, but keep one.
+ *(last_nonzero+2) = '\0';
+ return buffer;
+ default:
+ return buffer;
+ }
+ }
+ return buffer;
+}
+
+
+std::string valueToString( bool value )
+{
+ return value ? "true" : "false";
+}
+
+std::string valueToQuotedString( const char *value )
+{
+ // Not sure how to handle unicode...
+ if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
+ return std::string("\"") + value + "\"";
+ // We have to walk value and escape any special characters.
+ // Appending to std::string is not efficient, but this should be rare.
+ // (Note: forward slashes are *not* rare, but I am not escaping them.)
+ unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
+ std::string result;
+ result.reserve(maxsize); // to avoid lots of mallocs
+ result += "\"";
+ for (const char* c=value; *c != 0; ++c)
+ {
+ switch(*c)
+ {
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ 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 '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default:
+ if ( isControlCharacter( *c ) )
+ {
+ std::ostringstream oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ }
+ else
+ {
+ result += *c;
+ }
+ break;
+ }
+ }
+ result += "\"";
+ return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer()
+{
+}
+
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+ : yamlCompatiblityEnabled_( false )
+{
+}
+
+
+void
+FastWriter::enableYAMLCompatibility()
+{
+ yamlCompatiblityEnabled_ = true;
+}
+
+
+std::string
+FastWriter::write( const Value &root )
+{
+ document_ = "";
+ writeValue( root );
+ document_ += "\n";
+ return document_;
+}
+
+
+void
+FastWriter::writeValue( const Value &value )
+{
+ switch ( value.type() )
+ {
+ case nullValue:
+ document_ += "null";
+ break;
+ case intValue:
+ document_ += valueToString( value.asInt() );
+ break;
+ case uintValue:
+ document_ += valueToString( value.asUInt() );
+ break;
+ case realValue:
+ document_ += valueToString( value.asDouble() );
+ break;
+ case stringValue:
+ document_ += valueToQuotedString( value.asCString() );
+ break;
+ case booleanValue:
+ document_ += valueToString( value.asBool() );
+ break;
+ case arrayValue:
+ {
+ document_ += "[";
+ int size = value.size();
+ for ( int index =0; index < size; ++index )
+ {
+ if ( index > 0 )
+ document_ += ",";
+ writeValue( value[index] );
+ }
+ document_ += "]";
+ }
+ break;
+ case objectValue:
+ {
+ Value::Members members( value.getMemberNames() );
+ document_ += "{";
+ for ( Value::Members::iterator it = members.begin();
+ it != members.end();
+ ++it )
+ {
+ const std::string &name = *it;
+ if ( it != members.begin() )
+ document_ += ",";
+ document_ += valueToQuotedString( name.c_str() );
+ document_ += yamlCompatiblityEnabled_ ? ": "
+ : ":";
+ writeValue( value[name] );
+ }
+ document_ += "}";
+ }
+ break;
+ }
+}
+
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+ : rightMargin_( 74 )
+ , indentSize_( 3 )
+{
+}
+
+
+std::string
+StyledWriter::write( const Value &root )
+{
+ document_ = "";
+ addChildValues_ = false;
+ indentString_ = "";
+ writeCommentBeforeValue( root );
+ writeValue( root );
+ writeCommentAfterValueOnSameLine( root );
+ document_ += "\n";
+ return document_;
+}
+
+
+void
+StyledWriter::writeValue( const Value &value )
+{
+ switch ( value.type() )
+ {
+ case nullValue:
+ pushValue( "null" );
+ break;
+ case intValue:
+ pushValue( valueToString( value.asInt() ) );
+ break;
+ case uintValue:
+ pushValue( valueToString( value.asUInt() ) );
+ break;
+ case realValue:
+ pushValue( valueToString( value.asDouble() ) );
+ break;
+ case stringValue:
+ pushValue( valueToQuotedString( value.asCString() ) );
+ break;
+ case booleanValue:
+ pushValue( valueToString( value.asBool() ) );
+ break;
+ case arrayValue:
+ writeArrayValue( value);
+ break;
+ case objectValue:
+ {
+ Value::Members members( value.getMemberNames() );
+ if ( members.empty() )
+ pushValue( "{}" );
+ else
+ {
+ writeWithIndent( "{" );
+ indent();
+ Value::Members::iterator it = members.begin();
+ while ( true )
+ {
+ const std::string &name = *it;
+ const Value &childValue = value[name];
+ writeCommentBeforeValue( childValue );
+ writeWithIndent( valueToQuotedString( name.c_str() ) );
+ document_ += " : ";
+ writeValue( childValue );
+ if ( ++it == members.end() )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ document_ += ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "}" );
+ }
+ }
+ break;
+ }
+}
+
+
+void
+StyledWriter::writeArrayValue( const Value &value )
+{
+ unsigned size = value.size();
+ if ( size == 0 )
+ pushValue( "[]" );
+ else
+ {
+ bool isArrayMultiLine = isMultineArray( value );
+ if ( isArrayMultiLine )
+ {
+ writeWithIndent( "[" );
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index =0;
+ while ( true )
+ {
+ const Value &childValue = value[index];
+ writeCommentBeforeValue( childValue );
+ if ( hasChildValue )
+ writeWithIndent( childValues_[index] );
+ else
+ {
+ writeIndent();
+ writeValue( childValue );
+ }
+ if ( ++index == size )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ document_ += ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "]" );
+ }
+ else // output on a single line
+ {
+ assert( childValues_.size() == size );
+ document_ += "[ ";
+ for ( unsigned index =0; index < size; ++index )
+ {
+ if ( index > 0 )
+ document_ += ", ";
+ document_ += childValues_[index];
+ }
+ document_ += " ]";
+ }
+ }
+}
+
+
+bool
+StyledWriter::isMultineArray( const Value &value )
+{
+ int size = value.size();
+ bool isMultiLine = size*3 >= rightMargin_ ;
+ childValues_.clear();
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ const Value &childValue = value[index];
+ isMultiLine = isMultiLine ||
+ ( (childValue.isArray() || childValue.isObject()) &&
+ childValue.size() > 0 );
+ }
+ if ( !isMultiLine ) // check if line length > max line length
+ {
+ childValues_.reserve( size );
+ addChildValues_ = true;
+ int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ writeValue( value[index] );
+ lineLength += int( childValues_[index].length() );
+ isMultiLine = isMultiLine && hasCommentForValue( value[index] );
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+
+void
+StyledWriter::pushValue( const std::string &value )
+{
+ if ( addChildValues_ )
+ childValues_.push_back( value );
+ else
+ document_ += value;
+}
+
+
+void
+StyledWriter::writeIndent()
+{
+ if ( !document_.empty() )
+ {
+ char last = document_[document_.length()-1];
+ if ( last == ' ' ) // already indented
+ return;
+ if ( last != '\n' ) // Comments may add new-line
+ document_ += '\n';
+ }
+ document_ += indentString_;
+}
+
+
+void
+StyledWriter::writeWithIndent( const std::string &value )
+{
+ writeIndent();
+ document_ += value;
+}
+
+
+void
+StyledWriter::indent()
+{
+ indentString_ += std::string( indentSize_, ' ' );
+}
+
+
+void
+StyledWriter::unindent()
+{
+ assert( int(indentString_.size()) >= indentSize_ );
+ indentString_.resize( indentString_.size() - indentSize_ );
+}
+
+
+void
+StyledWriter::writeCommentBeforeValue( const Value &root )
+{
+ if ( !root.hasComment( commentBefore ) )
+ return;
+ document_ += normalizeEOL( root.getComment( commentBefore ) );
+ document_ += "\n";
+}
+
+
+void
+StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+ if ( root.hasComment( commentAfterOnSameLine ) )
+ document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+ if ( root.hasComment( commentAfter ) )
+ {
+ document_ += "\n";
+ document_ += normalizeEOL( root.getComment( commentAfter ) );
+ document_ += "\n";
+ }
+}
+
+
+bool
+StyledWriter::hasCommentForValue( const Value &value )
+{
+ return value.hasComment( commentBefore )
+ || value.hasComment( commentAfterOnSameLine )
+ || value.hasComment( commentAfter );
+}
+
+
+std::string
+StyledWriter::normalizeEOL( const std::string &text )
+{
+ std::string normalized;
+ normalized.reserve( text.length() );
+ const char *begin = text.c_str();
+ const char *end = begin + text.length();
+ const char *current = begin;
+ while ( current != end )
+ {
+ char c = *current++;
+ if ( c == '\r' ) // mac or dos EOL
+ {
+ if ( *current == '\n' ) // convert dos EOL
+ ++current;
+ normalized += '\n';
+ }
+ else // handle unix EOL & other char
+ normalized += c;
+ }
+ return normalized;
+}
+
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter( std::string indentation )
+ : document_(NULL)
+ , rightMargin_( 74 )
+ , indentation_( indentation )
+{
+}
+
+
+void
+StyledStreamWriter::write( std::ostream &out, const Value &root )
+{
+ document_ = &out;
+ addChildValues_ = false;
+ indentString_ = "";
+ writeCommentBeforeValue( root );
+ writeValue( root );
+ writeCommentAfterValueOnSameLine( root );
+ *document_ << "\n";
+ document_ = NULL; // Forget the stream, for safety.
+}
+
+
+void
+StyledStreamWriter::writeValue( const Value &value )
+{
+ switch ( value.type() )
+ {
+ case nullValue:
+ pushValue( "null" );
+ break;
+ case intValue:
+ pushValue( valueToString( value.asInt() ) );
+ break;
+ case uintValue:
+ pushValue( valueToString( value.asUInt() ) );
+ break;
+ case realValue:
+ pushValue( valueToString( value.asDouble() ) );
+ break;
+ case stringValue:
+ pushValue( valueToQuotedString( value.asCString() ) );
+ break;
+ case booleanValue:
+ pushValue( valueToString( value.asBool() ) );
+ break;
+ case arrayValue:
+ writeArrayValue( value);
+ break;
+ case objectValue:
+ {
+ Value::Members members( value.getMemberNames() );
+ if ( members.empty() )
+ pushValue( "{}" );
+ else
+ {
+ writeWithIndent( "{" );
+ indent();
+ Value::Members::iterator it = members.begin();
+ while ( true )
+ {
+ const std::string &name = *it;
+ const Value &childValue = value[name];
+ writeCommentBeforeValue( childValue );
+ writeWithIndent( valueToQuotedString( name.c_str() ) );
+ *document_ << " : ";
+ writeValue( childValue );
+ if ( ++it == members.end() )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "}" );
+ }
+ }
+ break;
+ }
+}
+
+
+void
+StyledStreamWriter::writeArrayValue( const Value &value )
+{
+ unsigned size = value.size();
+ if ( size == 0 )
+ pushValue( "[]" );
+ else
+ {
+ bool isArrayMultiLine = isMultineArray( value );
+ if ( isArrayMultiLine )
+ {
+ writeWithIndent( "[" );
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index =0;
+ while ( true )
+ {
+ const Value &childValue = value[index];
+ writeCommentBeforeValue( childValue );
+ if ( hasChildValue )
+ writeWithIndent( childValues_[index] );
+ else
+ {
+ writeIndent();
+ writeValue( childValue );
+ }
+ if ( ++index == size )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "]" );
+ }
+ else // output on a single line
+ {
+ assert( childValues_.size() == size );
+ *document_ << "[ ";
+ for ( unsigned index =0; index < size; ++index )
+ {
+ if ( index > 0 )
+ *document_ << ", ";
+ *document_ << childValues_[index];
+ }
+ *document_ << " ]";
+ }
+ }
+}
+
+
+bool
+StyledStreamWriter::isMultineArray( const Value &value )
+{
+ int size = value.size();
+ bool isMultiLine = size*3 >= rightMargin_ ;
+ childValues_.clear();
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ const Value &childValue = value[index];
+ isMultiLine = isMultiLine ||
+ ( (childValue.isArray() || childValue.isObject()) &&
+ childValue.size() > 0 );
+ }
+ if ( !isMultiLine ) // check if line length > max line length
+ {
+ childValues_.reserve( size );
+ addChildValues_ = true;
+ int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ writeValue( value[index] );
+ lineLength += int( childValues_[index].length() );
+ isMultiLine = isMultiLine && hasCommentForValue( value[index] );
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+
+void
+StyledStreamWriter::pushValue( const std::string &value )
+{
+ if ( addChildValues_ )
+ childValues_.push_back( value );
+ else
+ *document_ << value;
+}
+
+
+void
+StyledStreamWriter::writeIndent()
+{
+ /*
+ Some comments in this method would have been nice. ;-)
+
+ if ( !document_.empty() )
+ {
+ char last = document_[document_.length()-1];
+ if ( last == ' ' ) // already indented
+ return;
+ if ( last != '\n' ) // Comments may add new-line
+ *document_ << '\n';
+ }
+ */
+ *document_ << '\n' << indentString_;
+}
+
+
+void
+StyledStreamWriter::writeWithIndent( const std::string &value )
+{
+ writeIndent();
+ *document_ << value;
+}
+
+
+void
+StyledStreamWriter::indent()
+{
+ indentString_ += indentation_;
+}
+
+
+void
+StyledStreamWriter::unindent()
+{
+ assert( indentString_.size() >= indentation_.size() );
+ indentString_.resize( indentString_.size() - indentation_.size() );
+}
+
+
+void
+StyledStreamWriter::writeCommentBeforeValue( const Value &root )
+{
+ if ( !root.hasComment( commentBefore ) )
+ return;
+ *document_ << normalizeEOL( root.getComment( commentBefore ) );
+ *document_ << "\n";
+}
+
+
+void
+StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+ if ( root.hasComment( commentAfterOnSameLine ) )
+ *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+ if ( root.hasComment( commentAfter ) )
+ {
+ *document_ << "\n";
+ *document_ << normalizeEOL( root.getComment( commentAfter ) );
+ *document_ << "\n";
+ }
+}
+
+
+bool
+StyledStreamWriter::hasCommentForValue( const Value &value )
+{
+ return value.hasComment( commentBefore )
+ || value.hasComment( commentAfterOnSameLine )
+ || value.hasComment( commentAfter );
+}
+
+
+std::string
+StyledStreamWriter::normalizeEOL( const std::string &text )
+{
+ std::string normalized;
+ normalized.reserve( text.length() );
+ const char *begin = text.c_str();
+ const char *end = begin + text.length();
+ const char *current = begin;
+ while ( current != end )
+ {
+ char c = *current++;
+ if ( c == '\r' ) // mac or dos EOL
+ {
+ if ( *current == '\n' ) // convert dos EOL
+ ++current;
+ normalized += '\n';
+ }
+ else // handle unix EOL & other char
+ normalized += c;
+ }
+ return normalized;
+}
+
+
+std::ostream& operator<<( std::ostream &sout, const Value &root )
+{
+ Json::StyledStreamWriter writer;
+ writer.write(sout, root);
+ return sout;
+}
+
+
+} // namespace Json
diff --git a/lib/jsoncpp/src/lib_json/sconscript b/lib/jsoncpp/src/lib_json/sconscript
new file mode 100644
index 000000000..6e7c6c8a0
--- /dev/null
+++ b/lib/jsoncpp/src/lib_json/sconscript
@@ -0,0 +1,8 @@
+Import( 'env buildLibrary' )
+
+buildLibrary( env, Split( """
+ json_reader.cpp
+ json_value.cpp
+ json_writer.cpp
+ """ ),
+ 'json' )
diff --git a/lib/lua/COPYRIGHT b/lib/lua/COPYRIGHT
new file mode 100644
index 000000000..3a53e741e
--- /dev/null
+++ b/lib/lua/COPYRIGHT
@@ -0,0 +1,34 @@
+Lua License
+-----------
+
+Lua is licensed under the terms of the MIT license reproduced below.
+This means that Lua is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+
+For details and rationale, see http://www.lua.org/license.html .
+
+===============================================================================
+
+Copyright (C) 1994-2008 Lua.org, PUC-Rio.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+===============================================================================
+
+(end of COPYRIGHT)
diff --git a/lib/lua/HISTORY b/lib/lua/HISTORY
new file mode 100644
index 000000000..ce0c95bc6
--- /dev/null
+++ b/lib/lua/HISTORY
@@ -0,0 +1,183 @@
+HISTORY for Lua 5.1
+
+* Changes from version 5.0 to 5.1
+ -------------------------------
+ Language:
+ + new module system.
+ + new semantics for control variables of fors.
+ + new semantics for setn/getn.
+ + new syntax/semantics for varargs.
+ + new long strings and comments.
+ + new `mod' operator (`%')
+ + new length operator #t
+ + metatables for all types
+ API:
+ + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.
+ + user supplies memory allocator (lua_open becomes lua_newstate).
+ + luaopen_* functions must be called through Lua.
+ Implementation:
+ + new configuration scheme via luaconf.h.
+ + incremental garbage collection.
+ + better handling of end-of-line in the lexer.
+ + fully reentrant parser (new Lua function `load')
+ + better support for 64-bit machines.
+ + native loadlib support for Mac OS X.
+ + standard distribution in only one library (lualib.a merged into lua.a)
+
+* Changes from version 4.0 to 5.0
+ -------------------------------
+ Language:
+ + lexical scoping.
+ + Lua coroutines.
+ + standard libraries now packaged in tables.
+ + tags replaced by metatables and tag methods replaced by metamethods,
+ stored in metatables.
+ + proper tail calls.
+ + each function can have its own global table, which can be shared.
+ + new __newindex metamethod, called when we insert a new key into a table.
+ + new block comments: --[[ ... ]].
+ + new generic for.
+ + new weak tables.
+ + new boolean type.
+ + new syntax "local function".
+ + (f()) returns the first value returned by f.
+ + {f()} fills a table with all values returned by f.
+ + \n ignored in [[\n .
+ + fixed and-or priorities.
+ + more general syntax for function definition (e.g. function a.x.y:f()...end).
+ + more general syntax for function calls (e.g. (print or write)(9)).
+ + new functions (time/date, tmpfile, unpack, require, load*, etc.).
+ API:
+ + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer.
+ + introduced lightweight userdata, a simple "void*" without a metatable.
+ + new error handling protocol: the core no longer prints error messages;
+ all errors are reported to the caller on the stack.
+ + new lua_atpanic for host cleanup.
+ + new, signal-safe, hook scheme.
+ Implementation:
+ + new license: MIT.
+ + new, faster, register-based virtual machine.
+ + support for external multithreading and coroutines.
+ + new and consistent error message format.
+ + the core no longer needs "stdio.h" for anything (except for a single
+ use of sprintf to convert numbers to strings).
+ + lua.c now runs the environment variable LUA_INIT, if present. It can
+ be "@filename", to run a file, or the chunk itself.
+ + support for user extensions in lua.c.
+ sample implementation given for command line editing.
+ + new dynamic loading library, active by default on several platforms.
+ + safe garbage-collector metamethods.
+ + precompiled bytecodes checked for integrity (secure binary dostring).
+ + strings are fully aligned.
+ + position capture in string.find.
+ + read('*l') can read lines with embedded zeros.
+
+* Changes from version 3.2 to 4.0
+ -------------------------------
+ Language:
+ + new "break" and "for" statements (both numerical and for tables).
+ + uniform treatment of globals: globals are now stored in a Lua table.
+ + improved error messages.
+ + no more '$debug': full speed *and* full debug information.
+ + new read form: read(N) for next N bytes.
+ + general read patterns now deprecated.
+ (still available with -DCOMPAT_READPATTERNS.)
+ + all return values are passed as arguments for the last function
+ (old semantics still available with -DLUA_COMPAT_ARGRET)
+ + garbage collection tag methods for tables now deprecated.
+ + there is now only one tag method for order.
+ API:
+ + New API: fully re-entrant, simpler, and more efficient.
+ + New debug API.
+ Implementation:
+ + faster than ever: cleaner virtual machine and new hashing algorithm.
+ + non-recursive garbage-collector algorithm.
+ + reduced memory usage for programs with many strings.
+ + improved treatment for memory allocation errors.
+ + improved support for 16-bit machines (we hope).
+ + code now compiles unmodified as both ANSI C and C++.
+ + numbers in bases other than 10 are converted using strtoul.
+ + new -f option in Lua to support #! scripts.
+ + luac can now combine text and binaries.
+
+* Changes from version 3.1 to 3.2
+ -------------------------------
+ + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT.
+ + increased limit on the number of constants and globals per function
+ (from 2^16 to 2^24).
+ + debugging info (lua_debug and hooks) moved into lua_state and new API
+ functions provided to get and set this info.
+ + new debug lib gives full debugging access within Lua.
+ + new table functions "foreachi", "sort", "tinsert", "tremove", "getn".
+ + new io functions "flush", "seek".
+
+* Changes from version 3.0 to 3.1
+ -------------------------------
+ + NEW FEATURE: anonymous functions with closures (via "upvalues").
+ + new syntax:
+ - local variables in chunks.
+ - better scope control with DO block END.
+ - constructors can now be also written: { record-part; list-part }.
+ - more general syntax for function calls and lvalues, e.g.:
+ f(x).y=1
+ o:f(x,y):g(z)
+ f"string" is sugar for f("string")
+ + strings may now contain arbitrary binary data (e.g., embedded zeros).
+ + major code re-organization and clean-up; reduced module interdependecies.
+ + no arbitrary limits on the total number of constants and globals.
+ + support for multiple global contexts.
+ + better syntax error messages.
+ + new traversal functions "foreach" and "foreachvar".
+ + the default for numbers is now double.
+ changing it to use floats or longs is easy.
+ + complete debug information stored in pre-compiled chunks.
+ + sample interpreter now prompts user when run interactively, and also
+ handles control-C interruptions gracefully.
+
+* Changes from version 2.5 to 3.0
+ -------------------------------
+ + NEW CONCEPT: "tag methods".
+ Tag methods replace fallbacks as the meta-mechanism for extending the
+ semantics of Lua. Whereas fallbacks had a global nature, tag methods
+ work on objects having the same tag (e.g., groups of tables).
+ Existing code that uses fallbacks should work without change.
+ + new, general syntax for constructors {[exp] = exp, ... }.
+ + support for handling variable number of arguments in functions (varargs).
+ + support for conditional compilation ($if ... $else ... $end).
+ + cleaner semantics in API simplifies host code.
+ + better support for writing libraries (auxlib.h).
+ + better type checking and error messages in the standard library.
+ + luac can now also undump.
+
+* Changes from version 2.4 to 2.5
+ -------------------------------
+ + io and string libraries are now based on pattern matching;
+ the old libraries are still available for compatibility
+ + dofile and dostring can now return values (via return statement)
+ + better support for 16- and 64-bit machines
+ + expanded documentation, with more examples
+
+* Changes from version 2.2 to 2.4
+ -------------------------------
+ + external compiler creates portable binary files that can be loaded faster
+ + interface for debugging and profiling
+ + new "getglobal" fallback
+ + new functions for handling references to Lua objects
+ + new functions in standard lib
+ + only one copy of each string is stored
+ + expanded documentation, with more examples
+
+* Changes from version 2.1 to 2.2
+ -------------------------------
+ + functions now may be declared with any "lvalue" as a name
+ + garbage collection of functions
+ + support for pipes
+
+* Changes from version 1.1 to 2.1
+ -------------------------------
+ + object-oriented support
+ + fallbacks
+ + simplified syntax for tables
+ + many internal improvements
+
+(end of HISTORY)
diff --git a/lib/lua/INSTALL b/lib/lua/INSTALL
new file mode 100644
index 000000000..17eb8aee8
--- /dev/null
+++ b/lib/lua/INSTALL
@@ -0,0 +1,99 @@
+INSTALL for Lua 5.1
+
+* Building Lua
+ ------------
+ Lua is built in the src directory, but the build process can be
+ controlled from the top-level Makefile.
+
+ Building Lua on Unix systems should be very easy. First do "make" and
+ see if your platform is listed. If so, just do "make xxx", where xxx
+ is your platform name. The platforms currently supported are:
+ aix ansi bsd freebsd generic linux macosx mingw posix solaris
+
+ If your platform is not listed, try the closest one or posix, generic,
+ ansi, in this order.
+
+ See below for customization instructions and for instructions on how
+ to build with other Windows compilers.
+
+ If you want to check that Lua has been built correctly, do "make test"
+ after building Lua. Also, have a look at the example programs in test.
+
+* Installing Lua
+ --------------
+ Once you have built Lua, you may want to install it in an official
+ place in your system. In this case, do "make install". The official
+ place and the way to install files are defined in Makefile. You must
+ have the right permissions to install files.
+
+ If you want to build and install Lua in one step, do "make xxx install",
+ where xxx is your platform name.
+
+ If you want to install Lua locally, then do "make local". This will
+ create directories bin, include, lib, man, and install Lua there as
+ follows:
+
+ bin: lua luac
+ include: lua.h luaconf.h lualib.h lauxlib.h lua.hpp
+ lib: liblua.a
+ man/man1: lua.1 luac.1
+
+ These are the only directories you need for development.
+
+ There are man pages for lua and luac, in both nroff and html, and a
+ reference manual in html in doc, some sample code in test, and some
+ useful stuff in etc. You don't need these directories for development.
+
+ If you want to install Lua locally, but in some other directory, do
+ "make install INSTALL_TOP=xxx", where xxx is your chosen directory.
+
+ See below for instructions for Windows and other systems.
+
+* Customization
+ -------------
+ Three things can be customized by editing a file:
+ - Where and how to install Lua -- edit Makefile.
+ - How to build Lua -- edit src/Makefile.
+ - Lua features -- edit src/luaconf.h.
+
+ You don't actually need to edit the Makefiles because you may set the
+ relevant variables when invoking make.
+
+ On the other hand, if you need to select some Lua features, you'll need
+ to edit src/luaconf.h. The edited file will be the one installed, and
+ it will be used by any Lua clients that you build, to ensure consistency.
+
+ We strongly recommend that you enable dynamic loading. This is done
+ automatically for all platforms listed above that have this feature
+ (and also Windows). See src/luaconf.h and also src/Makefile.
+
+* Building Lua on Windows and other systems
+ -----------------------------------------
+ If you're not using the usual Unix tools, then the instructions for
+ building Lua depend on the compiler you use. You'll need to create
+ projects (or whatever your compiler uses) for building the library,
+ the interpreter, and the compiler, as follows:
+
+ library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
+ lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c
+ ltable.c ltm.c lundump.c lvm.c lzio.c
+ lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c
+ ltablib.c lstrlib.c loadlib.c linit.c
+
+ interpreter: library, lua.c
+
+ compiler: library, luac.c print.c
+
+ If you use Visual Studio .NET, you can use etc/luavs.bat in its
+ "Command Prompt".
+
+ If all you want is to build the Lua interpreter, you may put all .c files
+ in a single project, except for luac.c and print.c. Or just use etc/all.c.
+
+ To use Lua as a library in your own programs, you'll need to know how to
+ create and use libraries with your compiler.
+
+ As mentioned above, you may edit luaconf.h to select some features before
+ building Lua.
+
+(end of INSTALL)
diff --git a/lib/lua/Makefile b/lib/lua/Makefile
new file mode 100644
index 000000000..6e78f66fa
--- /dev/null
+++ b/lib/lua/Makefile
@@ -0,0 +1,128 @@
+# makefile for installing Lua
+# see INSTALL for installation instructions
+# see src/Makefile and src/luaconf.h for further customization
+
+# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
+
+# Your platform. See PLATS for possible values.
+PLAT= none
+
+# Where to install. The installation starts in the src and doc directories,
+# so take care if INSTALL_TOP is not an absolute path.
+INSTALL_TOP= /usr/local
+INSTALL_BIN= $(INSTALL_TOP)/bin
+INSTALL_INC= $(INSTALL_TOP)/include
+INSTALL_LIB= $(INSTALL_TOP)/lib
+INSTALL_MAN= $(INSTALL_TOP)/man/man1
+#
+# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with
+# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc).
+INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
+INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
+
+# How to install. If your install program does not support "-p", then you
+# may have to run ranlib on the installed liblua.a (do "make ranlib").
+INSTALL= install -p
+INSTALL_EXEC= $(INSTALL) -m 0755
+INSTALL_DATA= $(INSTALL) -m 0644
+#
+# If you don't have install you can use cp instead.
+# INSTALL= cp -p
+# INSTALL_EXEC= $(INSTALL)
+# INSTALL_DATA= $(INSTALL)
+
+# Utilities.
+MKDIR= mkdir -p
+RANLIB= ranlib
+
+# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+# Convenience platforms targets.
+PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+
+# What to install.
+TO_BIN= lua luac
+TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
+TO_LIB= liblua.a
+TO_MAN= lua.1 luac.1
+
+# Lua version and release.
+V= 5.1
+R= 5.1.4
+
+all: $(PLAT)
+
+$(PLATS) clean:
+ cd src && $(MAKE) $@
+
+test: dummy
+ src/lua test/hello.lua
+
+install: dummy
+ cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
+ cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
+ cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
+ cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
+ cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
+
+ranlib:
+ cd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB)
+
+local:
+ $(MAKE) install INSTALL_TOP=..
+
+none:
+ @echo "Please do"
+ @echo " make PLATFORM"
+ @echo "where PLATFORM is one of these:"
+ @echo " $(PLATS)"
+ @echo "See INSTALL for complete instructions."
+
+# make may get confused with test/ and INSTALL in a case-insensitive OS
+dummy:
+
+# echo config parameters
+echo:
+ @echo ""
+ @echo "These are the parameters currently set in src/Makefile to build Lua $R:"
+ @echo ""
+ @cd src && $(MAKE) -s echo
+ @echo ""
+ @echo "These are the parameters currently set in Makefile to install Lua $R:"
+ @echo ""
+ @echo "PLAT = $(PLAT)"
+ @echo "INSTALL_TOP = $(INSTALL_TOP)"
+ @echo "INSTALL_BIN = $(INSTALL_BIN)"
+ @echo "INSTALL_INC = $(INSTALL_INC)"
+ @echo "INSTALL_LIB = $(INSTALL_LIB)"
+ @echo "INSTALL_MAN = $(INSTALL_MAN)"
+ @echo "INSTALL_LMOD = $(INSTALL_LMOD)"
+ @echo "INSTALL_CMOD = $(INSTALL_CMOD)"
+ @echo "INSTALL_EXEC = $(INSTALL_EXEC)"
+ @echo "INSTALL_DATA = $(INSTALL_DATA)"
+ @echo ""
+ @echo "See also src/luaconf.h ."
+ @echo ""
+
+# echo private config parameters
+pecho:
+ @echo "V = $(V)"
+ @echo "R = $(R)"
+ @echo "TO_BIN = $(TO_BIN)"
+ @echo "TO_INC = $(TO_INC)"
+ @echo "TO_LIB = $(TO_LIB)"
+ @echo "TO_MAN = $(TO_MAN)"
+
+# echo config parameters as Lua code
+# uncomment the last sed expression if you want nil instead of empty strings
+lecho:
+ @echo "-- installation parameters for Lua $R"
+ @echo "VERSION = '$V'"
+ @echo "RELEASE = '$R'"
+ @$(MAKE) echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/'
+ @echo "-- EOF"
+
+# list targets that do not create files (but not all makes understand .PHONY)
+.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho
+
+# (end of Makefile)
diff --git a/lib/lua/README b/lib/lua/README
new file mode 100644
index 000000000..11b4dff70
--- /dev/null
+++ b/lib/lua/README
@@ -0,0 +1,37 @@
+README for Lua 5.1
+
+See INSTALL for installation instructions.
+See HISTORY for a summary of changes since the last released version.
+
+* What is Lua?
+ ------------
+ Lua is a powerful, light-weight programming language designed for extending
+ applications. Lua is also frequently used as a general-purpose, stand-alone
+ language. Lua is free software.
+
+ For complete information, visit Lua's web site at http://www.lua.org/ .
+ For an executive summary, see http://www.lua.org/about.html .
+
+ Lua has been used in many different projects around the world.
+ For a short list, see http://www.lua.org/uses.html .
+
+* Availability
+ ------------
+ Lua is freely available for both academic and commercial purposes.
+ See COPYRIGHT and http://www.lua.org/license.html for details.
+ Lua can be downloaded at http://www.lua.org/download.html .
+
+* Installation
+ ------------
+ Lua is implemented in pure ANSI C, and compiles unmodified in all known
+ platforms that have an ANSI C compiler. In most Unix-like platforms, simply
+ do "make" with a suitable target. See INSTALL for detailed instructions.
+
+* Origin
+ ------
+ Lua is developed at Lua.org, a laboratory of the Department of Computer
+ Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro
+ in Brazil).
+ For more information about the authors, see http://www.lua.org/authors.html .
+
+(end of README)
diff --git a/lib/lua/src/Makefile b/lib/lua/src/Makefile
new file mode 100644
index 000000000..e4a3cd610
--- /dev/null
+++ b/lib/lua/src/Makefile
@@ -0,0 +1,182 @@
+# makefile for building Lua
+# see ../INSTALL for installation instructions
+# see ../Makefile and luaconf.h for further customization
+
+# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
+
+# Your platform. See PLATS for possible values.
+PLAT= none
+
+CC= gcc
+CFLAGS= -O2 -Wall $(MYCFLAGS)
+AR= ar rcu
+RANLIB= ranlib
+RM= rm -f
+LIBS= -lm $(MYLIBS)
+
+MYCFLAGS=
+MYLDFLAGS=
+MYLIBS=
+
+# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+
+LUA_A= liblua.a
+CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
+ lundump.o lvm.o lzio.o
+LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ lstrlib.o loadlib.o linit.o
+
+LUA_T= lua
+LUA_O= lua.o
+
+LUAC_T= luac
+LUAC_O= luac.o print.o
+
+ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
+ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
+ALL_A= $(LUA_A)
+
+default: $(PLAT)
+
+all: $(ALL_T)
+
+o: $(ALL_O)
+
+a: $(ALL_A)
+
+$(LUA_A): $(CORE_O) $(LIB_O)
+ $(AR) $@ $?
+ $(RANLIB) $@
+
+$(LUA_T): $(LUA_O) $(LUA_A)
+ $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
+
+$(LUAC_T): $(LUAC_O) $(LUA_A)
+ $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
+
+clean:
+ $(RM) $(ALL_T) $(ALL_O)
+
+depend:
+ @$(CC) $(CFLAGS) -MM l*.c print.c
+
+echo:
+ @echo "PLAT = $(PLAT)"
+ @echo "CC = $(CC)"
+ @echo "CFLAGS = $(CFLAGS)"
+ @echo "AR = $(AR)"
+ @echo "RANLIB = $(RANLIB)"
+ @echo "RM = $(RM)"
+ @echo "MYCFLAGS = $(MYCFLAGS)"
+ @echo "MYLDFLAGS = $(MYLDFLAGS)"
+ @echo "MYLIBS = $(MYLIBS)"
+
+# convenience targets for popular platforms
+
+none:
+ @echo "Please choose a platform:"
+ @echo " $(PLATS)"
+
+aix:
+ $(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall"
+
+ansi:
+ $(MAKE) all MYCFLAGS=-DLUA_ANSI
+
+bsd:
+ $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
+
+freebsd:
+ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
+
+generic:
+ $(MAKE) all MYCFLAGS=
+
+linux:
+ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
+
+macosx:
+ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
+# use this on Mac OS X 10.3-
+# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
+
+mingw:
+ $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \
+ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
+ "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe
+ $(MAKE) "LUAC_T=luac.exe" luac.exe
+
+posix:
+ $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX
+
+solaris:
+ $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl"
+
+# list targets that do not create files (but not all makes understand .PHONY)
+.PHONY: all $(PLATS) default o a clean depend echo none
+
+# DO NOT DELETE
+
+lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \
+ lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \
+ lundump.h lvm.h
+lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h
+lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h
+lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
+ lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \
+ ltable.h
+ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h
+ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \
+ llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \
+ lfunc.h lstring.h lgc.h ltable.h lvm.h
+ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
+ lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \
+ ltable.h lundump.h lvm.h
+ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \
+ lzio.h lmem.h lundump.h
+lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \
+ lstate.h ltm.h lzio.h
+lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
+ lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
+linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h
+liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h
+llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \
+ lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h
+lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
+lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h ldo.h
+loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
+lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
+ ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
+lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h
+loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h
+lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
+ lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \
+ lfunc.h lstring.h lgc.h ltable.h
+lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h
+lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \
+ ltm.h lzio.h lstring.h lgc.h
+lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h
+ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h
+ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
+ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
+ lmem.h lstring.h lgc.h ltable.h
+lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
+luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \
+ lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \
+ lundump.h
+lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \
+ llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h
+lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
+ lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
+lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
+ lzio.h
+print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lopcodes.h lundump.h
+
+# (end of Makefile)
diff --git a/lib/lua/src/lapi.c b/lib/lua/src/lapi.c
new file mode 100644
index 000000000..5d5145d2e
--- /dev/null
+++ b/lib/lua/src/lapi.c
@@ -0,0 +1,1087 @@
+/*
+** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $
+** Lua API
+** See Copyright Notice in lua.h
+*/
+
+
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define lapi_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+
+
+
+const char lua_ident[] =
+ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n"
+ "$Authors: " LUA_AUTHORS " $\n"
+ "$URL: www.lua.org $\n";
+
+
+
+#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
+
+#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject)
+
+#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
+
+
+
+static TValue *index2adr (lua_State *L, int idx) {
+ if (idx > 0) {
+ TValue *o = L->base + (idx - 1);
+ api_check(L, idx <= L->ci->top - L->base);
+ if (o >= L->top) return cast(TValue *, luaO_nilobject);
+ else return o;
+ }
+ else if (idx > LUA_REGISTRYINDEX) {
+ api_check(L, idx != 0 && -idx <= L->top - L->base);
+ return L->top + idx;
+ }
+ else switch (idx) { /* pseudo-indices */
+ case LUA_REGISTRYINDEX: return registry(L);
+ case LUA_ENVIRONINDEX: {
+ Closure *func = curr_func(L);
+ sethvalue(L, &L->env, func->c.env);
+ return &L->env;
+ }
+ case LUA_GLOBALSINDEX: return gt(L);
+ default: {
+ Closure *func = curr_func(L);
+ idx = LUA_GLOBALSINDEX - idx;
+ return (idx <= func->c.nupvalues)
+ ? &func->c.upvalue[idx-1]
+ : cast(TValue *, luaO_nilobject);
+ }
+ }
+}
+
+
+static Table *getcurrenv (lua_State *L) {
+ if (L->ci == L->base_ci) /* no enclosing function? */
+ return hvalue(gt(L)); /* use global table as environment */
+ else {
+ Closure *func = curr_func(L);
+ return func->c.env;
+ }
+}
+
+
+void luaA_pushobject (lua_State *L, const TValue *o) {
+ setobj2s(L, L->top, o);
+ api_incr_top(L);
+}
+
+
+LUA_API int lua_checkstack (lua_State *L, int size) {
+ int res = 1;
+ lua_lock(L);
+ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)
+ res = 0; /* stack overflow */
+ else if (size > 0) {
+ luaD_checkstack(L, size);
+ if (L->ci->top < L->top + size)
+ L->ci->top = L->top + size;
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
+ int i;
+ if (from == to) return;
+ lua_lock(to);
+ api_checknelems(from, n);
+ api_check(from, G(from) == G(to));
+ api_check(from, to->ci->top - to->top >= n);
+ from->top -= n;
+ for (i = 0; i < n; i++) {
+ setobj2s(to, to->top++, from->top + i);
+ }
+ lua_unlock(to);
+}
+
+
+LUA_API void lua_setlevel (lua_State *from, lua_State *to) {
+ to->nCcalls = from->nCcalls;
+}
+
+
+LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
+ lua_CFunction old;
+ lua_lock(L);
+ old = G(L)->panic;
+ G(L)->panic = panicf;
+ lua_unlock(L);
+ return old;
+}
+
+
+LUA_API lua_State *lua_newthread (lua_State *L) {
+ lua_State *L1;
+ lua_lock(L);
+ luaC_checkGC(L);
+ L1 = luaE_newthread(L);
+ setthvalue(L, L->top, L1);
+ api_incr_top(L);
+ lua_unlock(L);
+ luai_userstatethread(L, L1);
+ return L1;
+}
+
+
+
+/*
+** basic stack manipulation
+*/
+
+
+LUA_API int lua_gettop (lua_State *L) {
+ return cast_int(L->top - L->base);
+}
+
+
+LUA_API void lua_settop (lua_State *L, int idx) {
+ lua_lock(L);
+ if (idx >= 0) {
+ api_check(L, idx <= L->stack_last - L->base);
+ while (L->top < L->base + idx)
+ setnilvalue(L->top++);
+ L->top = L->base + idx;
+ }
+ else {
+ api_check(L, -(idx+1) <= (L->top - L->base));
+ L->top += idx+1; /* `subtract' index (index is negative) */
+ }
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_remove (lua_State *L, int idx) {
+ StkId p;
+ lua_lock(L);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ while (++p < L->top) setobjs2s(L, p-1, p);
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_insert (lua_State *L, int idx) {
+ StkId p;
+ StkId q;
+ lua_lock(L);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);
+ setobjs2s(L, p, L->top);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_replace (lua_State *L, int idx) {
+ StkId o;
+ lua_lock(L);
+ /* explicit test for incompatible code */
+ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)
+ luaG_runerror(L, "no calling environment");
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ if (idx == LUA_ENVIRONINDEX) {
+ Closure *func = curr_func(L);
+ api_check(L, ttistable(L->top - 1));
+ func->c.env = hvalue(L->top - 1);
+ luaC_barrier(L, func, L->top - 1);
+ }
+ else {
+ setobj(L, o, L->top - 1);
+ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */
+ luaC_barrier(L, curr_func(L), L->top - 1);
+ }
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushvalue (lua_State *L, int idx) {
+ lua_lock(L);
+ setobj2s(L, L->top, index2adr(L, idx));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+
+/*
+** access functions (stack -> C)
+*/
+
+
+LUA_API int lua_type (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
+}
+
+
+LUA_API const char *lua_typename (lua_State *L, int t) {
+ UNUSED(L);
+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+}
+
+
+LUA_API int lua_iscfunction (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return iscfunction(o);
+}
+
+
+LUA_API int lua_isnumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ return tonumber(o, &n);
+}
+
+
+LUA_API int lua_isstring (lua_State *L, int idx) {
+ int t = lua_type(L, idx);
+ return (t == LUA_TSTRING || t == LUA_TNUMBER);
+}
+
+
+LUA_API int lua_isuserdata (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return (ttisuserdata(o) || ttislightuserdata(o));
+}
+
+
+LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
+ StkId o1 = index2adr(L, index1);
+ StkId o2 = index2adr(L, index2);
+ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaO_rawequalObj(o1, o2);
+}
+
+
+LUA_API int lua_equal (lua_State *L, int index1, int index2) {
+ StkId o1, o2;
+ int i;
+ lua_lock(L); /* may call tag method */
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
+ lua_unlock(L);
+ return i;
+}
+
+
+LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
+ StkId o1, o2;
+ int i;
+ lua_lock(L); /* may call tag method */
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaV_lessthan(L, o1, o2);
+ lua_unlock(L);
+ return i;
+}
+
+
+
+LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n))
+ return nvalue(o);
+ else
+ return 0;
+}
+
+
+LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+ lua_Integer res;
+ lua_Number num = nvalue(o);
+ lua_number2integer(res, num);
+ return res;
+ }
+ else
+ return 0;
+}
+
+
+LUA_API int lua_toboolean (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return !l_isfalse(o);
+}
+
+
+LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
+ StkId o = index2adr(L, idx);
+ if (!ttisstring(o)) {
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+ if (!luaV_tostring(L, o)) { /* conversion failed? */
+ if (len != NULL) *len = 0;
+ lua_unlock(L);
+ return NULL;
+ }
+ luaC_checkGC(L);
+ o = index2adr(L, idx); /* previous call may reallocate the stack */
+ lua_unlock(L);
+ }
+ if (len != NULL) *len = tsvalue(o)->len;
+ return svalue(o);
+}
+
+
+LUA_API size_t lua_objlen (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TSTRING: return tsvalue(o)->len;
+ case LUA_TUSERDATA: return uvalue(o)->len;
+ case LUA_TTABLE: return luaH_getn(hvalue(o));
+ case LUA_TNUMBER: {
+ size_t l;
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
+ lua_unlock(L);
+ return l;
+ }
+ default: return 0;
+ }
+}
+
+
+LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;
+}
+
+
+LUA_API void *lua_touserdata (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TUSERDATA: return (rawuvalue(o) + 1);
+ case LUA_TLIGHTUSERDATA: return pvalue(o);
+ default: return NULL;
+ }
+}
+
+
+LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (!ttisthread(o)) ? NULL : thvalue(o);
+}
+
+
+LUA_API const void *lua_topointer (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TTABLE: return hvalue(o);
+ case LUA_TFUNCTION: return clvalue(o);
+ case LUA_TTHREAD: return thvalue(o);
+ case LUA_TUSERDATA:
+ case LUA_TLIGHTUSERDATA:
+ return lua_touserdata(L, idx);
+ default: return NULL;
+ }
+}
+
+
+
+/*
+** push functions (C -> stack)
+*/
+
+
+LUA_API void lua_pushnil (lua_State *L) {
+ lua_lock(L);
+ setnilvalue(L->top);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+ lua_lock(L);
+ setnvalue(L->top, n);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
+ lua_lock(L);
+ setnvalue(L->top, cast_num(n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+ lua_lock(L);
+ luaC_checkGC(L);
+ setsvalue2s(L, L->top, luaS_newlstr(L, s, len));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushstring (lua_State *L, const char *s) {
+ if (s == NULL)
+ lua_pushnil(L);
+ else
+ lua_pushlstring(L, s, strlen(s));
+}
+
+
+LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp) {
+ const char *ret;
+ lua_lock(L);
+ luaC_checkGC(L);
+ ret = luaO_pushvfstring(L, fmt, argp);
+ lua_unlock(L);
+ return ret;
+}
+
+
+LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
+ const char *ret;
+ va_list argp;
+ lua_lock(L);
+ luaC_checkGC(L);
+ va_start(argp, fmt);
+ ret = luaO_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ lua_unlock(L);
+ return ret;
+}
+
+
+LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
+ Closure *cl;
+ lua_lock(L);
+ luaC_checkGC(L);
+ api_checknelems(L, n);
+ cl = luaF_newCclosure(L, n, getcurrenv(L));
+ cl->c.f = fn;
+ L->top -= n;
+ while (n--)
+ setobj2n(L, &cl->c.upvalue[n], L->top+n);
+ setclvalue(L, L->top, cl);
+ lua_assert(iswhite(obj2gco(cl)));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushboolean (lua_State *L, int b) {
+ lua_lock(L);
+ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
+ lua_lock(L);
+ setpvalue(L->top, p);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_pushthread (lua_State *L) {
+ lua_lock(L);
+ setthvalue(L, L->top, L);
+ api_incr_top(L);
+ lua_unlock(L);
+ return (G(L)->mainthread == L);
+}
+
+
+
+/*
+** get functions (Lua -> stack)
+*/
+
+
+LUA_API void lua_gettable (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ luaV_gettable(L, t, L->top - 1, L->top - 1);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_gettable(L, t, &key, L->top);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawget (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
+ StkId o;
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+ setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
+ lua_lock(L);
+ luaC_checkGC(L);
+ sethvalue(L, L->top, luaH_new(L, narray, nrec));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_getmetatable (lua_State *L, int objindex) {
+ const TValue *obj;
+ Table *mt = NULL;
+ int res;
+ lua_lock(L);
+ obj = index2adr(L, objindex);
+ switch (ttype(obj)) {
+ case LUA_TTABLE:
+ mt = hvalue(obj)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
+ default:
+ mt = G(L)->mt[ttype(obj)];
+ break;
+ }
+ if (mt == NULL)
+ res = 0;
+ else {
+ sethvalue(L, L->top, mt);
+ api_incr_top(L);
+ res = 1;
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+LUA_API void lua_getfenv (lua_State *L, int idx) {
+ StkId o;
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ sethvalue(L, L->top, clvalue(o)->c.env);
+ break;
+ case LUA_TUSERDATA:
+ sethvalue(L, L->top, uvalue(o)->env);
+ break;
+ case LUA_TTHREAD:
+ setobj2s(L, L->top, gt(thvalue(o)));
+ break;
+ default:
+ setnilvalue(L->top);
+ break;
+ }
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+/*
+** set functions (stack -> Lua)
+*/
+
+
+LUA_API void lua_settable (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ api_checknelems(L, 2);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ luaV_settable(L, t, L->top - 2, L->top - 1);
+ L->top -= 2; /* pop index and value */
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_settable(L, t, &key, L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawset (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ api_checknelems(L, 2);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
+ luaC_barriert(L, hvalue(t), L->top-1);
+ L->top -= 2;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
+ StkId o;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_setmetatable (lua_State *L, int objindex) {
+ TValue *obj;
+ Table *mt;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ obj = index2adr(L, objindex);
+ api_checkvalidindex(L, obj);
+ if (ttisnil(L->top - 1))
+ mt = NULL;
+ else {
+ api_check(L, ttistable(L->top - 1));
+ mt = hvalue(L->top - 1);
+ }
+ switch (ttype(obj)) {
+ case LUA_TTABLE: {
+ hvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarriert(L, hvalue(obj), mt);
+ break;
+ }
+ case LUA_TUSERDATA: {
+ uvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarrier(L, rawuvalue(obj), mt);
+ break;
+ }
+ default: {
+ G(L)->mt[ttype(obj)] = mt;
+ break;
+ }
+ }
+ L->top--;
+ lua_unlock(L);
+ return 1;
+}
+
+
+LUA_API int lua_setfenv (lua_State *L, int idx) {
+ StkId o;
+ int res = 1;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ api_check(L, ttistable(L->top - 1));
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ clvalue(o)->c.env = hvalue(L->top - 1);
+ break;
+ case LUA_TUSERDATA:
+ uvalue(o)->env = hvalue(L->top - 1);
+ break;
+ case LUA_TTHREAD:
+ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));
+ break;
+ default:
+ res = 0;
+ break;
+ }
+ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
+ L->top--;
+ lua_unlock(L);
+ return res;
+}
+
+
+/*
+** `load' and `call' functions (run Lua code)
+*/
+
+
+#define adjustresults(L,nres) \
+ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }
+
+
+#define checkresults(L,na,nr) \
+ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
+
+
+LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
+ StkId func;
+ lua_lock(L);
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
+ func = L->top - (nargs+1);
+ luaD_call(L, func, nresults);
+ adjustresults(L, nresults);
+ lua_unlock(L);
+}
+
+
+
+/*
+** Execute a protected call.
+*/
+struct CallS { /* data to `f_call' */
+ StkId func;
+ int nresults;
+};
+
+
+static void f_call (lua_State *L, void *ud) {
+ struct CallS *c = cast(struct CallS *, ud);
+ luaD_call(L, c->func, c->nresults);
+}
+
+
+
+LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
+ struct CallS c;
+ int status;
+ ptrdiff_t func;
+ lua_lock(L);
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
+ if (errfunc == 0)
+ func = 0;
+ else {
+ StkId o = index2adr(L, errfunc);
+ api_checkvalidindex(L, o);
+ func = savestack(L, o);
+ }
+ c.func = L->top - (nargs+1); /* function to be called */
+ c.nresults = nresults;
+ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
+ adjustresults(L, nresults);
+ lua_unlock(L);
+ return status;
+}
+
+
+/*
+** Execute a protected C call.
+*/
+struct CCallS { /* data to `f_Ccall' */
+ lua_CFunction func;
+ void *ud;
+};
+
+
+static void f_Ccall (lua_State *L, void *ud) {
+ struct CCallS *c = cast(struct CCallS *, ud);
+ Closure *cl;
+ cl = luaF_newCclosure(L, 0, getcurrenv(L));
+ cl->c.f = c->func;
+ setclvalue(L, L->top, cl); /* push function */
+ api_incr_top(L);
+ setpvalue(L->top, c->ud); /* push only argument */
+ api_incr_top(L);
+ luaD_call(L, L->top - 2, 0);
+}
+
+
+LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
+ struct CCallS c;
+ int status;
+ lua_lock(L);
+ c.func = func;
+ c.ud = ud;
+ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
+ const char *chunkname) {
+ ZIO z;
+ int status;
+ lua_lock(L);
+ if (!chunkname) chunkname = "?";
+ luaZ_init(L, &z, reader, data);
+ status = luaD_protectedparser(L, &z, chunkname);
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
+ int status;
+ TValue *o;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = L->top - 1;
+ if (isLfunction(o))
+ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
+ else
+ status = 1;
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_status (lua_State *L) {
+ return L->status;
+}
+
+
+/*
+** Garbage-collection function
+*/
+
+LUA_API int lua_gc (lua_State *L, int what, int data) {
+ int res = 0;
+ global_State *g;
+ lua_lock(L);
+ g = G(L);
+ switch (what) {
+ case LUA_GCSTOP: {
+ g->GCthreshold = MAX_LUMEM;
+ break;
+ }
+ case LUA_GCRESTART: {
+ g->GCthreshold = g->totalbytes;
+ break;
+ }
+ case LUA_GCCOLLECT: {
+ luaC_fullgc(L);
+ break;
+ }
+ case LUA_GCCOUNT: {
+ /* GC values are expressed in Kbytes: #bytes/2^10 */
+ res = cast_int(g->totalbytes >> 10);
+ break;
+ }
+ case LUA_GCCOUNTB: {
+ res = cast_int(g->totalbytes & 0x3ff);
+ break;
+ }
+ case LUA_GCSTEP: {
+ lu_mem a = (cast(lu_mem, data) << 10);
+ if (a <= g->totalbytes)
+ g->GCthreshold = g->totalbytes - a;
+ else
+ g->GCthreshold = 0;
+ while (g->GCthreshold <= g->totalbytes) {
+ luaC_step(L);
+ if (g->gcstate == GCSpause) { /* end of cycle? */
+ res = 1; /* signal it */
+ break;
+ }
+ }
+ break;
+ }
+ case LUA_GCSETPAUSE: {
+ res = g->gcpause;
+ g->gcpause = data;
+ break;
+ }
+ case LUA_GCSETSTEPMUL: {
+ res = g->gcstepmul;
+ g->gcstepmul = data;
+ break;
+ }
+ default: res = -1; /* invalid option */
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+
+/*
+** miscellaneous functions
+*/
+
+
+LUA_API int lua_error (lua_State *L) {
+ lua_lock(L);
+ api_checknelems(L, 1);
+ luaG_errormsg(L);
+ lua_unlock(L);
+ return 0; /* to avoid warnings */
+}
+
+
+LUA_API int lua_next (lua_State *L, int idx) {
+ StkId t;
+ int more;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ more = luaH_next(L, hvalue(t), L->top - 1);
+ if (more) {
+ api_incr_top(L);
+ }
+ else /* no more elements */
+ L->top -= 1; /* remove key */
+ lua_unlock(L);
+ return more;
+}
+
+
+LUA_API void lua_concat (lua_State *L, int n) {
+ lua_lock(L);
+ api_checknelems(L, n);
+ if (n >= 2) {
+ luaC_checkGC(L);
+ luaV_concat(L, n, cast_int(L->top - L->base) - 1);
+ L->top -= (n-1);
+ }
+ else if (n == 0) { /* push empty string */
+ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
+ api_incr_top(L);
+ }
+ /* else n == 1; nothing to do */
+ lua_unlock(L);
+}
+
+
+LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
+ lua_Alloc f;
+ lua_lock(L);
+ if (ud) *ud = G(L)->ud;
+ f = G(L)->frealloc;
+ lua_unlock(L);
+ return f;
+}
+
+
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
+ lua_lock(L);
+ G(L)->ud = ud;
+ G(L)->frealloc = f;
+ lua_unlock(L);
+}
+
+
+LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
+ Udata *u;
+ lua_lock(L);
+ luaC_checkGC(L);
+ u = luaS_newudata(L, size, getcurrenv(L));
+ setuvalue(L, L->top, u);
+ api_incr_top(L);
+ lua_unlock(L);
+ return u + 1;
+}
+
+
+
+
+static const char *aux_upvalue (StkId fi, int n, TValue **val) {
+ Closure *f;
+ if (!ttisfunction(fi)) return NULL;
+ f = clvalue(fi);
+ if (f->c.isC) {
+ if (!(1 <= n && n <= f->c.nupvalues)) return NULL;
+ *val = &f->c.upvalue[n-1];
+ return "";
+ }
+ else {
+ Proto *p = f->l.p;
+ if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
+ *val = f->l.upvals[n-1]->v;
+ return getstr(p->upvalues[n-1]);
+ }
+}
+
+
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
+ const char *name;
+ TValue *val;
+ lua_lock(L);
+ name = aux_upvalue(index2adr(L, funcindex), n, &val);
+ if (name) {
+ setobj2s(L, L->top, val);
+ api_incr_top(L);
+ }
+ lua_unlock(L);
+ return name;
+}
+
+
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
+ const char *name;
+ TValue *val;
+ StkId fi;
+ lua_lock(L);
+ fi = index2adr(L, funcindex);
+ api_checknelems(L, 1);
+ name = aux_upvalue(fi, n, &val);
+ if (name) {
+ L->top--;
+ setobj(L, val, L->top);
+ luaC_barrier(L, clvalue(fi), L->top);
+ }
+ lua_unlock(L);
+ return name;
+}
+
diff --git a/lib/lua/src/lapi.h b/lib/lua/src/lapi.h
new file mode 100644
index 000000000..2c3fab244
--- /dev/null
+++ b/lib/lua/src/lapi.h
@@ -0,0 +1,16 @@
+/*
+** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions from Lua API
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lapi_h
+#define lapi_h
+
+
+#include "lobject.h"
+
+
+LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+
+#endif
diff --git a/lib/lua/src/lauxlib.c b/lib/lua/src/lauxlib.c
new file mode 100644
index 000000000..10f14e2c0
--- /dev/null
+++ b/lib/lua/src/lauxlib.c
@@ -0,0 +1,652 @@
+/*
+** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* This file uses only the official API of Lua.
+** Any function declared here could be written as an application function.
+*/
+
+#define lauxlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+
+
+#define FREELIST_REF 0 /* free list of references */
+
+
+/* convert a stack index to positive */
+#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
+ lua_gettop(L) + (i) + 1)
+
+
+/*
+** {======================================================
+** Error-report functions
+** =======================================================
+*/
+
+
+LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
+ lua_Debug ar;
+ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
+ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
+ lua_getinfo(L, "n", &ar);
+ if (strcmp(ar.namewhat, "method") == 0) {
+ narg--; /* do not count `self' */
+ if (narg == 0) /* error is in the self argument itself? */
+ return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
+ ar.name, extramsg);
+ }
+ if (ar.name == NULL)
+ ar.name = "?";
+ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
+ narg, ar.name, extramsg);
+}
+
+
+LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
+ const char *msg = lua_pushfstring(L, "%s expected, got %s",
+ tname, luaL_typename(L, narg));
+ return luaL_argerror(L, narg, msg);
+}
+
+
+static void tag_error (lua_State *L, int narg, int tag) {
+ luaL_typerror(L, narg, lua_typename(L, tag));
+}
+
+
+LUALIB_API void luaL_where (lua_State *L, int level) {
+ lua_Debug ar;
+ if (lua_getstack(L, level, &ar)) { /* check function at level */
+ lua_getinfo(L, "Sl", &ar); /* get info about it */
+ if (ar.currentline > 0) { /* is there info? */
+ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
+ return;
+ }
+ }
+ lua_pushliteral(L, ""); /* else, no information available... */
+}
+
+
+LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ luaL_where(L, 1);
+ lua_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ lua_concat(L, 2);
+ return lua_error(L);
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
+ const char *const lst[]) {
+ const char *name = (def) ? luaL_optstring(L, narg, def) :
+ luaL_checkstring(L, narg);
+ int i;
+ for (i=0; lst[i]; i++)
+ if (strcmp(lst[i], name) == 0)
+ return i;
+ return luaL_argerror(L, narg,
+ lua_pushfstring(L, "invalid option " LUA_QS, name));
+}
+
+
+LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
+ if (!lua_isnil(L, -1)) /* name already in use? */
+ return 0; /* leave previous value on top, but return 0 */
+ lua_pop(L, 1);
+ lua_newtable(L); /* create metatable */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
+ return 1;
+}
+
+
+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return p;
+ }
+ }
+ }
+ luaL_typerror(L, ud, tname); /* else error */
+ return NULL; /* to avoid warnings */
+}
+
+
+LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
+ if (!lua_checkstack(L, space))
+ luaL_error(L, "stack overflow (%s)", mes);
+}
+
+
+LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
+ if (lua_type(L, narg) != t)
+ tag_error(L, narg, t);
+}
+
+
+LUALIB_API void luaL_checkany (lua_State *L, int narg) {
+ if (lua_type(L, narg) == LUA_TNONE)
+ luaL_argerror(L, narg, "value expected");
+}
+
+
+LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
+ const char *s = lua_tolstring(L, narg, len);
+ if (!s) tag_error(L, narg, LUA_TSTRING);
+ return s;
+}
+
+
+LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
+ const char *def, size_t *len) {
+ if (lua_isnoneornil(L, narg)) {
+ if (len)
+ *len = (def ? strlen(def) : 0);
+ return def;
+ }
+ else return luaL_checklstring(L, narg, len);
+}
+
+
+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
+ lua_Number d = lua_tonumber(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
+ return luaL_opt(L, luaL_checknumber, narg, def);
+}
+
+
+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+ lua_Integer d = lua_tointeger(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
+ lua_Integer def) {
+ return luaL_opt(L, luaL_checkinteger, narg, def);
+}
+
+
+LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+ if (!lua_getmetatable(L, obj)) /* no metatable? */
+ return 0;
+ lua_pushstring(L, event);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 2); /* remove metatable and metafield */
+ return 0;
+ }
+ else {
+ lua_remove(L, -2); /* remove only metatable */
+ return 1;
+ }
+}
+
+
+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
+ obj = abs_index(L, obj);
+ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
+ return 0;
+ lua_pushvalue(L, obj);
+ lua_call(L, 1, 1);
+ return 1;
+}
+
+
+LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
+ const luaL_Reg *l) {
+ luaI_openlib(L, libname, l, 0);
+}
+
+
+static int libsize (const luaL_Reg *l) {
+ int size = 0;
+ for (; l->name; l++) size++;
+ return size;
+}
+
+
+LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
+ const luaL_Reg *l, int nup) {
+ if (libname) {
+ int size = libsize(l);
+ /* check whether lib already exists */
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
+ lua_getfield(L, -1, libname); /* get _LOADED[libname] */
+ if (!lua_istable(L, -1)) { /* not found? */
+ lua_pop(L, 1); /* remove previous result */
+ /* try global variable (and create one if it does not exist) */
+ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
+ luaL_error(L, "name conflict for module " LUA_QS, libname);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
+ }
+ lua_remove(L, -2); /* remove _LOADED table */
+ lua_insert(L, -(nup+1)); /* move library table to below upvalues */
+ }
+ for (; l->name; l++) {
+ int i;
+ for (i=0; i<nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -nup);
+ lua_pushcclosure(L, l->func, nup);
+ lua_setfield(L, -(nup+2), l->name);
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+
+
+
+/*
+** {======================================================
+** getn-setn: size for arrays
+** =======================================================
+*/
+
+#if defined(LUA_COMPAT_GETN)
+
+static int checkint (lua_State *L, int topop) {
+ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
+ lua_pop(L, topop);
+ return n;
+}
+
+
+static void getsizes (lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
+ if (lua_isnil(L, -1)) { /* no `size' table? */
+ lua_pop(L, 1); /* remove nil */
+ lua_newtable(L); /* create it */
+ lua_pushvalue(L, -1); /* `size' will be its own metatable */
+ lua_setmetatable(L, -2);
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */
+ }
+}
+
+
+LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
+ t = abs_index(L, t);
+ lua_pushliteral(L, "n");
+ lua_rawget(L, t);
+ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
+ lua_pushliteral(L, "n"); /* use it */
+ lua_pushinteger(L, n);
+ lua_rawset(L, t);
+ }
+ else { /* use `sizes' */
+ getsizes(L);
+ lua_pushvalue(L, t);
+ lua_pushinteger(L, n);
+ lua_rawset(L, -3); /* sizes[t] = n */
+ lua_pop(L, 1); /* remove `sizes' */
+ }
+}
+
+
+LUALIB_API int luaL_getn (lua_State *L, int t) {
+ int n;
+ t = abs_index(L, t);
+ lua_pushliteral(L, "n"); /* try t.n */
+ lua_rawget(L, t);
+ if ((n = checkint(L, 1)) >= 0) return n;
+ getsizes(L); /* else try sizes[t] */
+ lua_pushvalue(L, t);
+ lua_rawget(L, -2);
+ if ((n = checkint(L, 2)) >= 0) return n;
+ return (int)lua_objlen(L, t);
+}
+
+#endif
+
+/* }====================================================== */
+
+
+
+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
+ const char *r) {
+ const char *wild;
+ size_t l = strlen(p);
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while ((wild = strstr(s, p)) != NULL) {
+ luaL_addlstring(&b, s, wild - s); /* push prefix */
+ luaL_addstring(&b, r); /* push replacement in place of pattern */
+ s = wild + l; /* continue after `p' */
+ }
+ luaL_addstring(&b, s); /* push last suffix */
+ luaL_pushresult(&b);
+ return lua_tostring(L, -1);
+}
+
+
+LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
+ const char *fname, int szhint) {
+ const char *e;
+ lua_pushvalue(L, idx);
+ do {
+ e = strchr(fname, '.');
+ if (e == NULL) e = fname + strlen(fname);
+ lua_pushlstring(L, fname, e - fname);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) { /* no such field? */
+ lua_pop(L, 1); /* remove this nil */
+ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
+ lua_pushlstring(L, fname, e - fname);
+ lua_pushvalue(L, -2);
+ lua_settable(L, -4); /* set new table into field */
+ }
+ else if (!lua_istable(L, -1)) { /* field has a non-table value? */
+ lua_pop(L, 2); /* remove table and value */
+ return fname; /* return problematic part of the name */
+ }
+ lua_remove(L, -2); /* remove previous table */
+ fname = e + 1;
+ } while (*e == '.');
+ return NULL;
+}
+
+
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+#define bufflen(B) ((B)->p - (B)->buffer)
+#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
+
+#define LIMIT (LUA_MINSTACK/2)
+
+
+static int emptybuffer (luaL_Buffer *B) {
+ size_t l = bufflen(B);
+ if (l == 0) return 0; /* put nothing on stack */
+ else {
+ lua_pushlstring(B->L, B->buffer, l);
+ B->p = B->buffer;
+ B->lvl++;
+ return 1;
+ }
+}
+
+
+static void adjuststack (luaL_Buffer *B) {
+ if (B->lvl > 1) {
+ lua_State *L = B->L;
+ int toget = 1; /* number of levels to concat */
+ size_t toplen = lua_strlen(L, -1);
+ do {
+ size_t l = lua_strlen(L, -(toget+1));
+ if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
+ toplen += l;
+ toget++;
+ }
+ else break;
+ } while (toget < B->lvl);
+ lua_concat(L, toget);
+ B->lvl = B->lvl - toget + 1;
+ }
+}
+
+
+LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
+ if (emptybuffer(B))
+ adjuststack(B);
+ return B->buffer;
+}
+
+
+LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
+ while (l--)
+ luaL_addchar(B, *s++);
+}
+
+
+LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
+ luaL_addlstring(B, s, strlen(s));
+}
+
+
+LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
+ emptybuffer(B);
+ lua_concat(B->L, B->lvl);
+ B->lvl = 1;
+}
+
+
+LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
+ lua_State *L = B->L;
+ size_t vl;
+ const char *s = lua_tolstring(L, -1, &vl);
+ if (vl <= bufffree(B)) { /* fit into buffer? */
+ memcpy(B->p, s, vl); /* put it there */
+ B->p += vl;
+ lua_pop(L, 1); /* remove from stack */
+ }
+ else {
+ if (emptybuffer(B))
+ lua_insert(L, -2); /* put buffer before new value */
+ B->lvl++; /* add new value into B stack */
+ adjuststack(B);
+ }
+}
+
+
+LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
+ B->L = L;
+ B->p = B->buffer;
+ B->lvl = 0;
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_ref (lua_State *L, int t) {
+ int ref;
+ t = abs_index(L, t);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1); /* remove from stack */
+ return LUA_REFNIL; /* `nil' has a unique fixed reference */
+ }
+ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
+ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
+ lua_pop(L, 1); /* remove it from stack */
+ if (ref != 0) { /* any free element? */
+ lua_rawgeti(L, t, ref); /* remove it from list */
+ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
+ }
+ else { /* no free elements */
+ ref = (int)lua_objlen(L, t);
+ ref++; /* create new reference */
+ }
+ lua_rawseti(L, t, ref);
+ return ref;
+}
+
+
+LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
+ if (ref >= 0) {
+ t = abs_index(L, t);
+ lua_rawgeti(L, t, FREELIST_REF);
+ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
+ lua_pushinteger(L, ref);
+ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
+ }
+}
+
+
+
+/*
+** {======================================================
+** Load functions
+** =======================================================
+*/
+
+typedef struct LoadF {
+ int extraline;
+ FILE *f;
+ char buff[LUAL_BUFFERSIZE];
+} LoadF;
+
+
+static const char *getF (lua_State *L, void *ud, size_t *size) {
+ LoadF *lf = (LoadF *)ud;
+ (void)L;
+ if (lf->extraline) {
+ lf->extraline = 0;
+ *size = 1;
+ return "\n";
+ }
+ if (feof(lf->f)) return NULL;
+ *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
+ return (*size > 0) ? lf->buff : NULL;
+}
+
+
+static int errfile (lua_State *L, const char *what, int fnameindex) {
+ const char *serr = strerror(errno);
+ const char *filename = lua_tostring(L, fnameindex) + 1;
+ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
+ lua_remove(L, fnameindex);
+ return LUA_ERRFILE;
+}
+
+
+LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
+ LoadF lf;
+ int status, readstatus;
+ int c;
+ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
+ lf.extraline = 0;
+ if (filename == NULL) {
+ lua_pushliteral(L, "=stdin");
+ lf.f = stdin;
+ }
+ else {
+ lua_pushfstring(L, "@%s", filename);
+ lf.f = fopen(filename, "r");
+ if (lf.f == NULL) return errfile(L, "open", fnameindex);
+ }
+ c = getc(lf.f);
+ if (c == '#') { /* Unix exec. file? */
+ lf.extraline = 1;
+ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
+ if (c == '\n') c = getc(lf.f);
+ }
+ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
+ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
+ if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
+ /* skip eventual `#!...' */
+ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
+ lf.extraline = 0;
+ }
+ ungetc(c, lf.f);
+ status = lua_load(L, getF, &lf, lua_tostring(L, -1));
+ readstatus = ferror(lf.f);
+ if (filename) fclose(lf.f); /* close file (even in case of errors) */
+ if (readstatus) {
+ lua_settop(L, fnameindex); /* ignore results from `lua_load' */
+ return errfile(L, "read", fnameindex);
+ }
+ lua_remove(L, fnameindex);
+ return status;
+}
+
+
+typedef struct LoadS {
+ const char *s;
+ size_t size;
+} LoadS;
+
+
+static const char *getS (lua_State *L, void *ud, size_t *size) {
+ LoadS *ls = (LoadS *)ud;
+ (void)L;
+ if (ls->size == 0) return NULL;
+ *size = ls->size;
+ ls->size = 0;
+ return ls->s;
+}
+
+
+LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
+ const char *name) {
+ LoadS ls;
+ ls.s = buff;
+ ls.size = size;
+ return lua_load(L, getS, &ls, name);
+}
+
+
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
+ return luaL_loadbuffer(L, s, strlen(s), s);
+}
+
+
+
+/* }====================================================== */
+
+
+static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
+ (void)ud;
+ (void)osize;
+ if (nsize == 0) {
+ free(ptr);
+ return NULL;
+ }
+ else
+ return realloc(ptr, nsize);
+}
+
+
+static int panic (lua_State *L) {
+ (void)L; /* to avoid warnings */
+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
+ lua_tostring(L, -1));
+ return 0;
+}
+
+
+LUALIB_API lua_State *luaL_newstate (void) {
+ lua_State *L = lua_newstate(l_alloc, NULL);
+ if (L) lua_atpanic(L, &panic);
+ return L;
+}
+
diff --git a/lib/lua/src/lauxlib.h b/lib/lua/src/lauxlib.h
new file mode 100644
index 000000000..34258235d
--- /dev/null
+++ b/lib/lua/src/lauxlib.h
@@ -0,0 +1,174 @@
+/*
+** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lauxlib_h
+#define lauxlib_h
+
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "lua.h"
+
+
+#if defined(LUA_COMPAT_GETN)
+LUALIB_API int (luaL_getn) (lua_State *L, int t);
+LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
+#else
+#define luaL_getn(L,i) ((int)lua_objlen(L, i))
+#define luaL_setn(L,i,j) ((void)0) /* no op! */
+#endif
+
+#if defined(LUA_COMPAT_OPENLIB)
+#define luaI_openlib luaL_openlib
+#endif
+
+
+/* extra error code for `luaL_load' */
+#define LUA_ERRFILE (LUA_ERRERR+1)
+
+
+typedef struct luaL_Reg {
+ const char *name;
+ lua_CFunction func;
+} luaL_Reg;
+
+
+
+LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
+ const luaL_Reg *l, int nup);
+LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
+ const luaL_Reg *l);
+LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
+LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
+LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
+ size_t *l);
+LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
+ const char *def, size_t *l);
+LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
+LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
+
+LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+ lua_Integer def);
+
+LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
+
+LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
+LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
+
+LUALIB_API void (luaL_where) (lua_State *L, int lvl);
+LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
+
+LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
+ const char *const lst[]);
+
+LUALIB_API int (luaL_ref) (lua_State *L, int t);
+LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
+
+LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
+LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
+ const char *name);
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
+
+LUALIB_API lua_State *(luaL_newstate) (void);
+
+
+LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
+ const char *r);
+
+LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
+ const char *fname, int szhint);
+
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define luaL_argcheck(L, cond,numarg,extramsg) \
+ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
+#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
+#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
+#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
+#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
+#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
+#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
+
+#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
+
+#define luaL_dofile(L, fn) \
+ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_dostring(L, s) \
+ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
+
+#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+
+typedef struct luaL_Buffer {
+ char *p; /* current position in buffer */
+ int lvl; /* number of strings in the stack (level) */
+ lua_State *L;
+ char buffer[LUAL_BUFFERSIZE];
+} luaL_Buffer;
+
+#define luaL_addchar(B,c) \
+ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
+ (*(B)->p++ = (char)(c)))
+
+/* compatibility only */
+#define luaL_putchar(B,c) luaL_addchar(B,c)
+
+#define luaL_addsize(B,n) ((B)->p += (n))
+
+LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
+LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
+LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
+LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
+LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
+LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
+
+
+/* }====================================================== */
+
+
+/* compatibility with ref system */
+
+/* pre-defined references */
+#define LUA_NOREF (-2)
+#define LUA_REFNIL (-1)
+
+#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
+ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
+
+#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
+
+#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
+
+
+#define luaL_reg luaL_Reg
+
+#endif
+
+
diff --git a/lib/lua/src/lbaselib.c b/lib/lua/src/lbaselib.c
new file mode 100644
index 000000000..2a4c079d3
--- /dev/null
+++ b/lib/lua/src/lbaselib.c
@@ -0,0 +1,653 @@
+/*
+** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $
+** Basic library
+** See Copyright Notice in lua.h
+*/
+
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lbaselib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+
+/*
+** If your system does not support `stdout', you can just remove this function.
+** If you need, you can define your own `print' function, following this
+** model but changing `fputs' to put the strings at a proper place
+** (a console window or a log file, for instance).
+*/
+static int luaB_print (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ lua_getglobal(L, "tostring");
+ for (i=1; i<=n; i++) {
+ const char *s;
+ lua_pushvalue(L, -1); /* function to be called */
+ lua_pushvalue(L, i); /* value to print */
+ lua_call(L, 1, 1);
+ s = lua_tostring(L, -1); /* get result */
+ if (s == NULL)
+ return luaL_error(L, LUA_QL("tostring") " must return a string to "
+ LUA_QL("print"));
+ if (i>1) fputs("\t", stdout);
+ fputs(s, stdout);
+ lua_pop(L, 1); /* pop result */
+ }
+ fputs("\n", stdout);
+ return 0;
+}
+
+
+static int luaB_tonumber (lua_State *L) {
+ int base = luaL_optint(L, 2, 10);
+ if (base == 10) { /* standard conversion */
+ luaL_checkany(L, 1);
+ if (lua_isnumber(L, 1)) {
+ lua_pushnumber(L, lua_tonumber(L, 1));
+ return 1;
+ }
+ }
+ else {
+ const char *s1 = luaL_checkstring(L, 1);
+ char *s2;
+ unsigned long n;
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+ n = strtoul(s1, &s2, base);
+ if (s1 != s2) { /* at least one valid digit? */
+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
+ if (*s2 == '\0') { /* no invalid trailing characters? */
+ lua_pushnumber(L, (lua_Number)n);
+ return 1;
+ }
+ }
+ }
+ lua_pushnil(L); /* else not a number */
+ return 1;
+}
+
+
+static int luaB_error (lua_State *L) {
+ int level = luaL_optint(L, 2, 1);
+ lua_settop(L, 1);
+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
+ luaL_where(L, level);
+ lua_pushvalue(L, 1);
+ lua_concat(L, 2);
+ }
+ return lua_error(L);
+}
+
+
+static int luaB_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L);
+ return 1; /* no metatable */
+ }
+ luaL_getmetafield(L, 1, "__metatable");
+ return 1; /* returns either __metatable field (if present) or metatable */
+}
+
+
+static int luaB_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ if (luaL_getmetafield(L, 1, "__metatable"))
+ luaL_error(L, "cannot change a protected metatable");
+ lua_settop(L, 2);
+ lua_setmetatable(L, 1);
+ return 1;
+}
+
+
+static void getfunc (lua_State *L, int opt) {
+ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
+ else {
+ lua_Debug ar;
+ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
+ luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
+ if (lua_getstack(L, level, &ar) == 0)
+ luaL_argerror(L, 1, "invalid level");
+ lua_getinfo(L, "f", &ar);
+ if (lua_isnil(L, -1))
+ luaL_error(L, "no function environment for tail call at level %d",
+ level);
+ }
+}
+
+
+static int luaB_getfenv (lua_State *L) {
+ getfunc(L, 1);
+ if (lua_iscfunction(L, -1)) /* is a C function? */
+ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */
+ else
+ lua_getfenv(L, -1);
+ return 1;
+}
+
+
+static int luaB_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ getfunc(L, 0);
+ lua_pushvalue(L, 2);
+ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
+ /* change environment of current thread */
+ lua_pushthread(L);
+ lua_insert(L, -2);
+ lua_setfenv(L, -2);
+ return 0;
+ }
+ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
+ luaL_error(L,
+ LUA_QL("setfenv") " cannot change environment of given object");
+ return 1;
+}
+
+
+static int luaB_rawequal (lua_State *L) {
+ luaL_checkany(L, 1);
+ luaL_checkany(L, 2);
+ lua_pushboolean(L, lua_rawequal(L, 1, 2));
+ return 1;
+}
+
+
+static int luaB_rawget (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_rawget(L, 1);
+ return 1;
+}
+
+static int luaB_rawset (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ luaL_checkany(L, 3);
+ lua_settop(L, 3);
+ lua_rawset(L, 1);
+ return 1;
+}
+
+
+static int luaB_gcinfo (lua_State *L) {
+ lua_pushinteger(L, lua_getgccount(L));
+ return 1;
+}
+
+
+static int luaB_collectgarbage (lua_State *L) {
+ static const char *const opts[] = {"stop", "restart", "collect",
+ "count", "step", "setpause", "setstepmul", NULL};
+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
+ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
+ int o = luaL_checkoption(L, 1, "collect", opts);
+ int ex = luaL_optint(L, 2, 0);
+ int res = lua_gc(L, optsnum[o], ex);
+ switch (optsnum[o]) {
+ case LUA_GCCOUNT: {
+ int b = lua_gc(L, LUA_GCCOUNTB, 0);
+ lua_pushnumber(L, res + ((lua_Number)b/1024));
+ return 1;
+ }
+ case LUA_GCSTEP: {
+ lua_pushboolean(L, res);
+ return 1;
+ }
+ default: {
+ lua_pushnumber(L, res);
+ return 1;
+ }
+ }
+}
+
+
+static int luaB_type (lua_State *L) {
+ luaL_checkany(L, 1);
+ lua_pushstring(L, luaL_typename(L, 1));
+ return 1;
+}
+
+
+static int luaB_next (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 2); /* create a 2nd argument if there isn't one */
+ if (lua_next(L, 1))
+ return 2;
+ else {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+
+static int luaB_pairs (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushnil(L); /* and initial value */
+ return 3;
+}
+
+
+static int ipairsaux (lua_State *L) {
+ int i = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i++; /* next value */
+ lua_pushinteger(L, i);
+ lua_rawgeti(L, 1, i);
+ return (lua_isnil(L, -1)) ? 0 : 2;
+}
+
+
+static int luaB_ipairs (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushinteger(L, 0); /* and initial value */
+ return 3;
+}
+
+
+static int load_aux (lua_State *L, int status) {
+ if (status == 0) /* OK? */
+ return 1;
+ else {
+ lua_pushnil(L);
+ lua_insert(L, -2); /* put before error message */
+ return 2; /* return nil plus error message */
+ }
+}
+
+
+static int luaB_loadstring (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ const char *chunkname = luaL_optstring(L, 2, s);
+ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
+}
+
+
+static int luaB_loadfile (lua_State *L) {
+ const char *fname = luaL_optstring(L, 1, NULL);
+ return load_aux(L, luaL_loadfile(L, fname));
+}
+
+
+/*
+** Reader for generic `load' function: `lua_load' uses the
+** stack for internal stuff, so the reader cannot change the
+** stack top. Instead, it keeps its resulting string in a
+** reserved slot inside the stack.
+*/
+static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
+ (void)ud; /* to avoid warnings */
+ luaL_checkstack(L, 2, "too many nested functions");
+ lua_pushvalue(L, 1); /* get function */
+ lua_call(L, 0, 1); /* call it */
+ if (lua_isnil(L, -1)) {
+ *size = 0;
+ return NULL;
+ }
+ else if (lua_isstring(L, -1)) {
+ lua_replace(L, 3); /* save string in a reserved stack slot */
+ return lua_tolstring(L, 3, size);
+ }
+ else luaL_error(L, "reader function must return a string");
+ return NULL; /* to avoid warnings */
+}
+
+
+static int luaB_load (lua_State *L) {
+ int status;
+ const char *cname = luaL_optstring(L, 2, "=(load)");
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */
+ status = lua_load(L, generic_reader, NULL, cname);
+ return load_aux(L, status);
+}
+
+
+static int luaB_dofile (lua_State *L) {
+ const char *fname = luaL_optstring(L, 1, NULL);
+ int n = lua_gettop(L);
+ if (luaL_loadfile(L, fname) != 0) lua_error(L);
+ lua_call(L, 0, LUA_MULTRET);
+ return lua_gettop(L) - n;
+}
+
+
+static int luaB_assert (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_toboolean(L, 1))
+ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
+ return lua_gettop(L);
+}
+
+
+static int luaB_unpack (lua_State *L) {
+ int i, e, n;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i = luaL_optint(L, 2, 1);
+ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
+ if (i > e) return 0; /* empty range */
+ n = e - i + 1; /* number of elements */
+ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
+ return luaL_error(L, "too many results to unpack");
+ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
+ while (i++ < e) /* push arg[i + 1...e] */
+ lua_rawgeti(L, 1, i);
+ return n;
+}
+
+
+static int luaB_select (lua_State *L) {
+ int n = lua_gettop(L);
+ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
+ lua_pushinteger(L, n-1);
+ return 1;
+ }
+ else {
+ int i = luaL_checkint(L, 1);
+ if (i < 0) i = n + i;
+ else if (i > n) i = n;
+ luaL_argcheck(L, 1 <= i, 1, "index out of range");
+ return n - i;
+ }
+}
+
+
+static int luaB_pcall (lua_State *L) {
+ int status;
+ luaL_checkany(L, 1);
+ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
+ lua_pushboolean(L, (status == 0));
+ lua_insert(L, 1);
+ return lua_gettop(L); /* return status + all results */
+}
+
+
+static int luaB_xpcall (lua_State *L) {
+ int status;
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_insert(L, 1); /* put error function under function to be called */
+ status = lua_pcall(L, 0, LUA_MULTRET, 1);
+ lua_pushboolean(L, (status == 0));
+ lua_replace(L, 1);
+ return lua_gettop(L); /* return status + all results */
+}
+
+
+static int luaB_tostring (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
+ return 1; /* use its value */
+ switch (lua_type(L, 1)) {
+ case LUA_TNUMBER:
+ lua_pushstring(L, lua_tostring(L, 1));
+ break;
+ case LUA_TSTRING:
+ lua_pushvalue(L, 1);
+ break;
+ case LUA_TBOOLEAN:
+ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
+ break;
+ case LUA_TNIL:
+ lua_pushliteral(L, "nil");
+ break;
+ default:
+ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
+ break;
+ }
+ return 1;
+}
+
+
+static int luaB_newproxy (lua_State *L) {
+ lua_settop(L, 1);
+ lua_newuserdata(L, 0); /* create proxy */
+ if (lua_toboolean(L, 1) == 0)
+ return 1; /* no metatable */
+ else if (lua_isboolean(L, 1)) {
+ lua_newtable(L); /* create a new metatable `m' ... */
+ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
+ lua_pushboolean(L, 1);
+ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */
+ }
+ else {
+ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
+ if (lua_getmetatable(L, 1)) {
+ lua_rawget(L, lua_upvalueindex(1));
+ validproxy = lua_toboolean(L, -1);
+ lua_pop(L, 1); /* remove value */
+ }
+ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
+ lua_getmetatable(L, 1); /* metatable is valid; get it */
+ }
+ lua_setmetatable(L, 2);
+ return 1;
+}
+
+
+static const luaL_Reg base_funcs[] = {
+ {"assert", luaB_assert},
+ {"collectgarbage", luaB_collectgarbage},
+ {"dofile", luaB_dofile},
+ {"error", luaB_error},
+ {"gcinfo", luaB_gcinfo},
+ {"getfenv", luaB_getfenv},
+ {"getmetatable", luaB_getmetatable},
+ {"loadfile", luaB_loadfile},
+ {"load", luaB_load},
+ {"loadstring", luaB_loadstring},
+ {"next", luaB_next},
+ {"pcall", luaB_pcall},
+ {"print", luaB_print},
+ {"rawequal", luaB_rawequal},
+ {"rawget", luaB_rawget},
+ {"rawset", luaB_rawset},
+ {"select", luaB_select},
+ {"setfenv", luaB_setfenv},
+ {"setmetatable", luaB_setmetatable},
+ {"tonumber", luaB_tonumber},
+ {"tostring", luaB_tostring},
+ {"type", luaB_type},
+ {"unpack", luaB_unpack},
+ {"xpcall", luaB_xpcall},
+ {NULL, NULL}
+};
+
+
+/*
+** {======================================================
+** Coroutine library
+** =======================================================
+*/
+
+#define CO_RUN 0 /* running */
+#define CO_SUS 1 /* suspended */
+#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */
+#define CO_DEAD 3
+
+static const char *const statnames[] =
+ {"running", "suspended", "normal", "dead"};
+
+static int costatus (lua_State *L, lua_State *co) {
+ if (L == co) return CO_RUN;
+ switch (lua_status(co)) {
+ case LUA_YIELD:
+ return CO_SUS;
+ case 0: {
+ lua_Debug ar;
+ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
+ return CO_NOR; /* it is running */
+ else if (lua_gettop(co) == 0)
+ return CO_DEAD;
+ else
+ return CO_SUS; /* initial state */
+ }
+ default: /* some error occured */
+ return CO_DEAD;
+ }
+}
+
+
+static int luaB_costatus (lua_State *L) {
+ lua_State *co = lua_tothread(L, 1);
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ lua_pushstring(L, statnames[costatus(L, co)]);
+ return 1;
+}
+
+
+static int auxresume (lua_State *L, lua_State *co, int narg) {
+ int status = costatus(L, co);
+ if (!lua_checkstack(co, narg))
+ luaL_error(L, "too many arguments to resume");
+ if (status != CO_SUS) {
+ lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
+ return -1; /* error flag */
+ }
+ lua_xmove(L, co, narg);
+ lua_setlevel(L, co);
+ status = lua_resume(co, narg);
+ if (status == 0 || status == LUA_YIELD) {
+ int nres = lua_gettop(co);
+ if (!lua_checkstack(L, nres + 1))
+ luaL_error(L, "too many results to resume");
+ lua_xmove(co, L, nres); /* move yielded values */
+ return nres;
+ }
+ else {
+ lua_xmove(co, L, 1); /* move error message */
+ return -1; /* error flag */
+ }
+}
+
+
+static int luaB_coresume (lua_State *L) {
+ lua_State *co = lua_tothread(L, 1);
+ int r;
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ r = auxresume(L, co, lua_gettop(L) - 1);
+ if (r < 0) {
+ lua_pushboolean(L, 0);
+ lua_insert(L, -2);
+ return 2; /* return false + error message */
+ }
+ else {
+ lua_pushboolean(L, 1);
+ lua_insert(L, -(r + 1));
+ return r + 1; /* return true + `resume' returns */
+ }
+}
+
+
+static int luaB_auxwrap (lua_State *L) {
+ lua_State *co = lua_tothread(L, lua_upvalueindex(1));
+ int r = auxresume(L, co, lua_gettop(L));
+ if (r < 0) {
+ if (lua_isstring(L, -1)) { /* error object is a string? */
+ luaL_where(L, 1); /* add extra info */
+ lua_insert(L, -2);
+ lua_concat(L, 2);
+ }
+ lua_error(L); /* propagate error */
+ }
+ return r;
+}
+
+
+static int luaB_cocreate (lua_State *L) {
+ lua_State *NL = lua_newthread(L);
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
+ "Lua function expected");
+ lua_pushvalue(L, 1); /* move function to top */
+ lua_xmove(L, NL, 1); /* move function from L to NL */
+ return 1;
+}
+
+
+static int luaB_cowrap (lua_State *L) {
+ luaB_cocreate(L);
+ lua_pushcclosure(L, luaB_auxwrap, 1);
+ return 1;
+}
+
+
+static int luaB_yield (lua_State *L) {
+ return lua_yield(L, lua_gettop(L));
+}
+
+
+static int luaB_corunning (lua_State *L) {
+ if (lua_pushthread(L))
+ lua_pushnil(L); /* main thread is not a coroutine */
+ return 1;
+}
+
+
+static const luaL_Reg co_funcs[] = {
+ {"create", luaB_cocreate},
+ {"resume", luaB_coresume},
+ {"running", luaB_corunning},
+ {"status", luaB_costatus},
+ {"wrap", luaB_cowrap},
+ {"yield", luaB_yield},
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+static void auxopen (lua_State *L, const char *name,
+ lua_CFunction f, lua_CFunction u) {
+ lua_pushcfunction(L, u);
+ lua_pushcclosure(L, f, 1);
+ lua_setfield(L, -2, name);
+}
+
+
+static void base_open (lua_State *L) {
+ /* set global _G */
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setglobal(L, "_G");
+ /* open lib into global table */
+ luaL_register(L, "_G", base_funcs);
+ lua_pushliteral(L, LUA_VERSION);
+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+ auxopen(L, "pairs", luaB_pairs, luaB_next);
+ /* `newproxy' needs a weaktable as upvalue */
+ lua_createtable(L, 0, 1); /* new table `w' */
+ lua_pushvalue(L, -1); /* `w' will be its own metatable */
+ lua_setmetatable(L, -2);
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
+ lua_pushcclosure(L, luaB_newproxy, 1);
+ lua_setglobal(L, "newproxy"); /* set global `newproxy' */
+}
+
+
+LUALIB_API int luaopen_base (lua_State *L) {
+ base_open(L);
+ luaL_register(L, LUA_COLIBNAME, co_funcs);
+ return 2;
+}
+
diff --git a/lib/lua/src/lcode.c b/lib/lua/src/lcode.c
new file mode 100644
index 000000000..cff626b7f
--- /dev/null
+++ b/lib/lua/src/lcode.c
@@ -0,0 +1,839 @@
+/*
+** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+
+#define lcode_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lgc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "ltable.h"
+
+
+#define hasjumps(e) ((e)->t != (e)->f)
+
+
+static int isnumeral(expdesc *e) {
+ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
+}
+
+
+void luaK_nil (FuncState *fs, int from, int n) {
+ Instruction *previous;
+ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
+ if (fs->pc == 0) { /* function start? */
+ if (from >= fs->nactvar)
+ return; /* positions are already clean */
+ }
+ else {
+ previous = &fs->f->code[fs->pc-1];
+ if (GET_OPCODE(*previous) == OP_LOADNIL) {
+ int pfrom = GETARG_A(*previous);
+ int pto = GETARG_B(*previous);
+ if (pfrom <= from && from <= pto+1) { /* can connect both? */
+ if (from+n-1 > pto)
+ SETARG_B(*previous, from+n-1);
+ return;
+ }
+ }
+ }
+ }
+ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */
+}
+
+
+int luaK_jump (FuncState *fs) {
+ int jpc = fs->jpc; /* save list of jumps to here */
+ int j;
+ fs->jpc = NO_JUMP;
+ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
+ luaK_concat(fs, &j, jpc); /* keep them on hold */
+ return j;
+}
+
+
+void luaK_ret (FuncState *fs, int first, int nret) {
+ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
+}
+
+
+static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
+ luaK_codeABC(fs, op, A, B, C);
+ return luaK_jump(fs);
+}
+
+
+static void fixjump (FuncState *fs, int pc, int dest) {
+ Instruction *jmp = &fs->f->code[pc];
+ int offset = dest-(pc+1);
+ lua_assert(dest != NO_JUMP);
+ if (abs(offset) > MAXARG_sBx)
+ luaX_syntaxerror(fs->ls, "control structure too long");
+ SETARG_sBx(*jmp, offset);
+}
+
+
+/*
+** returns current `pc' and marks it as a jump target (to avoid wrong
+** optimizations with consecutive instructions not in the same basic block).
+*/
+int luaK_getlabel (FuncState *fs) {
+ fs->lasttarget = fs->pc;
+ return fs->pc;
+}
+
+
+static int getjump (FuncState *fs, int pc) {
+ int offset = GETARG_sBx(fs->f->code[pc]);
+ if (offset == NO_JUMP) /* point to itself represents end of list */
+ return NO_JUMP; /* end of list */
+ else
+ return (pc+1)+offset; /* turn offset into absolute position */
+}
+
+
+static Instruction *getjumpcontrol (FuncState *fs, int pc) {
+ Instruction *pi = &fs->f->code[pc];
+ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
+ return pi-1;
+ else
+ return pi;
+}
+
+
+/*
+** check whether list has any jump that do not produce a value
+** (or produce an inverted value)
+*/
+static int need_value (FuncState *fs, int list) {
+ for (; list != NO_JUMP; list = getjump(fs, list)) {
+ Instruction i = *getjumpcontrol(fs, list);
+ if (GET_OPCODE(i) != OP_TESTSET) return 1;
+ }
+ return 0; /* not found */
+}
+
+
+static int patchtestreg (FuncState *fs, int node, int reg) {
+ Instruction *i = getjumpcontrol(fs, node);
+ if (GET_OPCODE(*i) != OP_TESTSET)
+ return 0; /* cannot patch other instructions */
+ if (reg != NO_REG && reg != GETARG_B(*i))
+ SETARG_A(*i, reg);
+ else /* no register to put value or register already has the value */
+ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
+
+ return 1;
+}
+
+
+static void removevalues (FuncState *fs, int list) {
+ for (; list != NO_JUMP; list = getjump(fs, list))
+ patchtestreg(fs, list, NO_REG);
+}
+
+
+static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
+ int dtarget) {
+ while (list != NO_JUMP) {
+ int next = getjump(fs, list);
+ if (patchtestreg(fs, list, reg))
+ fixjump(fs, list, vtarget);
+ else
+ fixjump(fs, list, dtarget); /* jump to default target */
+ list = next;
+ }
+}
+
+
+static void dischargejpc (FuncState *fs) {
+ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
+ fs->jpc = NO_JUMP;
+}
+
+
+void luaK_patchlist (FuncState *fs, int list, int target) {
+ if (target == fs->pc)
+ luaK_patchtohere(fs, list);
+ else {
+ lua_assert(target < fs->pc);
+ patchlistaux(fs, list, target, NO_REG, target);
+ }
+}
+
+
+void luaK_patchtohere (FuncState *fs, int list) {
+ luaK_getlabel(fs);
+ luaK_concat(fs, &fs->jpc, list);
+}
+
+
+void luaK_concat (FuncState *fs, int *l1, int l2) {
+ if (l2 == NO_JUMP) return;
+ else if (*l1 == NO_JUMP)
+ *l1 = l2;
+ else {
+ int list = *l1;
+ int next;
+ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
+ list = next;
+ fixjump(fs, list, l2);
+ }
+}
+
+
+void luaK_checkstack (FuncState *fs, int n) {
+ int newstack = fs->freereg + n;
+ if (newstack > fs->f->maxstacksize) {
+ if (newstack >= MAXSTACK)
+ luaX_syntaxerror(fs->ls, "function or expression too complex");
+ fs->f->maxstacksize = cast_byte(newstack);
+ }
+}
+
+
+void luaK_reserveregs (FuncState *fs, int n) {
+ luaK_checkstack(fs, n);
+ fs->freereg += n;
+}
+
+
+static void freereg (FuncState *fs, int reg) {
+ if (!ISK(reg) && reg >= fs->nactvar) {
+ fs->freereg--;
+ lua_assert(reg == fs->freereg);
+ }
+}
+
+
+static void freeexp (FuncState *fs, expdesc *e) {
+ if (e->k == VNONRELOC)
+ freereg(fs, e->u.s.info);
+}
+
+
+static int addk (FuncState *fs, TValue *k, TValue *v) {
+ lua_State *L = fs->L;
+ TValue *idx = luaH_set(L, fs->h, k);
+ Proto *f = fs->f;
+ int oldsize = f->sizek;
+ if (ttisnumber(idx)) {
+ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+ return cast_int(nvalue(idx));
+ }
+ else { /* constant not found; create a new entry */
+ setnvalue(idx, cast_num(fs->nk));
+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+ setobj(L, &f->k[fs->nk], v);
+ luaC_barrier(L, f, v);
+ return fs->nk++;
+ }
+}
+
+
+int luaK_stringK (FuncState *fs, TString *s) {
+ TValue o;
+ setsvalue(fs->L, &o, s);
+ return addk(fs, &o, &o);
+}
+
+
+int luaK_numberK (FuncState *fs, lua_Number r) {
+ TValue o;
+ setnvalue(&o, r);
+ return addk(fs, &o, &o);
+}
+
+
+static int boolK (FuncState *fs, int b) {
+ TValue o;
+ setbvalue(&o, b);
+ return addk(fs, &o, &o);
+}
+
+
+static int nilK (FuncState *fs) {
+ TValue k, v;
+ setnilvalue(&v);
+ /* cannot use nil as key; instead use table itself to represent nil */
+ sethvalue(fs->L, &k, fs->h);
+ return addk(fs, &k, &v);
+}
+
+
+void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
+ if (e->k == VCALL) { /* expression is an open function call? */
+ SETARG_C(getcode(fs, e), nresults+1);
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), nresults+1);
+ SETARG_A(getcode(fs, e), fs->freereg);
+ luaK_reserveregs(fs, 1);
+ }
+}
+
+
+void luaK_setoneret (FuncState *fs, expdesc *e) {
+ if (e->k == VCALL) { /* expression is an open function call? */
+ e->k = VNONRELOC;
+ e->u.s.info = GETARG_A(getcode(fs, e));
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), 2);
+ e->k = VRELOCABLE; /* can relocate its simple result */
+ }
+}
+
+
+void luaK_dischargevars (FuncState *fs, expdesc *e) {
+ switch (e->k) {
+ case VLOCAL: {
+ e->k = VNONRELOC;
+ break;
+ }
+ case VUPVAL: {
+ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VGLOBAL: {
+ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VINDEXED: {
+ freereg(fs, e->u.s.aux);
+ freereg(fs, e->u.s.info);
+ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VVARARG:
+ case VCALL: {
+ luaK_setoneret(fs, e);
+ break;
+ }
+ default: break; /* there is one value available (somewhere) */
+ }
+}
+
+
+static int code_label (FuncState *fs, int A, int b, int jump) {
+ luaK_getlabel(fs); /* those instructions may be jump targets */
+ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
+}
+
+
+static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: {
+ luaK_nil(fs, reg, 1);
+ break;
+ }
+ case VFALSE: case VTRUE: {
+ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
+ break;
+ }
+ case VK: {
+ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
+ break;
+ }
+ case VKNUM: {
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+ break;
+ }
+ case VRELOCABLE: {
+ Instruction *pc = &getcode(fs, e);
+ SETARG_A(*pc, reg);
+ break;
+ }
+ case VNONRELOC: {
+ if (reg != e->u.s.info)
+ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
+ break;
+ }
+ default: {
+ lua_assert(e->k == VVOID || e->k == VJMP);
+ return; /* nothing to do... */
+ }
+ }
+ e->u.s.info = reg;
+ e->k = VNONRELOC;
+}
+
+
+static void discharge2anyreg (FuncState *fs, expdesc *e) {
+ if (e->k != VNONRELOC) {
+ luaK_reserveregs(fs, 1);
+ discharge2reg(fs, e, fs->freereg-1);
+ }
+}
+
+
+static void exp2reg (FuncState *fs, expdesc *e, int reg) {
+ discharge2reg(fs, e, reg);
+ if (e->k == VJMP)
+ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */
+ if (hasjumps(e)) {
+ int final; /* position after whole expression */
+ int p_f = NO_JUMP; /* position of an eventual LOAD false */
+ int p_t = NO_JUMP; /* position of an eventual LOAD true */
+ if (need_value(fs, e->t) || need_value(fs, e->f)) {
+ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
+ p_f = code_label(fs, reg, 0, 1);
+ p_t = code_label(fs, reg, 1, 0);
+ luaK_patchtohere(fs, fj);
+ }
+ final = luaK_getlabel(fs);
+ patchlistaux(fs, e->f, final, reg, p_f);
+ patchlistaux(fs, e->t, final, reg, p_t);
+ }
+ e->f = e->t = NO_JUMP;
+ e->u.s.info = reg;
+ e->k = VNONRELOC;
+}
+
+
+void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ freeexp(fs, e);
+ luaK_reserveregs(fs, 1);
+ exp2reg(fs, e, fs->freereg - 1);
+}
+
+
+int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ if (e->k == VNONRELOC) {
+ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */
+ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
+ exp2reg(fs, e, e->u.s.info); /* put value on it */
+ return e->u.s.info;
+ }
+ }
+ luaK_exp2nextreg(fs, e); /* default */
+ return e->u.s.info;
+}
+
+
+void luaK_exp2val (FuncState *fs, expdesc *e) {
+ if (hasjumps(e))
+ luaK_exp2anyreg(fs, e);
+ else
+ luaK_dischargevars(fs, e);
+}
+
+
+int luaK_exp2RK (FuncState *fs, expdesc *e) {
+ luaK_exp2val(fs, e);
+ switch (e->k) {
+ case VKNUM:
+ case VTRUE:
+ case VFALSE:
+ case VNIL: {
+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
+ e->u.s.info = (e->k == VNIL) ? nilK(fs) :
+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
+ boolK(fs, (e->k == VTRUE));
+ e->k = VK;
+ return RKASK(e->u.s.info);
+ }
+ else break;
+ }
+ case VK: {
+ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
+ return RKASK(e->u.s.info);
+ else break;
+ }
+ default: break;
+ }
+ /* not a constant in the right range: put it in a register */
+ return luaK_exp2anyreg(fs, e);
+}
+
+
+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
+ switch (var->k) {
+ case VLOCAL: {
+ freeexp(fs, ex);
+ exp2reg(fs, ex, var->u.s.info);
+ return;
+ }
+ case VUPVAL: {
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
+ break;
+ }
+ case VGLOBAL: {
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
+ break;
+ }
+ case VINDEXED: {
+ int e = luaK_exp2RK(fs, ex);
+ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
+ break;
+ }
+ default: {
+ lua_assert(0); /* invalid var kind to store */
+ break;
+ }
+ }
+ freeexp(fs, ex);
+}
+
+
+void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
+ int func;
+ luaK_exp2anyreg(fs, e);
+ freeexp(fs, e);
+ func = fs->freereg;
+ luaK_reserveregs(fs, 2);
+ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
+ freeexp(fs, key);
+ e->u.s.info = func;
+ e->k = VNONRELOC;
+}
+
+
+static void invertjump (FuncState *fs, expdesc *e) {
+ Instruction *pc = getjumpcontrol(fs, e->u.s.info);
+ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
+ GET_OPCODE(*pc) != OP_TEST);
+ SETARG_A(*pc, !(GETARG_A(*pc)));
+}
+
+
+static int jumponcond (FuncState *fs, expdesc *e, int cond) {
+ if (e->k == VRELOCABLE) {
+ Instruction ie = getcode(fs, e);
+ if (GET_OPCODE(ie) == OP_NOT) {
+ fs->pc--; /* remove previous OP_NOT */
+ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
+ }
+ /* else go through */
+ }
+ discharge2anyreg(fs, e);
+ freeexp(fs, e);
+ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
+}
+
+
+void luaK_goiftrue (FuncState *fs, expdesc *e) {
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VK: case VKNUM: case VTRUE: {
+ pc = NO_JUMP; /* always true; do nothing */
+ break;
+ }
+ case VFALSE: {
+ pc = luaK_jump(fs); /* always jump */
+ break;
+ }
+ case VJMP: {
+ invertjump(fs, e);
+ pc = e->u.s.info;
+ break;
+ }
+ default: {
+ pc = jumponcond(fs, e, 0);
+ break;
+ }
+ }
+ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
+ luaK_patchtohere(fs, e->t);
+ e->t = NO_JUMP;
+}
+
+
+static void luaK_goiffalse (FuncState *fs, expdesc *e) {
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: case VFALSE: {
+ pc = NO_JUMP; /* always false; do nothing */
+ break;
+ }
+ case VTRUE: {
+ pc = luaK_jump(fs); /* always jump */
+ break;
+ }
+ case VJMP: {
+ pc = e->u.s.info;
+ break;
+ }
+ default: {
+ pc = jumponcond(fs, e, 1);
+ break;
+ }
+ }
+ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
+ luaK_patchtohere(fs, e->f);
+ e->f = NO_JUMP;
+}
+
+
+static void codenot (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: case VFALSE: {
+ e->k = VTRUE;
+ break;
+ }
+ case VK: case VKNUM: case VTRUE: {
+ e->k = VFALSE;
+ break;
+ }
+ case VJMP: {
+ invertjump(fs, e);
+ break;
+ }
+ case VRELOCABLE:
+ case VNONRELOC: {
+ discharge2anyreg(fs, e);
+ freeexp(fs, e);
+ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
+ e->k = VRELOCABLE;
+ break;
+ }
+ default: {
+ lua_assert(0); /* cannot happen */
+ break;
+ }
+ }
+ /* interchange true and false lists */
+ { int temp = e->f; e->f = e->t; e->t = temp; }
+ removevalues(fs, e->f);
+ removevalues(fs, e->t);
+}
+
+
+void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
+ t->u.s.aux = luaK_exp2RK(fs, k);
+ t->k = VINDEXED;
+}
+
+
+static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+ lua_Number v1, v2, r;
+ if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+ v1 = e1->u.nval;
+ v2 = e2->u.nval;
+ switch (op) {
+ case OP_ADD: r = luai_numadd(v1, v2); break;
+ case OP_SUB: r = luai_numsub(v1, v2); break;
+ case OP_MUL: r = luai_nummul(v1, v2); break;
+ case OP_DIV:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_numdiv(v1, v2); break;
+ case OP_MOD:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_nummod(v1, v2); break;
+ case OP_POW: r = luai_numpow(v1, v2); break;
+ case OP_UNM: r = luai_numunm(v1); break;
+ case OP_LEN: return 0; /* no constant folding for 'len' */
+ default: lua_assert(0); r = 0; break;
+ }
+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
+ e1->u.nval = r;
+ return 1;
+}
+
+
+static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
+ if (constfolding(op, e1, e2))
+ return;
+ else {
+ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
+ int o1 = luaK_exp2RK(fs, e1);
+ if (o1 > o2) {
+ freeexp(fs, e1);
+ freeexp(fs, e2);
+ }
+ else {
+ freeexp(fs, e2);
+ freeexp(fs, e1);
+ }
+ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
+ e1->k = VRELOCABLE;
+ }
+}
+
+
+static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
+ expdesc *e2) {
+ int o1 = luaK_exp2RK(fs, e1);
+ int o2 = luaK_exp2RK(fs, e2);
+ freeexp(fs, e2);
+ freeexp(fs, e1);
+ if (cond == 0 && op != OP_EQ) {
+ int temp; /* exchange args to replace by `<' or `<=' */
+ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
+ cond = 1;
+ }
+ e1->u.s.info = condjump(fs, op, cond, o1, o2);
+ e1->k = VJMP;
+}
+
+
+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+ expdesc e2;
+ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
+ switch (op) {
+ case OPR_MINUS: {
+ if (!isnumeral(e))
+ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
+ codearith(fs, OP_UNM, e, &e2);
+ break;
+ }
+ case OPR_NOT: codenot(fs, e); break;
+ case OPR_LEN: {
+ luaK_exp2anyreg(fs, e); /* cannot operate on constants */
+ codearith(fs, OP_LEN, e, &e2);
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
+ switch (op) {
+ case OPR_AND: {
+ luaK_goiftrue(fs, v);
+ break;
+ }
+ case OPR_OR: {
+ luaK_goiffalse(fs, v);
+ break;
+ }
+ case OPR_CONCAT: {
+ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
+ break;
+ }
+ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
+ case OPR_MOD: case OPR_POW: {
+ if (!isnumeral(v)) luaK_exp2RK(fs, v);
+ break;
+ }
+ default: {
+ luaK_exp2RK(fs, v);
+ break;
+ }
+ }
+}
+
+
+void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
+ switch (op) {
+ case OPR_AND: {
+ lua_assert(e1->t == NO_JUMP); /* list must be closed */
+ luaK_dischargevars(fs, e2);
+ luaK_concat(fs, &e2->f, e1->f);
+ *e1 = *e2;
+ break;
+ }
+ case OPR_OR: {
+ lua_assert(e1->f == NO_JUMP); /* list must be closed */
+ luaK_dischargevars(fs, e2);
+ luaK_concat(fs, &e2->t, e1->t);
+ *e1 = *e2;
+ break;
+ }
+ case OPR_CONCAT: {
+ luaK_exp2val(fs, e2);
+ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
+ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
+ freeexp(fs, e1);
+ SETARG_B(getcode(fs, e2), e1->u.s.info);
+ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
+ }
+ else {
+ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
+ codearith(fs, OP_CONCAT, e1, e2);
+ }
+ break;
+ }
+ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
+ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
+ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
+ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
+ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
+ case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
+ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
+ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
+ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
+ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
+ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
+ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
+ default: lua_assert(0);
+ }
+}
+
+
+void luaK_fixline (FuncState *fs, int line) {
+ fs->f->lineinfo[fs->pc - 1] = line;
+}
+
+
+static int luaK_code (FuncState *fs, Instruction i, int line) {
+ Proto *f = fs->f;
+ dischargejpc(fs); /* `pc' will change */
+ /* put new instruction in code array */
+ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
+ MAX_INT, "code size overflow");
+ f->code[fs->pc] = i;
+ /* save corresponding line information */
+ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
+ MAX_INT, "code size overflow");
+ f->lineinfo[fs->pc] = line;
+ return fs->pc++;
+}
+
+
+int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
+ lua_assert(getOpMode(o) == iABC);
+ lua_assert(getBMode(o) != OpArgN || b == 0);
+ lua_assert(getCMode(o) != OpArgN || c == 0);
+ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
+}
+
+
+int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
+ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
+ lua_assert(getCMode(o) == OpArgN);
+ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
+}
+
+
+void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
+ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
+ int b = (tostore == LUA_MULTRET) ? 0 : tostore;
+ lua_assert(tostore != 0);
+ if (c <= MAXARG_C)
+ luaK_codeABC(fs, OP_SETLIST, base, b, c);
+ else {
+ luaK_codeABC(fs, OP_SETLIST, base, b, 0);
+ luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
+ }
+ fs->freereg = base + 1; /* free registers with list values */
+}
+
diff --git a/lib/lua/src/lcode.h b/lib/lua/src/lcode.h
new file mode 100644
index 000000000..b941c6072
--- /dev/null
+++ b/lib/lua/src/lcode.h
@@ -0,0 +1,76 @@
+/*
+** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lcode_h
+#define lcode_h
+
+#include "llex.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+
+
+/*
+** Marks the end of a patch list. It is an invalid value both as an absolute
+** address, and as a list link (would link an element to itself).
+*/
+#define NO_JUMP (-1)
+
+
+/*
+** grep "ORDER OPR" if you change these enums
+*/
+typedef enum BinOpr {
+ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
+ OPR_CONCAT,
+ OPR_NE, OPR_EQ,
+ OPR_LT, OPR_LE, OPR_GT, OPR_GE,
+ OPR_AND, OPR_OR,
+ OPR_NOBINOPR
+} BinOpr;
+
+
+typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
+
+
+#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info])
+
+#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
+
+#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
+
+LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
+LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
+LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
+LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
+LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
+LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
+LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
+LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
+LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
+LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
+LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
+LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
+LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_jump (FuncState *fs);
+LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
+LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
+LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
+LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
+LUAI_FUNC int luaK_getlabel (FuncState *fs);
+LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
+LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
+
+
+#endif
diff --git a/lib/lua/src/ldblib.c b/lib/lua/src/ldblib.c
new file mode 100644
index 000000000..67de1222a
--- /dev/null
+++ b/lib/lua/src/ldblib.c
@@ -0,0 +1,397 @@
+/*
+** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
+** Interface from Lua to its debug API
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ldblib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+static int db_getregistry (lua_State *L) {
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
+ return 1;
+}
+
+
+static int db_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L); /* no metatable */
+ }
+ return 1;
+}
+
+
+static int db_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ lua_settop(L, 2);
+ lua_pushboolean(L, lua_setmetatable(L, 1));
+ return 1;
+}
+
+
+static int db_getfenv (lua_State *L) {
+ lua_getfenv(L, 1);
+ return 1;
+}
+
+
+static int db_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_settop(L, 2);
+ if (lua_setfenv(L, 1) == 0)
+ luaL_error(L, LUA_QL("setfenv")
+ " cannot change environment of given object");
+ return 1;
+}
+
+
+static void settabss (lua_State *L, const char *i, const char *v) {
+ lua_pushstring(L, v);
+ lua_setfield(L, -2, i);
+}
+
+
+static void settabsi (lua_State *L, const char *i, int v) {
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, i);
+}
+
+
+static lua_State *getthread (lua_State *L, int *arg) {
+ if (lua_isthread(L, 1)) {
+ *arg = 1;
+ return lua_tothread(L, 1);
+ }
+ else {
+ *arg = 0;
+ return L;
+ }
+}
+
+
+static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
+ if (L == L1) {
+ lua_pushvalue(L, -2);
+ lua_remove(L, -3);
+ }
+ else
+ lua_xmove(L1, L, 1);
+ lua_setfield(L, -2, fname);
+}
+
+
+static int db_getinfo (lua_State *L) {
+ lua_Debug ar;
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ const char *options = luaL_optstring(L, arg+2, "flnSu");
+ if (lua_isnumber(L, arg+1)) {
+ if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
+ lua_pushnil(L); /* level out of range */
+ return 1;
+ }
+ }
+ else if (lua_isfunction(L, arg+1)) {
+ lua_pushfstring(L, ">%s", options);
+ options = lua_tostring(L, -1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
+ }
+ else
+ return luaL_argerror(L, arg+1, "function or level expected");
+ if (!lua_getinfo(L1, options, &ar))
+ return luaL_argerror(L, arg+2, "invalid option");
+ lua_createtable(L, 0, 2);
+ if (strchr(options, 'S')) {
+ settabss(L, "source", ar.source);
+ settabss(L, "short_src", ar.short_src);
+ settabsi(L, "linedefined", ar.linedefined);
+ settabsi(L, "lastlinedefined", ar.lastlinedefined);
+ settabss(L, "what", ar.what);
+ }
+ if (strchr(options, 'l'))
+ settabsi(L, "currentline", ar.currentline);
+ if (strchr(options, 'u'))
+ settabsi(L, "nups", ar.nups);
+ if (strchr(options, 'n')) {
+ settabss(L, "name", ar.name);
+ settabss(L, "namewhat", ar.namewhat);
+ }
+ if (strchr(options, 'L'))
+ treatstackoption(L, L1, "activelines");
+ if (strchr(options, 'f'))
+ treatstackoption(L, L1, "func");
+ return 1; /* return table */
+}
+
+
+static int db_getlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ const char *name;
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
+ if (name) {
+ lua_xmove(L1, L, 1);
+ lua_pushstring(L, name);
+ lua_pushvalue(L, -2);
+ return 2;
+ }
+ else {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+
+static int db_setlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ luaL_checkany(L, arg+3);
+ lua_settop(L, arg+3);
+ lua_xmove(L, L1, 1);
+ lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
+ return 1;
+}
+
+
+static int auxupvalue (lua_State *L, int get) {
+ const char *name;
+ int n = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */
+ name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
+ if (name == NULL) return 0;
+ lua_pushstring(L, name);
+ lua_insert(L, -(get+1));
+ return get + 1;
+}
+
+
+static int db_getupvalue (lua_State *L) {
+ return auxupvalue(L, 1);
+}
+
+
+static int db_setupvalue (lua_State *L) {
+ luaL_checkany(L, 3);
+ return auxupvalue(L, 0);
+}
+
+
+
+static const char KEY_HOOK = 'h';
+
+
+static void hookf (lua_State *L, lua_Debug *ar) {
+ static const char *const hooknames[] =
+ {"call", "return", "line", "count", "tail return"};
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, L);
+ lua_rawget(L, -2);
+ if (lua_isfunction(L, -1)) {
+ lua_pushstring(L, hooknames[(int)ar->event]);
+ if (ar->currentline >= 0)
+ lua_pushinteger(L, ar->currentline);
+ else lua_pushnil(L);
+ lua_assert(lua_getinfo(L, "lS", ar));
+ lua_call(L, 2, 0);
+ }
+}
+
+
+static int makemask (const char *smask, int count) {
+ int mask = 0;
+ if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
+ if (strchr(smask, 'r')) mask |= LUA_MASKRET;
+ if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+ if (count > 0) mask |= LUA_MASKCOUNT;
+ return mask;
+}
+
+
+static char *unmakemask (int mask, char *smask) {
+ int i = 0;
+ if (mask & LUA_MASKCALL) smask[i++] = 'c';
+ if (mask & LUA_MASKRET) smask[i++] = 'r';
+ if (mask & LUA_MASKLINE) smask[i++] = 'l';
+ smask[i] = '\0';
+ return smask;
+}
+
+
+static void gethooktable (lua_State *L) {
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ lua_createtable(L, 0, 1);
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+}
+
+
+static int db_sethook (lua_State *L) {
+ int arg, mask, count;
+ lua_Hook func;
+ lua_State *L1 = getthread(L, &arg);
+ if (lua_isnoneornil(L, arg+1)) {
+ lua_settop(L, arg+1);
+ func = NULL; mask = 0; count = 0; /* turn off hooks */
+ }
+ else {
+ const char *smask = luaL_checkstring(L, arg+2);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ count = luaL_optint(L, arg+3, 0);
+ func = hookf; mask = makemask(smask, count);
+ }
+ gethooktable(L);
+ lua_pushlightuserdata(L, L1);
+ lua_pushvalue(L, arg+1);
+ lua_rawset(L, -3); /* set new hook */
+ lua_pop(L, 1); /* remove hook table */
+ lua_sethook(L1, func, mask, count); /* set hooks */
+ return 0;
+}
+
+
+static int db_gethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ char buff[5];
+ int mask = lua_gethookmask(L1);
+ lua_Hook hook = lua_gethook(L1);
+ if (hook != NULL && hook != hookf) /* external hook? */
+ lua_pushliteral(L, "external hook");
+ else {
+ gethooktable(L);
+ lua_pushlightuserdata(L, L1);
+ lua_rawget(L, -2); /* get hook */
+ lua_remove(L, -2); /* remove hook table */
+ }
+ lua_pushstring(L, unmakemask(mask, buff));
+ lua_pushinteger(L, lua_gethookcount(L1));
+ return 3;
+}
+
+
+static int db_debug (lua_State *L) {
+ for (;;) {
+ char buffer[250];
+ fputs("lua_debug> ", stderr);
+ if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
+ strcmp(buffer, "cont\n") == 0)
+ return 0;
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
+ lua_pcall(L, 0, 0, 0)) {
+ fputs(lua_tostring(L, -1), stderr);
+ fputs("\n", stderr);
+ }
+ lua_settop(L, 0); /* remove eventual returns */
+ }
+}
+
+
+#define LEVELS1 12 /* size of the first part of the stack */
+#define LEVELS2 10 /* size of the second part of the stack */
+
+static int db_errorfb (lua_State *L) {
+ int level;
+ int firstpart = 1; /* still before eventual `...' */
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ if (lua_isnumber(L, arg+2)) {
+ level = (int)lua_tointeger(L, arg+2);
+ lua_pop(L, 1);
+ }
+ else
+ level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
+ if (lua_gettop(L) == arg)
+ lua_pushliteral(L, "");
+ else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
+ else lua_pushliteral(L, "\n");
+ lua_pushliteral(L, "stack traceback:");
+ while (lua_getstack(L1, level++, &ar)) {
+ if (level > LEVELS1 && firstpart) {
+ /* no more than `LEVELS2' more levels? */
+ if (!lua_getstack(L1, level+LEVELS2, &ar))
+ level--; /* keep going */
+ else {
+ lua_pushliteral(L, "\n\t..."); /* too many levels */
+ while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
+ level++;
+ }
+ firstpart = 0;
+ continue;
+ }
+ lua_pushliteral(L, "\n\t");
+ lua_getinfo(L1, "Snl", &ar);
+ lua_pushfstring(L, "%s:", ar.short_src);
+ if (ar.currentline > 0)
+ lua_pushfstring(L, "%d:", ar.currentline);
+ if (*ar.namewhat != '\0') /* is there a name? */
+ lua_pushfstring(L, " in function " LUA_QS, ar.name);
+ else {
+ if (*ar.what == 'm') /* main? */
+ lua_pushfstring(L, " in main chunk");
+ else if (*ar.what == 'C' || *ar.what == 't')
+ lua_pushliteral(L, " ?"); /* C function or tail call */
+ else
+ lua_pushfstring(L, " in function <%s:%d>",
+ ar.short_src, ar.linedefined);
+ }
+ lua_concat(L, lua_gettop(L) - arg);
+ }
+ lua_concat(L, lua_gettop(L) - arg);
+ return 1;
+}
+
+
+static const luaL_Reg dblib[] = {
+ {"debug", db_debug},
+ {"getfenv", db_getfenv},
+ {"gethook", db_gethook},
+ {"getinfo", db_getinfo},
+ {"getlocal", db_getlocal},
+ {"getregistry", db_getregistry},
+ {"getmetatable", db_getmetatable},
+ {"getupvalue", db_getupvalue},
+ {"setfenv", db_setfenv},
+ {"sethook", db_sethook},
+ {"setlocal", db_setlocal},
+ {"setmetatable", db_setmetatable},
+ {"setupvalue", db_setupvalue},
+ {"traceback", db_errorfb},
+ {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_debug (lua_State *L) {
+ luaL_register(L, LUA_DBLIBNAME, dblib);
+ return 1;
+}
+
diff --git a/lib/lua/src/ldebug.c b/lib/lua/src/ldebug.c
new file mode 100644
index 000000000..50ad3d380
--- /dev/null
+++ b/lib/lua/src/ldebug.c
@@ -0,0 +1,638 @@
+/*
+** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $
+** Debug Interface
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+
+
+#define ldebug_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+
+
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
+
+
+static int currentpc (lua_State *L, CallInfo *ci) {
+ if (!isLua(ci)) return -1; /* function is not a Lua function? */
+ if (ci == L->ci)
+ ci->savedpc = L->savedpc;
+ return pcRel(ci->savedpc, ci_func(ci)->l.p);
+}
+
+
+static int currentline (lua_State *L, CallInfo *ci) {
+ int pc = currentpc(L, ci);
+ if (pc < 0)
+ return -1; /* only active lua functions have current-line information */
+ else
+ return getline(ci_func(ci)->l.p, pc);
+}
+
+
+/*
+** this function can be called asynchronous (e.g. during a signal)
+*/
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
+ if (func == NULL || mask == 0) { /* turn off hooks? */
+ mask = 0;
+ func = NULL;
+ }
+ L->hook = func;
+ L->basehookcount = count;
+ resethookcount(L);
+ L->hookmask = cast_byte(mask);
+ return 1;
+}
+
+
+LUA_API lua_Hook lua_gethook (lua_State *L) {
+ return L->hook;
+}
+
+
+LUA_API int lua_gethookmask (lua_State *L) {
+ return L->hookmask;
+}
+
+
+LUA_API int lua_gethookcount (lua_State *L) {
+ return L->basehookcount;
+}
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
+ int status;
+ CallInfo *ci;
+ lua_lock(L);
+ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
+ level--;
+ if (f_isLua(ci)) /* Lua function? */
+ level -= ci->tailcalls; /* skip lost tail calls */
+ }
+ if (level == 0 && ci > L->base_ci) { /* level found? */
+ status = 1;
+ ar->i_ci = cast_int(ci - L->base_ci);
+ }
+ else if (level < 0) { /* level is of a lost tail call? */
+ status = 1;
+ ar->i_ci = 0;
+ }
+ else status = 0; /* no such level */
+ lua_unlock(L);
+ return status;
+}
+
+
+static Proto *getluaproto (CallInfo *ci) {
+ return (isLua(ci) ? ci_func(ci)->l.p : NULL);
+}
+
+
+static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
+ const char *name;
+ Proto *fp = getluaproto(ci);
+ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
+ return name; /* is a local variable in a Lua function */
+ else {
+ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
+ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */
+ return "(*temporary)";
+ else
+ return NULL;
+ }
+}
+
+
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
+ lua_lock(L);
+ if (name)
+ luaA_pushobject(L, ci->base + (n - 1));
+ lua_unlock(L);
+ return name;
+}
+
+
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
+ lua_lock(L);
+ if (name)
+ setobjs2s(L, ci->base + (n - 1), L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+ return name;
+}
+
+
+static void funcinfo (lua_Debug *ar, Closure *cl) {
+ if (cl->c.isC) {
+ ar->source = "=[C]";
+ ar->linedefined = -1;
+ ar->lastlinedefined = -1;
+ ar->what = "C";
+ }
+ else {
+ ar->source = getstr(cl->l.p->source);
+ ar->linedefined = cl->l.p->linedefined;
+ ar->lastlinedefined = cl->l.p->lastlinedefined;
+ ar->what = (ar->linedefined == 0) ? "main" : "Lua";
+ }
+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+}
+
+
+static void info_tailcall (lua_Debug *ar) {
+ ar->name = ar->namewhat = "";
+ ar->what = "tail";
+ ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
+ ar->source = "=(tail call)";
+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+ ar->nups = 0;
+}
+
+
+static void collectvalidlines (lua_State *L, Closure *f) {
+ if (f == NULL || f->c.isC) {
+ setnilvalue(L->top);
+ }
+ else {
+ Table *t = luaH_new(L, 0, 0);
+ int *lineinfo = f->l.p->lineinfo;
+ int i;
+ for (i=0; i<f->l.p->sizelineinfo; i++)
+ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
+ sethvalue(L, L->top, t);
+ }
+ incr_top(L);
+}
+
+
+static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
+ Closure *f, CallInfo *ci) {
+ int status = 1;
+ if (f == NULL) {
+ info_tailcall(ar);
+ return status;
+ }
+ for (; *what; what++) {
+ switch (*what) {
+ case 'S': {
+ funcinfo(ar, f);
+ break;
+ }
+ case 'l': {
+ ar->currentline = (ci) ? currentline(L, ci) : -1;
+ break;
+ }
+ case 'u': {
+ ar->nups = f->c.nupvalues;
+ break;
+ }
+ case 'n': {
+ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
+ if (ar->namewhat == NULL) {
+ ar->namewhat = ""; /* not found */
+ ar->name = NULL;
+ }
+ break;
+ }
+ case 'L':
+ case 'f': /* handled by lua_getinfo */
+ break;
+ default: status = 0; /* invalid option */
+ }
+ }
+ return status;
+}
+
+
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
+ int status;
+ Closure *f = NULL;
+ CallInfo *ci = NULL;
+ lua_lock(L);
+ if (*what == '>') {
+ StkId func = L->top - 1;
+ luai_apicheck(L, ttisfunction(func));
+ what++; /* skip the '>' */
+ f = clvalue(func);
+ L->top--; /* pop function */
+ }
+ else if (ar->i_ci != 0) { /* no tail call? */
+ ci = L->base_ci + ar->i_ci;
+ lua_assert(ttisfunction(ci->func));
+ f = clvalue(ci->func);
+ }
+ status = auxgetinfo(L, what, ar, f, ci);
+ if (strchr(what, 'f')) {
+ if (f == NULL) setnilvalue(L->top);
+ else setclvalue(L, L->top, f);
+ incr_top(L);
+ }
+ if (strchr(what, 'L'))
+ collectvalidlines(L, f);
+ lua_unlock(L);
+ return status;
+}
+
+
+/*
+** {======================================================
+** Symbolic Execution and code checker
+** =======================================================
+*/
+
+#define check(x) if (!(x)) return 0;
+
+#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode)
+
+#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize)
+
+
+
+static int precheck (const Proto *pt) {
+ check(pt->maxstacksize <= MAXSTACK);
+ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
+ check(!(pt->is_vararg & VARARG_NEEDSARG) ||
+ (pt->is_vararg & VARARG_HASARG));
+ check(pt->sizeupvalues <= pt->nups);
+ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
+ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
+ return 1;
+}
+
+
+#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
+
+int luaG_checkopenop (Instruction i) {
+ switch (GET_OPCODE(i)) {
+ case OP_CALL:
+ case OP_TAILCALL:
+ case OP_RETURN:
+ case OP_SETLIST: {
+ check(GETARG_B(i) == 0);
+ return 1;
+ }
+ default: return 0; /* invalid instruction after an open call */
+ }
+}
+
+
+static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
+ switch (mode) {
+ case OpArgN: check(r == 0); break;
+ case OpArgU: break;
+ case OpArgR: checkreg(pt, r); break;
+ case OpArgK:
+ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
+ break;
+ }
+ return 1;
+}
+
+
+static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
+ int pc;
+ int last; /* stores position of last instruction that changed `reg' */
+ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
+ check(precheck(pt));
+ for (pc = 0; pc < lastpc; pc++) {
+ Instruction i = pt->code[pc];
+ OpCode op = GET_OPCODE(i);
+ int a = GETARG_A(i);
+ int b = 0;
+ int c = 0;
+ check(op < NUM_OPCODES);
+ checkreg(pt, a);
+ switch (getOpMode(op)) {
+ case iABC: {
+ b = GETARG_B(i);
+ c = GETARG_C(i);
+ check(checkArgMode(pt, b, getBMode(op)));
+ check(checkArgMode(pt, c, getCMode(op)));
+ break;
+ }
+ case iABx: {
+ b = GETARG_Bx(i);
+ if (getBMode(op) == OpArgK) check(b < pt->sizek);
+ break;
+ }
+ case iAsBx: {
+ b = GETARG_sBx(i);
+ if (getBMode(op) == OpArgR) {
+ int dest = pc+1+b;
+ check(0 <= dest && dest < pt->sizecode);
+ if (dest > 0) {
+ int j;
+ /* check that it does not jump to a setlist count; this
+ is tricky, because the count from a previous setlist may
+ have the same value of an invalid setlist; so, we must
+ go all the way back to the first of them (if any) */
+ for (j = 0; j < dest; j++) {
+ Instruction d = pt->code[dest-1-j];
+ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
+ }
+ /* if 'j' is even, previous value is not a setlist (even if
+ it looks like one) */
+ check((j&1) == 0);
+ }
+ }
+ break;
+ }
+ }
+ if (testAMode(op)) {
+ if (a == reg) last = pc; /* change register `a' */
+ }
+ if (testTMode(op)) {
+ check(pc+2 < pt->sizecode); /* check skip */
+ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
+ }
+ switch (op) {
+ case OP_LOADBOOL: {
+ if (c == 1) { /* does it jump? */
+ check(pc+2 < pt->sizecode); /* check its jump */
+ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
+ GETARG_C(pt->code[pc+1]) != 0);
+ }
+ break;
+ }
+ case OP_LOADNIL: {
+ if (a <= reg && reg <= b)
+ last = pc; /* set registers from `a' to `b' */
+ break;
+ }
+ case OP_GETUPVAL:
+ case OP_SETUPVAL: {
+ check(b < pt->nups);
+ break;
+ }
+ case OP_GETGLOBAL:
+ case OP_SETGLOBAL: {
+ check(ttisstring(&pt->k[b]));
+ break;
+ }
+ case OP_SELF: {
+ checkreg(pt, a+1);
+ if (reg == a+1) last = pc;
+ break;
+ }
+ case OP_CONCAT: {
+ check(b < c); /* at least two operands */
+ break;
+ }
+ case OP_TFORLOOP: {
+ check(c >= 1); /* at least one result (control variable) */
+ checkreg(pt, a+2+c); /* space for results */
+ if (reg >= a+2) last = pc; /* affect all regs above its base */
+ break;
+ }
+ case OP_FORLOOP:
+ case OP_FORPREP:
+ checkreg(pt, a+3);
+ /* go through */
+ case OP_JMP: {
+ int dest = pc+1+b;
+ /* not full check and jump is forward and do not skip `lastpc'? */
+ if (reg != NO_REG && pc < dest && dest <= lastpc)
+ pc += b; /* do the jump */
+ break;
+ }
+ case OP_CALL:
+ case OP_TAILCALL: {
+ if (b != 0) {
+ checkreg(pt, a+b-1);
+ }
+ c--; /* c = num. returns */
+ if (c == LUA_MULTRET) {
+ check(checkopenop(pt, pc));
+ }
+ else if (c != 0)
+ checkreg(pt, a+c-1);
+ if (reg >= a) last = pc; /* affect all registers above base */
+ break;
+ }
+ case OP_RETURN: {
+ b--; /* b = num. returns */
+ if (b > 0) checkreg(pt, a+b-1);
+ break;
+ }
+ case OP_SETLIST: {
+ if (b > 0) checkreg(pt, a + b);
+ if (c == 0) {
+ pc++;
+ check(pc < pt->sizecode - 1);
+ }
+ break;
+ }
+ case OP_CLOSURE: {
+ int nup, j;
+ check(b < pt->sizep);
+ nup = pt->p[b]->nups;
+ check(pc + nup < pt->sizecode);
+ for (j = 1; j <= nup; j++) {
+ OpCode op1 = GET_OPCODE(pt->code[pc + j]);
+ check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
+ }
+ if (reg != NO_REG) /* tracing? */
+ pc += nup; /* do not 'execute' these pseudo-instructions */
+ break;
+ }
+ case OP_VARARG: {
+ check((pt->is_vararg & VARARG_ISVARARG) &&
+ !(pt->is_vararg & VARARG_NEEDSARG));
+ b--;
+ if (b == LUA_MULTRET) check(checkopenop(pt, pc));
+ checkreg(pt, a+b-1);
+ break;
+ }
+ default: break;
+ }
+ }
+ return pt->code[last];
+}
+
+#undef check
+#undef checkjump
+#undef checkreg
+
+/* }====================================================== */
+
+
+int luaG_checkcode (const Proto *pt) {
+ return (symbexec(pt, pt->sizecode, NO_REG) != 0);
+}
+
+
+static const char *kname (Proto *p, int c) {
+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
+ return svalue(&p->k[INDEXK(c)]);
+ else
+ return "?";
+}
+
+
+static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
+ const char **name) {
+ if (isLua(ci)) { /* a Lua function? */
+ Proto *p = ci_func(ci)->l.p;
+ int pc = currentpc(L, ci);
+ Instruction i;
+ *name = luaF_getlocalname(p, stackpos+1, pc);
+ if (*name) /* is a local? */
+ return "local";
+ i = symbexec(p, pc, stackpos); /* try symbolic execution */
+ lua_assert(pc != -1);
+ switch (GET_OPCODE(i)) {
+ case OP_GETGLOBAL: {
+ int g = GETARG_Bx(i); /* global index */
+ lua_assert(ttisstring(&p->k[g]));
+ *name = svalue(&p->k[g]);
+ return "global";
+ }
+ case OP_MOVE: {
+ int a = GETARG_A(i);
+ int b = GETARG_B(i); /* move from `b' to `a' */
+ if (b < a)
+ return getobjname(L, ci, b, name); /* get name for `b' */
+ break;
+ }
+ case OP_GETTABLE: {
+ int k = GETARG_C(i); /* key index */
+ *name = kname(p, k);
+ return "field";
+ }
+ case OP_GETUPVAL: {
+ int u = GETARG_B(i); /* upvalue index */
+ *name = p->upvalues ? getstr(p->upvalues[u]) : "?";
+ return "upvalue";
+ }
+ case OP_SELF: {
+ int k = GETARG_C(i); /* key index */
+ *name = kname(p, k);
+ return "method";
+ }
+ default: break;
+ }
+ }
+ return NULL; /* no useful name found */
+}
+
+
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
+ Instruction i;
+ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
+ return NULL; /* calling function is not Lua (or is unknown) */
+ ci--; /* calling function */
+ i = ci_func(ci)->l.p->code[currentpc(L, ci)];
+ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
+ GET_OPCODE(i) == OP_TFORLOOP)
+ return getobjname(L, ci, GETARG_A(i), name);
+ else
+ return NULL; /* no useful name can be found */
+}
+
+
+/* only ANSI way to check whether a pointer points to an array */
+static int isinstack (CallInfo *ci, const TValue *o) {
+ StkId p;
+ for (p = ci->base; p < ci->top; p++)
+ if (o == p) return 1;
+ return 0;
+}
+
+
+void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+ const char *name = NULL;
+ const char *t = luaT_typenames[ttype(o)];
+ const char *kind = (isinstack(L->ci, o)) ?
+ getobjname(L, L->ci, cast_int(o - L->base), &name) :
+ NULL;
+ if (kind)
+ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
+ op, kind, name, t);
+ else
+ luaG_runerror(L, "attempt to %s a %s value", op, t);
+}
+
+
+void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
+ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
+ lua_assert(!ttisstring(p1) && !ttisnumber(p1));
+ luaG_typeerror(L, p1, "concatenate");
+}
+
+
+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
+ TValue temp;
+ if (luaV_tonumber(p1, &temp) == NULL)
+ p2 = p1; /* first operand is wrong */
+ luaG_typeerror(L, p2, "perform arithmetic on");
+}
+
+
+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
+ const char *t1 = luaT_typenames[ttype(p1)];
+ const char *t2 = luaT_typenames[ttype(p2)];
+ if (t1[2] == t2[2])
+ luaG_runerror(L, "attempt to compare two %s values", t1);
+ else
+ luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
+ return 0;
+}
+
+
+static void addinfo (lua_State *L, const char *msg) {
+ CallInfo *ci = L->ci;
+ if (isLua(ci)) { /* is Lua code? */
+ char buff[LUA_IDSIZE]; /* add file:line information */
+ int line = currentline(L, ci);
+ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
+ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
+ }
+}
+
+
+void luaG_errormsg (lua_State *L) {
+ if (L->errfunc != 0) { /* is there an error handling function? */
+ StkId errfunc = restorestack(L, L->errfunc);
+ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
+ setobjs2s(L, L->top, L->top - 1); /* move argument */
+ setobjs2s(L, L->top - 1, errfunc); /* push function */
+ incr_top(L);
+ luaD_call(L, L->top - 2, 1); /* call it */
+ }
+ luaD_throw(L, LUA_ERRRUN);
+}
+
+
+void luaG_runerror (lua_State *L, const char *fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ addinfo(L, luaO_pushvfstring(L, fmt, argp));
+ va_end(argp);
+ luaG_errormsg(L);
+}
+
diff --git a/lib/lua/src/ldebug.h b/lib/lua/src/ldebug.h
new file mode 100644
index 000000000..ba28a9724
--- /dev/null
+++ b/lib/lua/src/ldebug.h
@@ -0,0 +1,33 @@
+/*
+** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions from Debug Interface module
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldebug_h
+#define ldebug_h
+
+
+#include "lstate.h"
+
+
+#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
+
+#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
+
+#define resethookcount(L) (L->hookcount = L->basehookcount)
+
+
+LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,
+ const char *opname);
+LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
+LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,
+ const TValue *p2);
+LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,
+ const TValue *p2);
+LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);
+LUAI_FUNC void luaG_errormsg (lua_State *L);
+LUAI_FUNC int luaG_checkcode (const Proto *pt);
+LUAI_FUNC int luaG_checkopenop (Instruction i);
+
+#endif
diff --git a/lib/lua/src/ldo.c b/lib/lua/src/ldo.c
new file mode 100644
index 000000000..8de05f728
--- /dev/null
+++ b/lib/lua/src/ldo.c
@@ -0,0 +1,518 @@
+/*
+** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ldo_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+#include "lzio.h"
+
+
+
+
+/*
+** {======================================================
+** Error-recovery functions
+** =======================================================
+*/
+
+
+/* chain list of long jump buffers */
+struct lua_longjmp {
+ struct lua_longjmp *previous;
+ luai_jmpbuf b;
+ volatile int status; /* error code */
+};
+
+
+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
+ switch (errcode) {
+ case LUA_ERRMEM: {
+ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
+ break;
+ }
+ case LUA_ERRERR: {
+ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
+ break;
+ }
+ case LUA_ERRSYNTAX:
+ case LUA_ERRRUN: {
+ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
+ break;
+ }
+ }
+ L->top = oldtop + 1;
+}
+
+
+static void restore_stack_limit (lua_State *L) {
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
+ int inuse = cast_int(L->ci - L->base_ci);
+ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
+ luaD_reallocCI(L, LUAI_MAXCALLS);
+ }
+}
+
+
+static void resetstack (lua_State *L, int status) {
+ L->ci = L->base_ci;
+ L->base = L->ci->base;
+ luaF_close(L, L->base); /* close eventual pending closures */
+ luaD_seterrorobj(L, status, L->base);
+ L->nCcalls = L->baseCcalls;
+ L->allowhook = 1;
+ restore_stack_limit(L);
+ L->errfunc = 0;
+ L->errorJmp = NULL;
+}
+
+
+void luaD_throw (lua_State *L, int errcode) {
+ if (L->errorJmp) {
+ L->errorJmp->status = errcode;
+ LUAI_THROW(L, L->errorJmp);
+ }
+ else {
+ L->status = cast_byte(errcode);
+ if (G(L)->panic) {
+ resetstack(L, errcode);
+ lua_unlock(L);
+ G(L)->panic(L);
+ }
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
+ struct lua_longjmp lj;
+ lj.status = 0;
+ lj.previous = L->errorJmp; /* chain new error handler */
+ L->errorJmp = &lj;
+ LUAI_TRY(L, &lj,
+ (*f)(L, ud);
+ );
+ L->errorJmp = lj.previous; /* restore old error handler */
+ return lj.status;
+}
+
+/* }====================================================== */
+
+
+static void correctstack (lua_State *L, TValue *oldstack) {
+ CallInfo *ci;
+ GCObject *up;
+ L->top = (L->top - oldstack) + L->stack;
+ for (up = L->openupval; up != NULL; up = up->gch.next)
+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
+ for (ci = L->base_ci; ci <= L->ci; ci++) {
+ ci->top = (ci->top - oldstack) + L->stack;
+ ci->base = (ci->base - oldstack) + L->stack;
+ ci->func = (ci->func - oldstack) + L->stack;
+ }
+ L->base = (L->base - oldstack) + L->stack;
+}
+
+
+void luaD_reallocstack (lua_State *L, int newsize) {
+ TValue *oldstack = L->stack;
+ int realsize = newsize + 1 + EXTRA_STACK;
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
+ L->stacksize = realsize;
+ L->stack_last = L->stack+newsize;
+ correctstack(L, oldstack);
+}
+
+
+void luaD_reallocCI (lua_State *L, int newsize) {
+ CallInfo *oldci = L->base_ci;
+ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
+ L->size_ci = newsize;
+ L->ci = (L->ci - oldci) + L->base_ci;
+ L->end_ci = L->base_ci + L->size_ci - 1;
+}
+
+
+void luaD_growstack (lua_State *L, int n) {
+ if (n <= L->stacksize) /* double size is enough? */
+ luaD_reallocstack(L, 2*L->stacksize);
+ else
+ luaD_reallocstack(L, L->stacksize + n);
+}
+
+
+static CallInfo *growCI (lua_State *L) {
+ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */
+ luaD_throw(L, LUA_ERRERR);
+ else {
+ luaD_reallocCI(L, 2*L->size_ci);
+ if (L->size_ci > LUAI_MAXCALLS)
+ luaG_runerror(L, "stack overflow");
+ }
+ return ++L->ci;
+}
+
+
+void luaD_callhook (lua_State *L, int event, int line) {
+ lua_Hook hook = L->hook;
+ if (hook && L->allowhook) {
+ ptrdiff_t top = savestack(L, L->top);
+ ptrdiff_t ci_top = savestack(L, L->ci->top);
+ lua_Debug ar;
+ ar.event = event;
+ ar.currentline = line;
+ if (event == LUA_HOOKTAILRET)
+ ar.i_ci = 0; /* tail call; no debug information about it */
+ else
+ ar.i_ci = cast_int(L->ci - L->base_ci);
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ L->ci->top = L->top + LUA_MINSTACK;
+ lua_assert(L->ci->top <= L->stack_last);
+ L->allowhook = 0; /* cannot call hooks inside a hook */
+ lua_unlock(L);
+ (*hook)(L, &ar);
+ lua_lock(L);
+ lua_assert(!L->allowhook);
+ L->allowhook = 1;
+ L->ci->top = restorestack(L, ci_top);
+ L->top = restorestack(L, top);
+ }
+}
+
+
+static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
+ int i;
+ int nfixargs = p->numparams;
+ Table *htab = NULL;
+ StkId base, fixed;
+ for (; actual < nfixargs; ++actual)
+ setnilvalue(L->top++);
+#if defined(LUA_COMPAT_VARARG)
+ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
+ int nvar = actual - nfixargs; /* number of extra arguments */
+ lua_assert(p->is_vararg & VARARG_HASARG);
+ luaC_checkGC(L);
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+ setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
+ /* store counter in field `n' */
+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
+ }
+#endif
+ /* move fixed parameters to final position */
+ fixed = L->top - actual; /* first fixed argument */
+ base = L->top; /* final position of first argument */
+ for (i=0; i<nfixargs; i++) {
+ setobjs2s(L, L->top++, fixed+i);
+ setnilvalue(fixed+i);
+ }
+ /* add `arg' parameter */
+ if (htab) {
+ sethvalue(L, L->top++, htab);
+ lua_assert(iswhite(obj2gco(htab)));
+ }
+ return base;
+}
+
+
+static StkId tryfuncTM (lua_State *L, StkId func) {
+ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
+ StkId p;
+ ptrdiff_t funcr = savestack(L, func);
+ if (!ttisfunction(tm))
+ luaG_typeerror(L, func, "call");
+ /* Open a hole inside the stack at `func' */
+ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
+ incr_top(L);
+ func = restorestack(L, funcr); /* previous call may change stack */
+ setobj2s(L, func, tm); /* tag method is the new function to be called */
+ return func;
+}
+
+
+
+#define inc_ci(L) \
+ ((L->ci == L->end_ci) ? growCI(L) : \
+ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
+
+
+int luaD_precall (lua_State *L, StkId func, int nresults) {
+ LClosure *cl;
+ ptrdiff_t funcr;
+ if (!ttisfunction(func)) /* `func' is not a function? */
+ func = tryfuncTM(L, func); /* check the `function' tag method */
+ funcr = savestack(L, func);
+ cl = &clvalue(func)->l;
+ L->ci->savedpc = L->savedpc;
+ if (!cl->isC) { /* Lua function? prepare its call */
+ CallInfo *ci;
+ StkId st, base;
+ Proto *p = cl->p;
+ luaD_checkstack(L, p->maxstacksize);
+ func = restorestack(L, funcr);
+ if (!p->is_vararg) { /* no varargs? */
+ base = func + 1;
+ if (L->top > base + p->numparams)
+ L->top = base + p->numparams;
+ }
+ else { /* vararg function */
+ int nargs = cast_int(L->top - func) - 1;
+ base = adjust_varargs(L, p, nargs);
+ func = restorestack(L, funcr); /* previous call may change the stack */
+ }
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = func;
+ L->base = ci->base = base;
+ ci->top = L->base + p->maxstacksize;
+ lua_assert(ci->top <= L->stack_last);
+ L->savedpc = p->code; /* starting point */
+ ci->tailcalls = 0;
+ ci->nresults = nresults;
+ for (st = L->top; st < ci->top; st++)
+ setnilvalue(st);
+ L->top = ci->top;
+ if (L->hookmask & LUA_MASKCALL) {
+ L->savedpc++; /* hooks assume 'pc' is already incremented */
+ luaD_callhook(L, LUA_HOOKCALL, -1);
+ L->savedpc--; /* correct 'pc' */
+ }
+ return PCRLUA;
+ }
+ else { /* if is a C function, call it */
+ CallInfo *ci;
+ int n;
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = restorestack(L, funcr);
+ L->base = ci->base = ci->func + 1;
+ ci->top = L->top + LUA_MINSTACK;
+ lua_assert(ci->top <= L->stack_last);
+ ci->nresults = nresults;
+ if (L->hookmask & LUA_MASKCALL)
+ luaD_callhook(L, LUA_HOOKCALL, -1);
+ lua_unlock(L);
+ n = (*curr_func(L)->c.f)(L); /* do the actual call */
+ lua_lock(L);
+ if (n < 0) /* yielding? */
+ return PCRYIELD;
+ else {
+ luaD_poscall(L, L->top - n);
+ return PCRC;
+ }
+ }
+}
+
+
+static StkId callrethooks (lua_State *L, StkId firstResult) {
+ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
+ luaD_callhook(L, LUA_HOOKRET, -1);
+ if (f_isLua(L->ci)) { /* Lua function? */
+ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
+ luaD_callhook(L, LUA_HOOKTAILRET, -1);
+ }
+ return restorestack(L, fr);
+}
+
+
+int luaD_poscall (lua_State *L, StkId firstResult) {
+ StkId res;
+ int wanted, i;
+ CallInfo *ci;
+ if (L->hookmask & LUA_MASKRET)
+ firstResult = callrethooks(L, firstResult);
+ ci = L->ci--;
+ res = ci->func; /* res == final position of 1st result */
+ wanted = ci->nresults;
+ L->base = (ci - 1)->base; /* restore base */
+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
+ /* move results to correct place */
+ for (i = wanted; i != 0 && firstResult < L->top; i--)
+ setobjs2s(L, res++, firstResult++);
+ while (i-- > 0)
+ setnilvalue(res++);
+ L->top = res;
+ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
+}
+
+
+/*
+** Call a function (C or Lua). The function to be called is at *func.
+** The arguments are on the stack, right after the function.
+** When returns, all the results are on the stack, starting at the original
+** function position.
+*/
+void luaD_call (lua_State *L, StkId func, int nResults) {
+ if (++L->nCcalls >= LUAI_MAXCCALLS) {
+ if (L->nCcalls == LUAI_MAXCCALLS)
+ luaG_runerror(L, "C stack overflow");
+ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
+ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
+ }
+ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
+ luaV_execute(L, 1); /* call it */
+ L->nCcalls--;
+ luaC_checkGC(L);
+}
+
+
+static void resume (lua_State *L, void *ud) {
+ StkId firstArg = cast(StkId, ud);
+ CallInfo *ci = L->ci;
+ if (L->status == 0) { /* start coroutine? */
+ lua_assert(ci == L->base_ci && firstArg > L->base);
+ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
+ return;
+ }
+ else { /* resuming from previous yield */
+ lua_assert(L->status == LUA_YIELD);
+ L->status = 0;
+ if (!f_isLua(ci)) { /* `common' yield? */
+ /* finish interrupted execution of `OP_CALL' */
+ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
+ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
+ if (luaD_poscall(L, firstArg)) /* complete it... */
+ L->top = L->ci->top; /* and correct top if not multiple results */
+ }
+ else /* yielded inside a hook: just continue its execution */
+ L->base = L->ci->base;
+ }
+ luaV_execute(L, cast_int(L->ci - L->base_ci));
+}
+
+
+static int resume_error (lua_State *L, const char *msg) {
+ L->top = L->ci->base;
+ setsvalue2s(L, L->top, luaS_new(L, msg));
+ incr_top(L);
+ lua_unlock(L);
+ return LUA_ERRRUN;
+}
+
+
+LUA_API int lua_resume (lua_State *L, int nargs) {
+ int status;
+ lua_lock(L);
+ if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
+ return resume_error(L, "cannot resume non-suspended coroutine");
+ if (L->nCcalls >= LUAI_MAXCCALLS)
+ return resume_error(L, "C stack overflow");
+ luai_userstateresume(L, nargs);
+ lua_assert(L->errfunc == 0);
+ L->baseCcalls = ++L->nCcalls;
+ status = luaD_rawrunprotected(L, resume, L->top - nargs);
+ if (status != 0) { /* error? */
+ L->status = cast_byte(status); /* mark thread as `dead' */
+ luaD_seterrorobj(L, status, L->top);
+ L->ci->top = L->top;
+ }
+ else {
+ lua_assert(L->nCcalls == L->baseCcalls);
+ status = L->status;
+ }
+ --L->nCcalls;
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_yield (lua_State *L, int nresults) {
+ luai_userstateyield(L, nresults);
+ lua_lock(L);
+ if (L->nCcalls > L->baseCcalls)
+ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
+ L->base = L->top - nresults; /* protect stack slots below */
+ L->status = LUA_YIELD;
+ lua_unlock(L);
+ return -1;
+}
+
+
+int luaD_pcall (lua_State *L, Pfunc func, void *u,
+ ptrdiff_t old_top, ptrdiff_t ef) {
+ int status;
+ unsigned short oldnCcalls = L->nCcalls;
+ ptrdiff_t old_ci = saveci(L, L->ci);
+ lu_byte old_allowhooks = L->allowhook;
+ ptrdiff_t old_errfunc = L->errfunc;
+ L->errfunc = ef;
+ status = luaD_rawrunprotected(L, func, u);
+ if (status != 0) { /* an error occurred? */
+ StkId oldtop = restorestack(L, old_top);
+ luaF_close(L, oldtop); /* close eventual pending closures */
+ luaD_seterrorobj(L, status, oldtop);
+ L->nCcalls = oldnCcalls;
+ L->ci = restoreci(L, old_ci);
+ L->base = L->ci->base;
+ L->savedpc = L->ci->savedpc;
+ L->allowhook = old_allowhooks;
+ restore_stack_limit(L);
+ }
+ L->errfunc = old_errfunc;
+ return status;
+}
+
+
+
+/*
+** Execute a protected parser.
+*/
+struct SParser { /* data to `f_parser' */
+ ZIO *z;
+ Mbuffer buff; /* buffer to be used by the scanner */
+ const char *name;
+};
+
+static void f_parser (lua_State *L, void *ud) {
+ int i;
+ Proto *tf;
+ Closure *cl;
+ struct SParser *p = cast(struct SParser *, ud);
+ int c = luaZ_lookahead(p->z);
+ luaC_checkGC(L);
+ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
+ &p->buff, p->name);
+ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
+ cl->l.p = tf;
+ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
+ cl->l.upvals[i] = luaF_newupval(L);
+ setclvalue(L, L->top, cl);
+ incr_top(L);
+}
+
+
+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
+ struct SParser p;
+ int status;
+ p.z = z; p.name = name;
+ luaZ_initbuffer(L, &p.buff);
+ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
+ luaZ_freebuffer(L, &p.buff);
+ return status;
+}
+
+
diff --git a/lib/lua/src/ldo.h b/lib/lua/src/ldo.h
new file mode 100644
index 000000000..98fddac59
--- /dev/null
+++ b/lib/lua/src/ldo.h
@@ -0,0 +1,57 @@
+/*
+** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldo_h
+#define ldo_h
+
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+#define luaD_checkstack(L,n) \
+ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
+ luaD_growstack(L, n); \
+ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
+
+
+#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
+
+#define savestack(L,p) ((char *)(p) - (char *)L->stack)
+#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
+
+#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
+#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
+
+
+/* results from luaD_precall */
+#define PCRLUA 0 /* initiated a call to a Lua function */
+#define PCRC 1 /* did a call to a C function */
+#define PCRYIELD 2 /* C funtion yielded */
+
+
+/* type of protected functions, to be ran by `runprotected' */
+typedef void (*Pfunc) (lua_State *L, void *ud);
+
+LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
+LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
+LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
+LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
+ ptrdiff_t oldtop, ptrdiff_t ef);
+LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
+LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
+LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
+LUAI_FUNC void luaD_growstack (lua_State *L, int n);
+
+LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
+LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
+
+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
+
+#endif
+
diff --git a/lib/lua/src/ldump.c b/lib/lua/src/ldump.c
new file mode 100644
index 000000000..c9d3d4870
--- /dev/null
+++ b/lib/lua/src/ldump.c
@@ -0,0 +1,164 @@
+/*
+** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
+** save precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#include <stddef.h>
+
+#define ldump_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lundump.h"
+
+typedef struct {
+ lua_State* L;
+ lua_Writer writer;
+ void* data;
+ int strip;
+ int status;
+} DumpState;
+
+#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
+#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
+
+static void DumpBlock(const void* b, size_t size, DumpState* D)
+{
+ if (D->status==0)
+ {
+ lua_unlock(D->L);
+ D->status=(*D->writer)(D->L,b,size,D->data);
+ lua_lock(D->L);
+ }
+}
+
+static void DumpChar(int y, DumpState* D)
+{
+ char x=(char)y;
+ DumpVar(x,D);
+}
+
+static void DumpInt(int x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
+static void DumpNumber(lua_Number x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
+static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+{
+ DumpInt(n,D);
+ DumpMem(b,n,size,D);
+}
+
+static void DumpString(const TString* s, DumpState* D)
+{
+ if (s==NULL || getstr(s)==NULL)
+ {
+ size_t size=0;
+ DumpVar(size,D);
+ }
+ else
+ {
+ size_t size=s->tsv.len+1; /* include trailing '\0' */
+ DumpVar(size,D);
+ DumpBlock(getstr(s),size,D);
+ }
+}
+
+#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
+
+static void DumpConstants(const Proto* f, DumpState* D)
+{
+ int i,n=f->sizek;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+ const TValue* o=&f->k[i];
+ DumpChar(ttype(o),D);
+ switch (ttype(o))
+ {
+ case LUA_TNIL:
+ break;
+ case LUA_TBOOLEAN:
+ DumpChar(bvalue(o),D);
+ break;
+ case LUA_TNUMBER:
+ DumpNumber(nvalue(o),D);
+ break;
+ case LUA_TSTRING:
+ DumpString(rawtsvalue(o),D);
+ break;
+ default:
+ lua_assert(0); /* cannot happen */
+ break;
+ }
+ }
+ n=f->sizep;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
+}
+
+static void DumpDebug(const Proto* f, DumpState* D)
+{
+ int i,n;
+ n= (D->strip) ? 0 : f->sizelineinfo;
+ DumpVector(f->lineinfo,n,sizeof(int),D);
+ n= (D->strip) ? 0 : f->sizelocvars;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+ DumpString(f->locvars[i].varname,D);
+ DumpInt(f->locvars[i].startpc,D);
+ DumpInt(f->locvars[i].endpc,D);
+ }
+ n= (D->strip) ? 0 : f->sizeupvalues;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
+}
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
+{
+ DumpString((f->source==p || D->strip) ? NULL : f->source,D);
+ DumpInt(f->linedefined,D);
+ DumpInt(f->lastlinedefined,D);
+ DumpChar(f->nups,D);
+ DumpChar(f->numparams,D);
+ DumpChar(f->is_vararg,D);
+ DumpChar(f->maxstacksize,D);
+ DumpCode(f,D);
+ DumpConstants(f,D);
+ DumpDebug(f,D);
+}
+
+static void DumpHeader(DumpState* D)
+{
+ char h[LUAC_HEADERSIZE];
+ luaU_header(h);
+ DumpBlock(h,LUAC_HEADERSIZE,D);
+}
+
+/*
+** dump Lua function as precompiled chunk
+*/
+int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
+{
+ DumpState D;
+ D.L=L;
+ D.writer=w;
+ D.data=data;
+ D.strip=strip;
+ D.status=0;
+ DumpHeader(&D);
+ DumpFunction(f,NULL,&D);
+ return D.status;
+}
diff --git a/lib/lua/src/lfunc.c b/lib/lua/src/lfunc.c
new file mode 100644
index 000000000..813e88f58
--- /dev/null
+++ b/lib/lua/src/lfunc.c
@@ -0,0 +1,174 @@
+/*
+** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lfunc_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
+ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
+ c->c.isC = 1;
+ c->c.env = e;
+ c->c.nupvalues = cast_byte(nelems);
+ return c;
+}
+
+
+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
+ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
+ c->l.isC = 0;
+ c->l.env = e;
+ c->l.nupvalues = cast_byte(nelems);
+ while (nelems--) c->l.upvals[nelems] = NULL;
+ return c;
+}
+
+
+UpVal *luaF_newupval (lua_State *L) {
+ UpVal *uv = luaM_new(L, UpVal);
+ luaC_link(L, obj2gco(uv), LUA_TUPVAL);
+ uv->v = &uv->u.value;
+ setnilvalue(uv->v);
+ return uv;
+}
+
+
+UpVal *luaF_findupval (lua_State *L, StkId level) {
+ global_State *g = G(L);
+ GCObject **pp = &L->openupval;
+ UpVal *p;
+ UpVal *uv;
+ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
+ lua_assert(p->v != &p->u.value);
+ if (p->v == level) { /* found a corresponding upvalue? */
+ if (isdead(g, obj2gco(p))) /* is it dead? */
+ changewhite(obj2gco(p)); /* ressurect it */
+ return p;
+ }
+ pp = &p->next;
+ }
+ uv = luaM_new(L, UpVal); /* not found: create a new one */
+ uv->tt = LUA_TUPVAL;
+ uv->marked = luaC_white(g);
+ uv->v = level; /* current value lives in the stack */
+ uv->next = *pp; /* chain it in the proper position */
+ *pp = obj2gco(uv);
+ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
+ uv->u.l.next = g->uvhead.u.l.next;
+ uv->u.l.next->u.l.prev = uv;
+ g->uvhead.u.l.next = uv;
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ return uv;
+}
+
+
+static void unlinkupval (UpVal *uv) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */
+ uv->u.l.prev->u.l.next = uv->u.l.next;
+}
+
+
+void luaF_freeupval (lua_State *L, UpVal *uv) {
+ if (uv->v != &uv->u.value) /* is it open? */
+ unlinkupval(uv); /* remove from open list */
+ luaM_free(L, uv); /* free upvalue */
+}
+
+
+void luaF_close (lua_State *L, StkId level) {
+ UpVal *uv;
+ global_State *g = G(L);
+ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
+ GCObject *o = obj2gco(uv);
+ lua_assert(!isblack(o) && uv->v != &uv->u.value);
+ L->openupval = uv->next; /* remove from `open' list */
+ if (isdead(g, o))
+ luaF_freeupval(L, uv); /* free upvalue */
+ else {
+ unlinkupval(uv);
+ setobj(L, &uv->u.value, uv->v);
+ uv->v = &uv->u.value; /* now current value lives here */
+ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
+ }
+ }
+}
+
+
+Proto *luaF_newproto (lua_State *L) {
+ Proto *f = luaM_new(L, Proto);
+ luaC_link(L, obj2gco(f), LUA_TPROTO);
+ f->k = NULL;
+ f->sizek = 0;
+ f->p = NULL;
+ f->sizep = 0;
+ f->code = NULL;
+ f->sizecode = 0;
+ f->sizelineinfo = 0;
+ f->sizeupvalues = 0;
+ f->nups = 0;
+ f->upvalues = NULL;
+ f->numparams = 0;
+ f->is_vararg = 0;
+ f->maxstacksize = 0;
+ f->lineinfo = NULL;
+ f->sizelocvars = 0;
+ f->locvars = NULL;
+ f->linedefined = 0;
+ f->lastlinedefined = 0;
+ f->source = NULL;
+ return f;
+}
+
+
+void luaF_freeproto (lua_State *L, Proto *f) {
+ luaM_freearray(L, f->code, f->sizecode, Instruction);
+ luaM_freearray(L, f->p, f->sizep, Proto *);
+ luaM_freearray(L, f->k, f->sizek, TValue);
+ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
+ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
+ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
+ luaM_free(L, f);
+}
+
+
+void luaF_freeclosure (lua_State *L, Closure *c) {
+ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
+ sizeLclosure(c->l.nupvalues);
+ luaM_freemem(L, c, size);
+}
+
+
+/*
+** Look for n-th local variable at line `line' in function `func'.
+** Returns NULL if not found.
+*/
+const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
+ int i;
+ for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
+ if (pc < f->locvars[i].endpc) { /* is variable active? */
+ local_number--;
+ if (local_number == 0)
+ return getstr(f->locvars[i].varname);
+ }
+ }
+ return NULL; /* not found */
+}
+
diff --git a/lib/lua/src/lfunc.h b/lib/lua/src/lfunc.h
new file mode 100644
index 000000000..a68cf5151
--- /dev/null
+++ b/lib/lua/src/lfunc.h
@@ -0,0 +1,34 @@
+/*
+** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lfunc_h
+#define lfunc_h
+
+
+#include "lobject.h"
+
+
+#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
+ cast(int, sizeof(TValue)*((n)-1)))
+
+#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
+ cast(int, sizeof(TValue *)*((n)-1)))
+
+
+LUAI_FUNC Proto *luaF_newproto (lua_State *L);
+LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
+LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
+LUAI_FUNC void luaF_close (lua_State *L, StkId level);
+LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
+LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
+LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
+LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
+ int pc);
+
+
+#endif
diff --git a/lib/lua/src/lgc.c b/lib/lua/src/lgc.c
new file mode 100644
index 000000000..d9e0b7829
--- /dev/null
+++ b/lib/lua/src/lgc.c
@@ -0,0 +1,711 @@
+/*
+** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#include <string.h>
+
+#define lgc_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+#define GCSTEPSIZE 1024u
+#define GCSWEEPMAX 40
+#define GCSWEEPCOST 10
+#define GCFINALIZECOST 100
+
+
+#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
+
+#define makewhite(g,x) \
+ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
+
+#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
+
+#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
+
+
+#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
+#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
+
+
+#define KEYWEAK bitmask(KEYWEAKBIT)
+#define VALUEWEAK bitmask(VALUEWEAKBIT)
+
+
+
+#define markvalue(g,o) { checkconsistency(o); \
+ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
+
+#define markobject(g,t) { if (iswhite(obj2gco(t))) \
+ reallymarkobject(g, obj2gco(t)); }
+
+
+#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
+
+
+static void removeentry (Node *n) {
+ lua_assert(ttisnil(gval(n)));
+ if (iscollectable(gkey(n)))
+ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
+}
+
+
+static void reallymarkobject (global_State *g, GCObject *o) {
+ lua_assert(iswhite(o) && !isdead(g, o));
+ white2gray(o);
+ switch (o->gch.tt) {
+ case LUA_TSTRING: {
+ return;
+ }
+ case LUA_TUSERDATA: {
+ Table *mt = gco2u(o)->metatable;
+ gray2black(o); /* udata are never gray */
+ if (mt) markobject(g, mt);
+ markobject(g, gco2u(o)->env);
+ return;
+ }
+ case LUA_TUPVAL: {
+ UpVal *uv = gco2uv(o);
+ markvalue(g, uv->v);
+ if (uv->v == &uv->u.value) /* closed? */
+ gray2black(o); /* open upvalues are never black */
+ return;
+ }
+ case LUA_TFUNCTION: {
+ gco2cl(o)->c.gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TTABLE: {
+ gco2h(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TTHREAD: {
+ gco2th(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TPROTO: {
+ gco2p(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+static void marktmu (global_State *g) {
+ GCObject *u = g->tmudata;
+ if (u) {
+ do {
+ u = u->gch.next;
+ makewhite(g, u); /* may be marked, if left from previous GC */
+ reallymarkobject(g, u);
+ } while (u != g->tmudata);
+ }
+}
+
+
+/* move `dead' udata that need finalization to list `tmudata' */
+size_t luaC_separateudata (lua_State *L, int all) {
+ global_State *g = G(L);
+ size_t deadmem = 0;
+ GCObject **p = &g->mainthread->next;
+ GCObject *curr;
+ while ((curr = *p) != NULL) {
+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
+ p = &curr->gch.next; /* don't bother with them */
+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
+ markfinalized(gco2u(curr)); /* don't need finalization */
+ p = &curr->gch.next;
+ }
+ else { /* must call its gc method */
+ deadmem += sizeudata(gco2u(curr));
+ markfinalized(gco2u(curr));
+ *p = curr->gch.next;
+ /* link `curr' at the end of `tmudata' list */
+ if (g->tmudata == NULL) /* list is empty? */
+ g->tmudata = curr->gch.next = curr; /* creates a circular list */
+ else {
+ curr->gch.next = g->tmudata->gch.next;
+ g->tmudata->gch.next = curr;
+ g->tmudata = curr;
+ }
+ }
+ }
+ return deadmem;
+}
+
+
+static int traversetable (global_State *g, Table *h) {
+ int i;
+ int weakkey = 0;
+ int weakvalue = 0;
+ const TValue *mode;
+ if (h->metatable)
+ markobject(g, h->metatable);
+ mode = gfasttm(g, h->metatable, TM_MODE);
+ if (mode && ttisstring(mode)) { /* is there a weak mode? */
+ weakkey = (strchr(svalue(mode), 'k') != NULL);
+ weakvalue = (strchr(svalue(mode), 'v') != NULL);
+ if (weakkey || weakvalue) { /* is really weak? */
+ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
+ h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
+ (weakvalue << VALUEWEAKBIT));
+ h->gclist = g->weak; /* must be cleared after GC, ... */
+ g->weak = obj2gco(h); /* ... so put in the appropriate list */
+ }
+ }
+ if (weakkey && weakvalue) return 1;
+ if (!weakvalue) {
+ i = h->sizearray;
+ while (i--)
+ markvalue(g, &h->array[i]);
+ }
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
+ if (ttisnil(gval(n)))
+ removeentry(n); /* remove empty entries */
+ else {
+ lua_assert(!ttisnil(gkey(n)));
+ if (!weakkey) markvalue(g, gkey(n));
+ if (!weakvalue) markvalue(g, gval(n));
+ }
+ }
+ return weakkey || weakvalue;
+}
+
+
+/*
+** All marks are conditional because a GC may happen while the
+** prototype is still being created
+*/
+static void traverseproto (global_State *g, Proto *f) {
+ int i;
+ if (f->source) stringmark(f->source);
+ for (i=0; i<f->sizek; i++) /* mark literals */
+ markvalue(g, &f->k[i]);
+ for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
+ if (f->upvalues[i])
+ stringmark(f->upvalues[i]);
+ }
+ for (i=0; i<f->sizep; i++) { /* mark nested protos */
+ if (f->p[i])
+ markobject(g, f->p[i]);
+ }
+ for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
+ if (f->locvars[i].varname)
+ stringmark(f->locvars[i].varname);
+ }
+}
+
+
+
+static void traverseclosure (global_State *g, Closure *cl) {
+ markobject(g, cl->c.env);
+ if (cl->c.isC) {
+ int i;
+ for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
+ markvalue(g, &cl->c.upvalue[i]);
+ }
+ else {
+ int i;
+ lua_assert(cl->l.nupvalues == cl->l.p->nups);
+ markobject(g, cl->l.p);
+ for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */
+ markobject(g, cl->l.upvals[i]);
+ }
+}
+
+
+static void checkstacksizes (lua_State *L, StkId max) {
+ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */
+ int s_used = cast_int(max - L->stack); /* part of stack in use */
+ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */
+ return; /* do not touch the stacks */
+ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
+ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
+ condhardstacktests(luaD_reallocCI(L, ci_used + 1));
+ if (4*s_used < L->stacksize &&
+ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
+ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
+ condhardstacktests(luaD_reallocstack(L, s_used));
+}
+
+
+static void traversestack (global_State *g, lua_State *l) {
+ StkId o, lim;
+ CallInfo *ci;
+ markvalue(g, gt(l));
+ lim = l->top;
+ for (ci = l->base_ci; ci <= l->ci; ci++) {
+ lua_assert(ci->top <= l->stack_last);
+ if (lim < ci->top) lim = ci->top;
+ }
+ for (o = l->stack; o < l->top; o++)
+ markvalue(g, o);
+ for (; o <= lim; o++)
+ setnilvalue(o);
+ checkstacksizes(l, lim);
+}
+
+
+/*
+** traverse one gray object, turning it to black.
+** Returns `quantity' traversed.
+*/
+static l_mem propagatemark (global_State *g) {
+ GCObject *o = g->gray;
+ lua_assert(isgray(o));
+ gray2black(o);
+ switch (o->gch.tt) {
+ case LUA_TTABLE: {
+ Table *h = gco2h(o);
+ g->gray = h->gclist;
+ if (traversetable(g, h)) /* table is weak? */
+ black2gray(o); /* keep it gray */
+ return sizeof(Table) + sizeof(TValue) * h->sizearray +
+ sizeof(Node) * sizenode(h);
+ }
+ case LUA_TFUNCTION: {
+ Closure *cl = gco2cl(o);
+ g->gray = cl->c.gclist;
+ traverseclosure(g, cl);
+ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
+ sizeLclosure(cl->l.nupvalues);
+ }
+ case LUA_TTHREAD: {
+ lua_State *th = gco2th(o);
+ g->gray = th->gclist;
+ th->gclist = g->grayagain;
+ g->grayagain = o;
+ black2gray(o);
+ traversestack(g, th);
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * th->size_ci;
+ }
+ case LUA_TPROTO: {
+ Proto *p = gco2p(o);
+ g->gray = p->gclist;
+ traverseproto(g, p);
+ return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
+ sizeof(Proto *) * p->sizep +
+ sizeof(TValue) * p->sizek +
+ sizeof(int) * p->sizelineinfo +
+ sizeof(LocVar) * p->sizelocvars +
+ sizeof(TString *) * p->sizeupvalues;
+ }
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+static size_t propagateall (global_State *g) {
+ size_t m = 0;
+ while (g->gray) m += propagatemark(g);
+ return m;
+}
+
+
+/*
+** The next function tells whether a key or value can be cleared from
+** a weak table. Non-collectable objects are never removed from weak
+** tables. Strings behave as `values', so are never removed too. for
+** other objects: if really collected, cannot keep them; for userdata
+** being finalized, keep them in keys, but not in values
+*/
+static int iscleared (const TValue *o, int iskey) {
+ if (!iscollectable(o)) return 0;
+ if (ttisstring(o)) {
+ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
+ return 0;
+ }
+ return iswhite(gcvalue(o)) ||
+ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
+}
+
+
+/*
+** clear collected entries from weaktables
+*/
+static void cleartable (GCObject *l) {
+ while (l) {
+ Table *h = gco2h(l);
+ int i = h->sizearray;
+ lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
+ testbit(h->marked, KEYWEAKBIT));
+ if (testbit(h->marked, VALUEWEAKBIT)) {
+ while (i--) {
+ TValue *o = &h->array[i];
+ if (iscleared(o, 0)) /* value was collected? */
+ setnilvalue(o); /* remove value */
+ }
+ }
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ if (!ttisnil(gval(n)) && /* non-empty entry? */
+ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
+ setnilvalue(gval(n)); /* remove value ... */
+ removeentry(n); /* remove entry from table */
+ }
+ }
+ l = h->gclist;
+ }
+}
+
+
+static void freeobj (lua_State *L, GCObject *o) {
+ switch (o->gch.tt) {
+ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
+ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
+ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
+ case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
+ case LUA_TTHREAD: {
+ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
+ luaE_freethread(L, gco2th(o));
+ break;
+ }
+ case LUA_TSTRING: {
+ G(L)->strt.nuse--;
+ luaM_freemem(L, o, sizestring(gco2ts(o)));
+ break;
+ }
+ case LUA_TUSERDATA: {
+ luaM_freemem(L, o, sizeudata(gco2u(o)));
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+
+#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
+
+
+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
+ GCObject *curr;
+ global_State *g = G(L);
+ int deadmask = otherwhite(g);
+ while ((curr = *p) != NULL && count-- > 0) {
+ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
+ sweepwholelist(L, &gco2th(curr)->openupval);
+ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
+ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
+ makewhite(g, curr); /* make it white (for next cycle) */
+ p = &curr->gch.next;
+ }
+ else { /* must erase `curr' */
+ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
+ *p = curr->gch.next;
+ if (curr == g->rootgc) /* is the first element of the list? */
+ g->rootgc = curr->gch.next; /* adjust first */
+ freeobj(L, curr);
+ }
+ }
+ return p;
+}
+
+
+static void checkSizes (lua_State *L) {
+ global_State *g = G(L);
+ /* check size of string hash */
+ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
+ g->strt.size > MINSTRTABSIZE*2)
+ luaS_resize(L, g->strt.size/2); /* table is too big */
+ /* check size of buffer */
+ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
+ size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
+ luaZ_resizebuffer(L, &g->buff, newsize);
+ }
+}
+
+
+static void GCTM (lua_State *L) {
+ global_State *g = G(L);
+ GCObject *o = g->tmudata->gch.next; /* get first element */
+ Udata *udata = rawgco2u(o);
+ const TValue *tm;
+ /* remove udata from `tmudata' */
+ if (o == g->tmudata) /* last element? */
+ g->tmudata = NULL;
+ else
+ g->tmudata->gch.next = udata->uv.next;
+ udata->uv.next = g->mainthread->next; /* return it to `root' list */
+ g->mainthread->next = o;
+ makewhite(g, o);
+ tm = fasttm(L, udata->uv.metatable, TM_GC);
+ if (tm != NULL) {
+ lu_byte oldah = L->allowhook;
+ lu_mem oldt = g->GCthreshold;
+ L->allowhook = 0; /* stop debug hooks during GC tag method */
+ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */
+ setobj2s(L, L->top, tm);
+ setuvalue(L, L->top+1, udata);
+ L->top += 2;
+ luaD_call(L, L->top - 2, 0);
+ L->allowhook = oldah; /* restore hooks */
+ g->GCthreshold = oldt; /* restore threshold */
+ }
+}
+
+
+/*
+** Call all GC tag methods
+*/
+void luaC_callGCTM (lua_State *L) {
+ while (G(L)->tmudata)
+ GCTM(L);
+}
+
+
+void luaC_freeall (lua_State *L) {
+ global_State *g = G(L);
+ int i;
+ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */
+ sweepwholelist(L, &g->rootgc);
+ for (i = 0; i < g->strt.size; i++) /* free all string lists */
+ sweepwholelist(L, &g->strt.hash[i]);
+}
+
+
+static void markmt (global_State *g) {
+ int i;
+ for (i=0; i<NUM_TAGS; i++)
+ if (g->mt[i]) markobject(g, g->mt[i]);
+}
+
+
+/* mark root set */
+static void markroot (lua_State *L) {
+ global_State *g = G(L);
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ markobject(g, g->mainthread);
+ /* make global table be traversed before main stack */
+ markvalue(g, gt(g->mainthread));
+ markvalue(g, registry(L));
+ markmt(g);
+ g->gcstate = GCSpropagate;
+}
+
+
+static void remarkupvals (global_State *g) {
+ UpVal *uv;
+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ if (isgray(obj2gco(uv)))
+ markvalue(g, uv->v);
+ }
+}
+
+
+static void atomic (lua_State *L) {
+ global_State *g = G(L);
+ size_t udsize; /* total size of userdata to be finalized */
+ /* remark occasional upvalues of (maybe) dead threads */
+ remarkupvals(g);
+ /* traverse objects cautch by write barrier and by 'remarkupvals' */
+ propagateall(g);
+ /* remark weak tables */
+ g->gray = g->weak;
+ g->weak = NULL;
+ lua_assert(!iswhite(obj2gco(g->mainthread)));
+ markobject(g, L); /* mark running thread */
+ markmt(g); /* mark basic metatables (again) */
+ propagateall(g);
+ /* remark gray again */
+ g->gray = g->grayagain;
+ g->grayagain = NULL;
+ propagateall(g);
+ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
+ marktmu(g); /* mark `preserved' userdata */
+ udsize += propagateall(g); /* remark, to propagate `preserveness' */
+ cleartable(g->weak); /* remove collected objects from weak tables */
+ /* flip current white */
+ g->currentwhite = cast_byte(otherwhite(g));
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gcstate = GCSsweepstring;
+ g->estimate = g->totalbytes - udsize; /* first estimate */
+}
+
+
+static l_mem singlestep (lua_State *L) {
+ global_State *g = G(L);
+ /*lua_checkmemory(L);*/
+ switch (g->gcstate) {
+ case GCSpause: {
+ markroot(L); /* start a new collection */
+ return 0;
+ }
+ case GCSpropagate: {
+ if (g->gray)
+ return propagatemark(g);
+ else { /* no more `gray' objects */
+ atomic(L); /* finish mark phase */
+ return 0;
+ }
+ }
+ case GCSsweepstring: {
+ lu_mem old = g->totalbytes;
+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
+ g->gcstate = GCSsweep; /* end sweep-string phase */
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPCOST;
+ }
+ case GCSsweep: {
+ lu_mem old = g->totalbytes;
+ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+ if (*g->sweepgc == NULL) { /* nothing more to sweep? */
+ checkSizes(L);
+ g->gcstate = GCSfinalize; /* end sweep phase */
+ }
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPMAX*GCSWEEPCOST;
+ }
+ case GCSfinalize: {
+ if (g->tmudata) {
+ GCTM(L);
+ if (g->estimate > GCFINALIZECOST)
+ g->estimate -= GCFINALIZECOST;
+ return GCFINALIZECOST;
+ }
+ else {
+ g->gcstate = GCSpause; /* end collection */
+ g->gcdept = 0;
+ return 0;
+ }
+ }
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+void luaC_step (lua_State *L) {
+ global_State *g = G(L);
+ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
+ if (lim == 0)
+ lim = (MAX_LUMEM-1)/2; /* no limit */
+ g->gcdept += g->totalbytes - g->GCthreshold;
+ do {
+ lim -= singlestep(L);
+ if (g->gcstate == GCSpause)
+ break;
+ } while (lim > 0);
+ if (g->gcstate != GCSpause) {
+ if (g->gcdept < GCSTEPSIZE)
+ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/
+ else {
+ g->gcdept -= GCSTEPSIZE;
+ g->GCthreshold = g->totalbytes;
+ }
+ }
+ else {
+ lua_assert(g->totalbytes >= g->estimate);
+ setthreshold(g);
+ }
+}
+
+
+void luaC_fullgc (lua_State *L) {
+ global_State *g = G(L);
+ if (g->gcstate <= GCSpropagate) {
+ /* reset sweep marks to sweep all elements (returning them to white) */
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ /* reset other collector lists */
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->gcstate = GCSsweepstring;
+ }
+ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
+ /* finish any pending sweep phase */
+ while (g->gcstate != GCSfinalize) {
+ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
+ singlestep(L);
+ }
+ markroot(L);
+ while (g->gcstate != GCSpause) {
+ singlestep(L);
+ }
+ setthreshold(g);
+}
+
+
+void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
+ global_State *g = G(L);
+ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ lua_assert(ttype(&o->gch) != LUA_TTABLE);
+ /* must keep invariant? */
+ if (g->gcstate == GCSpropagate)
+ reallymarkobject(g, v); /* restore invariant */
+ else /* don't mind */
+ makewhite(g, o); /* mark as white just to avoid other barriers */
+}
+
+
+void luaC_barrierback (lua_State *L, Table *t) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(t);
+ lua_assert(isblack(o) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ black2gray(o); /* make table gray (again) */
+ t->gclist = g->grayagain;
+ g->grayagain = o;
+}
+
+
+void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
+ global_State *g = G(L);
+ o->gch.next = g->rootgc;
+ g->rootgc = o;
+ o->gch.marked = luaC_white(g);
+ o->gch.tt = tt;
+}
+
+
+void luaC_linkupval (lua_State *L, UpVal *uv) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(uv);
+ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
+ g->rootgc = o;
+ if (isgray(o)) {
+ if (g->gcstate == GCSpropagate) {
+ gray2black(o); /* closed upvalues need barrier */
+ luaC_barrier(L, uv, uv->v);
+ }
+ else { /* sweep phase: sweep it (turning it into white) */
+ makewhite(g, o);
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ }
+ }
+}
+
diff --git a/lib/lua/src/lgc.h b/lib/lua/src/lgc.h
new file mode 100644
index 000000000..5a8dc605b
--- /dev/null
+++ b/lib/lua/src/lgc.h
@@ -0,0 +1,110 @@
+/*
+** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lgc_h
+#define lgc_h
+
+
+#include "lobject.h"
+
+
+/*
+** Possible states of the Garbage Collector
+*/
+#define GCSpause 0
+#define GCSpropagate 1
+#define GCSsweepstring 2
+#define GCSsweep 3
+#define GCSfinalize 4
+
+
+/*
+** some userful bit tricks
+*/
+#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
+#define setbits(x,m) ((x) |= (m))
+#define testbits(x,m) ((x) & (m))
+#define bitmask(b) (1<<(b))
+#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
+#define l_setbit(x,b) setbits(x, bitmask(b))
+#define resetbit(x,b) resetbits(x, bitmask(b))
+#define testbit(x,b) testbits(x, bitmask(b))
+#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
+#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
+#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
+
+
+
+/*
+** Layout for bit use in `marked' field:
+** bit 0 - object is white (type 0)
+** bit 1 - object is white (type 1)
+** bit 2 - object is black
+** bit 3 - for userdata: has been finalized
+** bit 3 - for tables: has weak keys
+** bit 4 - for tables: has weak values
+** bit 5 - object is fixed (should not be collected)
+** bit 6 - object is "super" fixed (only the main thread)
+*/
+
+
+#define WHITE0BIT 0
+#define WHITE1BIT 1
+#define BLACKBIT 2
+#define FINALIZEDBIT 3
+#define KEYWEAKBIT 3
+#define VALUEWEAKBIT 4
+#define FIXEDBIT 5
+#define SFIXEDBIT 6
+#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
+
+
+#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
+#define isgray(x) (!isblack(x) && !iswhite(x))
+
+#define otherwhite(g) (g->currentwhite ^ WHITEBITS)
+#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS)
+
+#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
+#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
+
+#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
+
+#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
+
+
+#define luaC_checkGC(L) { \
+ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
+ if (G(L)->totalbytes >= G(L)->GCthreshold) \
+ luaC_step(L); }
+
+
+#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
+
+#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \
+ luaC_barrierback(L,t); }
+
+#define luaC_objbarrier(L,p,o) \
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
+
+#define luaC_objbarriert(L,t,o) \
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
+
+LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
+LUAI_FUNC void luaC_callGCTM (lua_State *L);
+LUAI_FUNC void luaC_freeall (lua_State *L);
+LUAI_FUNC void luaC_step (lua_State *L);
+LUAI_FUNC void luaC_fullgc (lua_State *L);
+LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
+LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
+LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
+LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
+
+
+#endif
diff --git a/lib/lua/src/linit.c b/lib/lua/src/linit.c
new file mode 100644
index 000000000..c1f90dfab
--- /dev/null
+++ b/lib/lua/src/linit.c
@@ -0,0 +1,38 @@
+/*
+** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
+** Initialization of libraries for lua.c
+** See Copyright Notice in lua.h
+*/
+
+
+#define linit_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lualib.h"
+#include "lauxlib.h"
+
+
+static const luaL_Reg lualibs[] = {
+ {"", luaopen_base},
+ {LUA_LOADLIBNAME, luaopen_package},
+ {LUA_TABLIBNAME, luaopen_table},
+ {LUA_IOLIBNAME, luaopen_io},
+ {LUA_OSLIBNAME, luaopen_os},
+ {LUA_STRLIBNAME, luaopen_string},
+ {LUA_MATHLIBNAME, luaopen_math},
+ {LUA_DBLIBNAME, luaopen_debug},
+ {NULL, NULL}
+};
+
+
+LUALIB_API void luaL_openlibs (lua_State *L) {
+ const luaL_Reg *lib = lualibs;
+ for (; lib->func; lib++) {
+ lua_pushcfunction(L, lib->func);
+ lua_pushstring(L, lib->name);
+ lua_call(L, 1, 0);
+ }
+}
+
diff --git a/lib/lua/src/liolib.c b/lib/lua/src/liolib.c
new file mode 100644
index 000000000..e79ed1cb2
--- /dev/null
+++ b/lib/lua/src/liolib.c
@@ -0,0 +1,553 @@
+/*
+** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
+** Standard I/O (and system) library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define liolib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+#define IO_INPUT 1
+#define IO_OUTPUT 2
+
+
+static const char *const fnames[] = {"input", "output"};
+
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+ int en = errno; /* calls to Lua API may change this value */
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ if (filename)
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ else
+ lua_pushfstring(L, "%s", strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+}
+
+
+static void fileerror (lua_State *L, int arg, const char *filename) {
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ luaL_argerror(L, arg, lua_tostring(L, -1));
+}
+
+
+#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
+
+
+static int io_type (lua_State *L) {
+ void *ud;
+ luaL_checkany(L, 1);
+ ud = lua_touserdata(L, 1);
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+ if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
+ lua_pushnil(L); /* not a file */
+ else if (*((FILE **)ud) == NULL)
+ lua_pushliteral(L, "closed file");
+ else
+ lua_pushliteral(L, "file");
+ return 1;
+}
+
+
+static FILE *tofile (lua_State *L) {
+ FILE **f = tofilep(L);
+ if (*f == NULL)
+ luaL_error(L, "attempt to use a closed file");
+ return *f;
+}
+
+
+
+/*
+** When creating file handles, always creates a `closed' file handle
+** before opening the actual file; so, if there is a memory error, the
+** file is not left opened.
+*/
+static FILE **newfile (lua_State *L) {
+ FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
+ *pf = NULL; /* file handle is currently `closed' */
+ luaL_getmetatable(L, LUA_FILEHANDLE);
+ lua_setmetatable(L, -2);
+ return pf;
+}
+
+
+/*
+** function to (not) close the standard files stdin, stdout, and stderr
+*/
+static int io_noclose (lua_State *L) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "cannot close standard file");
+ return 2;
+}
+
+
+/*
+** function to close 'popen' files
+*/
+static int io_pclose (lua_State *L) {
+ FILE **p = tofilep(L);
+ int ok = lua_pclose(L, *p);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+/*
+** function to close regular files
+*/
+static int io_fclose (lua_State *L) {
+ FILE **p = tofilep(L);
+ int ok = (fclose(*p) == 0);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+static int aux_close (lua_State *L) {
+ lua_getfenv(L, 1);
+ lua_getfield(L, -1, "__close");
+ return (lua_tocfunction(L, -1))(L);
+}
+
+
+static int io_close (lua_State *L) {
+ if (lua_isnone(L, 1))
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
+ tofile(L); /* make sure argument is a file */
+ return aux_close(L);
+}
+
+
+static int io_gc (lua_State *L) {
+ FILE *f = *tofilep(L);
+ /* ignore closed files */
+ if (f != NULL)
+ aux_close(L);
+ return 0;
+}
+
+
+static int io_tostring (lua_State *L) {
+ FILE *f = *tofilep(L);
+ if (f == NULL)
+ lua_pushliteral(L, "file (closed)");
+ else
+ lua_pushfstring(L, "file (%p)", f);
+ return 1;
+}
+
+
+static int io_open (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+/*
+** this function has a separated environment, which defines the
+** correct __close for 'popen' files
+*/
+static int io_popen (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ FILE **pf = newfile(L);
+ *pf = lua_popen(L, filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+static int io_tmpfile (lua_State *L) {
+ FILE **pf = newfile(L);
+ *pf = tmpfile();
+ return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
+}
+
+
+static FILE *getiofile (lua_State *L, int findex) {
+ FILE *f;
+ lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
+ f = *(FILE **)lua_touserdata(L, -1);
+ if (f == NULL)
+ luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
+ return f;
+}
+
+
+static int g_iofile (lua_State *L, int f, const char *mode) {
+ if (!lua_isnoneornil(L, 1)) {
+ const char *filename = lua_tostring(L, 1);
+ if (filename) {
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, mode);
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
+ }
+ else {
+ tofile(L); /* check that it's a valid file handle */
+ lua_pushvalue(L, 1);
+ }
+ lua_rawseti(L, LUA_ENVIRONINDEX, f);
+ }
+ /* return current value */
+ lua_rawgeti(L, LUA_ENVIRONINDEX, f);
+ return 1;
+}
+
+
+static int io_input (lua_State *L) {
+ return g_iofile(L, IO_INPUT, "r");
+}
+
+
+static int io_output (lua_State *L) {
+ return g_iofile(L, IO_OUTPUT, "w");
+}
+
+
+static int io_readline (lua_State *L);
+
+
+static void aux_lines (lua_State *L, int idx, int toclose) {
+ lua_pushvalue(L, idx);
+ lua_pushboolean(L, toclose); /* close/not close file when finished */
+ lua_pushcclosure(L, io_readline, 2);
+}
+
+
+static int f_lines (lua_State *L) {
+ tofile(L); /* check that it's a valid file handle */
+ aux_lines(L, 1, 0);
+ return 1;
+}
+
+
+static int io_lines (lua_State *L) {
+ if (lua_isnoneornil(L, 1)) { /* no arguments? */
+ /* will iterate over default input */
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
+ return f_lines(L);
+ }
+ else {
+ const char *filename = luaL_checkstring(L, 1);
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, "r");
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
+ aux_lines(L, lua_gettop(L), 1);
+ return 1;
+ }
+}
+
+
+/*
+** {======================================================
+** READ
+** =======================================================
+*/
+
+
+static int read_number (lua_State *L, FILE *f) {
+ lua_Number d;
+ if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
+ lua_pushnumber(L, d);
+ return 1;
+ }
+ else return 0; /* read fails */
+}
+
+
+static int test_eof (lua_State *L, FILE *f) {
+ int c = getc(f);
+ ungetc(c, f);
+ lua_pushlstring(L, NULL, 0);
+ return (c != EOF);
+}
+
+
+static int read_line (lua_State *L, FILE *f) {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (;;) {
+ size_t l;
+ char *p = luaL_prepbuffer(&b);
+ if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
+ luaL_pushresult(&b); /* close buffer */
+ return (lua_objlen(L, -1) > 0); /* check whether read something */
+ }
+ l = strlen(p);
+ if (l == 0 || p[l-1] != '\n')
+ luaL_addsize(&b, l);
+ else {
+ luaL_addsize(&b, l - 1); /* do not include `eol' */
+ luaL_pushresult(&b); /* close buffer */
+ return 1; /* read at least an `eol' */
+ }
+ }
+}
+
+
+static int read_chars (lua_State *L, FILE *f, size_t n) {
+ size_t rlen; /* how much to read */
+ size_t nr; /* number of chars actually read */
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
+ do {
+ char *p = luaL_prepbuffer(&b);
+ if (rlen > n) rlen = n; /* cannot read more than asked */
+ nr = fread(p, sizeof(char), rlen, f);
+ luaL_addsize(&b, nr);
+ n -= nr; /* still have to read `n' chars */
+ } while (n > 0 && nr == rlen); /* until end of count or eof */
+ luaL_pushresult(&b); /* close buffer */
+ return (n == 0 || lua_objlen(L, -1) > 0);
+}
+
+
+static int g_read (lua_State *L, FILE *f, int first) {
+ int nargs = lua_gettop(L) - 1;
+ int success;
+ int n;
+ clearerr(f);
+ if (nargs == 0) { /* no arguments? */
+ success = read_line(L, f);
+ n = first+1; /* to return 1 result */
+ }
+ else { /* ensure stack space for all results and for auxlib's buffer */
+ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+ success = 1;
+ for (n = first; nargs-- && success; n++) {
+ if (lua_type(L, n) == LUA_TNUMBER) {
+ size_t l = (size_t)lua_tointeger(L, n);
+ success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
+ }
+ else {
+ const char *p = lua_tostring(L, n);
+ luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
+ switch (p[1]) {
+ case 'n': /* number */
+ success = read_number(L, f);
+ break;
+ case 'l': /* line */
+ success = read_line(L, f);
+ break;
+ case 'a': /* file */
+ read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
+ success = 1; /* always success */
+ break;
+ default:
+ return luaL_argerror(L, n, "invalid format");
+ }
+ }
+ }
+ }
+ if (ferror(f))
+ return pushresult(L, 0, NULL);
+ if (!success) {
+ lua_pop(L, 1); /* remove last result */
+ lua_pushnil(L); /* push nil instead */
+ }
+ return n - first;
+}
+
+
+static int io_read (lua_State *L) {
+ return g_read(L, getiofile(L, IO_INPUT), 1);
+}
+
+
+static int f_read (lua_State *L) {
+ return g_read(L, tofile(L), 2);
+}
+
+
+static int io_readline (lua_State *L) {
+ FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
+ int sucess;
+ if (f == NULL) /* file is already closed? */
+ luaL_error(L, "file is already closed");
+ sucess = read_line(L, f);
+ if (ferror(f))
+ return luaL_error(L, "%s", strerror(errno));
+ if (sucess) return 1;
+ else { /* EOF */
+ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
+ lua_settop(L, 0);
+ lua_pushvalue(L, lua_upvalueindex(1));
+ aux_close(L); /* close it */
+ }
+ return 0;
+ }
+}
+
+/* }====================================================== */
+
+
+static int g_write (lua_State *L, FILE *f, int arg) {
+ int nargs = lua_gettop(L) - 1;
+ int status = 1;
+ for (; nargs--; arg++) {
+ if (lua_type(L, arg) == LUA_TNUMBER) {
+ /* optimization: could be done exactly as for strings */
+ status = status &&
+ fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ }
+ else {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ status = status && (fwrite(s, sizeof(char), l, f) == l);
+ }
+ }
+ return pushresult(L, status, NULL);
+}
+
+
+static int io_write (lua_State *L) {
+ return g_write(L, getiofile(L, IO_OUTPUT), 1);
+}
+
+
+static int f_write (lua_State *L) {
+ return g_write(L, tofile(L), 2);
+}
+
+
+static int f_seek (lua_State *L) {
+ static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
+ static const char *const modenames[] = {"set", "cur", "end", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, "cur", modenames);
+ long offset = luaL_optlong(L, 3, 0);
+ op = fseek(f, offset, mode[op]);
+ if (op)
+ return pushresult(L, 0, NULL); /* error */
+ else {
+ lua_pushinteger(L, ftell(f));
+ return 1;
+ }
+}
+
+
+static int f_setvbuf (lua_State *L) {
+ static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+ lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
+}
+
+
+
+static int io_flush (lua_State *L) {
+ return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
+}
+
+
+static int f_flush (lua_State *L) {
+ return pushresult(L, fflush(tofile(L)) == 0, NULL);
+}
+
+
+static const luaL_Reg iolib[] = {
+ {"close", io_close},
+ {"flush", io_flush},
+ {"input", io_input},
+ {"lines", io_lines},
+ {"open", io_open},
+ {"output", io_output},
+ {"popen", io_popen},
+ {"read", io_read},
+ {"tmpfile", io_tmpfile},
+ {"type", io_type},
+ {"write", io_write},
+ {NULL, NULL}
+};
+
+
+static const luaL_Reg flib[] = {
+ {"close", io_close},
+ {"flush", f_flush},
+ {"lines", f_lines},
+ {"read", f_read},
+ {"seek", f_seek},
+ {"setvbuf", f_setvbuf},
+ {"write", f_write},
+ {"__gc", io_gc},
+ {"__tostring", io_tostring},
+ {NULL, NULL}
+};
+
+
+static void createmeta (lua_State *L) {
+ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, flib); /* file methods */
+}
+
+
+static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
+ *newfile(L) = f;
+ if (k > 0) {
+ lua_pushvalue(L, -1);
+ lua_rawseti(L, LUA_ENVIRONINDEX, k);
+ }
+ lua_pushvalue(L, -2); /* copy environment */
+ lua_setfenv(L, -2); /* set it */
+ lua_setfield(L, -3, fname);
+}
+
+
+static void newfenv (lua_State *L, lua_CFunction cls) {
+ lua_createtable(L, 0, 1);
+ lua_pushcfunction(L, cls);
+ lua_setfield(L, -2, "__close");
+}
+
+
+LUALIB_API int luaopen_io (lua_State *L) {
+ createmeta(L);
+ /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
+ newfenv(L, io_fclose);
+ lua_replace(L, LUA_ENVIRONINDEX);
+ /* open library */
+ luaL_register(L, LUA_IOLIBNAME, iolib);
+ /* create (and set) default files */
+ newfenv(L, io_noclose); /* close function for default files */
+ createstdfile(L, stdin, IO_INPUT, "stdin");
+ createstdfile(L, stdout, IO_OUTPUT, "stdout");
+ createstdfile(L, stderr, 0, "stderr");
+ lua_pop(L, 1); /* pop environment for default files */
+ lua_getfield(L, -1, "popen");
+ newfenv(L, io_pclose); /* create environment for 'popen' */
+ lua_setfenv(L, -2); /* set fenv for 'popen' */
+ lua_pop(L, 1); /* pop 'popen' */
+ return 1;
+}
+
diff --git a/lib/lua/src/llex.c b/lib/lua/src/llex.c
new file mode 100644
index 000000000..02849fa8f
--- /dev/null
+++ b/lib/lua/src/llex.c
@@ -0,0 +1,465 @@
+/*
+** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <locale.h>
+#include <string.h>
+
+#define llex_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "llex.h"
+#include "lobject.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "lzio.h"
+
+
+
+#define next(ls) (ls->current = zgetc(ls->z))
+
+
+
+
+#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
+
+
+/* ORDER RESERVED */
+const char *const luaX_tokens [] = {
+ "and", "break", "do", "else", "elseif",
+ "end", "false", "for", "function", "if",
+ "in", "local", "nil", "not", "or", "repeat",
+ "return", "then", "true", "until", "while",
+ "..", "...", "==", ">=", "<=", "~=",
+ "<number>", "<name>", "<string>", "<eof>",
+ NULL
+};
+
+
+#define save_and_next(ls) (save(ls, ls->current), next(ls))
+
+
+static void save (LexState *ls, int c) {
+ Mbuffer *b = ls->buff;
+ if (b->n + 1 > b->buffsize) {
+ size_t newsize;
+ if (b->buffsize >= MAX_SIZET/2)
+ luaX_lexerror(ls, "lexical element too long", 0);
+ newsize = b->buffsize * 2;
+ luaZ_resizebuffer(ls->L, b, newsize);
+ }
+ b->buffer[b->n++] = cast(char, c);
+}
+
+
+void luaX_init (lua_State *L) {
+ int i;
+ for (i=0; i<NUM_RESERVED; i++) {
+ TString *ts = luaS_new(L, luaX_tokens[i]);
+ luaS_fix(ts); /* reserved words are never collected */
+ lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
+ ts->tsv.reserved = cast_byte(i+1); /* reserved word */
+ }
+}
+
+
+#define MAXSRC 80
+
+
+const char *luaX_token2str (LexState *ls, int token) {
+ if (token < FIRST_RESERVED) {
+ lua_assert(token == cast(unsigned char, token));
+ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) :
+ luaO_pushfstring(ls->L, "%c", token);
+ }
+ else
+ return luaX_tokens[token-FIRST_RESERVED];
+}
+
+
+static const char *txtToken (LexState *ls, int token) {
+ switch (token) {
+ case TK_NAME:
+ case TK_STRING:
+ case TK_NUMBER:
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
+ default:
+ return luaX_token2str(ls, token);
+ }
+}
+
+
+void luaX_lexerror (LexState *ls, const char *msg, int token) {
+ char buff[MAXSRC];
+ luaO_chunkid(buff, getstr(ls->source), MAXSRC);
+ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
+ if (token)
+ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token));
+ luaD_throw(ls->L, LUA_ERRSYNTAX);
+}
+
+
+void luaX_syntaxerror (LexState *ls, const char *msg) {
+ luaX_lexerror(ls, msg, ls->t.token);
+}
+
+
+TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
+ lua_State *L = ls->L;
+ TString *ts = luaS_newlstr(L, str, l);
+ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */
+ if (ttisnil(o))
+ setbvalue(o, 1); /* make sure `str' will not be collected */
+ return ts;
+}
+
+
+static void inclinenumber (LexState *ls) {
+ int old = ls->current;
+ lua_assert(currIsNewline(ls));
+ next(ls); /* skip `\n' or `\r' */
+ if (currIsNewline(ls) && ls->current != old)
+ next(ls); /* skip `\n\r' or `\r\n' */
+ if (++ls->linenumber >= MAX_INT)
+ luaX_syntaxerror(ls, "chunk has too many lines");
+}
+
+
+void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
+ ls->decpoint = '.';
+ ls->L = L;
+ ls->lookahead.token = TK_EOS; /* no look-ahead token */
+ ls->z = z;
+ ls->fs = NULL;
+ ls->linenumber = 1;
+ ls->lastline = 1;
+ ls->source = source;
+ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
+ next(ls); /* read first char */
+}
+
+
+
+/*
+** =======================================================
+** LEXICAL ANALYZER
+** =======================================================
+*/
+
+
+
+static int check_next (LexState *ls, const char *set) {
+ if (!strchr(set, ls->current))
+ return 0;
+ save_and_next(ls);
+ return 1;
+}
+
+
+static void buffreplace (LexState *ls, char from, char to) {
+ size_t n = luaZ_bufflen(ls->buff);
+ char *p = luaZ_buffer(ls->buff);
+ while (n--)
+ if (p[n] == from) p[n] = to;
+}
+
+
+static void trydecpoint (LexState *ls, SemInfo *seminfo) {
+ /* format error: try to update decimal point separator */
+ char old = ls->decpoint;
+#if defined(ANDROID_NDK)
+ ls->decpoint = '.';
+#else
+ struct lconv *cv = localeconv();
+ ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+#endif
+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
+ /* format error with correct decimal point: no more options */
+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
+ luaX_lexerror(ls, "malformed number", TK_NUMBER);
+ }
+}
+
+
+/* LUA_NUMBER */
+static void read_numeral (LexState *ls, SemInfo *seminfo) {
+ lua_assert(isdigit(ls->current));
+ do {
+ save_and_next(ls);
+ } while (isdigit(ls->current) || ls->current == '.');
+ if (check_next(ls, "Ee")) /* `E'? */
+ check_next(ls, "+-"); /* optional exponent sign */
+ while (isalnum(ls->current) || ls->current == '_')
+ save_and_next(ls);
+ save(ls, '\0');
+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
+ trydecpoint(ls, seminfo); /* try to update decimal point separator */
+}
+
+
+static int skip_sep (LexState *ls) {
+ int count = 0;
+ int s = ls->current;
+ lua_assert(s == '[' || s == ']');
+ save_and_next(ls);
+ while (ls->current == '=') {
+ save_and_next(ls);
+ count++;
+ }
+ return (ls->current == s) ? count : (-count) - 1;
+}
+
+
+static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
+ int cont = 0;
+ (void)(cont); /* avoid warnings when `cont' is not used */
+ save_and_next(ls); /* skip 2nd `[' */
+ if (currIsNewline(ls)) /* string starts with a newline? */
+ inclinenumber(ls); /* skip it */
+ for (;;) {
+ switch (ls->current) {
+ case EOZ:
+ luaX_lexerror(ls, (seminfo) ? "unfinished long string" :
+ "unfinished long comment", TK_EOS);
+ break; /* to avoid warnings */
+#if defined(LUA_COMPAT_LSTR)
+ case '[': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `[' */
+ cont++;
+#if LUA_COMPAT_LSTR == 1
+ if (sep == 0)
+ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '[');
+#endif
+ }
+ break;
+ }
+#endif
+ case ']': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `]' */
+#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2
+ cont--;
+ if (sep == 0 && cont >= 0) break;
+#endif
+ goto endloop;
+ }
+ break;
+ }
+ case '\n':
+ case '\r': {
+ save(ls, '\n');
+ inclinenumber(ls);
+ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
+ break;
+ }
+ default: {
+ if (seminfo) save_and_next(ls);
+ else next(ls);
+ }
+ }
+ } endloop:
+ if (seminfo)
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
+ luaZ_bufflen(ls->buff) - 2*(2 + sep));
+}
+
+
+static void read_string (LexState *ls, int del, SemInfo *seminfo) {
+ save_and_next(ls);
+ while (ls->current != del) {
+ switch (ls->current) {
+ case EOZ:
+ luaX_lexerror(ls, "unfinished string", TK_EOS);
+ continue; /* to avoid warnings */
+ case '\n':
+ case '\r':
+ luaX_lexerror(ls, "unfinished string", TK_STRING);
+ continue; /* to avoid warnings */
+ case '\\': {
+ int c;
+ next(ls); /* do not save the `\' */
+ switch (ls->current) {
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\n': /* go through */
+ case '\r': save(ls, '\n'); inclinenumber(ls); continue;
+ case EOZ: continue; /* will raise an error next loop */
+ default: {
+ if (!isdigit(ls->current))
+ save_and_next(ls); /* handles \\, \", \', and \? */
+ else { /* \xxx */
+ int i = 0;
+ c = 0;
+ do {
+ c = 10*c + (ls->current-'0');
+ next(ls);
+ } while (++i<3 && isdigit(ls->current));
+ if (c > UCHAR_MAX)
+ luaX_lexerror(ls, "escape sequence too large", TK_STRING);
+ save(ls, c);
+ }
+ continue;
+ }
+ }
+ save(ls, c);
+ next(ls);
+ continue;
+ }
+ default:
+ save_and_next(ls);
+ }
+ }
+ save_and_next(ls); /* skip delimiter */
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
+ luaZ_bufflen(ls->buff) - 2);
+}
+
+
+static int llex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
+ for (;;) {
+ switch (ls->current) {
+ case '\n':
+ case '\r': {
+ inclinenumber(ls);
+ continue;
+ }
+ case '-': {
+ next(ls);
+ if (ls->current != '-') return '-';
+ /* else is a comment */
+ next(ls);
+ if (ls->current == '[') {
+ int sep = skip_sep(ls);
+ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */
+ if (sep >= 0) {
+ read_long_string(ls, NULL, sep); /* long comment */
+ luaZ_resetbuffer(ls->buff);
+ continue;
+ }
+ }
+ /* else short comment */
+ while (!currIsNewline(ls) && ls->current != EOZ)
+ next(ls);
+ continue;
+ }
+ case '[': {
+ int sep = skip_sep(ls);
+ if (sep >= 0) {
+ read_long_string(ls, seminfo, sep);
+ return TK_STRING;
+ }
+ else if (sep == -1) return '[';
+ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
+ }
+ case '=': {
+ next(ls);
+ if (ls->current != '=') return '=';
+ else { next(ls); return TK_EQ; }
+ }
+ case '<': {
+ next(ls);
+ if (ls->current != '=') return '<';
+ else { next(ls); return TK_LE; }
+ }
+ case '>': {
+ next(ls);
+ if (ls->current != '=') return '>';
+ else { next(ls); return TK_GE; }
+ }
+ case '~': {
+ next(ls);
+ if (ls->current != '=') return '~';
+ else { next(ls); return TK_NE; }
+ }
+ case '"':
+ case '\'': {
+ read_string(ls, ls->current, seminfo);
+ return TK_STRING;
+ }
+ case '.': {
+ save_and_next(ls);
+ if (check_next(ls, ".")) {
+ if (check_next(ls, "."))
+ return TK_DOTS; /* ... */
+ else return TK_CONCAT; /* .. */
+ }
+ else if (!isdigit(ls->current)) return '.';
+ else {
+ read_numeral(ls, seminfo);
+ return TK_NUMBER;
+ }
+ }
+ case EOZ: {
+ return TK_EOS;
+ }
+ default: {
+ if (isspace(ls->current)) {
+ lua_assert(!currIsNewline(ls));
+ next(ls);
+ continue;
+ }
+ else if (isdigit(ls->current)) {
+ read_numeral(ls, seminfo);
+ return TK_NUMBER;
+ }
+ else if (isalpha(ls->current) || ls->current == '_') {
+ /* identifier or reserved word */
+ TString *ts;
+ do {
+ save_and_next(ls);
+ } while (isalnum(ls->current) || ls->current == '_');
+ ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
+ luaZ_bufflen(ls->buff));
+ if (ts->tsv.reserved > 0) /* reserved word? */
+ return ts->tsv.reserved - 1 + FIRST_RESERVED;
+ else {
+ seminfo->ts = ts;
+ return TK_NAME;
+ }
+ }
+ else {
+ int c = ls->current;
+ next(ls);
+ return c; /* single-char tokens (+ - / ...) */
+ }
+ }
+ }
+ }
+}
+
+
+void luaX_next (LexState *ls) {
+ ls->lastline = ls->linenumber;
+ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
+ ls->t = ls->lookahead; /* use this one */
+ ls->lookahead.token = TK_EOS; /* and discharge it */
+ }
+ else
+ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
+}
+
+
+void luaX_lookahead (LexState *ls) {
+ lua_assert(ls->lookahead.token == TK_EOS);
+ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
+}
+
diff --git a/lib/lua/src/llex.h b/lib/lua/src/llex.h
new file mode 100644
index 000000000..a9201cee4
--- /dev/null
+++ b/lib/lua/src/llex.h
@@ -0,0 +1,81 @@
+/*
+** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llex_h
+#define llex_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+
+#define FIRST_RESERVED 257
+
+/* maximum length of a reserved word */
+#define TOKEN_LEN (sizeof("function")/sizeof(char))
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER RESERVED"
+*/
+enum RESERVED {
+ /* terminal symbols denoted by reserved words */
+ TK_AND = FIRST_RESERVED, TK_BREAK,
+ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
+ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
+ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+ /* other terminal symbols */
+ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+ TK_NAME, TK_STRING, TK_EOS
+};
+
+/* number of reserved words */
+#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
+
+
+/* array with token `names' */
+LUAI_DATA const char *const luaX_tokens [];
+
+
+typedef union {
+ lua_Number r;
+ TString *ts;
+} SemInfo; /* semantics information */
+
+
+typedef struct Token {
+ int token;
+ SemInfo seminfo;
+} Token;
+
+
+typedef struct LexState {
+ int current; /* current character (charint) */
+ int linenumber; /* input line counter */
+ int lastline; /* line of last token `consumed' */
+ Token t; /* current token */
+ Token lookahead; /* look ahead token */
+ struct FuncState *fs; /* `FuncState' is private to the parser */
+ struct lua_State *L;
+ ZIO *z; /* input stream */
+ Mbuffer *buff; /* buffer for tokens */
+ TString *source; /* current source name */
+ char decpoint; /* locale decimal point */
+} LexState;
+
+
+LUAI_FUNC void luaX_init (lua_State *L);
+LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
+ TString *source);
+LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
+LUAI_FUNC void luaX_next (LexState *ls);
+LUAI_FUNC void luaX_lookahead (LexState *ls);
+LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);
+LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);
+LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
+
+
+#endif
diff --git a/lib/lua/src/llimits.h b/lib/lua/src/llimits.h
new file mode 100644
index 000000000..ca8dcb722
--- /dev/null
+++ b/lib/lua/src/llimits.h
@@ -0,0 +1,128 @@
+/*
+** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $
+** Limits, basic types, and some other `installation-dependent' definitions
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llimits_h
+#define llimits_h
+
+
+#include <limits.h>
+#include <stddef.h>
+
+
+#include "lua.h"
+
+
+typedef LUAI_UINT32 lu_int32;
+
+typedef LUAI_UMEM lu_mem;
+
+typedef LUAI_MEM l_mem;
+
+
+
+/* chars used as small naturals (so that `char' is reserved for characters) */
+typedef unsigned char lu_byte;
+
+
+#define MAX_SIZET ((size_t)(~(size_t)0)-2)
+
+#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2)
+
+
+#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
+
+/*
+** conversion of pointer to integer
+** this is for hashing only; there is no problem if the integer
+** cannot hold the whole pointer value
+*/
+#define IntPoint(p) ((unsigned int)(lu_mem)(p))
+
+
+
+/* type to ensure maximum alignment */
+typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
+
+
+/* result of a `usual argument conversion' over lua_Number */
+typedef LUAI_UACNUMBER l_uacNumber;
+
+
+/* internal assertions for in-house debugging */
+#ifdef lua_assert
+
+#define check_exp(c,e) (lua_assert(c), (e))
+#define api_check(l,e) lua_assert(e)
+
+#else
+
+#define lua_assert(c) ((void)0)
+#define check_exp(c,e) (e)
+#define api_check luai_apicheck
+
+#endif
+
+
+#ifndef UNUSED
+#define UNUSED(x) ((void)(x)) /* to avoid warnings */
+#endif
+
+
+#ifndef cast
+#define cast(t, exp) ((t)(exp))
+#endif
+
+#define cast_byte(i) cast(lu_byte, (i))
+#define cast_num(i) cast(lua_Number, (i))
+#define cast_int(i) cast(int, (i))
+
+
+
+/*
+** type for virtual-machine instructions
+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+*/
+typedef lu_int32 Instruction;
+
+
+
+/* maximum stack for a Lua function */
+#define MAXSTACK 250
+
+
+
+/* minimum size for the string table (must be power of 2) */
+#ifndef MINSTRTABSIZE
+#define MINSTRTABSIZE 32
+#endif
+
+
+/* minimum size for string buffer */
+#ifndef LUA_MINBUFFER
+#define LUA_MINBUFFER 32
+#endif
+
+
+#ifndef lua_lock
+#define lua_lock(L) ((void) 0)
+#define lua_unlock(L) ((void) 0)
+#endif
+
+#ifndef luai_threadyield
+#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
+#endif
+
+
+/*
+** macro to control inclusion of some hard tests on stack reallocation
+*/
+#ifndef HARDSTACKTESTS
+#define condhardstacktests(x) ((void)0)
+#else
+#define condhardstacktests(x) x
+#endif
+
+#endif
diff --git a/lib/lua/src/lmathlib.c b/lib/lua/src/lmathlib.c
new file mode 100644
index 000000000..441fbf736
--- /dev/null
+++ b/lib/lua/src/lmathlib.c
@@ -0,0 +1,263 @@
+/*
+** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $
+** Standard mathematical library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+#include <math.h>
+
+#define lmathlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#undef PI
+#define PI (3.14159265358979323846)
+#define RADIANS_PER_DEGREE (PI/180.0)
+
+
+
+static int math_abs (lua_State *L) {
+ lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sin (lua_State *L) {
+ lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sinh (lua_State *L) {
+ lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_cos (lua_State *L) {
+ lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_cosh (lua_State *L) {
+ lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tan (lua_State *L) {
+ lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tanh (lua_State *L) {
+ lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_asin (lua_State *L) {
+ lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_acos (lua_State *L) {
+ lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_atan (lua_State *L) {
+ lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_atan2 (lua_State *L) {
+ lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_ceil (lua_State *L) {
+ lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_floor (lua_State *L) {
+ lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_fmod (lua_State *L) {
+ lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_modf (lua_State *L) {
+ double ip;
+ double fp = modf(luaL_checknumber(L, 1), &ip);
+ lua_pushnumber(L, ip);
+ lua_pushnumber(L, fp);
+ return 2;
+}
+
+static int math_sqrt (lua_State *L) {
+ lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_pow (lua_State *L) {
+ lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_log (lua_State *L) {
+ lua_pushnumber(L, log(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_log10 (lua_State *L) {
+ lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_exp (lua_State *L) {
+ lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_deg (lua_State *L) {
+ lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
+ return 1;
+}
+
+static int math_rad (lua_State *L) {
+ lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
+ return 1;
+}
+
+static int math_frexp (lua_State *L) {
+ int e;
+ lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
+ lua_pushinteger(L, e);
+ return 2;
+}
+
+static int math_ldexp (lua_State *L) {
+ lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+
+
+static int math_min (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmin = luaL_checknumber(L, 1);
+ int i;
+ for (i=2; i<=n; i++) {
+ lua_Number d = luaL_checknumber(L, i);
+ if (d < dmin)
+ dmin = d;
+ }
+ lua_pushnumber(L, dmin);
+ return 1;
+}
+
+
+static int math_max (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmax = luaL_checknumber(L, 1);
+ int i;
+ for (i=2; i<=n; i++) {
+ lua_Number d = luaL_checknumber(L, i);
+ if (d > dmax)
+ dmax = d;
+ }
+ lua_pushnumber(L, dmax);
+ return 1;
+}
+
+
+static int math_random (lua_State *L) {
+ /* the `%' avoids the (rare) case of r==1, and is needed also because on
+ some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+ switch (lua_gettop(L)) { /* check number of arguments */
+ case 0: { /* no arguments */
+ lua_pushnumber(L, r); /* Number between 0 and 1 */
+ break;
+ }
+ case 1: { /* only upper limit */
+ int u = luaL_checkint(L, 1);
+ luaL_argcheck(L, 1<=u, 1, "interval is empty");
+ lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
+ break;
+ }
+ case 2: { /* lower and upper limits */
+ int l = luaL_checkint(L, 1);
+ int u = luaL_checkint(L, 2);
+ luaL_argcheck(L, l<=u, 2, "interval is empty");
+ lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
+ break;
+ }
+ default: return luaL_error(L, "wrong number of arguments");
+ }
+ return 1;
+}
+
+
+static int math_randomseed (lua_State *L) {
+ srand(luaL_checkint(L, 1));
+ return 0;
+}
+
+
+static const luaL_Reg mathlib[] = {
+ {"abs", math_abs},
+ {"acos", math_acos},
+ {"asin", math_asin},
+ {"atan2", math_atan2},
+ {"atan", math_atan},
+ {"ceil", math_ceil},
+ {"cosh", math_cosh},
+ {"cos", math_cos},
+ {"deg", math_deg},
+ {"exp", math_exp},
+ {"floor", math_floor},
+ {"fmod", math_fmod},
+ {"frexp", math_frexp},
+ {"ldexp", math_ldexp},
+ {"log10", math_log10},
+ {"log", math_log},
+ {"max", math_max},
+ {"min", math_min},
+ {"modf", math_modf},
+ {"pow", math_pow},
+ {"rad", math_rad},
+ {"random", math_random},
+ {"randomseed", math_randomseed},
+ {"sinh", math_sinh},
+ {"sin", math_sin},
+ {"sqrt", math_sqrt},
+ {"tanh", math_tanh},
+ {"tan", math_tan},
+ {NULL, NULL}
+};
+
+
+/*
+** Open math library
+*/
+LUALIB_API int luaopen_math (lua_State *L) {
+ luaL_register(L, LUA_MATHLIBNAME, mathlib);
+ lua_pushnumber(L, PI);
+ lua_setfield(L, -2, "pi");
+ lua_pushnumber(L, HUGE_VAL);
+ lua_setfield(L, -2, "huge");
+#if defined(LUA_COMPAT_MOD)
+ lua_getfield(L, -1, "fmod");
+ lua_setfield(L, -2, "mod");
+#endif
+ return 1;
+}
+
diff --git a/lib/lua/src/lmem.c b/lib/lua/src/lmem.c
new file mode 100644
index 000000000..ae7d8c965
--- /dev/null
+++ b/lib/lua/src/lmem.c
@@ -0,0 +1,86 @@
+/*
+** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lmem_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+/*
+** About the realloc function:
+** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
+** (`osize' is the old size, `nsize' is the new size)
+**
+** Lua ensures that (ptr == NULL) iff (osize == 0).
+**
+** * frealloc(ud, NULL, 0, x) creates a new block of size `x'
+**
+** * frealloc(ud, p, x, 0) frees the block `p'
+** (in this specific case, frealloc must return NULL).
+** particularly, frealloc(ud, NULL, 0, 0) does nothing
+** (which is equivalent to free(NULL) in ANSI C)
+**
+** frealloc returns NULL if it cannot create or reallocate the area
+** (any reallocation to an equal or smaller size cannot fail!)
+*/
+
+
+
+#define MINSIZEARRAY 4
+
+
+void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
+ int limit, const char *errormsg) {
+ void *newblock;
+ int newsize;
+ if (*size >= limit/2) { /* cannot double it? */
+ if (*size >= limit) /* cannot grow even a little? */
+ luaG_runerror(L, errormsg);
+ newsize = limit; /* still have at least one free place */
+ }
+ else {
+ newsize = (*size)*2;
+ if (newsize < MINSIZEARRAY)
+ newsize = MINSIZEARRAY; /* minimum size */
+ }
+ newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
+ *size = newsize; /* update only when everything else is OK */
+ return newblock;
+}
+
+
+void *luaM_toobig (lua_State *L) {
+ luaG_runerror(L, "memory allocation error: block too big");
+ return NULL; /* to avoid warnings */
+}
+
+
+
+/*
+** generic allocation routine.
+*/
+void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
+ global_State *g = G(L);
+ lua_assert((osize == 0) == (block == NULL));
+ block = (*g->frealloc)(g->ud, block, osize, nsize);
+ if (block == NULL && nsize > 0)
+ luaD_throw(L, LUA_ERRMEM);
+ lua_assert((nsize == 0) == (block == NULL));
+ g->totalbytes = (g->totalbytes - osize) + nsize;
+ return block;
+}
+
diff --git a/lib/lua/src/lmem.h b/lib/lua/src/lmem.h
new file mode 100644
index 000000000..7c2dcb322
--- /dev/null
+++ b/lib/lua/src/lmem.h
@@ -0,0 +1,49 @@
+/*
+** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lmem_h
+#define lmem_h
+
+
+#include <stddef.h>
+
+#include "llimits.h"
+#include "lua.h"
+
+#define MEMERRMSG "not enough memory"
+
+
+#define luaM_reallocv(L,b,on,n,e) \
+ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \
+ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \
+ luaM_toobig(L))
+
+#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
+#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0)
+#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t))
+
+#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t))
+#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t)))
+#define luaM_newvector(L,n,t) \
+ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))
+
+#define luaM_growvector(L,v,nelems,size,t,limit,e) \
+ if ((nelems)+1 > (size)) \
+ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))
+
+#define luaM_reallocvector(L, v,oldn,n,t) \
+ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
+
+
+LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+ size_t size);
+LUAI_FUNC void *luaM_toobig (lua_State *L);
+LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
+ size_t size_elem, int limit,
+ const char *errormsg);
+
+#endif
+
diff --git a/lib/lua/src/loadlib.c b/lib/lua/src/loadlib.c
new file mode 100644
index 000000000..0d401eba1
--- /dev/null
+++ b/lib/lua/src/loadlib.c
@@ -0,0 +1,666 @@
+/*
+** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $
+** Dynamic library loader for Lua
+** See Copyright Notice in lua.h
+**
+** This module contains an implementation of loadlib for Unix systems
+** that have dlfcn, an implementation for Darwin (Mac OS X), an
+** implementation for Windows, and a stub for other systems.
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#define loadlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+/* prefix for open functions in C libraries */
+#define LUA_POF "luaopen_"
+
+/* separator for open functions in C libraries */
+#define LUA_OFSEP "_"
+
+
+#define LIBPREFIX "LOADLIB: "
+
+#define POF LUA_POF
+#define LIB_FAIL "open"
+
+
+/* error codes for ll_loadfunc */
+#define ERRLIB 1
+#define ERRFUNC 2
+
+#define setprogdir(L) ((void)0)
+
+
+static void ll_unloadlib (void *lib);
+static void *ll_load (lua_State *L, const char *path);
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
+
+
+
+#if defined(LUA_DL_DLOPEN)
+/*
+** {========================================================================
+** This is an implementation of loadlib based on the dlfcn interface.
+** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
+** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
+** as an emulation layer on top of native functions.
+** =========================================================================
+*/
+
+#include <dlfcn.h>
+
+static void ll_unloadlib (void *lib) {
+ dlclose(lib);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ void *lib = dlopen(path, RTLD_NOW);
+ if (lib == NULL) lua_pushstring(L, dlerror());
+ return lib;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
+ if (f == NULL) lua_pushstring(L, dlerror());
+ return f;
+}
+
+/* }====================================================== */
+
+
+
+#elif defined(LUA_DL_DLL)
+/*
+** {======================================================================
+** This is an implementation of loadlib for Windows using native functions.
+** =======================================================================
+*/
+
+#include <windows.h>
+
+
+#undef setprogdir
+
+static void setprogdir (lua_State *L) {
+ char buff[MAX_PATH + 1];
+ char *lb;
+ DWORD nsize = sizeof(buff)/sizeof(char);
+ DWORD n = GetModuleFileNameA(NULL, buff, nsize);
+ if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
+ luaL_error(L, "unable to get ModuleFileName");
+ else {
+ *lb = '\0';
+ luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
+ lua_remove(L, -2); /* remove original string */
+ }
+}
+
+
+static void pusherror (lua_State *L) {
+ int error = GetLastError();
+ char buffer[128];
+ if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error, 0, buffer, sizeof(buffer), NULL))
+ lua_pushstring(L, buffer);
+ else
+ lua_pushfstring(L, "system error %d\n", error);
+}
+
+static void ll_unloadlib (void *lib) {
+ FreeLibrary((HINSTANCE)lib);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ HINSTANCE lib = LoadLibraryA(path);
+ if (lib == NULL) pusherror(L);
+ return lib;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
+ if (f == NULL) pusherror(L);
+ return f;
+}
+
+/* }====================================================== */
+
+
+
+#elif defined(LUA_DL_DYLD)
+/*
+** {======================================================================
+** Native Mac OS X / Darwin Implementation
+** =======================================================================
+*/
+
+#include <mach-o/dyld.h>
+
+
+/* Mac appends a `_' before C function names */
+#undef POF
+#define POF "_" LUA_POF
+
+
+static void pusherror (lua_State *L) {
+ const char *err_str;
+ const char *err_file;
+ NSLinkEditErrors err;
+ int err_num;
+ NSLinkEditError(&err, &err_num, &err_file, &err_str);
+ lua_pushstring(L, err_str);
+}
+
+
+static const char *errorfromcode (NSObjectFileImageReturnCode ret) {
+ switch (ret) {
+ case NSObjectFileImageInappropriateFile:
+ return "file is not a bundle";
+ case NSObjectFileImageArch:
+ return "library is for wrong CPU type";
+ case NSObjectFileImageFormat:
+ return "bad format";
+ case NSObjectFileImageAccess:
+ return "cannot access file";
+ case NSObjectFileImageFailure:
+ default:
+ return "unable to load library";
+ }
+}
+
+
+static void ll_unloadlib (void *lib) {
+ NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ NSObjectFileImage img;
+ NSObjectFileImageReturnCode ret;
+ /* this would be a rare case, but prevents crashing if it happens */
+ if(!_dyld_present()) {
+ lua_pushliteral(L, "dyld not present");
+ return NULL;
+ }
+ ret = NSCreateObjectFileImageFromFile(path, &img);
+ if (ret == NSObjectFileImageSuccess) {
+ NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ NSDestroyObjectFileImage(img);
+ if (mod == NULL) pusherror(L);
+ return mod;
+ }
+ lua_pushstring(L, errorfromcode(ret));
+ return NULL;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);
+ if (nss == NULL) {
+ lua_pushfstring(L, "symbol " LUA_QS " not found", sym);
+ return NULL;
+ }
+ return (lua_CFunction)NSAddressOfSymbol(nss);
+}
+
+/* }====================================================== */
+
+
+
+#else
+/*
+** {======================================================
+** Fallback for other systems
+** =======================================================
+*/
+
+#undef LIB_FAIL
+#define LIB_FAIL "absent"
+
+
+#define DLMSG "dynamic libraries not enabled; check your Lua installation"
+
+
+static void ll_unloadlib (void *lib) {
+ (void)lib; /* to avoid warnings */
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ (void)path; /* to avoid warnings */
+ lua_pushliteral(L, DLMSG);
+ return NULL;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ (void)lib; (void)sym; /* to avoid warnings */
+ lua_pushliteral(L, DLMSG);
+ return NULL;
+}
+
+/* }====================================================== */
+#endif
+
+
+
+static void **ll_register (lua_State *L, const char *path) {
+ void **plib;
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
+ if (!lua_isnil(L, -1)) /* is there an entry? */
+ plib = (void **)lua_touserdata(L, -1);
+ else { /* no entry yet; create one */
+ lua_pop(L, 1);
+ plib = (void **)lua_newuserdata(L, sizeof(const void *));
+ *plib = NULL;
+ luaL_getmetatable(L, "_LOADLIB");
+ lua_setmetatable(L, -2);
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_pushvalue(L, -2);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ }
+ return plib;
+}
+
+
+/*
+** __gc tag method: calls library's `ll_unloadlib' function with the lib
+** handle
+*/
+static int gctm (lua_State *L) {
+ void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
+ if (*lib) ll_unloadlib(*lib);
+ *lib = NULL; /* mark library as closed */
+ return 0;
+}
+
+
+static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
+ void **reg = ll_register(L, path);
+ if (*reg == NULL) *reg = ll_load(L, path);
+ if (*reg == NULL)
+ return ERRLIB; /* unable to load library */
+ else {
+ lua_CFunction f = ll_sym(L, *reg, sym);
+ if (f == NULL)
+ return ERRFUNC; /* unable to find function */
+ lua_pushcfunction(L, f);
+ return 0; /* return function */
+ }
+}
+
+
+static int ll_loadlib (lua_State *L) {
+ const char *path = luaL_checkstring(L, 1);
+ const char *init = luaL_checkstring(L, 2);
+ int stat = ll_loadfunc(L, path, init);
+ if (stat == 0) /* no errors? */
+ return 1; /* return the loaded function */
+ else { /* error; error message is on stack top */
+ lua_pushnil(L);
+ lua_insert(L, -2);
+ lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
+ return 3; /* return nil, error message, and where */
+ }
+}
+
+
+
+/*
+** {======================================================
+** 'require' function
+** =======================================================
+*/
+
+
+static int readable (const char *filename) {
+ FILE *f = fopen(filename, "r"); /* try to open file */
+ if (f == NULL) return 0; /* open failed */
+ fclose(f);
+ return 1;
+}
+
+
+static const char *pushnexttemplate (lua_State *L, const char *path) {
+ const char *l;
+ while (*path == *LUA_PATHSEP) path++; /* skip separators */
+ if (*path == '\0') return NULL; /* no more templates */
+ l = strchr(path, *LUA_PATHSEP); /* find next separator */
+ if (l == NULL) l = path + strlen(path);
+ lua_pushlstring(L, path, l - path); /* template */
+ return l;
+}
+
+
+static const char *findfile (lua_State *L, const char *name,
+ const char *pname) {
+ const char *path;
+ name = luaL_gsub(L, name, ".", LUA_DIRSEP);
+ lua_getfield(L, LUA_ENVIRONINDEX, pname);
+ path = lua_tostring(L, -1);
+ if (path == NULL)
+ luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
+ lua_pushliteral(L, ""); /* error accumulator */
+ while ((path = pushnexttemplate(L, path)) != NULL) {
+ const char *filename;
+ filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
+ lua_remove(L, -2); /* remove path template */
+ if (readable(filename)) /* does file exist and is readable? */
+ return filename; /* return that file name */
+ lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
+ lua_remove(L, -2); /* remove file name */
+ lua_concat(L, 2); /* add entry to possible error message */
+ }
+ return NULL; /* not found */
+}
+
+
+static void loaderror (lua_State *L, const char *filename) {
+ luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
+ lua_tostring(L, 1), filename, lua_tostring(L, -1));
+}
+
+
+static int loader_Lua (lua_State *L) {
+ const char *filename;
+ const char *name = luaL_checkstring(L, 1);
+ filename = findfile(L, name, "path");
+ if (filename == NULL) return 1; /* library not found in this path */
+ if (luaL_loadfile(L, filename) != 0)
+ loaderror(L, filename);
+ return 1; /* library loaded successfully */
+}
+
+
+static const char *mkfuncname (lua_State *L, const char *modname) {
+ const char *funcname;
+ const char *mark = strchr(modname, *LUA_IGMARK);
+ if (mark) modname = mark + 1;
+ funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
+ funcname = lua_pushfstring(L, POF"%s", funcname);
+ lua_remove(L, -2); /* remove 'gsub' result */
+ return funcname;
+}
+
+
+static int loader_C (lua_State *L) {
+ const char *funcname;
+ const char *name = luaL_checkstring(L, 1);
+ const char *filename = findfile(L, name, "cpath");
+ if (filename == NULL) return 1; /* library not found in this path */
+ funcname = mkfuncname(L, name);
+ if (ll_loadfunc(L, filename, funcname) != 0)
+ loaderror(L, filename);
+ return 1; /* library loaded successfully */
+}
+
+
+static int loader_Croot (lua_State *L) {
+ const char *funcname;
+ const char *filename;
+ const char *name = luaL_checkstring(L, 1);
+ const char *p = strchr(name, '.');
+ int stat;
+ if (p == NULL) return 0; /* is root */
+ lua_pushlstring(L, name, p - name);
+ filename = findfile(L, lua_tostring(L, -1), "cpath");
+ if (filename == NULL) return 1; /* root not found */
+ funcname = mkfuncname(L, name);
+ if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {
+ if (stat != ERRFUNC) loaderror(L, filename); /* real error */
+ lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
+ name, filename);
+ return 1; /* function not found */
+ }
+ return 1;
+}
+
+
+static int loader_preload (lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ lua_getfield(L, LUA_ENVIRONINDEX, "preload");
+ if (!lua_istable(L, -1))
+ luaL_error(L, LUA_QL("package.preload") " must be a table");
+ lua_getfield(L, -1, name);
+ if (lua_isnil(L, -1)) /* not found? */
+ lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
+ return 1;
+}
+
+
+static const int sentinel_ = 0;
+#define sentinel ((void *)&sentinel_)
+
+
+static int ll_require (lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ int i;
+ lua_settop(L, 1); /* _LOADED table will be at index 2 */
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_getfield(L, 2, name);
+ if (lua_toboolean(L, -1)) { /* is it there? */
+ if (lua_touserdata(L, -1) == sentinel) /* check loops */
+ luaL_error(L, "loop or previous error loading module " LUA_QS, name);
+ return 1; /* package is already loaded */
+ }
+ /* else must load it; iterate over available loaders */
+ lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
+ if (!lua_istable(L, -1))
+ luaL_error(L, LUA_QL("package.loaders") " must be a table");
+ lua_pushliteral(L, ""); /* error message accumulator */
+ for (i=1; ; i++) {
+ lua_rawgeti(L, -2, i); /* get a loader */
+ if (lua_isnil(L, -1))
+ luaL_error(L, "module " LUA_QS " not found:%s",
+ name, lua_tostring(L, -2));
+ lua_pushstring(L, name);
+ lua_call(L, 1, 1); /* call it */
+ if (lua_isfunction(L, -1)) /* did it find module? */
+ break; /* module loaded successfully */
+ else if (lua_isstring(L, -1)) /* loader returned error message? */
+ lua_concat(L, 2); /* accumulate it */
+ else
+ lua_pop(L, 1);
+ }
+ lua_pushlightuserdata(L, sentinel);
+ lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
+ lua_pushstring(L, name); /* pass name as argument to module */
+ lua_call(L, 1, 1); /* run loaded module */
+ if (!lua_isnil(L, -1)) /* non-nil return? */
+ lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
+ lua_getfield(L, 2, name);
+ if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */
+ lua_pushboolean(L, 1); /* use true as result */
+ lua_pushvalue(L, -1); /* extra copy to be returned */
+ lua_setfield(L, 2, name); /* _LOADED[name] = true */
+ }
+ return 1;
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** 'module' function
+** =======================================================
+*/
+
+
+static void setfenv (lua_State *L) {
+ lua_Debug ar;
+ if (lua_getstack(L, 1, &ar) == 0 ||
+ lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
+ lua_iscfunction(L, -1))
+ luaL_error(L, LUA_QL("module") " not called from a Lua function");
+ lua_pushvalue(L, -2);
+ lua_setfenv(L, -2);
+ lua_pop(L, 1);
+}
+
+
+static void dooptions (lua_State *L, int n) {
+ int i;
+ for (i = 2; i <= n; i++) {
+ lua_pushvalue(L, i); /* get option (a function) */
+ lua_pushvalue(L, -2); /* module */
+ lua_call(L, 1, 0);
+ }
+}
+
+
+static void modinit (lua_State *L, const char *modname) {
+ const char *dot;
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "_M"); /* module._M = module */
+ lua_pushstring(L, modname);
+ lua_setfield(L, -2, "_NAME");
+ dot = strrchr(modname, '.'); /* look for last dot in module name */
+ if (dot == NULL) dot = modname;
+ else dot++;
+ /* set _PACKAGE as package name (full module name minus last part) */
+ lua_pushlstring(L, modname, dot - modname);
+ lua_setfield(L, -2, "_PACKAGE");
+}
+
+
+static int ll_module (lua_State *L) {
+ const char *modname = luaL_checkstring(L, 1);
+ int loaded = lua_gettop(L) + 1; /* index of _LOADED table */
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
+ if (!lua_istable(L, -1)) { /* not found? */
+ lua_pop(L, 1); /* remove previous result */
+ /* try global variable (and create one if it does not exist) */
+ if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
+ return luaL_error(L, "name conflict for module " LUA_QS, modname);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
+ }
+ /* check whether table already has a _NAME field */
+ lua_getfield(L, -1, "_NAME");
+ if (!lua_isnil(L, -1)) /* is table an initialized module? */
+ lua_pop(L, 1);
+ else { /* no; initialize it */
+ lua_pop(L, 1);
+ modinit(L, modname);
+ }
+ lua_pushvalue(L, -1);
+ setfenv(L);
+ dooptions(L, loaded - 1);
+ return 0;
+}
+
+
+static int ll_seeall (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ if (!lua_getmetatable(L, 1)) {
+ lua_createtable(L, 0, 1); /* create new metatable */
+ lua_pushvalue(L, -1);
+ lua_setmetatable(L, 1);
+ }
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setfield(L, -2, "__index"); /* mt.__index = _G */
+ return 0;
+}
+
+
+/* }====================================================== */
+
+
+
+/* auxiliary mark (for internal use) */
+#define AUXMARK "\1"
+
+static void setpath (lua_State *L, const char *fieldname, const char *envname,
+ const char *def) {
+ const char *path = getenv(envname);
+ if (path == NULL) /* no environment variable? */
+ lua_pushstring(L, def); /* use default */
+ else {
+ /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
+ path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
+ LUA_PATHSEP AUXMARK LUA_PATHSEP);
+ luaL_gsub(L, path, AUXMARK, def);
+ lua_remove(L, -2);
+ }
+ setprogdir(L);
+ lua_setfield(L, -2, fieldname);
+}
+
+
+static const luaL_Reg pk_funcs[] = {
+ {"loadlib", ll_loadlib},
+ {"seeall", ll_seeall},
+ {NULL, NULL}
+};
+
+
+static const luaL_Reg ll_funcs[] = {
+ {"module", ll_module},
+ {"require", ll_require},
+ {NULL, NULL}
+};
+
+
+static const lua_CFunction loaders[] =
+ {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
+
+
+LUALIB_API int luaopen_package (lua_State *L) {
+ int i;
+ /* create new type _LOADLIB */
+ luaL_newmetatable(L, "_LOADLIB");
+ lua_pushcfunction(L, gctm);
+ lua_setfield(L, -2, "__gc");
+ /* create `package' table */
+ luaL_register(L, LUA_LOADLIBNAME, pk_funcs);
+#if defined(LUA_COMPAT_LOADLIB)
+ lua_getfield(L, -1, "loadlib");
+ lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
+#endif
+ lua_pushvalue(L, -1);
+ lua_replace(L, LUA_ENVIRONINDEX);
+ /* create `loaders' table */
+ lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1);
+ /* fill it with pre-defined loaders */
+ for (i=0; loaders[i] != NULL; i++) {
+ lua_pushcfunction(L, loaders[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+ lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */
+ setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */
+ setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */
+ /* store config information */
+ lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"
+ LUA_EXECDIR "\n" LUA_IGMARK);
+ lua_setfield(L, -2, "config");
+ /* set field `loaded' */
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
+ lua_setfield(L, -2, "loaded");
+ /* set field `preload' */
+ lua_newtable(L);
+ lua_setfield(L, -2, "preload");
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ luaL_register(L, NULL, ll_funcs); /* open lib into global table */
+ lua_pop(L, 1);
+ return 1; /* return 'package' table */
+}
+
diff --git a/lib/lua/src/lobject.c b/lib/lua/src/lobject.c
new file mode 100644
index 000000000..4ff50732a
--- /dev/null
+++ b/lib/lua/src/lobject.c
@@ -0,0 +1,214 @@
+/*
+** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
+** Some generic functions over Lua objects
+** See Copyright Notice in lua.h
+*/
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lobject_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "lvm.h"
+
+
+
+const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+
+
+/*
+** converts an integer to a "floating point byte", represented as
+** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
+** eeeee != 0 and (xxx) otherwise.
+*/
+int luaO_int2fb (unsigned int x) {
+ int e = 0; /* expoent */
+ while (x >= 16) {
+ x = (x+1) >> 1;
+ e++;
+ }
+ if (x < 8) return x;
+ else return ((e+1) << 3) | (cast_int(x) - 8);
+}
+
+
+/* converts back */
+int luaO_fb2int (int x) {
+ int e = (x >> 3) & 31;
+ if (e == 0) return x;
+ else return ((x & 7)+8) << (e - 1);
+}
+
+
+int luaO_log2 (unsigned int x) {
+ static const lu_byte log_2[256] = {
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+ };
+ int l = -1;
+ while (x >= 256) { l += 8; x >>= 8; }
+ return l + log_2[x];
+
+}
+
+
+int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+ if (ttype(t1) != ttype(t2)) return 0;
+ else switch (ttype(t1)) {
+ case LUA_TNIL:
+ return 1;
+ case LUA_TNUMBER:
+ return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
+ case LUA_TLIGHTUSERDATA:
+ return pvalue(t1) == pvalue(t2);
+ default:
+ lua_assert(iscollectable(t1));
+ return gcvalue(t1) == gcvalue(t2);
+ }
+}
+
+
+int luaO_str2d (const char *s, lua_Number *result) {
+ char *endptr;
+ *result = lua_str2number(s, &endptr);
+ if (endptr == s) return 0; /* conversion failed */
+ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
+ *result = cast_num(strtoul(s, &endptr, 16));
+ if (*endptr == '\0') return 1; /* most common case */
+ while (isspace(cast(unsigned char, *endptr))) endptr++;
+ if (*endptr != '\0') return 0; /* invalid trailing characters? */
+ return 1;
+}
+
+
+
+static void pushstr (lua_State *L, const char *str) {
+ setsvalue2s(L, L->top, luaS_new(L, str));
+ incr_top(L);
+}
+
+
+/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
+const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
+ int n = 1;
+ pushstr(L, "");
+ for (;;) {
+ const char *e = strchr(fmt, '%');
+ if (e == NULL) break;
+ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
+ incr_top(L);
+ switch (*(e+1)) {
+ case 's': {
+ const char *s = va_arg(argp, char *);
+ if (s == NULL) s = "(null)";
+ pushstr(L, s);
+ break;
+ }
+ case 'c': {
+ char buff[2];
+ buff[0] = cast(char, va_arg(argp, int));
+ buff[1] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ case 'd': {
+ setnvalue(L->top, cast_num(va_arg(argp, int)));
+ incr_top(L);
+ break;
+ }
+ case 'f': {
+ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
+ incr_top(L);
+ break;
+ }
+ case 'p': {
+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
+ sprintf(buff, "%p", va_arg(argp, void *));
+ pushstr(L, buff);
+ break;
+ }
+ case '%': {
+ pushstr(L, "%");
+ break;
+ }
+ default: {
+ char buff[3];
+ buff[0] = '%';
+ buff[1] = *(e+1);
+ buff[2] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ }
+ n += 2;
+ fmt = e+2;
+ }
+ pushstr(L, fmt);
+ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);
+ L->top -= n;
+ return svalue(L->top - 1);
+}
+
+
+const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
+ const char *msg;
+ va_list argp;
+ va_start(argp, fmt);
+ msg = luaO_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ return msg;
+}
+
+
+void luaO_chunkid (char *out, const char *source, size_t bufflen) {
+ if (*source == '=') {
+ strncpy(out, source+1, bufflen); /* remove first char */
+ out[bufflen-1] = '\0'; /* ensures null termination */
+ }
+ else { /* out = "source", or "...source" */
+ if (*source == '@') {
+ size_t l;
+ source++; /* skip the `@' */
+ bufflen -= sizeof(" '...' ");
+ l = strlen(source);
+ strcpy(out, "");
+ if (l > bufflen) {
+ source += (l-bufflen); /* get last part of file name */
+ strcat(out, "...");
+ }
+ strcat(out, source);
+ }
+ else { /* out = [string "string"] */
+ size_t len = strcspn(source, "\n\r"); /* stop at first newline */
+ bufflen -= sizeof(" [string \"...\"] ");
+ if (len > bufflen) len = bufflen;
+ strcpy(out, "[string \"");
+ if (source[len] != '\0') { /* must truncate? */
+ strncat(out, source, len);
+ strcat(out, "...");
+ }
+ else
+ strcat(out, source);
+ strcat(out, "\"]");
+ }
+ }
+}
diff --git a/lib/lua/src/lobject.h b/lib/lua/src/lobject.h
new file mode 100644
index 000000000..f1e447ef3
--- /dev/null
+++ b/lib/lua/src/lobject.h
@@ -0,0 +1,381 @@
+/*
+** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $
+** Type definitions for Lua objects
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lobject_h
+#define lobject_h
+
+
+#include <stdarg.h>
+
+
+#include "llimits.h"
+#include "lua.h"
+
+
+/* tags for values visible from Lua */
+#define LAST_TAG LUA_TTHREAD
+
+#define NUM_TAGS (LAST_TAG+1)
+
+
+/*
+** Extra tags for non-values
+*/
+#define LUA_TPROTO (LAST_TAG+1)
+#define LUA_TUPVAL (LAST_TAG+2)
+#define LUA_TDEADKEY (LAST_TAG+3)
+
+
+/*
+** Union of all collectable objects
+*/
+typedef union GCObject GCObject;
+
+
+/*
+** Common Header for all collectable objects (in macro form, to be
+** included in other objects)
+*/
+#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
+
+
+/*
+** Common header in struct form
+*/
+typedef struct GCheader {
+ CommonHeader;
+} GCheader;
+
+
+
+
+/*
+** Union of all Lua values
+*/
+typedef union {
+ GCObject *gc;
+ void *p;
+ lua_Number n;
+ int b;
+} Value;
+
+
+/*
+** Tagged Values
+*/
+
+#define TValuefields Value value; int tt
+
+typedef struct lua_TValue {
+ TValuefields;
+} TValue;
+
+
+/* Macros to test type */
+#define ttisnil(o) (ttype(o) == LUA_TNIL)
+#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
+#define ttisstring(o) (ttype(o) == LUA_TSTRING)
+#define ttistable(o) (ttype(o) == LUA_TTABLE)
+#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
+#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
+#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
+#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
+#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
+
+/* Macros to access values */
+#define ttype(o) ((o)->tt)
+#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
+#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
+#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
+#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
+#define tsvalue(o) (&rawtsvalue(o)->tsv)
+#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
+#define uvalue(o) (&rawuvalue(o)->uv)
+#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
+#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
+#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
+#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
+
+#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
+
+/*
+** for internal debug only
+*/
+#define checkconsistency(obj) \
+ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
+
+#define checkliveness(g,obj) \
+ lua_assert(!iscollectable(obj) || \
+ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
+
+
+/* Macros to set values */
+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
+#define setnvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
+
+#define setpvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+
+#define setbvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
+
+#define setsvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
+ checkliveness(G(L),i_o); }
+
+#define setuvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
+ checkliveness(G(L),i_o); }
+
+#define setthvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
+ checkliveness(G(L),i_o); }
+
+#define setclvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
+ checkliveness(G(L),i_o); }
+
+#define sethvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
+ checkliveness(G(L),i_o); }
+
+#define setptvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+ checkliveness(G(L),i_o); }
+
+
+
+
+#define setobj(L,obj1,obj2) \
+ { const TValue *o2=(obj2); TValue *o1=(obj1); \
+ o1->value = o2->value; o1->tt=o2->tt; \
+ checkliveness(G(L),o1); }
+
+
+/*
+** different types of sets, according to destination
+*/
+
+/* from stack to (same) stack */
+#define setobjs2s setobj
+/* to stack (not from same stack) */
+#define setobj2s setobj
+#define setsvalue2s setsvalue
+#define sethvalue2s sethvalue
+#define setptvalue2s setptvalue
+/* from table to same table */
+#define setobjt2t setobj
+/* to table */
+#define setobj2t setobj
+/* to new object */
+#define setobj2n setobj
+#define setsvalue2n setsvalue
+
+#define setttype(obj, tt) (ttype(obj) = (tt))
+
+
+#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
+
+
+
+typedef TValue *StkId; /* index to stack elements */
+
+
+/*
+** String headers for string table
+*/
+typedef union TString {
+ L_Umaxalign dummy; /* ensures maximum alignment for strings */
+ struct {
+ CommonHeader;
+ lu_byte reserved;
+ unsigned int hash;
+ size_t len;
+ } tsv;
+} TString;
+
+
+#define getstr(ts) cast(const char *, (ts) + 1)
+#define svalue(o) getstr(rawtsvalue(o))
+
+
+
+typedef union Udata {
+ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
+ struct {
+ CommonHeader;
+ struct Table *metatable;
+ struct Table *env;
+ size_t len;
+ } uv;
+} Udata;
+
+
+
+
+/*
+** Function Prototypes
+*/
+typedef struct Proto {
+ CommonHeader;
+ TValue *k; /* constants used by the function */
+ Instruction *code;
+ struct Proto **p; /* functions defined inside the function */
+ int *lineinfo; /* map from opcodes to source lines */
+ struct LocVar *locvars; /* information about local variables */
+ TString **upvalues; /* upvalue names */
+ TString *source;
+ int sizeupvalues;
+ int sizek; /* size of `k' */
+ int sizecode;
+ int sizelineinfo;
+ int sizep; /* size of `p' */
+ int sizelocvars;
+ int linedefined;
+ int lastlinedefined;
+ GCObject *gclist;
+ lu_byte nups; /* number of upvalues */
+ lu_byte numparams;
+ lu_byte is_vararg;
+ lu_byte maxstacksize;
+} Proto;
+
+
+/* masks for new-style vararg */
+#define VARARG_HASARG 1
+#define VARARG_ISVARARG 2
+#define VARARG_NEEDSARG 4
+
+
+typedef struct LocVar {
+ TString *varname;
+ int startpc; /* first point where variable is active */
+ int endpc; /* first point where variable is dead */
+} LocVar;
+
+
+
+/*
+** Upvalues
+*/
+
+typedef struct UpVal {
+ CommonHeader;
+ TValue *v; /* points to stack or to its own value */
+ union {
+ TValue value; /* the value (when closed) */
+ struct { /* double linked list (when open) */
+ struct UpVal *prev;
+ struct UpVal *next;
+ } l;
+ } u;
+} UpVal;
+
+
+/*
+** Closures
+*/
+
+#define ClosureHeader \
+ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
+ struct Table *env
+
+typedef struct CClosure {
+ ClosureHeader;
+ lua_CFunction f;
+ TValue upvalue[1];
+} CClosure;
+
+
+typedef struct LClosure {
+ ClosureHeader;
+ struct Proto *p;
+ UpVal *upvals[1];
+} LClosure;
+
+
+typedef union Closure {
+ CClosure c;
+ LClosure l;
+} Closure;
+
+
+#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
+#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
+
+
+/*
+** Tables
+*/
+
+typedef union TKey {
+ struct {
+ TValuefields;
+ struct Node *next; /* for chaining */
+ } nk;
+ TValue tvk;
+} TKey;
+
+
+typedef struct Node {
+ TValue i_val;
+ TKey i_key;
+} Node;
+
+
+typedef struct Table {
+ CommonHeader;
+ lu_byte flags; /* 1<<p means tagmethod(p) is not present */
+ lu_byte lsizenode; /* log2 of size of `node' array */
+ struct Table *metatable;
+ TValue *array; /* array part */
+ Node *node;
+ Node *lastfree; /* any free position is before this position */
+ GCObject *gclist;
+ int sizearray; /* size of `array' array */
+} Table;
+
+
+
+/*
+** `module' operation for hashing (size is always a power of 2)
+*/
+#define lmod(s,size) \
+ (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
+
+
+#define twoto(x) (1<<(x))
+#define sizenode(t) (twoto((t)->lsizenode))
+
+
+#define luaO_nilobject (&luaO_nilobject_)
+
+LUAI_DATA const TValue luaO_nilobject_;
+
+#define ceillog2(x) (luaO_log2((x)-1) + 1)
+
+LUAI_FUNC int luaO_log2 (unsigned int x);
+LUAI_FUNC int luaO_int2fb (unsigned int x);
+LUAI_FUNC int luaO_fb2int (int x);
+LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp);
+LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+
+
+#endif
+
diff --git a/lib/lua/src/lopcodes.c b/lib/lua/src/lopcodes.c
new file mode 100644
index 000000000..4cc745230
--- /dev/null
+++ b/lib/lua/src/lopcodes.c
@@ -0,0 +1,102 @@
+/*
+** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
+** See Copyright Notice in lua.h
+*/
+
+
+#define lopcodes_c
+#define LUA_CORE
+
+
+#include "lopcodes.h"
+
+
+/* ORDER OP */
+
+const char *const luaP_opnames[NUM_OPCODES+1] = {
+ "MOVE",
+ "LOADK",
+ "LOADBOOL",
+ "LOADNIL",
+ "GETUPVAL",
+ "GETGLOBAL",
+ "GETTABLE",
+ "SETGLOBAL",
+ "SETUPVAL",
+ "SETTABLE",
+ "NEWTABLE",
+ "SELF",
+ "ADD",
+ "SUB",
+ "MUL",
+ "DIV",
+ "MOD",
+ "POW",
+ "UNM",
+ "NOT",
+ "LEN",
+ "CONCAT",
+ "JMP",
+ "EQ",
+ "LT",
+ "LE",
+ "TEST",
+ "TESTSET",
+ "CALL",
+ "TAILCALL",
+ "RETURN",
+ "FORLOOP",
+ "FORPREP",
+ "TFORLOOP",
+ "SETLIST",
+ "CLOSE",
+ "CLOSURE",
+ "VARARG",
+ NULL
+};
+
+
+#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
+
+const lu_byte luaP_opmodes[NUM_OPCODES] = {
+/* T A B C mode opcode */
+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
+ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
+ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
+ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
+ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */
+ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
+ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
+};
+
diff --git a/lib/lua/src/lopcodes.h b/lib/lua/src/lopcodes.h
new file mode 100644
index 000000000..41224d6ee
--- /dev/null
+++ b/lib/lua/src/lopcodes.h
@@ -0,0 +1,268 @@
+/*
+** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $
+** Opcodes for Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lopcodes_h
+#define lopcodes_h
+
+#include "llimits.h"
+
+
+/*===========================================================================
+ We assume that instructions are unsigned numbers.
+ All instructions have an opcode in the first 6 bits.
+ Instructions can have the following fields:
+ `A' : 8 bits
+ `B' : 9 bits
+ `C' : 9 bits
+ `Bx' : 18 bits (`B' and `C' together)
+ `sBx' : signed Bx
+
+ A signed argument is represented in excess K; that is, the number
+ value is the unsigned value minus K. K is exactly the maximum value
+ for that argument (so that -max is represented by 0, and +max is
+ represented by 2*max), which is half the maximum for the corresponding
+ unsigned argument.
+===========================================================================*/
+
+
+enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
+
+
+/*
+** size and position of opcode arguments.
+*/
+#define SIZE_C 9
+#define SIZE_B 9
+#define SIZE_Bx (SIZE_C + SIZE_B)
+#define SIZE_A 8
+
+#define SIZE_OP 6
+
+#define POS_OP 0
+#define POS_A (POS_OP + SIZE_OP)
+#define POS_C (POS_A + SIZE_A)
+#define POS_B (POS_C + SIZE_C)
+#define POS_Bx POS_C
+
+
+/*
+** limits for opcode arguments.
+** we use (signed) int to manipulate most arguments,
+** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
+*/
+#if SIZE_Bx < LUAI_BITSINT-1
+#define MAXARG_Bx ((1<<SIZE_Bx)-1)
+#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
+#else
+#define MAXARG_Bx MAX_INT
+#define MAXARG_sBx MAX_INT
+#endif
+
+
+#define MAXARG_A ((1<<SIZE_A)-1)
+#define MAXARG_B ((1<<SIZE_B)-1)
+#define MAXARG_C ((1<<SIZE_C)-1)
+
+
+/* creates a mask with `n' 1 bits at position `p' */
+#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p)
+
+/* creates a mask with `n' 0 bits at position `p' */
+#define MASK0(n,p) (~MASK1(n,p))
+
+/*
+** the following macros help to manipulate instructions
+*/
+
+#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
+#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
+ ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
+
+#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
+#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
+ ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
+
+#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
+#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
+ ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
+
+#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
+#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
+ ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
+
+#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
+#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
+ ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
+
+#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
+#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
+
+
+#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \
+ | (cast(Instruction, a)<<POS_A) \
+ | (cast(Instruction, b)<<POS_B) \
+ | (cast(Instruction, c)<<POS_C))
+
+#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
+ | (cast(Instruction, a)<<POS_A) \
+ | (cast(Instruction, bc)<<POS_Bx))
+
+
+/*
+** Macros to operate RK indices
+*/
+
+/* this bit 1 means constant (0 means register) */
+#define BITRK (1 << (SIZE_B - 1))
+
+/* test whether value is a constant */
+#define ISK(x) ((x) & BITRK)
+
+/* gets the index of the constant */
+#define INDEXK(r) ((int)(r) & ~BITRK)
+
+#define MAXINDEXRK (BITRK - 1)
+
+/* code a constant index as a RK value */
+#define RKASK(x) ((x) | BITRK)
+
+
+/*
+** invalid register that fits in 8 bits
+*/
+#define NO_REG MAXARG_A
+
+
+/*
+** R(x) - register
+** Kst(x) - constant (in constant table)
+** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
+*/
+
+
+/*
+** grep "ORDER OP" if you change these enums
+*/
+
+typedef enum {
+/*----------------------------------------------------------------------
+name args description
+------------------------------------------------------------------------*/
+OP_MOVE,/* A B R(A) := R(B) */
+OP_LOADK,/* A Bx R(A) := Kst(Bx) */
+OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
+OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
+OP_GETUPVAL,/* A B R(A) := UpValue[B] */
+
+OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
+OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
+
+OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
+OP_SETUPVAL,/* A B UpValue[B] := R(A) */
+OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
+
+OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
+
+OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
+
+OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
+OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
+OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
+OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
+OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
+OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
+OP_UNM,/* A B R(A) := -R(B) */
+OP_NOT,/* A B R(A) := not R(B) */
+OP_LEN,/* A B R(A) := length of R(B) */
+
+OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
+
+OP_JMP,/* sBx pc+=sBx */
+
+OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
+OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
+OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
+
+OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
+OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
+
+OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
+
+OP_FORLOOP,/* A sBx R(A)+=R(A+2);
+ if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
+OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
+
+OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
+ if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
+OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
+
+OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
+OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
+
+OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
+} OpCode;
+
+
+#define NUM_OPCODES (cast(int, OP_VARARG) + 1)
+
+
+
+/*===========================================================================
+ Notes:
+ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
+ and can be 0: OP_CALL then sets `top' to last_result+1, so
+ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
+
+ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
+ set top (like in OP_CALL with C == 0).
+
+ (*) In OP_RETURN, if (B == 0) then return up to `top'
+
+ (*) In OP_SETLIST, if (B == 0) then B = `top';
+ if (C == 0) then next `instruction' is real C
+
+ (*) For comparisons, A specifies what condition the test should accept
+ (true or false).
+
+ (*) All `skips' (pc++) assume that next instruction is a jump
+===========================================================================*/
+
+
+/*
+** masks for instruction properties. The format is:
+** bits 0-1: op mode
+** bits 2-3: C arg mode
+** bits 4-5: B arg mode
+** bit 6: instruction set register A
+** bit 7: operator is a test
+*/
+
+enum OpArgMask {
+ OpArgN, /* argument is not used */
+ OpArgU, /* argument is used */
+ OpArgR, /* argument is a register or a jump offset */
+ OpArgK /* argument is a constant or register/constant */
+};
+
+LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
+
+#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
+#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
+#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
+#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
+#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
+
+
+LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
+
+
+/* number of list items to accumulate before a SETLIST instruction */
+#define LFIELDS_PER_FLUSH 50
+
+
+#endif
diff --git a/lib/lua/src/loslib.c b/lib/lua/src/loslib.c
new file mode 100644
index 000000000..da06a572a
--- /dev/null
+++ b/lib/lua/src/loslib.c
@@ -0,0 +1,243 @@
+/*
+** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
+** Standard Operating System library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define loslib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+static int os_pushresult (lua_State *L, int i, const char *filename) {
+ int en = errno; /* calls to Lua API may change this value */
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+}
+
+
+static int os_execute (lua_State *L) {
+ lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
+ return 1;
+}
+
+
+static int os_remove (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ return os_pushresult(L, remove(filename) == 0, filename);
+}
+
+
+static int os_rename (lua_State *L) {
+ const char *fromname = luaL_checkstring(L, 1);
+ const char *toname = luaL_checkstring(L, 2);
+ return os_pushresult(L, rename(fromname, toname) == 0, fromname);
+}
+
+
+static int os_tmpname (lua_State *L) {
+ char buff[LUA_TMPNAMBUFSIZE];
+ int err;
+ lua_tmpnam(buff, err);
+ if (err)
+ return luaL_error(L, "unable to generate a unique filename");
+ lua_pushstring(L, buff);
+ return 1;
+}
+
+
+static int os_getenv (lua_State *L) {
+ lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
+ return 1;
+}
+
+
+static int os_clock (lua_State *L) {
+ lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
+ return 1;
+}
+
+
+/*
+** {======================================================
+** Time/Date operations
+** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
+** wday=%w+1, yday=%j, isdst=? }
+** =======================================================
+*/
+
+static void setfield (lua_State *L, const char *key, int value) {
+ lua_pushinteger(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static void setboolfield (lua_State *L, const char *key, int value) {
+ if (value < 0) /* undefined? */
+ return; /* does not set field */
+ lua_pushboolean(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static int getboolfield (lua_State *L, const char *key) {
+ int res;
+ lua_getfield(L, -1, key);
+ res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int getfield (lua_State *L, const char *key, int d) {
+ int res;
+ lua_getfield(L, -1, key);
+ if (lua_isnumber(L, -1))
+ res = (int)lua_tointeger(L, -1);
+ else {
+ if (d < 0)
+ return luaL_error(L, "field " LUA_QS " missing in date table", key);
+ res = d;
+ }
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int os_date (lua_State *L) {
+ const char *s = luaL_optstring(L, 1, "%c");
+ time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
+ struct tm *stm;
+ if (*s == '!') { /* UTC? */
+ stm = gmtime(&t);
+ s++; /* skip `!' */
+ }
+ else
+ stm = localtime(&t);
+ if (stm == NULL) /* invalid date? */
+ lua_pushnil(L);
+ else if (strcmp(s, "*t") == 0) {
+ lua_createtable(L, 0, 9); /* 9 = number of fields */
+ setfield(L, "sec", stm->tm_sec);
+ setfield(L, "min", stm->tm_min);
+ setfield(L, "hour", stm->tm_hour);
+ setfield(L, "day", stm->tm_mday);
+ setfield(L, "month", stm->tm_mon+1);
+ setfield(L, "year", stm->tm_year+1900);
+ setfield(L, "wday", stm->tm_wday+1);
+ setfield(L, "yday", stm->tm_yday+1);
+ setboolfield(L, "isdst", stm->tm_isdst);
+ }
+ else {
+ char cc[3];
+ luaL_Buffer b;
+ cc[0] = '%'; cc[2] = '\0';
+ luaL_buffinit(L, &b);
+ for (; *s; s++) {
+ if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
+ luaL_addchar(&b, *s);
+ else {
+ size_t reslen;
+ char buff[200]; /* should be big enough for any conversion result */
+ cc[1] = *(++s);
+ reslen = strftime(buff, sizeof(buff), cc, stm);
+ luaL_addlstring(&b, buff, reslen);
+ }
+ }
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+
+static int os_time (lua_State *L) {
+ time_t t;
+ if (lua_isnoneornil(L, 1)) /* called without args? */
+ t = time(NULL); /* get current time */
+ else {
+ struct tm ts;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 1); /* make sure table is at the top */
+ ts.tm_sec = getfield(L, "sec", 0);
+ ts.tm_min = getfield(L, "min", 0);
+ ts.tm_hour = getfield(L, "hour", 12);
+ ts.tm_mday = getfield(L, "day", -1);
+ ts.tm_mon = getfield(L, "month", -1) - 1;
+ ts.tm_year = getfield(L, "year", -1) - 1900;
+ ts.tm_isdst = getboolfield(L, "isdst");
+ t = mktime(&ts);
+ }
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+ else
+ lua_pushnumber(L, (lua_Number)t);
+ return 1;
+}
+
+
+static int os_difftime (lua_State *L) {
+ lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+ (time_t)(luaL_optnumber(L, 2, 0))));
+ return 1;
+}
+
+/* }====================================================== */
+
+
+static int os_setlocale (lua_State *L) {
+ static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
+ LC_NUMERIC, LC_TIME};
+ static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
+ "numeric", "time", NULL};
+ const char *l = luaL_optstring(L, 1, NULL);
+ int op = luaL_checkoption(L, 2, "all", catnames);
+ lua_pushstring(L, setlocale(cat[op], l));
+ return 1;
+}
+
+
+static int os_exit (lua_State *L) {
+ exit(luaL_optint(L, 1, EXIT_SUCCESS));
+}
+
+static const luaL_Reg syslib[] = {
+ {"clock", os_clock},
+ {"date", os_date},
+ {"difftime", os_difftime},
+ {"execute", os_execute},
+ {"exit", os_exit},
+ {"getenv", os_getenv},
+ {"remove", os_remove},
+ {"rename", os_rename},
+ {"setlocale", os_setlocale},
+ {"time", os_time},
+ {"tmpname", os_tmpname},
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+LUALIB_API int luaopen_os (lua_State *L) {
+ luaL_register(L, LUA_OSLIBNAME, syslib);
+ return 1;
+}
+
diff --git a/lib/lua/src/lparser.c b/lib/lua/src/lparser.c
new file mode 100644
index 000000000..1e2a9a88b
--- /dev/null
+++ b/lib/lua/src/lparser.c
@@ -0,0 +1,1339 @@
+/*
+** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lparser_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+
+
+
+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
+
+#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
+
+#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
+
+
+/*
+** nodes for block list (list of active blocks)
+*/
+typedef struct BlockCnt {
+ struct BlockCnt *previous; /* chain */
+ int breaklist; /* list of jumps out of this loop */
+ lu_byte nactvar; /* # active locals outside the breakable structure */
+ lu_byte upval; /* true if some variable in the block is an upvalue */
+ lu_byte isbreakable; /* true if `block' is a loop */
+} BlockCnt;
+
+
+
+/*
+** prototypes for recursive non-terminal functions
+*/
+static void chunk (LexState *ls);
+static void expr (LexState *ls, expdesc *v);
+
+
+static void anchor_token (LexState *ls) {
+ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
+ TString *ts = ls->t.seminfo.ts;
+ luaX_newstring(ls, getstr(ts), ts->tsv.len);
+ }
+}
+
+
+static void error_expected (LexState *ls, int token) {
+ luaX_syntaxerror(ls,
+ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token)));
+}
+
+
+static void errorlimit (FuncState *fs, int limit, const char *what) {
+ const char *msg = (fs->f->linedefined == 0) ?
+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+ fs->f->linedefined, limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
+}
+
+
+static int testnext (LexState *ls, int c) {
+ if (ls->t.token == c) {
+ luaX_next(ls);
+ return 1;
+ }
+ else return 0;
+}
+
+
+static void check (LexState *ls, int c) {
+ if (ls->t.token != c)
+ error_expected(ls, c);
+}
+
+static void checknext (LexState *ls, int c) {
+ check(ls, c);
+ luaX_next(ls);
+}
+
+
+#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); }
+
+
+
+static void check_match (LexState *ls, int what, int who, int where) {
+ if (!testnext(ls, what)) {
+ if (where == ls->linenumber)
+ error_expected(ls, what);
+ else {
+ luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
+ LUA_QS " expected (to close " LUA_QS " at line %d)",
+ luaX_token2str(ls, what), luaX_token2str(ls, who), where));
+ }
+ }
+}
+
+
+static TString *str_checkname (LexState *ls) {
+ TString *ts;
+ check(ls, TK_NAME);
+ ts = ls->t.seminfo.ts;
+ luaX_next(ls);
+ return ts;
+}
+
+
+static void init_exp (expdesc *e, expkind k, int i) {
+ e->f = e->t = NO_JUMP;
+ e->k = k;
+ e->u.s.info = i;
+}
+
+
+static void codestring (LexState *ls, expdesc *e, TString *s) {
+ init_exp(e, VK, luaK_stringK(ls->fs, s));
+}
+
+
+static void checkname(LexState *ls, expdesc *e) {
+ codestring(ls, e, str_checkname(ls));
+}
+
+
+static int registerlocalvar (LexState *ls, TString *varname) {
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int oldsize = f->sizelocvars;
+ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
+ LocVar, SHRT_MAX, "too many local variables");
+ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
+ f->locvars[fs->nlocvars].varname = varname;
+ luaC_objbarrier(ls->L, f, varname);
+ return fs->nlocvars++;
+}
+
+
+#define new_localvarliteral(ls,v,n) \
+ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
+
+
+static void new_localvar (LexState *ls, TString *name, int n) {
+ FuncState *fs = ls->fs;
+ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
+ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
+}
+
+
+static void adjustlocalvars (LexState *ls, int nvars) {
+ FuncState *fs = ls->fs;
+ fs->nactvar = cast_byte(fs->nactvar + nvars);
+ for (; nvars; nvars--) {
+ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
+ }
+}
+
+
+static void removevars (LexState *ls, int tolevel) {
+ FuncState *fs = ls->fs;
+ while (fs->nactvar > tolevel)
+ getlocvar(fs, --fs->nactvar).endpc = fs->pc;
+}
+
+
+static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
+ int i;
+ Proto *f = fs->f;
+ int oldsize = f->sizeupvalues;
+ for (i=0; i<f->nups; i++) {
+ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
+ lua_assert(f->upvalues[i] == name);
+ return i;
+ }
+ }
+ /* new one */
+ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues");
+ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
+ TString *, MAX_INT, "");
+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
+ f->upvalues[f->nups] = name;
+ luaC_objbarrier(fs->L, f, name);
+ lua_assert(v->k == VLOCAL || v->k == VUPVAL);
+ fs->upvalues[f->nups].k = cast_byte(v->k);
+ fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
+ return f->nups++;
+}
+
+
+static int searchvar (FuncState *fs, TString *n) {
+ int i;
+ for (i=fs->nactvar-1; i >= 0; i--) {
+ if (n == getlocvar(fs, i).varname)
+ return i;
+ }
+ return -1; /* not found */
+}
+
+
+static void markupval (FuncState *fs, int level) {
+ BlockCnt *bl = fs->bl;
+ while (bl && bl->nactvar > level) bl = bl->previous;
+ if (bl) bl->upval = 1;
+}
+
+
+static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
+ if (fs == NULL) { /* no more levels? */
+ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */
+ return VGLOBAL;
+ }
+ else {
+ int v = searchvar(fs, n); /* look up at current level */
+ if (v >= 0) {
+ init_exp(var, VLOCAL, v);
+ if (!base)
+ markupval(fs, v); /* local will be used as an upval */
+ return VLOCAL;
+ }
+ else { /* not found at current level; try upper one */
+ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
+ return VGLOBAL;
+ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
+ var->k = VUPVAL; /* upvalue in this level */
+ return VUPVAL;
+ }
+ }
+}
+
+
+static void singlevar (LexState *ls, expdesc *var) {
+ TString *varname = str_checkname(ls);
+ FuncState *fs = ls->fs;
+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
+ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
+}
+
+
+static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
+ FuncState *fs = ls->fs;
+ int extra = nvars - nexps;
+ if (hasmultret(e->k)) {
+ extra++; /* includes call itself */
+ if (extra < 0) extra = 0;
+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
+ if (extra > 1) luaK_reserveregs(fs, extra-1);
+ }
+ else {
+ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
+ if (extra > 0) {
+ int reg = fs->freereg;
+ luaK_reserveregs(fs, extra);
+ luaK_nil(fs, reg, extra);
+ }
+ }
+}
+
+
+static void enterlevel (LexState *ls) {
+ if (++ls->L->nCcalls > LUAI_MAXCCALLS)
+ luaX_lexerror(ls, "chunk has too many syntax levels", 0);
+}
+
+
+#define leavelevel(ls) ((ls)->L->nCcalls--)
+
+
+static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
+ bl->breaklist = NO_JUMP;
+ bl->isbreakable = isbreakable;
+ bl->nactvar = fs->nactvar;
+ bl->upval = 0;
+ bl->previous = fs->bl;
+ fs->bl = bl;
+ lua_assert(fs->freereg == fs->nactvar);
+}
+
+
+static void leaveblock (FuncState *fs) {
+ BlockCnt *bl = fs->bl;
+ fs->bl = bl->previous;
+ removevars(fs->ls, bl->nactvar);
+ if (bl->upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ /* a block either controls scope or breaks (never both) */
+ lua_assert(!bl->isbreakable || !bl->upval);
+ lua_assert(bl->nactvar == fs->nactvar);
+ fs->freereg = fs->nactvar; /* free registers */
+ luaK_patchtohere(fs, bl->breaklist);
+}
+
+
+static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int oldsize = f->sizep;
+ int i;
+ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizep) f->p[oldsize++] = NULL;
+ f->p[fs->np++] = func->f;
+ luaC_objbarrier(ls->L, f, func->f);
+ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
+ for (i=0; i<func->f->nups; i++) {
+ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
+ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
+ }
+}
+
+
+static void open_func (LexState *ls, FuncState *fs) {
+ lua_State *L = ls->L;
+ Proto *f = luaF_newproto(L);
+ fs->f = f;
+ fs->prev = ls->fs; /* linked list of funcstates */
+ fs->ls = ls;
+ fs->L = L;
+ ls->fs = fs;
+ fs->pc = 0;
+ fs->lasttarget = -1;
+ fs->jpc = NO_JUMP;
+ fs->freereg = 0;
+ fs->nk = 0;
+ fs->np = 0;
+ fs->nlocvars = 0;
+ fs->nactvar = 0;
+ fs->bl = NULL;
+ f->source = ls->source;
+ f->maxstacksize = 2; /* registers 0/1 are always valid */
+ fs->h = luaH_new(L, 0, 0);
+ /* anchor table of constants and prototype (to avoid being collected) */
+ sethvalue2s(L, L->top, fs->h);
+ incr_top(L);
+ setptvalue2s(L, L->top, f);
+ incr_top(L);
+}
+
+
+static void close_func (LexState *ls) {
+ lua_State *L = ls->L;
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ removevars(ls, 0);
+ luaK_ret(fs, 0, 0); /* final return */
+ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
+ f->sizecode = fs->pc;
+ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
+ f->sizelineinfo = fs->pc;
+ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
+ f->sizek = fs->nk;
+ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
+ f->sizep = fs->np;
+ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
+ f->sizelocvars = fs->nlocvars;
+ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
+ f->sizeupvalues = f->nups;
+ lua_assert(luaG_checkcode(f));
+ lua_assert(fs->bl == NULL);
+ ls->fs = fs->prev;
+ L->top -= 2; /* remove table and prototype from the stack */
+ /* last token read was anchored in defunct function; must reanchor it */
+ if (fs) anchor_token(ls);
+}
+
+
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
+ struct LexState lexstate;
+ struct FuncState funcstate;
+ lexstate.buff = buff;
+ luaX_setinput(L, &lexstate, z, luaS_new(L, name));
+ open_func(&lexstate, &funcstate);
+ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
+ luaX_next(&lexstate); /* read first token */
+ chunk(&lexstate);
+ check(&lexstate, TK_EOS);
+ close_func(&lexstate);
+ lua_assert(funcstate.prev == NULL);
+ lua_assert(funcstate.f->nups == 0);
+ lua_assert(lexstate.fs == NULL);
+ return funcstate.f;
+}
+
+
+
+/*============================================================*/
+/* GRAMMAR RULES */
+/*============================================================*/
+
+
+static void field (LexState *ls, expdesc *v) {
+ /* field -> ['.' | ':'] NAME */
+ FuncState *fs = ls->fs;
+ expdesc key;
+ luaK_exp2anyreg(fs, v);
+ luaX_next(ls); /* skip the dot or colon */
+ checkname(ls, &key);
+ luaK_indexed(fs, v, &key);
+}
+
+
+static void yindex (LexState *ls, expdesc *v) {
+ /* index -> '[' expr ']' */
+ luaX_next(ls); /* skip the '[' */
+ expr(ls, v);
+ luaK_exp2val(ls->fs, v);
+ checknext(ls, ']');
+}
+
+
+/*
+** {======================================================================
+** Rules for Constructors
+** =======================================================================
+*/
+
+
+struct ConsControl {
+ expdesc v; /* last list item read */
+ expdesc *t; /* table descriptor */
+ int nh; /* total number of `record' elements */
+ int na; /* total number of array elements */
+ int tostore; /* number of array elements pending to be stored */
+};
+
+
+static void recfield (LexState *ls, struct ConsControl *cc) {
+ /* recfield -> (NAME | `['exp1`]') = exp1 */
+ FuncState *fs = ls->fs;
+ int reg = ls->fs->freereg;
+ expdesc key, val;
+ int rkkey;
+ if (ls->t.token == TK_NAME) {
+ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
+ checkname(ls, &key);
+ }
+ else /* ls->t.token == '[' */
+ yindex(ls, &key);
+ cc->nh++;
+ checknext(ls, '=');
+ rkkey = luaK_exp2RK(fs, &key);
+ expr(ls, &val);
+ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));
+ fs->freereg = reg; /* free registers */
+}
+
+
+static void closelistfield (FuncState *fs, struct ConsControl *cc) {
+ if (cc->v.k == VVOID) return; /* there is no list item */
+ luaK_exp2nextreg(fs, &cc->v);
+ cc->v.k = VVOID;
+ if (cc->tostore == LFIELDS_PER_FLUSH) {
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */
+ cc->tostore = 0; /* no more items pending */
+ }
+}
+
+
+static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
+ if (cc->tostore == 0) return;
+ if (hasmultret(cc->v.k)) {
+ luaK_setmultret(fs, &cc->v);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);
+ cc->na--; /* do not count last expression (unknown number of elements) */
+ }
+ else {
+ if (cc->v.k != VVOID)
+ luaK_exp2nextreg(fs, &cc->v);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
+ }
+}
+
+
+static void listfield (LexState *ls, struct ConsControl *cc) {
+ expr(ls, &cc->v);
+ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
+ cc->na++;
+ cc->tostore++;
+}
+
+
+static void constructor (LexState *ls, expdesc *t) {
+ /* constructor -> ?? */
+ FuncState *fs = ls->fs;
+ int line = ls->linenumber;
+ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
+ struct ConsControl cc;
+ cc.na = cc.nh = cc.tostore = 0;
+ cc.t = t;
+ init_exp(t, VRELOCABLE, pc);
+ init_exp(&cc.v, VVOID, 0); /* no value (yet) */
+ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */
+ checknext(ls, '{');
+ do {
+ lua_assert(cc.v.k == VVOID || cc.tostore > 0);
+ if (ls->t.token == '}') break;
+ closelistfield(fs, &cc);
+ switch(ls->t.token) {
+ case TK_NAME: { /* may be listfields or recfields */
+ luaX_lookahead(ls);
+ if (ls->lookahead.token != '=') /* expression? */
+ listfield(ls, &cc);
+ else
+ recfield(ls, &cc);
+ break;
+ }
+ case '[': { /* constructor_item -> recfield */
+ recfield(ls, &cc);
+ break;
+ }
+ default: { /* constructor_part -> listfield */
+ listfield(ls, &cc);
+ break;
+ }
+ }
+ } while (testnext(ls, ',') || testnext(ls, ';'));
+ check_match(ls, '}', '{', line);
+ lastlistfield(fs, &cc);
+ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
+ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
+}
+
+/* }====================================================================== */
+
+
+
+static void parlist (LexState *ls) {
+ /* parlist -> [ param { `,' param } ] */
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int nparams = 0;
+ f->is_vararg = 0;
+ if (ls->t.token != ')') { /* is `parlist' not empty? */
+ do {
+ switch (ls->t.token) {
+ case TK_NAME: { /* param -> NAME */
+ new_localvar(ls, str_checkname(ls), nparams++);
+ break;
+ }
+ case TK_DOTS: { /* param -> `...' */
+ luaX_next(ls);
+#if defined(LUA_COMPAT_VARARG)
+ /* use `arg' as default name */
+ new_localvarliteral(ls, "arg", nparams++);
+ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
+#endif
+ f->is_vararg |= VARARG_ISVARARG;
+ break;
+ }
+ default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
+ }
+ } while (!f->is_vararg && testnext(ls, ','));
+ }
+ adjustlocalvars(ls, nparams);
+ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
+ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
+}
+
+
+static void body (LexState *ls, expdesc *e, int needself, int line) {
+ /* body -> `(' parlist `)' chunk END */
+ FuncState new_fs;
+ open_func(ls, &new_fs);
+ new_fs.f->linedefined = line;
+ checknext(ls, '(');
+ if (needself) {
+ new_localvarliteral(ls, "self", 0);
+ adjustlocalvars(ls, 1);
+ }
+ parlist(ls);
+ checknext(ls, ')');
+ chunk(ls);
+ new_fs.f->lastlinedefined = ls->linenumber;
+ check_match(ls, TK_END, TK_FUNCTION, line);
+ close_func(ls);
+ pushclosure(ls, &new_fs, e);
+}
+
+
+static int explist1 (LexState *ls, expdesc *v) {
+ /* explist1 -> expr { `,' expr } */
+ int n = 1; /* at least one expression */
+ expr(ls, v);
+ while (testnext(ls, ',')) {
+ luaK_exp2nextreg(ls->fs, v);
+ expr(ls, v);
+ n++;
+ }
+ return n;
+}
+
+
+static void funcargs (LexState *ls, expdesc *f) {
+ FuncState *fs = ls->fs;
+ expdesc args;
+ int base, nparams;
+ int line = ls->linenumber;
+ switch (ls->t.token) {
+ case '(': { /* funcargs -> `(' [ explist1 ] `)' */
+ if (line != ls->lastline)
+ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
+ luaX_next(ls);
+ if (ls->t.token == ')') /* arg list is empty? */
+ args.k = VVOID;
+ else {
+ explist1(ls, &args);
+ luaK_setmultret(fs, &args);
+ }
+ check_match(ls, ')', '(', line);
+ break;
+ }
+ case '{': { /* funcargs -> constructor */
+ constructor(ls, &args);
+ break;
+ }
+ case TK_STRING: { /* funcargs -> STRING */
+ codestring(ls, &args, ls->t.seminfo.ts);
+ luaX_next(ls); /* must use `seminfo' before `next' */
+ break;
+ }
+ default: {
+ luaX_syntaxerror(ls, "function arguments expected");
+ return;
+ }
+ }
+ lua_assert(f->k == VNONRELOC);
+ base = f->u.s.info; /* base register for call */
+ if (hasmultret(args.k))
+ nparams = LUA_MULTRET; /* open call */
+ else {
+ if (args.k != VVOID)
+ luaK_exp2nextreg(fs, &args); /* close last argument */
+ nparams = fs->freereg - (base+1);
+ }
+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+ luaK_fixline(fs, line);
+ fs->freereg = base+1; /* call remove function and arguments and leaves
+ (unless changed) one result */
+}
+
+
+
+
+/*
+** {======================================================================
+** Expression parsing
+** =======================================================================
+*/
+
+
+static void prefixexp (LexState *ls, expdesc *v) {
+ /* prefixexp -> NAME | '(' expr ')' */
+ switch (ls->t.token) {
+ case '(': {
+ int line = ls->linenumber;
+ luaX_next(ls);
+ expr(ls, v);
+ check_match(ls, ')', '(', line);
+ luaK_dischargevars(ls->fs, v);
+ return;
+ }
+ case TK_NAME: {
+ singlevar(ls, v);
+ return;
+ }
+ default: {
+ luaX_syntaxerror(ls, "unexpected symbol");
+ return;
+ }
+ }
+}
+
+
+static void primaryexp (LexState *ls, expdesc *v) {
+ /* primaryexp ->
+ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
+ FuncState *fs = ls->fs;
+ prefixexp(ls, v);
+ for (;;) {
+ switch (ls->t.token) {
+ case '.': { /* field */
+ field(ls, v);
+ break;
+ }
+ case '[': { /* `[' exp1 `]' */
+ expdesc key;
+ luaK_exp2anyreg(fs, v);
+ yindex(ls, &key);
+ luaK_indexed(fs, v, &key);
+ break;
+ }
+ case ':': { /* `:' NAME funcargs */
+ expdesc key;
+ luaX_next(ls);
+ checkname(ls, &key);
+ luaK_self(fs, v, &key);
+ funcargs(ls, v);
+ break;
+ }
+ case '(': case TK_STRING: case '{': { /* funcargs */
+ luaK_exp2nextreg(fs, v);
+ funcargs(ls, v);
+ break;
+ }
+ default: return;
+ }
+ }
+}
+
+
+static void simpleexp (LexState *ls, expdesc *v) {
+ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
+ constructor | FUNCTION body | primaryexp */
+ switch (ls->t.token) {
+ case TK_NUMBER: {
+ init_exp(v, VKNUM, 0);
+ v->u.nval = ls->t.seminfo.r;
+ break;
+ }
+ case TK_STRING: {
+ codestring(ls, v, ls->t.seminfo.ts);
+ break;
+ }
+ case TK_NIL: {
+ init_exp(v, VNIL, 0);
+ break;
+ }
+ case TK_TRUE: {
+ init_exp(v, VTRUE, 0);
+ break;
+ }
+ case TK_FALSE: {
+ init_exp(v, VFALSE, 0);
+ break;
+ }
+ case TK_DOTS: { /* vararg */
+ FuncState *fs = ls->fs;
+ check_condition(ls, fs->f->is_vararg,
+ "cannot use " LUA_QL("...") " outside a vararg function");
+ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
+ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
+ break;
+ }
+ case '{': { /* constructor */
+ constructor(ls, v);
+ return;
+ }
+ case TK_FUNCTION: {
+ luaX_next(ls);
+ body(ls, v, 0, ls->linenumber);
+ return;
+ }
+ default: {
+ primaryexp(ls, v);
+ return;
+ }
+ }
+ luaX_next(ls);
+}
+
+
+static UnOpr getunopr (int op) {
+ switch (op) {
+ case TK_NOT: return OPR_NOT;
+ case '-': return OPR_MINUS;
+ case '#': return OPR_LEN;
+ default: return OPR_NOUNOPR;
+ }
+}
+
+
+static BinOpr getbinopr (int op) {
+ switch (op) {
+ case '+': return OPR_ADD;
+ case '-': return OPR_SUB;
+ case '*': return OPR_MUL;
+ case '/': return OPR_DIV;
+ case '%': return OPR_MOD;
+ case '^': return OPR_POW;
+ case TK_CONCAT: return OPR_CONCAT;
+ case TK_NE: return OPR_NE;
+ case TK_EQ: return OPR_EQ;
+ case '<': return OPR_LT;
+ case TK_LE: return OPR_LE;
+ case '>': return OPR_GT;
+ case TK_GE: return OPR_GE;
+ case TK_AND: return OPR_AND;
+ case TK_OR: return OPR_OR;
+ default: return OPR_NOBINOPR;
+ }
+}
+
+
+static const struct {
+ lu_byte left; /* left priority for each binary operator */
+ lu_byte right; /* right priority */
+} priority[] = { /* ORDER OPR */
+ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */
+ {10, 9}, {5, 4}, /* power and concat (right associative) */
+ {3, 3}, {3, 3}, /* equality and inequality */
+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
+ {2, 2}, {1, 1} /* logical (and/or) */
+};
+
+#define UNARY_PRIORITY 8 /* priority for unary operators */
+
+
+/*
+** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
+** where `binop' is any binary operator with a priority higher than `limit'
+*/
+static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
+ BinOpr op;
+ UnOpr uop;
+ enterlevel(ls);
+ uop = getunopr(ls->t.token);
+ if (uop != OPR_NOUNOPR) {
+ luaX_next(ls);
+ subexpr(ls, v, UNARY_PRIORITY);
+ luaK_prefix(ls->fs, uop, v);
+ }
+ else simpleexp(ls, v);
+ /* expand while operators have priorities higher than `limit' */
+ op = getbinopr(ls->t.token);
+ while (op != OPR_NOBINOPR && priority[op].left > limit) {
+ expdesc v2;
+ BinOpr nextop;
+ luaX_next(ls);
+ luaK_infix(ls->fs, op, v);
+ /* read sub-expression with higher priority */
+ nextop = subexpr(ls, &v2, priority[op].right);
+ luaK_posfix(ls->fs, op, v, &v2);
+ op = nextop;
+ }
+ leavelevel(ls);
+ return op; /* return first untreated operator */
+}
+
+
+static void expr (LexState *ls, expdesc *v) {
+ subexpr(ls, v, 0);
+}
+
+/* }==================================================================== */
+
+
+
+/*
+** {======================================================================
+** Rules for Statements
+** =======================================================================
+*/
+
+
+static int block_follow (int token) {
+ switch (token) {
+ case TK_ELSE: case TK_ELSEIF: case TK_END:
+ case TK_UNTIL: case TK_EOS:
+ return 1;
+ default: return 0;
+ }
+}
+
+
+static void block (LexState *ls) {
+ /* block -> chunk */
+ FuncState *fs = ls->fs;
+ BlockCnt bl;
+ enterblock(fs, &bl, 0);
+ chunk(ls);
+ lua_assert(bl.breaklist == NO_JUMP);
+ leaveblock(fs);
+}
+
+
+/*
+** structure to chain all variables in the left-hand side of an
+** assignment
+*/
+struct LHS_assign {
+ struct LHS_assign *prev;
+ expdesc v; /* variable (global, local, upvalue, or indexed) */
+};
+
+
+/*
+** check whether, in an assignment to a local variable, the local variable
+** is needed in a previous assignment (to a table). If so, save original
+** local value in a safe place and use this safe copy in the previous
+** assignment.
+*/
+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
+ FuncState *fs = ls->fs;
+ int extra = fs->freereg; /* eventual position to save local variable */
+ int conflict = 0;
+ for (; lh; lh = lh->prev) {
+ if (lh->v.k == VINDEXED) {
+ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */
+ conflict = 1;
+ lh->v.u.s.info = extra; /* previous assignment will use safe copy */
+ }
+ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */
+ conflict = 1;
+ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */
+ }
+ }
+ }
+ if (conflict) {
+ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */
+ luaK_reserveregs(fs, 1);
+ }
+}
+
+
+static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
+ expdesc e;
+ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
+ "syntax error");
+ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
+ struct LHS_assign nv;
+ nv.prev = lh;
+ primaryexp(ls, &nv.v);
+ if (nv.v.k == VLOCAL)
+ check_conflict(ls, lh, &nv.v);
+ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
+ "variables in assignment");
+ assignment(ls, &nv, nvars+1);
+ }
+ else { /* assignment -> `=' explist1 */
+ int nexps;
+ checknext(ls, '=');
+ nexps = explist1(ls, &e);
+ if (nexps != nvars) {
+ adjust_assign(ls, nvars, nexps, &e);
+ if (nexps > nvars)
+ ls->fs->freereg -= nexps - nvars; /* remove extra values */
+ }
+ else {
+ luaK_setoneret(ls->fs, &e); /* close last expression */
+ luaK_storevar(ls->fs, &lh->v, &e);
+ return; /* avoid default */
+ }
+ }
+ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */
+ luaK_storevar(ls->fs, &lh->v, &e);
+}
+
+
+static int cond (LexState *ls) {
+ /* cond -> exp */
+ expdesc v;
+ expr(ls, &v); /* read condition */
+ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
+ luaK_goiftrue(ls->fs, &v);
+ return v.f;
+}
+
+
+static void breakstat (LexState *ls) {
+ FuncState *fs = ls->fs;
+ BlockCnt *bl = fs->bl;
+ int upval = 0;
+ while (bl && !bl->isbreakable) {
+ upval |= bl->upval;
+ bl = bl->previous;
+ }
+ if (!bl)
+ luaX_syntaxerror(ls, "no loop to break");
+ if (upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
+}
+
+
+static void whilestat (LexState *ls, int line) {
+ /* whilestat -> WHILE cond DO block END */
+ FuncState *fs = ls->fs;
+ int whileinit;
+ int condexit;
+ BlockCnt bl;
+ luaX_next(ls); /* skip WHILE */
+ whileinit = luaK_getlabel(fs);
+ condexit = cond(ls);
+ enterblock(fs, &bl, 1);
+ checknext(ls, TK_DO);
+ block(ls);
+ luaK_patchlist(fs, luaK_jump(fs), whileinit);
+ check_match(ls, TK_END, TK_WHILE, line);
+ leaveblock(fs);
+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
+}
+
+
+static void repeatstat (LexState *ls, int line) {
+ /* repeatstat -> REPEAT block UNTIL cond */
+ int condexit;
+ FuncState *fs = ls->fs;
+ int repeat_init = luaK_getlabel(fs);
+ BlockCnt bl1, bl2;
+ enterblock(fs, &bl1, 1); /* loop block */
+ enterblock(fs, &bl2, 0); /* scope block */
+ luaX_next(ls); /* skip REPEAT */
+ chunk(ls);
+ check_match(ls, TK_UNTIL, TK_REPEAT, line);
+ condexit = cond(ls); /* read condition (inside scope block) */
+ if (!bl2.upval) { /* no upvalues? */
+ leaveblock(fs); /* finish scope */
+ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
+ }
+ else { /* complete semantics when there are upvalues */
+ breakstat(ls); /* if condition then break */
+ luaK_patchtohere(ls->fs, condexit); /* else... */
+ leaveblock(fs); /* finish scope... */
+ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
+ }
+ leaveblock(fs); /* finish loop */
+}
+
+
+static int exp1 (LexState *ls) {
+ expdesc e;
+ int k;
+ expr(ls, &e);
+ k = e.k;
+ luaK_exp2nextreg(ls->fs, &e);
+ return k;
+}
+
+
+static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
+ /* forbody -> DO block */
+ BlockCnt bl;
+ FuncState *fs = ls->fs;
+ int prep, endfor;
+ adjustlocalvars(ls, 3); /* control variables */
+ checknext(ls, TK_DO);
+ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
+ enterblock(fs, &bl, 0); /* scope for declared variables */
+ adjustlocalvars(ls, nvars);
+ luaK_reserveregs(fs, nvars);
+ block(ls);
+ leaveblock(fs); /* end of scope for declared variables */
+ luaK_patchtohere(fs, prep);
+ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
+ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
+ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
+ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
+}
+
+
+static void fornum (LexState *ls, TString *varname, int line) {
+ /* fornum -> NAME = exp1,exp1[,exp1] forbody */
+ FuncState *fs = ls->fs;
+ int base = fs->freereg;
+ new_localvarliteral(ls, "(for index)", 0);
+ new_localvarliteral(ls, "(for limit)", 1);
+ new_localvarliteral(ls, "(for step)", 2);
+ new_localvar(ls, varname, 3);
+ checknext(ls, '=');
+ exp1(ls); /* initial value */
+ checknext(ls, ',');
+ exp1(ls); /* limit */
+ if (testnext(ls, ','))
+ exp1(ls); /* optional step */
+ else { /* default step = 1 */
+ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
+ luaK_reserveregs(fs, 1);
+ }
+ forbody(ls, base, line, 1, 1);
+}
+
+
+static void forlist (LexState *ls, TString *indexname) {
+ /* forlist -> NAME {,NAME} IN explist1 forbody */
+ FuncState *fs = ls->fs;
+ expdesc e;
+ int nvars = 0;
+ int line;
+ int base = fs->freereg;
+ /* create control variables */
+ new_localvarliteral(ls, "(for generator)", nvars++);
+ new_localvarliteral(ls, "(for state)", nvars++);
+ new_localvarliteral(ls, "(for control)", nvars++);
+ /* create declared variables */
+ new_localvar(ls, indexname, nvars++);
+ while (testnext(ls, ','))
+ new_localvar(ls, str_checkname(ls), nvars++);
+ checknext(ls, TK_IN);
+ line = ls->linenumber;
+ adjust_assign(ls, 3, explist1(ls, &e), &e);
+ luaK_checkstack(fs, 3); /* extra space to call generator */
+ forbody(ls, base, line, nvars - 3, 0);
+}
+
+
+static void forstat (LexState *ls, int line) {
+ /* forstat -> FOR (fornum | forlist) END */
+ FuncState *fs = ls->fs;
+ TString *varname;
+ BlockCnt bl;
+ enterblock(fs, &bl, 1); /* scope for loop and control variables */
+ luaX_next(ls); /* skip `for' */
+ varname = str_checkname(ls); /* first variable name */
+ switch (ls->t.token) {
+ case '=': fornum(ls, varname, line); break;
+ case ',': case TK_IN: forlist(ls, varname); break;
+ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
+ }
+ check_match(ls, TK_END, TK_FOR, line);
+ leaveblock(fs); /* loop scope (`break' jumps to this point) */
+}
+
+
+static int test_then_block (LexState *ls) {
+ /* test_then_block -> [IF | ELSEIF] cond THEN block */
+ int condexit;
+ luaX_next(ls); /* skip IF or ELSEIF */
+ condexit = cond(ls);
+ checknext(ls, TK_THEN);
+ block(ls); /* `then' part */
+ return condexit;
+}
+
+
+static void ifstat (LexState *ls, int line) {
+ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
+ FuncState *fs = ls->fs;
+ int flist;
+ int escapelist = NO_JUMP;
+ flist = test_then_block(ls); /* IF cond THEN block */
+ while (ls->t.token == TK_ELSEIF) {
+ luaK_concat(fs, &escapelist, luaK_jump(fs));
+ luaK_patchtohere(fs, flist);
+ flist = test_then_block(ls); /* ELSEIF cond THEN block */
+ }
+ if (ls->t.token == TK_ELSE) {
+ luaK_concat(fs, &escapelist, luaK_jump(fs));
+ luaK_patchtohere(fs, flist);
+ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */
+ block(ls); /* `else' part */
+ }
+ else
+ luaK_concat(fs, &escapelist, flist);
+ luaK_patchtohere(fs, escapelist);
+ check_match(ls, TK_END, TK_IF, line);
+}
+
+
+static void localfunc (LexState *ls) {
+ expdesc v, b;
+ FuncState *fs = ls->fs;
+ new_localvar(ls, str_checkname(ls), 0);
+ init_exp(&v, VLOCAL, fs->freereg);
+ luaK_reserveregs(fs, 1);
+ adjustlocalvars(ls, 1);
+ body(ls, &b, 0, ls->linenumber);
+ luaK_storevar(fs, &v, &b);
+ /* debug information will only see the variable after this point! */
+ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
+}
+
+
+static void localstat (LexState *ls) {
+ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
+ int nvars = 0;
+ int nexps;
+ expdesc e;
+ do {
+ new_localvar(ls, str_checkname(ls), nvars++);
+ } while (testnext(ls, ','));
+ if (testnext(ls, '='))
+ nexps = explist1(ls, &e);
+ else {
+ e.k = VVOID;
+ nexps = 0;
+ }
+ adjust_assign(ls, nvars, nexps, &e);
+ adjustlocalvars(ls, nvars);
+}
+
+
+static int funcname (LexState *ls, expdesc *v) {
+ /* funcname -> NAME {field} [`:' NAME] */
+ int needself = 0;
+ singlevar(ls, v);
+ while (ls->t.token == '.')
+ field(ls, v);
+ if (ls->t.token == ':') {
+ needself = 1;
+ field(ls, v);
+ }
+ return needself;
+}
+
+
+static void funcstat (LexState *ls, int line) {
+ /* funcstat -> FUNCTION funcname body */
+ int needself;
+ expdesc v, b;
+ luaX_next(ls); /* skip FUNCTION */
+ needself = funcname(ls, &v);
+ body(ls, &b, needself, line);
+ luaK_storevar(ls->fs, &v, &b);
+ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
+}
+
+
+static void exprstat (LexState *ls) {
+ /* stat -> func | assignment */
+ FuncState *fs = ls->fs;
+ struct LHS_assign v;
+ primaryexp(ls, &v.v);
+ if (v.v.k == VCALL) /* stat -> func */
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
+ else { /* stat -> assignment */
+ v.prev = NULL;
+ assignment(ls, &v, 1);
+ }
+}
+
+
+static void retstat (LexState *ls) {
+ /* stat -> RETURN explist */
+ FuncState *fs = ls->fs;
+ expdesc e;
+ int first, nret; /* registers with returned values */
+ luaX_next(ls); /* skip RETURN */
+ if (block_follow(ls->t.token) || ls->t.token == ';')
+ first = nret = 0; /* return no values */
+ else {
+ nret = explist1(ls, &e); /* optional return values */
+ if (hasmultret(e.k)) {
+ luaK_setmultret(fs, &e);
+ if (e.k == VCALL && nret == 1) { /* tail call? */
+ SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
+ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
+ }
+ first = fs->nactvar;
+ nret = LUA_MULTRET; /* return all values */
+ }
+ else {
+ if (nret == 1) /* only one single value? */
+ first = luaK_exp2anyreg(fs, &e);
+ else {
+ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
+ first = fs->nactvar; /* return all `active' values */
+ lua_assert(nret == fs->freereg - first);
+ }
+ }
+ }
+ luaK_ret(fs, first, nret);
+}
+
+
+static int statement (LexState *ls) {
+ int line = ls->linenumber; /* may be needed for error messages */
+ switch (ls->t.token) {
+ case TK_IF: { /* stat -> ifstat */
+ ifstat(ls, line);
+ return 0;
+ }
+ case TK_WHILE: { /* stat -> whilestat */
+ whilestat(ls, line);
+ return 0;
+ }
+ case TK_DO: { /* stat -> DO block END */
+ luaX_next(ls); /* skip DO */
+ block(ls);
+ check_match(ls, TK_END, TK_DO, line);
+ return 0;
+ }
+ case TK_FOR: { /* stat -> forstat */
+ forstat(ls, line);
+ return 0;
+ }
+ case TK_REPEAT: { /* stat -> repeatstat */
+ repeatstat(ls, line);
+ return 0;
+ }
+ case TK_FUNCTION: {
+ funcstat(ls, line); /* stat -> funcstat */
+ return 0;
+ }
+ case TK_LOCAL: { /* stat -> localstat */
+ luaX_next(ls); /* skip LOCAL */
+ if (testnext(ls, TK_FUNCTION)) /* local function? */
+ localfunc(ls);
+ else
+ localstat(ls);
+ return 0;
+ }
+ case TK_RETURN: { /* stat -> retstat */
+ retstat(ls);
+ return 1; /* must be last statement */
+ }
+ case TK_BREAK: { /* stat -> breakstat */
+ luaX_next(ls); /* skip BREAK */
+ breakstat(ls);
+ return 1; /* must be last statement */
+ }
+ default: {
+ exprstat(ls);
+ return 0; /* to avoid warnings */
+ }
+ }
+}
+
+
+static void chunk (LexState *ls) {
+ /* chunk -> { stat [`;'] } */
+ int islast = 0;
+ enterlevel(ls);
+ while (!islast && !block_follow(ls->t.token)) {
+ islast = statement(ls);
+ testnext(ls, ';');
+ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
+ ls->fs->freereg >= ls->fs->nactvar);
+ ls->fs->freereg = ls->fs->nactvar; /* free registers */
+ }
+ leavelevel(ls);
+}
+
+/* }====================================================================== */
diff --git a/lib/lua/src/lparser.h b/lib/lua/src/lparser.h
new file mode 100644
index 000000000..18836afd1
--- /dev/null
+++ b/lib/lua/src/lparser.h
@@ -0,0 +1,82 @@
+/*
+** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lparser_h
+#define lparser_h
+
+#include "llimits.h"
+#include "lobject.h"
+#include "lzio.h"
+
+
+/*
+** Expression descriptor
+*/
+
+typedef enum {
+ VVOID, /* no value */
+ VNIL,
+ VTRUE,
+ VFALSE,
+ VK, /* info = index of constant in `k' */
+ VKNUM, /* nval = numerical value */
+ VLOCAL, /* info = local register */
+ VUPVAL, /* info = index of upvalue in `upvalues' */
+ VGLOBAL, /* info = index of table; aux = index of global name in `k' */
+ VINDEXED, /* info = table register; aux = index register (or `k') */
+ VJMP, /* info = instruction pc */
+ VRELOCABLE, /* info = instruction pc */
+ VNONRELOC, /* info = result register */
+ VCALL, /* info = instruction pc */
+ VVARARG /* info = instruction pc */
+} expkind;
+
+typedef struct expdesc {
+ expkind k;
+ union {
+ struct { int info, aux; } s;
+ lua_Number nval;
+ } u;
+ int t; /* patch list of `exit when true' */
+ int f; /* patch list of `exit when false' */
+} expdesc;
+
+
+typedef struct upvaldesc {
+ lu_byte k;
+ lu_byte info;
+} upvaldesc;
+
+
+struct BlockCnt; /* defined in lparser.c */
+
+
+/* state needed to generate code for a given function */
+typedef struct FuncState {
+ Proto *f; /* current function header */
+ Table *h; /* table to find (and reuse) elements in `k' */
+ struct FuncState *prev; /* enclosing function */
+ struct LexState *ls; /* lexical state */
+ struct lua_State *L; /* copy of the Lua state */
+ struct BlockCnt *bl; /* chain of current blocks */
+ int pc; /* next position to code (equivalent to `ncode') */
+ int lasttarget; /* `pc' of last `jump target' */
+ int jpc; /* list of pending jumps to `pc' */
+ int freereg; /* first free register */
+ int nk; /* number of elements in `k' */
+ int np; /* number of elements in `p' */
+ short nlocvars; /* number of elements in `locvars' */
+ lu_byte nactvar; /* number of active local variables */
+ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
+ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
+} FuncState;
+
+
+LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ const char *name);
+
+
+#endif
diff --git a/lib/lua/src/lstate.c b/lib/lua/src/lstate.c
new file mode 100644
index 000000000..4313b83a0
--- /dev/null
+++ b/lib/lua/src/lstate.c
@@ -0,0 +1,214 @@
+/*
+** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lstate_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE)
+#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE)
+#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))
+
+
+/*
+** Main thread combines a thread state and the global state
+*/
+typedef struct LG {
+ lua_State l;
+ global_State g;
+} LG;
+
+
+
+static void stack_init (lua_State *L1, lua_State *L) {
+ /* initialize CallInfo array */
+ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
+ L1->ci = L1->base_ci;
+ L1->size_ci = BASIC_CI_SIZE;
+ L1->end_ci = L1->base_ci + L1->size_ci - 1;
+ /* initialize stack array */
+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
+ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
+ L1->top = L1->stack;
+ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
+ /* initialize first ci */
+ L1->ci->func = L1->top;
+ setnilvalue(L1->top++); /* `function' entry for this `ci' */
+ L1->base = L1->ci->base = L1->top;
+ L1->ci->top = L1->top + LUA_MINSTACK;
+}
+
+
+static void freestack (lua_State *L, lua_State *L1) {
+ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
+ luaM_freearray(L, L1->stack, L1->stacksize, TValue);
+}
+
+
+/*
+** open parts that may cause memory-allocation errors
+*/
+static void f_luaopen (lua_State *L, void *ud) {
+ global_State *g = G(L);
+ UNUSED(ud);
+ stack_init(L, L); /* init stack */
+ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
+ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
+ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
+ luaT_init(L);
+ luaX_init(L);
+ luaS_fix(luaS_newliteral(L, MEMERRMSG));
+ g->GCthreshold = 4*g->totalbytes;
+}
+
+
+static void preinit_state (lua_State *L, global_State *g) {
+ G(L) = g;
+ L->stack = NULL;
+ L->stacksize = 0;
+ L->errorJmp = NULL;
+ L->hook = NULL;
+ L->hookmask = 0;
+ L->basehookcount = 0;
+ L->allowhook = 1;
+ resethookcount(L);
+ L->openupval = NULL;
+ L->size_ci = 0;
+ L->nCcalls = L->baseCcalls = 0;
+ L->status = 0;
+ L->base_ci = L->ci = NULL;
+ L->savedpc = NULL;
+ L->errfunc = 0;
+ setnilvalue(gt(L));
+}
+
+
+static void close_state (lua_State *L) {
+ global_State *g = G(L);
+ luaF_close(L, L->stack); /* close all upvalues for this thread */
+ luaC_freeall(L); /* collect all objects */
+ lua_assert(g->rootgc == obj2gco(L));
+ lua_assert(g->strt.nuse == 0);
+ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
+ luaZ_freebuffer(L, &g->buff);
+ freestack(L, L);
+ lua_assert(g->totalbytes == sizeof(LG));
+ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
+}
+
+
+lua_State *luaE_newthread (lua_State *L) {
+ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
+ luaC_link(L, obj2gco(L1), LUA_TTHREAD);
+ preinit_state(L1, G(L));
+ stack_init(L1, L); /* init stack */
+ setobj2n(L, gt(L1), gt(L)); /* share table of globals */
+ L1->hookmask = L->hookmask;
+ L1->basehookcount = L->basehookcount;
+ L1->hook = L->hook;
+ resethookcount(L1);
+ lua_assert(iswhite(obj2gco(L1)));
+ return L1;
+}
+
+
+void luaE_freethread (lua_State *L, lua_State *L1) {
+ luaF_close(L1, L1->stack); /* close all upvalues for this thread */
+ lua_assert(L1->openupval == NULL);
+ luai_userstatefree(L1);
+ freestack(L, L1);
+ luaM_freemem(L, fromstate(L1), state_size(lua_State));
+}
+
+
+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
+ int i;
+ lua_State *L;
+ global_State *g;
+ void *l = (*f)(ud, NULL, 0, state_size(LG));
+ if (l == NULL) return NULL;
+ L = tostate(l);
+ g = &((LG *)L)->g;
+ L->next = NULL;
+ L->tt = LUA_TTHREAD;
+ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
+ L->marked = luaC_white(g);
+ set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
+ preinit_state(L, g);
+ g->frealloc = f;
+ g->ud = ud;
+ g->mainthread = L;
+ g->uvhead.u.l.prev = &g->uvhead;
+ g->uvhead.u.l.next = &g->uvhead;
+ g->GCthreshold = 0; /* mark it as unfinished state */
+ g->strt.size = 0;
+ g->strt.nuse = 0;
+ g->strt.hash = NULL;
+ setnilvalue(registry(L));
+ luaZ_initbuffer(L, &g->buff);
+ g->panic = NULL;
+ g->gcstate = GCSpause;
+ g->rootgc = obj2gco(L);
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->tmudata = NULL;
+ g->totalbytes = sizeof(LG);
+ g->gcpause = LUAI_GCPAUSE;
+ g->gcstepmul = LUAI_GCMUL;
+ g->gcdept = 0;
+ for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
+ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
+ /* memory allocation error: free partial state */
+ close_state(L);
+ L = NULL;
+ }
+ else
+ luai_userstateopen(L);
+ return L;
+}
+
+
+static void callallgcTM (lua_State *L, void *ud) {
+ UNUSED(ud);
+ luaC_callGCTM(L); /* call GC metamethods for all udata */
+}
+
+
+LUA_API void lua_close (lua_State *L) {
+ L = G(L)->mainthread; /* only the main thread can be closed */
+ lua_lock(L);
+ luaF_close(L, L->stack); /* close all upvalues for this thread */
+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
+ L->errfunc = 0; /* no error function during GC metamethods */
+ do { /* repeat until no more errors */
+ L->ci = L->base_ci;
+ L->base = L->top = L->ci->base;
+ L->nCcalls = L->baseCcalls = 0;
+ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
+ lua_assert(G(L)->tmudata == NULL);
+ luai_userstateclose(L);
+ close_state(L);
+}
+
diff --git a/lib/lua/src/lstate.h b/lib/lua/src/lstate.h
new file mode 100644
index 000000000..3bc575b6b
--- /dev/null
+++ b/lib/lua/src/lstate.h
@@ -0,0 +1,169 @@
+/*
+** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstate_h
+#define lstate_h
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "ltm.h"
+#include "lzio.h"
+
+
+
+struct lua_longjmp; /* defined in ldo.c */
+
+
+/* table of globals */
+#define gt(L) (&L->l_gt)
+
+/* registry */
+#define registry(L) (&G(L)->l_registry)
+
+
+/* extra stack space to handle TM calls and some other extras */
+#define EXTRA_STACK 5
+
+
+#define BASIC_CI_SIZE 8
+
+#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
+
+
+
+typedef struct stringtable {
+ GCObject **hash;
+ lu_int32 nuse; /* number of elements */
+ int size;
+} stringtable;
+
+
+/*
+** informations about a call
+*/
+typedef struct CallInfo {
+ StkId base; /* base for this function */
+ StkId func; /* function index in the stack */
+ StkId top; /* top for this function */
+ const Instruction *savedpc;
+ int nresults; /* expected number of results from this function */
+ int tailcalls; /* number of tail calls lost under this entry */
+} CallInfo;
+
+
+
+#define curr_func(L) (clvalue(L->ci->func))
+#define ci_func(ci) (clvalue((ci)->func))
+#define f_isLua(ci) (!ci_func(ci)->c.isC)
+#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
+
+
+/*
+** `global state', shared by all threads of this state
+*/
+typedef struct global_State {
+ stringtable strt; /* hash table for strings */
+ lua_Alloc frealloc; /* function to reallocate memory */
+ void *ud; /* auxiliary data to `frealloc' */
+ lu_byte currentwhite;
+ lu_byte gcstate; /* state of garbage collector */
+ int sweepstrgc; /* position of sweep in `strt' */
+ GCObject *rootgc; /* list of all collectable objects */
+ GCObject **sweepgc; /* position of sweep in `rootgc' */
+ GCObject *gray; /* list of gray objects */
+ GCObject *grayagain; /* list of objects to be traversed atomically */
+ GCObject *weak; /* list of weak tables (to be cleared) */
+ GCObject *tmudata; /* last element of list of userdata to be GC */
+ Mbuffer buff; /* temporary buffer for string concatentation */
+ lu_mem GCthreshold;
+ lu_mem totalbytes; /* number of bytes currently allocated */
+ lu_mem estimate; /* an estimate of number of bytes actually in use */
+ lu_mem gcdept; /* how much GC is `behind schedule' */
+ int gcpause; /* size of pause between successive GCs */
+ int gcstepmul; /* GC `granularity' */
+ lua_CFunction panic; /* to be called in unprotected errors */
+ TValue l_registry;
+ struct lua_State *mainthread;
+ UpVal uvhead; /* head of double-linked list of all open upvalues */
+ struct Table *mt[NUM_TAGS]; /* metatables for basic types */
+ TString *tmname[TM_N]; /* array with tag-method names */
+} global_State;
+
+
+/*
+** `per thread' state
+*/
+struct lua_State {
+ CommonHeader;
+ lu_byte status;
+ StkId top; /* first free slot in the stack */
+ StkId base; /* base of current function */
+ global_State *l_G;
+ CallInfo *ci; /* call info for current function */
+ const Instruction *savedpc; /* `savedpc' of current function */
+ StkId stack_last; /* last free slot in the stack */
+ StkId stack; /* stack base */
+ CallInfo *end_ci; /* points after end of ci array*/
+ CallInfo *base_ci; /* array of CallInfo's */
+ int stacksize;
+ int size_ci; /* size of array `base_ci' */
+ unsigned short nCcalls; /* number of nested C calls */
+ unsigned short baseCcalls; /* nested C calls when resuming coroutine */
+ lu_byte hookmask;
+ lu_byte allowhook;
+ int basehookcount;
+ int hookcount;
+ lua_Hook hook;
+ TValue l_gt; /* table of globals */
+ TValue env; /* temporary place for environments */
+ GCObject *openupval; /* list of open upvalues in this stack */
+ GCObject *gclist;
+ struct lua_longjmp *errorJmp; /* current error recover point */
+ ptrdiff_t errfunc; /* current error handling function (stack index) */
+};
+
+
+#define G(L) (L->l_G)
+
+
+/*
+** Union of all collectable objects
+*/
+union GCObject {
+ GCheader gch;
+ union TString ts;
+ union Udata u;
+ union Closure cl;
+ struct Table h;
+ struct Proto p;
+ struct UpVal uv;
+ struct lua_State th; /* thread */
+};
+
+
+/* macros to convert a GCObject into a specific value */
+#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
+#define gco2ts(o) (&rawgco2ts(o)->tsv)
+#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
+#define gco2u(o) (&rawgco2u(o)->uv)
+#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
+#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
+#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
+#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define ngcotouv(o) \
+ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+
+/* macro to convert any Lua object into a GCObject */
+#define obj2gco(v) (cast(GCObject *, (v)))
+
+
+LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
+LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
+
+#endif
+
diff --git a/lib/lua/src/lstring.c b/lib/lua/src/lstring.c
new file mode 100644
index 000000000..49113151c
--- /dev/null
+++ b/lib/lua/src/lstring.c
@@ -0,0 +1,111 @@
+/*
+** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
+** String table (keeps all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lstring_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+
+
+
+void luaS_resize (lua_State *L, int newsize) {
+ GCObject **newhash;
+ stringtable *tb;
+ int i;
+ if (G(L)->gcstate == GCSsweepstring)
+ return; /* cannot resize during GC traverse */
+ newhash = luaM_newvector(L, newsize, GCObject *);
+ tb = &G(L)->strt;
+ for (i=0; i<newsize; i++) newhash[i] = NULL;
+ /* rehash */
+ for (i=0; i<tb->size; i++) {
+ GCObject *p = tb->hash[i];
+ while (p) { /* for each node in the list */
+ GCObject *next = p->gch.next; /* save next */
+ unsigned int h = gco2ts(p)->hash;
+ int h1 = lmod(h, newsize); /* new position */
+ lua_assert(cast_int(h%newsize) == lmod(h, newsize));
+ p->gch.next = newhash[h1]; /* chain it */
+ newhash[h1] = p;
+ p = next;
+ }
+ }
+ luaM_freearray(L, tb->hash, tb->size, TString *);
+ tb->size = newsize;
+ tb->hash = newhash;
+}
+
+
+static TString *newlstr (lua_State *L, const char *str, size_t l,
+ unsigned int h) {
+ TString *ts;
+ stringtable *tb;
+ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+ luaM_toobig(L);
+ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
+ ts->tsv.len = l;
+ ts->tsv.hash = h;
+ ts->tsv.marked = luaC_white(G(L));
+ ts->tsv.tt = LUA_TSTRING;
+ ts->tsv.reserved = 0;
+ memcpy(ts+1, str, l*sizeof(char));
+ ((char *)(ts+1))[l] = '\0'; /* ending 0 */
+ tb = &G(L)->strt;
+ h = lmod(h, tb->size);
+ ts->tsv.next = tb->hash[h]; /* chain new entry */
+ tb->hash[h] = obj2gco(ts);
+ tb->nuse++;
+ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
+ luaS_resize(L, tb->size*2); /* too crowded */
+ return ts;
+}
+
+
+TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
+ GCObject *o;
+ unsigned int h = cast(unsigned int, l); /* seed */
+ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
+ size_t l1;
+ for (l1=l; l1>=step; l1-=step) /* compute hash */
+ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
+ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
+ o != NULL;
+ o = o->gch.next) {
+ TString *ts = rawgco2ts(o);
+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
+ /* string may be dead */
+ if (isdead(G(L), o)) changewhite(o);
+ return ts;
+ }
+ }
+ return newlstr(L, str, l, h); /* not found */
+}
+
+
+Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
+ Udata *u;
+ if (s > MAX_SIZET - sizeof(Udata))
+ luaM_toobig(L);
+ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
+ u->uv.marked = luaC_white(G(L)); /* is not finalized */
+ u->uv.tt = LUA_TUSERDATA;
+ u->uv.len = s;
+ u->uv.metatable = NULL;
+ u->uv.env = e;
+ /* chain it on udata list (after main thread) */
+ u->uv.next = G(L)->mainthread->next;
+ G(L)->mainthread->next = obj2gco(u);
+ return u;
+}
+
diff --git a/lib/lua/src/lstring.h b/lib/lua/src/lstring.h
new file mode 100644
index 000000000..73a2ff8b3
--- /dev/null
+++ b/lib/lua/src/lstring.h
@@ -0,0 +1,31 @@
+/*
+** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $
+** String table (keep all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstring_h
+#define lstring_h
+
+
+#include "lgc.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
+
+#define sizeudata(u) (sizeof(union Udata)+(u)->len)
+
+#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
+#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
+ (sizeof(s)/sizeof(char))-1))
+
+#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
+
+LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+
+
+#endif
diff --git a/lib/lua/src/lstrlib.c b/lib/lua/src/lstrlib.c
new file mode 100644
index 000000000..1b4763d4e
--- /dev/null
+++ b/lib/lua/src/lstrlib.c
@@ -0,0 +1,869 @@
+/*
+** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $
+** Standard library for string operations and pattern-matching
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lstrlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+/* macro to `unsign' a character */
+#define uchar(c) ((unsigned char)(c))
+
+
+
+static int str_len (lua_State *L) {
+ size_t l;
+ luaL_checklstring(L, 1, &l);
+ lua_pushinteger(L, l);
+ return 1;
+}
+
+
+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
+ /* relative string position: negative means back from end */
+ if (pos < 0) pos += (ptrdiff_t)len + 1;
+ return (pos >= 0) ? pos : 0;
+}
+
+
+static int str_sub (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
+ if (start < 1) start = 1;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+ if (start <= end)
+ lua_pushlstring(L, s+start-1, end-start+1);
+ else lua_pushliteral(L, "");
+ return 1;
+}
+
+
+static int str_reverse (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ while (l--) luaL_addchar(&b, s[l]);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_lower (lua_State *L) {
+ size_t l;
+ size_t i;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ for (i=0; i<l; i++)
+ luaL_addchar(&b, tolower(uchar(s[i])));
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_upper (lua_State *L) {
+ size_t l;
+ size_t i;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ for (i=0; i<l; i++)
+ luaL_addchar(&b, toupper(uchar(s[i])));
+ luaL_pushresult(&b);
+ return 1;
+}
+
+static int str_rep (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ int n = luaL_checkint(L, 2);
+ luaL_buffinit(L, &b);
+ while (n-- > 0)
+ luaL_addlstring(&b, s, l);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_byte (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+ if (posi > pose) return 0; /* empty interval; return no values */
+ n = (int)(pose - posi + 1);
+ if (posi + n <= pose) /* overflow? */
+ luaL_error(L, "string slice too long");
+ luaL_checkstack(L, n, "string slice too long");
+ for (i=0; i<n; i++)
+ lua_pushinteger(L, uchar(s[posi+i-1]));
+ return n;
+}
+
+
+static int str_char (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (i=1; i<=n; i++) {
+ int c = luaL_checkint(L, i);
+ luaL_argcheck(L, uchar(c) == c, i, "invalid value");
+ luaL_addchar(&b, uchar(c));
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int writer (lua_State *L, const void* b, size_t size, void* B) {
+ (void)L;
+ luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+ return 0;
+}
+
+
+static int str_dump (lua_State *L) {
+ luaL_Buffer b;
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
+ luaL_buffinit(L,&b);
+ if (lua_dump(L, writer, &b) != 0)
+ luaL_error(L, "unable to dump given function");
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** PATTERN MATCHING
+** =======================================================
+*/
+
+
+#define CAP_UNFINISHED (-1)
+#define CAP_POSITION (-2)
+
+typedef struct MatchState {
+ const char *src_init; /* init of source string */
+ const char *src_end; /* end (`\0') of source string */
+ lua_State *L;
+ int level; /* total number of captures (finished or unfinished) */
+ struct {
+ const char *init;
+ ptrdiff_t len;
+ } capture[LUA_MAXCAPTURES];
+} MatchState;
+
+
+#define L_ESC '%'
+#define SPECIALS "^$*+?.([%-"
+
+
+static int check_capture (MatchState *ms, int l) {
+ l -= '1';
+ if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
+ return luaL_error(ms->L, "invalid capture index");
+ return l;
+}
+
+
+static int capture_to_close (MatchState *ms) {
+ int level = ms->level;
+ for (level--; level>=0; level--)
+ if (ms->capture[level].len == CAP_UNFINISHED) return level;
+ return luaL_error(ms->L, "invalid pattern capture");
+}
+
+
+static const char *classend (MatchState *ms, const char *p) {
+ switch (*p++) {
+ case L_ESC: {
+ if (*p == '\0')
+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
+ return p+1;
+ }
+ case '[': {
+ if (*p == '^') p++;
+ do { /* look for a `]' */
+ if (*p == '\0')
+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+ if (*(p++) == L_ESC && *p != '\0')
+ p++; /* skip escapes (e.g. `%]') */
+ } while (*p != ']');
+ return p+1;
+ }
+ default: {
+ return p;
+ }
+ }
+}
+
+
+static int match_class (int c, int cl) {
+ int res;
+ switch (tolower(cl)) {
+ case 'a' : res = isalpha(c); break;
+ case 'c' : res = iscntrl(c); break;
+ case 'd' : res = isdigit(c); break;
+ case 'l' : res = islower(c); break;
+ case 'p' : res = ispunct(c); break;
+ case 's' : res = isspace(c); break;
+ case 'u' : res = isupper(c); break;
+ case 'w' : res = isalnum(c); break;
+ case 'x' : res = isxdigit(c); break;
+ case 'z' : res = (c == 0); break;
+ default: return (cl == c);
+ }
+ return (islower(cl) ? res : !res);
+}
+
+
+static int matchbracketclass (int c, const char *p, const char *ec) {
+ int sig = 1;
+ if (*(p+1) == '^') {
+ sig = 0;
+ p++; /* skip the `^' */
+ }
+ while (++p < ec) {
+ if (*p == L_ESC) {
+ p++;
+ if (match_class(c, uchar(*p)))
+ return sig;
+ }
+ else if ((*(p+1) == '-') && (p+2 < ec)) {
+ p+=2;
+ if (uchar(*(p-2)) <= c && c <= uchar(*p))
+ return sig;
+ }
+ else if (uchar(*p) == c) return sig;
+ }
+ return !sig;
+}
+
+
+static int singlematch (int c, const char *p, const char *ep) {
+ switch (*p) {
+ case '.': return 1; /* matches any char */
+ case L_ESC: return match_class(c, uchar(*(p+1)));
+ case '[': return matchbracketclass(c, p, ep-1);
+ default: return (uchar(*p) == c);
+ }
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p);
+
+
+static const char *matchbalance (MatchState *ms, const char *s,
+ const char *p) {
+ if (*p == 0 || *(p+1) == 0)
+ luaL_error(ms->L, "unbalanced pattern");
+ if (*s != *p) return NULL;
+ else {
+ int b = *p;
+ int e = *(p+1);
+ int cont = 1;
+ while (++s < ms->src_end) {
+ if (*s == e) {
+ if (--cont == 0) return s+1;
+ }
+ else if (*s == b) cont++;
+ }
+ }
+ return NULL; /* string ends out of balance */
+}
+
+
+static const char *max_expand (MatchState *ms, const char *s,
+ const char *p, const char *ep) {
+ ptrdiff_t i = 0; /* counts maximum expand for item */
+ while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
+ i++;
+ /* keeps trying to match with the maximum repetitions */
+ while (i>=0) {
+ const char *res = match(ms, (s+i), ep+1);
+ if (res) return res;
+ i--; /* else didn't match; reduce 1 repetition to try again */
+ }
+ return NULL;
+}
+
+
+static const char *min_expand (MatchState *ms, const char *s,
+ const char *p, const char *ep) {
+ for (;;) {
+ const char *res = match(ms, s, ep+1);
+ if (res != NULL)
+ return res;
+ else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
+ s++; /* try with one more repetition */
+ else return NULL;
+ }
+}
+
+
+static const char *start_capture (MatchState *ms, const char *s,
+ const char *p, int what) {
+ const char *res;
+ int level = ms->level;
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
+ ms->capture[level].init = s;
+ ms->capture[level].len = what;
+ ms->level = level+1;
+ if ((res=match(ms, s, p)) == NULL) /* match failed? */
+ ms->level--; /* undo capture */
+ return res;
+}
+
+
+static const char *end_capture (MatchState *ms, const char *s,
+ const char *p) {
+ int l = capture_to_close(ms);
+ const char *res;
+ ms->capture[l].len = s - ms->capture[l].init; /* close capture */
+ if ((res = match(ms, s, p)) == NULL) /* match failed? */
+ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
+ return res;
+}
+
+
+static const char *match_capture (MatchState *ms, const char *s, int l) {
+ size_t len;
+ l = check_capture(ms, l);
+ len = ms->capture[l].len;
+ if ((size_t)(ms->src_end-s) >= len &&
+ memcmp(ms->capture[l].init, s, len) == 0)
+ return s+len;
+ else return NULL;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p) {
+ init: /* using goto's to optimize tail recursion */
+ switch (*p) {
+ case '(': { /* start capture */
+ if (*(p+1) == ')') /* position capture? */
+ return start_capture(ms, s, p+2, CAP_POSITION);
+ else
+ return start_capture(ms, s, p+1, CAP_UNFINISHED);
+ }
+ case ')': { /* end capture */
+ return end_capture(ms, s, p+1);
+ }
+ case L_ESC: {
+ switch (*(p+1)) {
+ case 'b': { /* balanced string? */
+ s = matchbalance(ms, s, p+2);
+ if (s == NULL) return NULL;
+ p+=4; goto init; /* else return match(ms, s, p+4); */
+ }
+ case 'f': { /* frontier? */
+ const char *ep; char previous;
+ p += 2;
+ if (*p != '[')
+ luaL_error(ms->L, "missing " LUA_QL("[") " after "
+ LUA_QL("%%f") " in pattern");
+ ep = classend(ms, p); /* points to what is next */
+ previous = (s == ms->src_init) ? '\0' : *(s-1);
+ if (matchbracketclass(uchar(previous), p, ep-1) ||
+ !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
+ p=ep; goto init; /* else return match(ms, s, ep); */
+ }
+ default: {
+ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
+ s = match_capture(ms, s, uchar(*(p+1)));
+ if (s == NULL) return NULL;
+ p+=2; goto init; /* else return match(ms, s, p+2) */
+ }
+ goto dflt; /* case default */
+ }
+ }
+ }
+ case '\0': { /* end of pattern */
+ return s; /* match succeeded */
+ }
+ case '$': {
+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
+ return (s == ms->src_end) ? s : NULL; /* check end of string */
+ else goto dflt;
+ }
+ default: dflt: { /* it is a pattern item */
+ const char *ep = classend(ms, p); /* points to what is next */
+ int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
+ switch (*ep) {
+ case '?': { /* optional */
+ const char *res;
+ if (m && ((res=match(ms, s+1, ep+1)) != NULL))
+ return res;
+ p=ep+1; goto init; /* else return match(ms, s, ep+1); */
+ }
+ case '*': { /* 0 or more repetitions */
+ return max_expand(ms, s, p, ep);
+ }
+ case '+': { /* 1 or more repetitions */
+ return (m ? max_expand(ms, s+1, p, ep) : NULL);
+ }
+ case '-': { /* 0 or more repetitions (minimum) */
+ return min_expand(ms, s, p, ep);
+ }
+ default: {
+ if (!m) return NULL;
+ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
+ }
+ }
+ }
+ }
+}
+
+
+
+static const char *lmemfind (const char *s1, size_t l1,
+ const char *s2, size_t l2) {
+ if (l2 == 0) return s1; /* empty strings are everywhere */
+ else if (l2 > l1) return NULL; /* avoids a negative `l1' */
+ else {
+ const char *init; /* to search for a `*s2' inside `s1' */
+ l2--; /* 1st char will be checked by `memchr' */
+ l1 = l1-l2; /* `s2' cannot be found after that */
+ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
+ init++; /* 1st char is already checked */
+ if (memcmp(init, s2+1, l2) == 0)
+ return init-1;
+ else { /* correct `l1' and `s1' to try again */
+ l1 -= init-s1;
+ s1 = init;
+ }
+ }
+ return NULL; /* not found */
+ }
+}
+
+
+static void push_onecapture (MatchState *ms, int i, const char *s,
+ const char *e) {
+ if (i >= ms->level) {
+ if (i == 0) /* ms->level == 0, too */
+ lua_pushlstring(ms->L, s, e - s); /* add whole match */
+ else
+ luaL_error(ms->L, "invalid capture index");
+ }
+ else {
+ ptrdiff_t l = ms->capture[i].len;
+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
+ if (l == CAP_POSITION)
+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
+ else
+ lua_pushlstring(ms->L, ms->capture[i].init, l);
+ }
+}
+
+
+static int push_captures (MatchState *ms, const char *s, const char *e) {
+ int i;
+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
+ luaL_checkstack(ms->L, nlevels, "too many captures");
+ for (i = 0; i < nlevels; i++)
+ push_onecapture(ms, i, s, e);
+ return nlevels; /* number of strings pushed */
+}
+
+
+static int str_find_aux (lua_State *L, int find) {
+ size_t l1, l2;
+ const char *s = luaL_checklstring(L, 1, &l1);
+ const char *p = luaL_checklstring(L, 2, &l2);
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
+ if (init < 0) init = 0;
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
+ /* do a plain search */
+ const char *s2 = lmemfind(s+init, l1-init, p, l2);
+ if (s2) {
+ lua_pushinteger(L, s2-s+1);
+ lua_pushinteger(L, s2-s+l2);
+ return 2;
+ }
+ }
+ else {
+ MatchState ms;
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ const char *s1=s+init;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+l1;
+ do {
+ const char *res;
+ ms.level = 0;
+ if ((res=match(&ms, s1, p)) != NULL) {
+ if (find) {
+ lua_pushinteger(L, s1-s+1); /* start */
+ lua_pushinteger(L, res-s); /* end */
+ return push_captures(&ms, NULL, 0) + 2;
+ }
+ else
+ return push_captures(&ms, s1, res);
+ }
+ } while (s1++ < ms.src_end && !anchor);
+ }
+ lua_pushnil(L); /* not found */
+ return 1;
+}
+
+
+static int str_find (lua_State *L) {
+ return str_find_aux(L, 1);
+}
+
+
+static int str_match (lua_State *L) {
+ return str_find_aux(L, 0);
+}
+
+
+static int gmatch_aux (lua_State *L) {
+ MatchState ms;
+ size_t ls;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ const char *p = lua_tostring(L, lua_upvalueindex(2));
+ const char *src;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+ls;
+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
+ src <= ms.src_end;
+ src++) {
+ const char *e;
+ ms.level = 0;
+ if ((e = match(&ms, src, p)) != NULL) {
+ lua_Integer newstart = e-s;
+ if (e == src) newstart++; /* empty match? go at least one position */
+ lua_pushinteger(L, newstart);
+ lua_replace(L, lua_upvalueindex(3));
+ return push_captures(&ms, src, e);
+ }
+ }
+ return 0; /* not found */
+}
+
+
+static int gmatch (lua_State *L) {
+ luaL_checkstring(L, 1);
+ luaL_checkstring(L, 2);
+ lua_settop(L, 2);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, gmatch_aux, 3);
+ return 1;
+}
+
+
+static int gfind_nodef (lua_State *L) {
+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
+ LUA_QL("string.gmatch"));
+}
+
+
+static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ size_t l, i;
+ const char *news = lua_tolstring(ms->L, 3, &l);
+ for (i = 0; i < l; i++) {
+ if (news[i] != L_ESC)
+ luaL_addchar(b, news[i]);
+ else {
+ i++; /* skip ESC */
+ if (!isdigit(uchar(news[i])))
+ luaL_addchar(b, news[i]);
+ else if (news[i] == '0')
+ luaL_addlstring(b, s, e - s);
+ else {
+ push_onecapture(ms, news[i] - '1', s, e);
+ luaL_addvalue(b); /* add capture to accumulated result */
+ }
+ }
+ }
+}
+
+
+static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ lua_State *L = ms->L;
+ switch (lua_type(L, 3)) {
+ case LUA_TNUMBER:
+ case LUA_TSTRING: {
+ add_s(ms, b, s, e);
+ return;
+ }
+ case LUA_TFUNCTION: {
+ int n;
+ lua_pushvalue(L, 3);
+ n = push_captures(ms, s, e);
+ lua_call(L, n, 1);
+ break;
+ }
+ case LUA_TTABLE: {
+ push_onecapture(ms, 0, s, e);
+ lua_gettable(L, 3);
+ break;
+ }
+ }
+ if (!lua_toboolean(L, -1)) { /* nil or false? */
+ lua_pop(L, 1);
+ lua_pushlstring(L, s, e - s); /* keep original text */
+ }
+ else if (!lua_isstring(L, -1))
+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
+ luaL_addvalue(b); /* add result to accumulator */
+}
+
+
+static int str_gsub (lua_State *L) {
+ size_t srcl;
+ const char *src = luaL_checklstring(L, 1, &srcl);
+ const char *p = luaL_checkstring(L, 2);
+ int tr = lua_type(L, 3);
+ int max_s = luaL_optint(L, 4, srcl+1);
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ int n = 0;
+ MatchState ms;
+ luaL_Buffer b;
+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
+ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
+ "string/function/table expected");
+ luaL_buffinit(L, &b);
+ ms.L = L;
+ ms.src_init = src;
+ ms.src_end = src+srcl;
+ while (n < max_s) {
+ const char *e;
+ ms.level = 0;
+ e = match(&ms, src, p);
+ if (e) {
+ n++;
+ add_value(&ms, &b, src, e);
+ }
+ if (e && e>src) /* non empty match? */
+ src = e; /* skip it */
+ else if (src < ms.src_end)
+ luaL_addchar(&b, *src++);
+ else break;
+ if (anchor) break;
+ }
+ luaL_addlstring(&b, src, ms.src_end-src);
+ luaL_pushresult(&b);
+ lua_pushinteger(L, n); /* number of substitutions */
+ return 2;
+}
+
+/* }====================================================== */
+
+
+/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
+#define MAX_ITEM 512
+/* valid flags in a format specification */
+#define FLAGS "-+ #0"
+/*
+** maximum size of each format specification (such as '%-099.99d')
+** (+10 accounts for %99.99x plus margin of error)
+*/
+#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
+
+
+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ luaL_addchar(b, '"');
+ while (l--) {
+ switch (*s) {
+ case '"': case '\\': case '\n': {
+ luaL_addchar(b, '\\');
+ luaL_addchar(b, *s);
+ break;
+ }
+ case '\r': {
+ luaL_addlstring(b, "\\r", 2);
+ break;
+ }
+ case '\0': {
+ luaL_addlstring(b, "\\000", 4);
+ break;
+ }
+ default: {
+ luaL_addchar(b, *s);
+ break;
+ }
+ }
+ s++;
+ }
+ luaL_addchar(b, '"');
+}
+
+static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
+ const char *p = strfrmt;
+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
+ luaL_error(L, "invalid format (repeated flags)");
+ if (isdigit(uchar(*p))) p++; /* skip width */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ if (*p == '.') {
+ p++;
+ if (isdigit(uchar(*p))) p++; /* skip precision */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ }
+ if (isdigit(uchar(*p)))
+ luaL_error(L, "invalid format (width or precision too long)");
+ *(form++) = '%';
+ strncpy(form, strfrmt, p - strfrmt + 1);
+ form += p - strfrmt + 1;
+ *form = '\0';
+ return p;
+}
+
+
+static void addintlen (char *form) {
+ size_t l = strlen(form);
+ char spec = form[l - 1];
+ strcpy(form + l - 1, LUA_INTFRMLEN);
+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
+}
+
+
+static int str_format (lua_State *L) {
+ int arg = 1;
+ size_t sfl;
+ const char *strfrmt = luaL_checklstring(L, arg, &sfl);
+ const char *strfrmt_end = strfrmt+sfl;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (strfrmt < strfrmt_end) {
+ if (*strfrmt != L_ESC)
+ luaL_addchar(&b, *strfrmt++);
+ else if (*++strfrmt == L_ESC)
+ luaL_addchar(&b, *strfrmt++); /* %% */
+ else { /* format item */
+ char form[MAX_FORMAT]; /* to store the format (`%...') */
+ char buff[MAX_ITEM]; /* to store the formatted item */
+ arg++;
+ strfrmt = scanformat(L, strfrmt, form);
+ switch (*strfrmt++) {
+ case 'c': {
+ sprintf(buff, form, (int)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'd': case 'i': {
+ addintlen(form);
+ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'o': case 'u': case 'x': case 'X': {
+ addintlen(form);
+ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'e': case 'E': case 'f':
+ case 'g': case 'G': {
+ sprintf(buff, form, (double)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'q': {
+ addquoted(L, &b, arg);
+ continue; /* skip the 'addsize' at the end */
+ }
+ case 's': {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ if (!strchr(form, '.') && l >= 100) {
+ /* no precision and string is too long to be formatted;
+ keep original string */
+ lua_pushvalue(L, arg);
+ luaL_addvalue(&b);
+ continue; /* skip the `addsize' at the end */
+ }
+ else {
+ sprintf(buff, form, s);
+ break;
+ }
+ }
+ default: { /* also treat cases `pnLlh' */
+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
+ LUA_QL("format"), *(strfrmt - 1));
+ }
+ }
+ luaL_addlstring(&b, buff, strlen(buff));
+ }
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static const luaL_Reg strlib[] = {
+ {"byte", str_byte},
+ {"char", str_char},
+ {"dump", str_dump},
+ {"find", str_find},
+ {"format", str_format},
+ {"gfind", gfind_nodef},
+ {"gmatch", gmatch},
+ {"gsub", str_gsub},
+ {"len", str_len},
+ {"lower", str_lower},
+ {"match", str_match},
+ {"rep", str_rep},
+ {"reverse", str_reverse},
+ {"sub", str_sub},
+ {"upper", str_upper},
+ {NULL, NULL}
+};
+
+
+static void createmetatable (lua_State *L) {
+ lua_createtable(L, 0, 1); /* create metatable for strings */
+ lua_pushliteral(L, ""); /* dummy string */
+ lua_pushvalue(L, -2);
+ lua_setmetatable(L, -2); /* set string metatable */
+ lua_pop(L, 1); /* pop dummy string */
+ lua_pushvalue(L, -2); /* string library... */
+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
+ lua_pop(L, 1); /* pop metatable */
+}
+
+
+/*
+** Open string library
+*/
+LUALIB_API int luaopen_string (lua_State *L) {
+ luaL_register(L, LUA_STRLIBNAME, strlib);
+#if defined(LUA_COMPAT_GFIND)
+ lua_getfield(L, -1, "gmatch");
+ lua_setfield(L, -2, "gfind");
+#endif
+ createmetatable(L);
+ return 1;
+}
+
diff --git a/lib/lua/src/ltable.c b/lib/lua/src/ltable.c
new file mode 100644
index 000000000..ec84f4fab
--- /dev/null
+++ b/lib/lua/src/ltable.c
@@ -0,0 +1,588 @@
+/*
+** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+
+/*
+** Implementation of tables (aka arrays, objects, or hash tables).
+** Tables keep its elements in two parts: an array part and a hash part.
+** Non-negative integer keys are all candidates to be kept in the array
+** part. The actual size of the array is the largest `n' such that at
+** least half the slots between 0 and n are in use.
+** Hash uses a mix of chained scatter table with Brent's variation.
+** A main invariant of these tables is that, if an element is not
+** in its main position (i.e. the `original' position that its hash gives
+** to it), then the colliding element is in its own main position.
+** Hence even when the load factor reaches 100%, performance remains good.
+*/
+
+#include <math.h>
+#include <string.h>
+
+#define ltable_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "ltable.h"
+
+
+/*
+** max size of array part is 2^MAXBITS
+*/
+#if LUAI_BITSINT > 26
+#define MAXBITS 26
+#else
+#define MAXBITS (LUAI_BITSINT-2)
+#endif
+
+#define MAXASIZE (1 << MAXBITS)
+
+
+#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
+
+#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
+#define hashboolean(t,p) hashpow2(t, p)
+
+
+/*
+** for some types, it is better to avoid modulus by power of 2, as
+** they tend to have many 2 factors.
+*/
+#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
+
+
+#define hashpointer(t,p) hashmod(t, IntPoint(p))
+
+
+/*
+** number of ints inside a lua_Number
+*/
+#define numints cast_int(sizeof(lua_Number)/sizeof(int))
+
+
+
+#define dummynode (&dummynode_)
+
+static const Node dummynode_ = {
+ {{NULL}, LUA_TNIL}, /* value */
+ {{{NULL}, LUA_TNIL, NULL}} /* key */
+};
+
+
+/*
+** hash for lua_Numbers
+*/
+static Node *hashnum (const Table *t, lua_Number n) {
+ unsigned int a[numints];
+ int i;
+ if (luai_numeq(n, 0)) /* avoid problems with -0 */
+ return gnode(t, 0);
+ memcpy(a, &n, sizeof(a));
+ for (i = 1; i < numints; i++) a[0] += a[i];
+ return hashmod(t, a[0]);
+}
+
+
+
+/*
+** returns the `main' position of an element in a table (that is, the index
+** of its hash value)
+*/
+static Node *mainposition (const Table *t, const TValue *key) {
+ switch (ttype(key)) {
+ case LUA_TNUMBER:
+ return hashnum(t, nvalue(key));
+ case LUA_TSTRING:
+ return hashstr(t, rawtsvalue(key));
+ case LUA_TBOOLEAN:
+ return hashboolean(t, bvalue(key));
+ case LUA_TLIGHTUSERDATA:
+ return hashpointer(t, pvalue(key));
+ default:
+ return hashpointer(t, gcvalue(key));
+ }
+}
+
+
+/*
+** returns the index for `key' if `key' is an appropriate key to live in
+** the array part of the table, -1 otherwise.
+*/
+static int arrayindex (const TValue *key) {
+ if (ttisnumber(key)) {
+ lua_Number n = nvalue(key);
+ int k;
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), n))
+ return k;
+ }
+ return -1; /* `key' did not match some condition */
+}
+
+
+/*
+** returns the index of a `key' for table traversals. First goes all
+** elements in the array part, then elements in the hash part. The
+** beginning of a traversal is signalled by -1.
+*/
+static int findindex (lua_State *L, Table *t, StkId key) {
+ int i;
+ if (ttisnil(key)) return -1; /* first iteration */
+ i = arrayindex(key);
+ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
+ return i-1; /* yes; that's the index (corrected to C) */
+ else {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ /* key may be dead already, but it is ok to use it in `next' */
+ if (luaO_rawequalObj(key2tval(n), key) ||
+ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
+ gcvalue(gkey(n)) == gcvalue(key))) {
+ i = cast_int(n - gnode(t, 0)); /* key index in hash table */
+ /* hash elements are numbered after array ones */
+ return i + t->sizearray;
+ }
+ else n = gnext(n);
+ } while (n);
+ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
+ return 0; /* to avoid warnings */
+ }
+}
+
+
+int luaH_next (lua_State *L, Table *t, StkId key) {
+ int i = findindex(L, t, key); /* find original element */
+ for (i++; i < t->sizearray; i++) { /* try first array part */
+ if (!ttisnil(&t->array[i])) { /* a non-nil value? */
+ setnvalue(key, cast_num(i+1));
+ setobj2s(L, key+1, &t->array[i]);
+ return 1;
+ }
+ }
+ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
+ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
+ setobj2s(L, key, key2tval(gnode(t, i)));
+ setobj2s(L, key+1, gval(gnode(t, i)));
+ return 1;
+ }
+ }
+ return 0; /* no more elements */
+}
+
+
+/*
+** {=============================================================
+** Rehash
+** ==============================================================
+*/
+
+
+static int computesizes (int nums[], int *narray) {
+ int i;
+ int twotoi; /* 2^i */
+ int a = 0; /* number of elements smaller than 2^i */
+ int na = 0; /* number of elements to go to array part */
+ int n = 0; /* optimal size for array part */
+ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
+ if (nums[i] > 0) {
+ a += nums[i];
+ if (a > twotoi/2) { /* more than half elements present? */
+ n = twotoi; /* optimal size (till now) */
+ na = a; /* all elements smaller than n will go to array part */
+ }
+ }
+ if (a == *narray) break; /* all elements already counted */
+ }
+ *narray = n;
+ lua_assert(*narray/2 <= na && na <= *narray);
+ return na;
+}
+
+
+static int countint (const TValue *key, int *nums) {
+ int k = arrayindex(key);
+ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
+ nums[ceillog2(k)]++; /* count as such */
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+static int numusearray (const Table *t, int *nums) {
+ int lg;
+ int ttlg; /* 2^lg */
+ int ause = 0; /* summation of `nums' */
+ int i = 1; /* count to traverse all array keys */
+ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */
+ int lc = 0; /* counter */
+ int lim = ttlg;
+ if (lim > t->sizearray) {
+ lim = t->sizearray; /* adjust upper limit */
+ if (i > lim)
+ break; /* no more elements to count */
+ }
+ /* count elements in range (2^(lg-1), 2^lg] */
+ for (; i <= lim; i++) {
+ if (!ttisnil(&t->array[i-1]))
+ lc++;
+ }
+ nums[lg] += lc;
+ ause += lc;
+ }
+ return ause;
+}
+
+
+static int numusehash (const Table *t, int *nums, int *pnasize) {
+ int totaluse = 0; /* total number of elements */
+ int ause = 0; /* summation of `nums' */
+ int i = sizenode(t);
+ while (i--) {
+ Node *n = &t->node[i];
+ if (!ttisnil(gval(n))) {
+ ause += countint(key2tval(n), nums);
+ totaluse++;
+ }
+ }
+ *pnasize += ause;
+ return totaluse;
+}
+
+
+static void setarrayvector (lua_State *L, Table *t, int size) {
+ int i;
+ luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
+ for (i=t->sizearray; i<size; i++)
+ setnilvalue(&t->array[i]);
+ t->sizearray = size;
+}
+
+
+static void setnodevector (lua_State *L, Table *t, int size) {
+ int lsize;
+ if (size == 0) { /* no elements to hash part? */
+ t->node = cast(Node *, dummynode); /* use common `dummynode' */
+ lsize = 0;
+ }
+ else {
+ int i;
+ lsize = ceillog2(size);
+ if (lsize > MAXBITS)
+ luaG_runerror(L, "table overflow");
+ size = twoto(lsize);
+ t->node = luaM_newvector(L, size, Node);
+ for (i=0; i<size; i++) {
+ Node *n = gnode(t, i);
+ gnext(n) = NULL;
+ setnilvalue(gkey(n));
+ setnilvalue(gval(n));
+ }
+ }
+ t->lsizenode = cast_byte(lsize);
+ t->lastfree = gnode(t, size); /* all positions are free */
+}
+
+
+static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
+ int i;
+ int oldasize = t->sizearray;
+ int oldhsize = t->lsizenode;
+ Node *nold = t->node; /* save old hash ... */
+ if (nasize > oldasize) /* array part must grow? */
+ setarrayvector(L, t, nasize);
+ /* create new hash part with appropriate size */
+ setnodevector(L, t, nhsize);
+ if (nasize < oldasize) { /* array part must shrink? */
+ t->sizearray = nasize;
+ /* re-insert elements from vanishing slice */
+ for (i=nasize; i<oldasize; i++) {
+ if (!ttisnil(&t->array[i]))
+ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
+ }
+ /* shrink array */
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+ }
+ /* re-insert elements from hash part */
+ for (i = twoto(oldhsize) - 1; i >= 0; i--) {
+ Node *old = nold+i;
+ if (!ttisnil(gval(old)))
+ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
+ }
+ if (nold != dummynode)
+ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
+}
+
+
+void luaH_resizearray (lua_State *L, Table *t, int nasize) {
+ int nsize = (t->node == dummynode) ? 0 : sizenode(t);
+ resize(L, t, nasize, nsize);
+}
+
+
+static void rehash (lua_State *L, Table *t, const TValue *ek) {
+ int nasize, na;
+ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */
+ int i;
+ int totaluse;
+ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
+ nasize = numusearray(t, nums); /* count keys in array part */
+ totaluse = nasize; /* all those keys are integer keys */
+ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
+ /* count extra key */
+ nasize += countint(ek, nums);
+ totaluse++;
+ /* compute new size for array part */
+ na = computesizes(nums, &nasize);
+ /* resize the table to new computed sizes */
+ resize(L, t, nasize, totaluse - na);
+}
+
+
+
+/*
+** }=============================================================
+*/
+
+
+Table *luaH_new (lua_State *L, int narray, int nhash) {
+ Table *t = luaM_new(L, Table);
+ luaC_link(L, obj2gco(t), LUA_TTABLE);
+ t->metatable = NULL;
+ t->flags = cast_byte(~0);
+ /* temporary values (kept only if some malloc fails) */
+ t->array = NULL;
+ t->sizearray = 0;
+ t->lsizenode = 0;
+ t->node = cast(Node *, dummynode);
+ setarrayvector(L, t, narray);
+ setnodevector(L, t, nhash);
+ return t;
+}
+
+
+void luaH_free (lua_State *L, Table *t) {
+ if (t->node != dummynode)
+ luaM_freearray(L, t->node, sizenode(t), Node);
+ luaM_freearray(L, t->array, t->sizearray, TValue);
+ luaM_free(L, t);
+}
+
+
+static Node *getfreepos (Table *t) {
+ while (t->lastfree-- > t->node) {
+ if (ttisnil(gkey(t->lastfree)))
+ return t->lastfree;
+ }
+ return NULL; /* could not find a free place */
+}
+
+
+
+/*
+** inserts a new key into a hash table; first, check whether key's main
+** position is free. If not, check whether colliding node is in its main
+** position or not: if it is not, move colliding node to an empty place and
+** put new key in its main position; otherwise (colliding node is in its main
+** position), new key goes to an empty position.
+*/
+static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
+ Node *mp = mainposition(t, key);
+ if (!ttisnil(gval(mp)) || mp == dummynode) {
+ Node *othern;
+ Node *n = getfreepos(t); /* get a free place */
+ if (n == NULL) { /* cannot find a free place? */
+ rehash(L, t, key); /* grow table */
+ return luaH_set(L, t, key); /* re-insert key into grown table */
+ }
+ lua_assert(n != dummynode);
+ othern = mainposition(t, key2tval(mp));
+ if (othern != mp) { /* is colliding node out of its main position? */
+ /* yes; move colliding node into free position */
+ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
+ gnext(mp) = NULL; /* now `mp' is free */
+ setnilvalue(gval(mp));
+ }
+ else { /* colliding node is in its own main position */
+ /* new node will go into free position */
+ gnext(n) = gnext(mp); /* chain new position */
+ gnext(mp) = n;
+ mp = n;
+ }
+ }
+ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
+ luaC_barriert(L, t, key);
+ lua_assert(ttisnil(gval(mp)));
+ return gval(mp);
+}
+
+
+/*
+** search function for integers
+*/
+const TValue *luaH_getnum (Table *t, int key) {
+ /* (1 <= key && key <= t->sizearray) */
+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
+ return &t->array[key-1];
+ else {
+ lua_Number nk = cast_num(key);
+ Node *n = hashnum(t, nk);
+ do { /* check whether `key' is somewhere in the chain */
+ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+ }
+}
+
+
+/*
+** search function for strings
+*/
+const TValue *luaH_getstr (Table *t, TString *key) {
+ Node *n = hashstr(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+}
+
+
+/*
+** main search function
+*/
+const TValue *luaH_get (Table *t, const TValue *key) {
+ switch (ttype(key)) {
+ case LUA_TNIL: return luaO_nilobject;
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
+ case LUA_TNUMBER: {
+ int k;
+ lua_Number n = nvalue(key);
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+ return luaH_getnum(t, k); /* use specialized version */
+ /* else go through */
+ }
+ default: {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (luaO_rawequalObj(key2tval(n), key))
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+ }
+ }
+}
+
+
+TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
+ const TValue *p = luaH_get(t, key);
+ t->flags = 0;
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+ else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
+ luaG_runerror(L, "table index is NaN");
+ return newkey(L, t, key);
+ }
+}
+
+
+TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+ const TValue *p = luaH_getnum(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setnvalue(&k, cast_num(key));
+ return newkey(L, t, &k);
+ }
+}
+
+
+TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
+ const TValue *p = luaH_getstr(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setsvalue(L, &k, key);
+ return newkey(L, t, &k);
+ }
+}
+
+
+static int unbound_search (Table *t, unsigned int j) {
+ unsigned int i = j; /* i is zero or a present index */
+ j++;
+ /* find `i' and `j' such that i is present and j is not */
+ while (!ttisnil(luaH_getnum(t, j))) {
+ i = j;
+ j *= 2;
+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ /* table was built with bad purposes: resort to linear search */
+ i = 1;
+ while (!ttisnil(luaH_getnum(t, i))) i++;
+ return i - 1;
+ }
+ }
+ /* now do a binary search between them */
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(luaH_getnum(t, m))) j = m;
+ else i = m;
+ }
+ return i;
+}
+
+
+/*
+** Try to find a boundary in table `t'. A `boundary' is an integer index
+** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
+*/
+int luaH_getn (Table *t) {
+ unsigned int j = t->sizearray;
+ if (j > 0 && ttisnil(&t->array[j - 1])) {
+ /* there is a boundary in the array part: (binary) search for it */
+ unsigned int i = 0;
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(&t->array[m - 1])) j = m;
+ else i = m;
+ }
+ return i;
+ }
+ /* else must find a boundary in hash part */
+ else if (t->node == dummynode) /* hash part is empty? */
+ return j; /* that is easy... */
+ else return unbound_search(t, j);
+}
+
+
+
+#if defined(LUA_DEBUG)
+
+Node *luaH_mainposition (const Table *t, const TValue *key) {
+ return mainposition(t, key);
+}
+
+int luaH_isdummy (Node *n) { return n == dummynode; }
+
+#endif
diff --git a/lib/lua/src/ltable.h b/lib/lua/src/ltable.h
new file mode 100644
index 000000000..f5b9d5ead
--- /dev/null
+++ b/lib/lua/src/ltable.h
@@ -0,0 +1,40 @@
+/*
+** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltable_h
+#define ltable_h
+
+#include "lobject.h"
+
+
+#define gnode(t,i) (&(t)->node[i])
+#define gkey(n) (&(n)->i_key.nk)
+#define gval(n) (&(n)->i_val)
+#define gnext(n) ((n)->i_key.nk.next)
+
+#define key2tval(n) (&(n)->i_key.tvk)
+
+
+LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
+LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
+LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
+LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
+LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
+LUAI_FUNC void luaH_free (lua_State *L, Table *t);
+LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
+LUAI_FUNC int luaH_getn (Table *t);
+
+
+#if defined(LUA_DEBUG)
+LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
+LUAI_FUNC int luaH_isdummy (Node *n);
+#endif
+
+
+#endif
diff --git a/lib/lua/src/ltablib.c b/lib/lua/src/ltablib.c
new file mode 100644
index 000000000..b6d9cb4ac
--- /dev/null
+++ b/lib/lua/src/ltablib.c
@@ -0,0 +1,287 @@
+/*
+** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $
+** Library for Table Manipulation
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define ltablib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
+
+
+static int foreachi (lua_State *L) {
+ int i;
+ int n = aux_getn(L, 1);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ for (i=1; i <= n; i++) {
+ lua_pushvalue(L, 2); /* function */
+ lua_pushinteger(L, i); /* 1st argument */
+ lua_rawgeti(L, 1, i); /* 2nd argument */
+ lua_call(L, 2, 1);
+ if (!lua_isnil(L, -1))
+ return 1;
+ lua_pop(L, 1); /* remove nil result */
+ }
+ return 0;
+}
+
+
+static int foreach (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 1)) {
+ lua_pushvalue(L, 2); /* function */
+ lua_pushvalue(L, -3); /* key */
+ lua_pushvalue(L, -3); /* value */
+ lua_call(L, 2, 1);
+ if (!lua_isnil(L, -1))
+ return 1;
+ lua_pop(L, 2); /* remove value and result */
+ }
+ return 0;
+}
+
+
+static int maxn (lua_State *L) {
+ lua_Number max = 0;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 1)) {
+ lua_pop(L, 1); /* remove value */
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ lua_Number v = lua_tonumber(L, -1);
+ if (v > max) max = v;
+ }
+ }
+ lua_pushnumber(L, max);
+ return 1;
+}
+
+
+static int getn (lua_State *L) {
+ lua_pushinteger(L, aux_getn(L, 1));
+ return 1;
+}
+
+
+static int setn (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+#ifndef luaL_setn
+ luaL_setn(L, 1, luaL_checkint(L, 2));
+#else
+ luaL_error(L, LUA_QL("setn") " is obsolete");
+#endif
+ lua_pushvalue(L, 1);
+ return 1;
+}
+
+
+static int tinsert (lua_State *L) {
+ int e = aux_getn(L, 1) + 1; /* first empty element */
+ int pos; /* where to insert new element */
+ switch (lua_gettop(L)) {
+ case 2: { /* called with only 2 arguments */
+ pos = e; /* insert new element at the end */
+ break;
+ }
+ case 3: {
+ int i;
+ pos = luaL_checkint(L, 2); /* 2nd argument is the position */
+ if (pos > e) e = pos; /* `grow' array if necessary */
+ for (i = e; i > pos; i--) { /* move up elements */
+ lua_rawgeti(L, 1, i-1);
+ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
+ }
+ break;
+ }
+ default: {
+ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
+ }
+ }
+ luaL_setn(L, 1, e); /* new size */
+ lua_rawseti(L, 1, pos); /* t[pos] = v */
+ return 0;
+}
+
+
+static int tremove (lua_State *L) {
+ int e = aux_getn(L, 1);
+ int pos = luaL_optint(L, 2, e);
+ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
+ return 0; /* nothing to remove */
+ luaL_setn(L, 1, e - 1); /* t.n = n-1 */
+ lua_rawgeti(L, 1, pos); /* result = t[pos] */
+ for ( ;pos<e; pos++) {
+ lua_rawgeti(L, 1, pos+1);
+ lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
+ }
+ lua_pushnil(L);
+ lua_rawseti(L, 1, e); /* t[e] = nil */
+ return 1;
+}
+
+
+static void addfield (lua_State *L, luaL_Buffer *b, int i) {
+ lua_rawgeti(L, 1, i);
+ if (!lua_isstring(L, -1))
+ luaL_error(L, "invalid value (%s) at index %d in table for "
+ LUA_QL("concat"), luaL_typename(L, -1), i);
+ luaL_addvalue(b);
+}
+
+
+static int tconcat (lua_State *L) {
+ luaL_Buffer b;
+ size_t lsep;
+ int i, last;
+ const char *sep = luaL_optlstring(L, 2, "", &lsep);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i = luaL_optint(L, 3, 1);
+ last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
+ luaL_buffinit(L, &b);
+ for (; i < last; i++) {
+ addfield(L, &b, i);
+ luaL_addlstring(&b, sep, lsep);
+ }
+ if (i == last) /* add last value (if interval was not empty) */
+ addfield(L, &b, i);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** Quicksort
+** (based on `Algorithms in MODULA-3', Robert Sedgewick;
+** Addison-Wesley, 1993.)
+*/
+
+
+static void set2 (lua_State *L, int i, int j) {
+ lua_rawseti(L, 1, i);
+ lua_rawseti(L, 1, j);
+}
+
+static int sort_comp (lua_State *L, int a, int b) {
+ if (!lua_isnil(L, 2)) { /* function? */
+ int res;
+ lua_pushvalue(L, 2);
+ lua_pushvalue(L, a-1); /* -1 to compensate function */
+ lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
+ lua_call(L, 2, 1);
+ res = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+ }
+ else /* a < b? */
+ return lua_lessthan(L, a, b);
+}
+
+static void auxsort (lua_State *L, int l, int u) {
+ while (l < u) { /* for tail recursion */
+ int i, j;
+ /* sort elements a[l], a[(l+u)/2] and a[u] */
+ lua_rawgeti(L, 1, l);
+ lua_rawgeti(L, 1, u);
+ if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
+ set2(L, l, u); /* swap a[l] - a[u] */
+ else
+ lua_pop(L, 2);
+ if (u-l == 1) break; /* only 2 elements */
+ i = (l+u)/2;
+ lua_rawgeti(L, 1, i);
+ lua_rawgeti(L, 1, l);
+ if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
+ set2(L, i, l);
+ else {
+ lua_pop(L, 1); /* remove a[l] */
+ lua_rawgeti(L, 1, u);
+ if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
+ set2(L, i, u);
+ else
+ lua_pop(L, 2);
+ }
+ if (u-l == 2) break; /* only 3 elements */
+ lua_rawgeti(L, 1, i); /* Pivot */
+ lua_pushvalue(L, -1);
+ lua_rawgeti(L, 1, u-1);
+ set2(L, i, u-1);
+ /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
+ i = l; j = u-1;
+ for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
+ /* repeat ++i until a[i] >= P */
+ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
+ if (i>u) luaL_error(L, "invalid order function for sorting");
+ lua_pop(L, 1); /* remove a[i] */
+ }
+ /* repeat --j until a[j] <= P */
+ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
+ if (j<l) luaL_error(L, "invalid order function for sorting");
+ lua_pop(L, 1); /* remove a[j] */
+ }
+ if (j<i) {
+ lua_pop(L, 3); /* pop pivot, a[i], a[j] */
+ break;
+ }
+ set2(L, i, j);
+ }
+ lua_rawgeti(L, 1, u-1);
+ lua_rawgeti(L, 1, i);
+ set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
+ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
+ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
+ if (i-l < u-i) {
+ j=l; i=i-1; l=i+2;
+ }
+ else {
+ j=i+1; i=u; u=j-2;
+ }
+ auxsort(L, j, i); /* call recursively the smaller one */
+ } /* repeat the routine for the larger one */
+}
+
+static int sort (lua_State *L) {
+ int n = aux_getn(L, 1);
+ luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
+ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ lua_settop(L, 2); /* make sure there is two arguments */
+ auxsort(L, 1, n);
+ return 0;
+}
+
+/* }====================================================== */
+
+
+static const luaL_Reg tab_funcs[] = {
+ {"concat", tconcat},
+ {"foreach", foreach},
+ {"foreachi", foreachi},
+ {"getn", getn},
+ {"maxn", maxn},
+ {"insert", tinsert},
+ {"remove", tremove},
+ {"setn", setn},
+ {"sort", sort},
+ {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_table (lua_State *L) {
+ luaL_register(L, LUA_TABLIBNAME, tab_funcs);
+ return 1;
+}
+
diff --git a/lib/lua/src/ltm.c b/lib/lua/src/ltm.c
new file mode 100644
index 000000000..c27f0f6fa
--- /dev/null
+++ b/lib/lua/src/ltm.c
@@ -0,0 +1,75 @@
+/*
+** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define ltm_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+
+const char *const luaT_typenames[] = {
+ "nil", "boolean", "userdata", "number",
+ "string", "table", "function", "userdata", "thread",
+ "proto", "upval"
+};
+
+
+void luaT_init (lua_State *L) {
+ static const char *const luaT_eventname[] = { /* ORDER TM */
+ "__index", "__newindex",
+ "__gc", "__mode", "__eq",
+ "__add", "__sub", "__mul", "__div", "__mod",
+ "__pow", "__unm", "__len", "__lt", "__le",
+ "__concat", "__call"
+ };
+ int i;
+ for (i=0; i<TM_N; i++) {
+ G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
+ luaS_fix(G(L)->tmname[i]); /* never collect these names */
+ }
+}
+
+
+/*
+** function to be used with macro "fasttm": optimized for absence of
+** tag methods
+*/
+const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
+ const TValue *tm = luaH_getstr(events, ename);
+ lua_assert(event <= TM_EQ);
+ if (ttisnil(tm)) { /* no tag method? */
+ events->flags |= cast_byte(1u<<event); /* cache this fact */
+ return NULL;
+ }
+ else return tm;
+}
+
+
+const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
+ Table *mt;
+ switch (ttype(o)) {
+ case LUA_TTABLE:
+ mt = hvalue(o)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(o)->metatable;
+ break;
+ default:
+ mt = G(L)->mt[ttype(o)];
+ }
+ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
+}
+
diff --git a/lib/lua/src/ltm.h b/lib/lua/src/ltm.h
new file mode 100644
index 000000000..64343b781
--- /dev/null
+++ b/lib/lua/src/ltm.h
@@ -0,0 +1,54 @@
+/*
+** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltm_h
+#define ltm_h
+
+
+#include "lobject.h"
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER TM"
+*/
+typedef enum {
+ TM_INDEX,
+ TM_NEWINDEX,
+ TM_GC,
+ TM_MODE,
+ TM_EQ, /* last tag method with `fast' access */
+ TM_ADD,
+ TM_SUB,
+ TM_MUL,
+ TM_DIV,
+ TM_MOD,
+ TM_POW,
+ TM_UNM,
+ TM_LEN,
+ TM_LT,
+ TM_LE,
+ TM_CONCAT,
+ TM_CALL,
+ TM_N /* number of elements in the enum */
+} TMS;
+
+
+
+#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
+ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
+
+#define fasttm(l,et,e) gfasttm(G(l), et, e)
+
+LUAI_DATA const char *const luaT_typenames[];
+
+
+LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
+LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
+ TMS event);
+LUAI_FUNC void luaT_init (lua_State *L);
+
+#endif
diff --git a/lib/lua/src/lua.c b/lib/lua/src/lua.c
new file mode 100644
index 000000000..3a4660932
--- /dev/null
+++ b/lib/lua/src/lua.c
@@ -0,0 +1,392 @@
+/*
+** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
+** Lua stand-alone interpreter
+** See Copyright Notice in lua.h
+*/
+
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lua_c
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+static lua_State *globalL = NULL;
+
+static const char *progname = LUA_PROGNAME;
+
+
+
+static void lstop (lua_State *L, lua_Debug *ar) {
+ (void)ar; /* unused arg. */
+ lua_sethook(L, NULL, 0, 0);
+ luaL_error(L, "interrupted!");
+}
+
+
+static void laction (int i) {
+ signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
+ terminate process (default action) */
+ lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
+}
+
+
+static void print_usage (void) {
+ fprintf(stderr,
+ "usage: %s [options] [script [args]].\n"
+ "Available options are:\n"
+ " -e stat execute string " LUA_QL("stat") "\n"
+ " -l name require library " LUA_QL("name") "\n"
+ " -i enter interactive mode after executing " LUA_QL("script") "\n"
+ " -v show version information\n"
+ " -- stop handling options\n"
+ " - execute stdin and stop handling options\n"
+ ,
+ progname);
+ fflush(stderr);
+}
+
+
+static void l_message (const char *pname, const char *msg) {
+ if (pname) fprintf(stderr, "%s: ", pname);
+ fprintf(stderr, "%s\n", msg);
+ fflush(stderr);
+}
+
+
+static int report (lua_State *L, int status) {
+ if (status && !lua_isnil(L, -1)) {
+ const char *msg = lua_tostring(L, -1);
+ if (msg == NULL) msg = "(error object is not a string)";
+ l_message(progname, msg);
+ lua_pop(L, 1);
+ }
+ return status;
+}
+
+
+static int traceback (lua_State *L) {
+ if (!lua_isstring(L, 1)) /* 'message' not a string? */
+ return 1; /* keep it intact */
+ lua_getfield(L, LUA_GLOBALSINDEX, "debug");
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ lua_getfield(L, -1, "traceback");
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 2);
+ return 1;
+ }
+ lua_pushvalue(L, 1); /* pass error message */
+ lua_pushinteger(L, 2); /* skip this function and traceback */
+ lua_call(L, 2, 1); /* call debug.traceback */
+ return 1;
+}
+
+
+static int docall (lua_State *L, int narg, int clear) {
+ int status;
+ int base = lua_gettop(L) - narg; /* function index */
+ lua_pushcfunction(L, traceback); /* push traceback function */
+ lua_insert(L, base); /* put it under chunk and args */
+ signal(SIGINT, laction);
+ status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
+ signal(SIGINT, SIG_DFL);
+ lua_remove(L, base); /* remove traceback function */
+ /* force a complete garbage collection in case of errors */
+ if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
+ return status;
+}
+
+
+static void print_version (void) {
+ l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT);
+}
+
+
+static int getargs (lua_State *L, char **argv, int n) {
+ int narg;
+ int i;
+ int argc = 0;
+ while (argv[argc]) argc++; /* count total number of arguments */
+ narg = argc - (n + 1); /* number of arguments to the script */
+ luaL_checkstack(L, narg + 3, "too many arguments to script");
+ for (i=n+1; i < argc; i++)
+ lua_pushstring(L, argv[i]);
+ lua_createtable(L, narg, n + 1);
+ for (i=0; i < argc; i++) {
+ lua_pushstring(L, argv[i]);
+ lua_rawseti(L, -2, i - n);
+ }
+ return narg;
+}
+
+
+static int dofile (lua_State *L, const char *name) {
+ int status = luaL_loadfile(L, name) || docall(L, 0, 1);
+ return report(L, status);
+}
+
+
+static int dostring (lua_State *L, const char *s, const char *name) {
+ int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
+ return report(L, status);
+}
+
+
+static int dolibrary (lua_State *L, const char *name) {
+ lua_getglobal(L, "require");
+ lua_pushstring(L, name);
+ return report(L, docall(L, 1, 1));
+}
+
+
+static const char *get_prompt (lua_State *L, int firstline) {
+ const char *p;
+ lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
+ p = lua_tostring(L, -1);
+ if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
+ lua_pop(L, 1); /* remove global */
+ return p;
+}
+
+
+static int incomplete (lua_State *L, int status) {
+ if (status == LUA_ERRSYNTAX) {
+ size_t lmsg;
+ const char *msg = lua_tolstring(L, -1, &lmsg);
+ const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
+ if (strstr(msg, LUA_QL("<eof>")) == tp) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ }
+ return 0; /* else... */
+}
+
+
+static int pushline (lua_State *L, int firstline) {
+ char buffer[LUA_MAXINPUT];
+ char *b = buffer;
+ size_t l;
+ const char *prmt = get_prompt(L, firstline);
+ if (lua_readline(L, b, prmt) == 0)
+ return 0; /* no input */
+ l = strlen(b);
+ if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
+ b[l-1] = '\0'; /* remove it */
+ if (firstline && b[0] == '=') /* first line starts with `=' ? */
+ lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
+ else
+ lua_pushstring(L, b);
+ lua_freeline(L, b);
+ return 1;
+}
+
+
+static int loadline (lua_State *L) {
+ int status;
+ lua_settop(L, 0);
+ if (!pushline(L, 1))
+ return -1; /* no input */
+ for (;;) { /* repeat until gets a complete line */
+ status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
+ if (!incomplete(L, status)) break; /* cannot try to add lines? */
+ if (!pushline(L, 0)) /* no more input? */
+ return -1;
+ lua_pushliteral(L, "\n"); /* add a new line... */
+ lua_insert(L, -2); /* ...between the two lines */
+ lua_concat(L, 3); /* join them */
+ }
+ lua_saveline(L, 1);
+ lua_remove(L, 1); /* remove line */
+ return status;
+}
+
+
+static void dotty (lua_State *L) {
+ int status;
+ const char *oldprogname = progname;
+ progname = NULL;
+ while ((status = loadline(L)) != -1) {
+ if (status == 0) status = docall(L, 0, 0);
+ report(L, status);
+ if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
+ lua_getglobal(L, "print");
+ lua_insert(L, 1);
+ if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
+ l_message(progname, lua_pushfstring(L,
+ "error calling " LUA_QL("print") " (%s)",
+ lua_tostring(L, -1)));
+ }
+ }
+ lua_settop(L, 0); /* clear stack */
+ fputs("\n", stdout);
+ fflush(stdout);
+ progname = oldprogname;
+}
+
+
+static int handle_script (lua_State *L, char **argv, int n) {
+ int status;
+ const char *fname;
+ int narg = getargs(L, argv, n); /* collect arguments */
+ lua_setglobal(L, "arg");
+ fname = argv[n];
+ if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
+ fname = NULL; /* stdin */
+ status = luaL_loadfile(L, fname);
+ lua_insert(L, -(narg+1));
+ if (status == 0)
+ status = docall(L, narg, 0);
+ else
+ lua_pop(L, narg);
+ return report(L, status);
+}
+
+
+/* check that argument has no extra characters at the end */
+#define notail(x) {if ((x)[2] != '\0') return -1;}
+
+
+static int collectargs (char **argv, int *pi, int *pv, int *pe) {
+ int i;
+ for (i = 1; argv[i] != NULL; i++) {
+ if (argv[i][0] != '-') /* not an option? */
+ return i;
+ switch (argv[i][1]) { /* option */
+ case '-':
+ notail(argv[i]);
+ return (argv[i+1] != NULL ? i+1 : 0);
+ case '\0':
+ return i;
+ case 'i':
+ notail(argv[i]);
+ *pi = 1; /* go through */
+ case 'v':
+ notail(argv[i]);
+ *pv = 1;
+ break;
+ case 'e':
+ *pe = 1; /* go through */
+ case 'l':
+ if (argv[i][2] == '\0') {
+ i++;
+ if (argv[i] == NULL) return -1;
+ }
+ break;
+ default: return -1; /* invalid option */
+ }
+ }
+ return 0;
+}
+
+
+static int runargs (lua_State *L, char **argv, int n) {
+ int i;
+ for (i = 1; i < n; i++) {
+ if (argv[i] == NULL) continue;
+ lua_assert(argv[i][0] == '-');
+ switch (argv[i][1]) { /* option */
+ case 'e': {
+ const char *chunk = argv[i] + 2;
+ if (*chunk == '\0') chunk = argv[++i];
+ lua_assert(chunk != NULL);
+ if (dostring(L, chunk, "=(command line)") != 0)
+ return 1;
+ break;
+ }
+ case 'l': {
+ const char *filename = argv[i] + 2;
+ if (*filename == '\0') filename = argv[++i];
+ lua_assert(filename != NULL);
+ if (dolibrary(L, filename))
+ return 1; /* stop if file fails */
+ break;
+ }
+ default: break;
+ }
+ }
+ return 0;
+}
+
+
+static int handle_luainit (lua_State *L) {
+ const char *init = getenv(LUA_INIT);
+ if (init == NULL) return 0; /* status OK */
+ else if (init[0] == '@')
+ return dofile(L, init+1);
+ else
+ return dostring(L, init, "=" LUA_INIT);
+}
+
+
+struct Smain {
+ int argc;
+ char **argv;
+ int status;
+};
+
+
+static int pmain (lua_State *L) {
+ struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
+ char **argv = s->argv;
+ int script;
+ int has_i = 0, has_v = 0, has_e = 0;
+ globalL = L;
+ if (argv[0] && argv[0][0]) progname = argv[0];
+ lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
+ luaL_openlibs(L); /* open libraries */
+ lua_gc(L, LUA_GCRESTART, 0);
+ s->status = handle_luainit(L);
+ if (s->status != 0) return 0;
+ script = collectargs(argv, &has_i, &has_v, &has_e);
+ if (script < 0) { /* invalid args? */
+ print_usage();
+ s->status = 1;
+ return 0;
+ }
+ if (has_v) print_version();
+ s->status = runargs(L, argv, (script > 0) ? script : s->argc);
+ if (s->status != 0) return 0;
+ if (script)
+ s->status = handle_script(L, argv, script);
+ if (s->status != 0) return 0;
+ if (has_i)
+ dotty(L);
+ else if (script == 0 && !has_e && !has_v) {
+ if (lua_stdin_is_tty()) {
+ print_version();
+ dotty(L);
+ }
+ else dofile(L, NULL); /* executes stdin as a file */
+ }
+ return 0;
+}
+
+
+int main (int argc, char **argv) {
+ int status;
+ struct Smain s;
+ lua_State *L = lua_open(); /* create state */
+ if (L == NULL) {
+ l_message(argv[0], "cannot create state: not enough memory");
+ return EXIT_FAILURE;
+ }
+ s.argc = argc;
+ s.argv = argv;
+ status = lua_cpcall(L, &pmain, &s);
+ report(L, status);
+ lua_close(L);
+ return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
diff --git a/lib/lua/src/lua.h b/lib/lua/src/lua.h
new file mode 100644
index 000000000..1f8513667
--- /dev/null
+++ b/lib/lua/src/lua.h
@@ -0,0 +1,390 @@
+/*
+** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
+** Lua - An Extensible Extension Language
+** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
+** See Copyright Notice at the end of this file
+*/
+
+
+#ifndef lua_h
+#define lua_h
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#ifndef _WIN32
+#define LUA_USE_POSIX
+#endif
+#include "luaconf.h"
+
+
+#define LUA_VERSION "Lua 5.1"
+#define LUA_RELEASE "Lua 5.1.4"
+#define LUA_VERSION_NUM 501
+#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
+#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+/* mark for precompiled code (`<esc>Lua') */
+#define LUA_SIGNATURE "\033Lua"
+
+/* option for multiple returns in `lua_pcall' and `lua_call' */
+#define LUA_MULTRET (-1)
+
+
+/*
+** pseudo-indices
+*/
+#define LUA_REGISTRYINDEX (-10000)
+#define LUA_ENVIRONINDEX (-10001)
+#define LUA_GLOBALSINDEX (-10002)
+#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
+
+
+/* thread status; 0 is OK */
+#define LUA_YIELD 1
+#define LUA_ERRRUN 2
+#define LUA_ERRSYNTAX 3
+#define LUA_ERRMEM 4
+#define LUA_ERRERR 5
+
+
+typedef struct lua_State lua_State;
+
+typedef int (*lua_CFunction) (lua_State *L);
+
+
+/*
+** functions that read/write blocks when loading/dumping Lua chunks
+*/
+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
+
+typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
+
+
+/*
+** prototype for memory-allocation functions
+*/
+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
+
+
+/*
+** basic types
+*/
+#define LUA_TNONE (-1)
+
+#define LUA_TNIL 0
+#define LUA_TBOOLEAN 1
+#define LUA_TLIGHTUSERDATA 2
+#define LUA_TNUMBER 3
+#define LUA_TSTRING 4
+#define LUA_TTABLE 5
+#define LUA_TFUNCTION 6
+#define LUA_TUSERDATA 7
+#define LUA_TTHREAD 8
+
+
+
+/* minimum Lua stack available to a C function */
+#define LUA_MINSTACK 20
+
+
+/*
+** generic extra include file
+*/
+#if defined(LUA_USER_H)
+#include LUA_USER_H
+#endif
+
+
+/* type of numbers in Lua */
+typedef LUA_NUMBER lua_Number;
+
+
+/* type for integer functions */
+typedef LUA_INTEGER lua_Integer;
+
+
+
+/*
+** state manipulation
+*/
+LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
+LUA_API void (lua_close) (lua_State *L);
+LUA_API lua_State *(lua_newthread) (lua_State *L);
+
+LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
+
+
+/*
+** basic stack manipulation
+*/
+LUA_API int (lua_gettop) (lua_State *L);
+LUA_API void (lua_settop) (lua_State *L, int idx);
+LUA_API void (lua_pushvalue) (lua_State *L, int idx);
+LUA_API void (lua_remove) (lua_State *L, int idx);
+LUA_API void (lua_insert) (lua_State *L, int idx);
+LUA_API void (lua_replace) (lua_State *L, int idx);
+LUA_API int (lua_checkstack) (lua_State *L, int sz);
+
+LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
+
+
+/*
+** access functions (stack -> C)
+*/
+
+LUA_API int (lua_isnumber) (lua_State *L, int idx);
+LUA_API int (lua_isstring) (lua_State *L, int idx);
+LUA_API int (lua_iscfunction) (lua_State *L, int idx);
+LUA_API int (lua_isuserdata) (lua_State *L, int idx);
+LUA_API int (lua_type) (lua_State *L, int idx);
+LUA_API const char *(lua_typename) (lua_State *L, int tp);
+
+LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
+LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
+LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
+
+LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
+LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
+LUA_API int (lua_toboolean) (lua_State *L, int idx);
+LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
+LUA_API size_t (lua_objlen) (lua_State *L, int idx);
+LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
+LUA_API void *(lua_touserdata) (lua_State *L, int idx);
+LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
+LUA_API const void *(lua_topointer) (lua_State *L, int idx);
+
+
+/*
+** push functions (C -> stack)
+*/
+LUA_API void (lua_pushnil) (lua_State *L);
+LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
+LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
+LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
+LUA_API void (lua_pushstring) (lua_State *L, const char *s);
+LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
+ va_list argp);
+LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
+LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
+LUA_API void (lua_pushboolean) (lua_State *L, int b);
+LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
+LUA_API int (lua_pushthread) (lua_State *L);
+
+
+/*
+** get functions (Lua -> stack)
+*/
+LUA_API void (lua_gettable) (lua_State *L, int idx);
+LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
+LUA_API void (lua_rawget) (lua_State *L, int idx);
+LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
+LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
+LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
+LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
+LUA_API void (lua_getfenv) (lua_State *L, int idx);
+
+
+/*
+** set functions (stack -> Lua)
+*/
+LUA_API void (lua_settable) (lua_State *L, int idx);
+LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
+LUA_API void (lua_rawset) (lua_State *L, int idx);
+LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
+LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
+LUA_API int (lua_setfenv) (lua_State *L, int idx);
+
+
+/*
+** `load' and `call' functions (load and run Lua code)
+*/
+LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
+LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
+LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
+LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
+ const char *chunkname);
+
+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
+
+
+/*
+** coroutine functions
+*/
+LUA_API int (lua_yield) (lua_State *L, int nresults);
+LUA_API int (lua_resume) (lua_State *L, int narg);
+LUA_API int (lua_status) (lua_State *L);
+
+/*
+** garbage-collection function and options
+*/
+
+#define LUA_GCSTOP 0
+#define LUA_GCRESTART 1
+#define LUA_GCCOLLECT 2
+#define LUA_GCCOUNT 3
+#define LUA_GCCOUNTB 4
+#define LUA_GCSTEP 5
+#define LUA_GCSETPAUSE 6
+#define LUA_GCSETSTEPMUL 7
+
+LUA_API int (lua_gc) (lua_State *L, int what, int data);
+
+
+/*
+** miscellaneous functions
+*/
+
+LUA_API int (lua_error) (lua_State *L);
+
+LUA_API int (lua_next) (lua_State *L, int idx);
+
+LUA_API void (lua_concat) (lua_State *L, int n);
+
+LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define lua_pop(L,n) lua_settop(L, -(n)-1)
+
+#define lua_newtable(L) lua_createtable(L, 0, 0)
+
+#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
+
+#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
+
+#define lua_strlen(L,i) lua_objlen(L, (i))
+
+#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
+#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
+#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
+#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
+#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
+#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
+#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
+#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
+
+#define lua_pushliteral(L, s) \
+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+
+#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
+#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
+
+#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
+
+
+
+/*
+** compatibility macros and functions
+*/
+
+#define lua_open() luaL_newstate()
+
+#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
+
+#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
+
+#define lua_Chunkreader lua_Reader
+#define lua_Chunkwriter lua_Writer
+
+
+/* hack */
+LUA_API void lua_setlevel (lua_State *from, lua_State *to);
+
+
+/*
+** {======================================================================
+** Debug API
+** =======================================================================
+*/
+
+
+/*
+** Event codes
+*/
+#define LUA_HOOKCALL 0
+#define LUA_HOOKRET 1
+#define LUA_HOOKLINE 2
+#define LUA_HOOKCOUNT 3
+#define LUA_HOOKTAILRET 4
+
+
+/*
+** Event masks
+*/
+#define LUA_MASKCALL (1 << LUA_HOOKCALL)
+#define LUA_MASKRET (1 << LUA_HOOKRET)
+#define LUA_MASKLINE (1 << LUA_HOOKLINE)
+#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
+
+typedef struct lua_Debug lua_Debug; /* activation record */
+
+
+/* Functions to be called by the debuger in specific events */
+typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
+
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
+LUA_API lua_Hook lua_gethook (lua_State *L);
+LUA_API int lua_gethookmask (lua_State *L);
+LUA_API int lua_gethookcount (lua_State *L);
+
+
+struct lua_Debug {
+ int event;
+ const char *name; /* (n) */
+ const char *namewhat; /* (n) `global', `local', `field', `method' */
+ const char *what; /* (S) `Lua', `C', `main', `tail' */
+ const char *source; /* (S) */
+ int currentline; /* (l) */
+ int nups; /* (u) number of upvalues */
+ int linedefined; /* (S) */
+ int lastlinedefined; /* (S) */
+ char short_src[LUA_IDSIZE]; /* (S) */
+ /* private part */
+ int i_ci; /* active function */
+};
+
+/* }====================================================================== */
+
+
+/******************************************************************************
+* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+
+#endif
diff --git a/lib/lua/src/luac.c b/lib/lua/src/luac.c
new file mode 100644
index 000000000..487715433
--- /dev/null
+++ b/lib/lua/src/luac.c
@@ -0,0 +1,202 @@
+/*
+** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $
+** Lua compiler (saves bytecodes to files; also list bytecodes)
+** See Copyright Notice in lua.h
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define luac_c
+#define LUA_CORE
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstring.h"
+#include "lundump.h"
+
+#define PROGNAME "luac" /* default program name */
+#define OUTPUT PROGNAME ".out" /* default output file */
+
+static int listing=0; /* list bytecodes? */
+static int dumping=1; /* dump bytecodes? */
+static int stripping=0; /* strip debug information? */
+static char Output[]={ OUTPUT }; /* default output file name */
+static const char* output=Output; /* actual output file name */
+static const char* progname=PROGNAME; /* actual program name */
+
+static void fatal(const char* message)
+{
+ fprintf(stderr,"%s: %s\n",progname,message);
+ exit(EXIT_FAILURE);
+}
+
+static void cannot(const char* what)
+{
+ fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
+ exit(EXIT_FAILURE);
+}
+
+static void usage(const char* message)
+{
+ if (*message=='-')
+ fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
+ else
+ fprintf(stderr,"%s: %s\n",progname,message);
+ fprintf(stderr,
+ "usage: %s [options] [filenames].\n"
+ "Available options are:\n"
+ " - process stdin\n"
+ " -l list\n"
+ " -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
+ " -p parse only\n"
+ " -s strip debug information\n"
+ " -v show version information\n"
+ " -- stop handling options\n",
+ progname,Output);
+ exit(EXIT_FAILURE);
+}
+
+#define IS(s) (strcmp(argv[i],s)==0)
+
+static int doargs(int argc, char* argv[])
+{
+ int i;
+ int version=0;
+ if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
+ for (i=1; i<argc; i++)
+ {
+ if (*argv[i]!='-') /* end of options; keep it */
+ break;
+ else if (IS("--")) /* end of options; skip it */
+ {
+ ++i;
+ if (version) ++version;
+ break;
+ }
+ else if (IS("-")) /* end of options; use stdin */
+ break;
+ else if (IS("-l")) /* list */
+ ++listing;
+ else if (IS("-o")) /* output file */
+ {
+ output=argv[++i];
+ if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument");
+ if (IS("-")) output=NULL;
+ }
+ else if (IS("-p")) /* parse only */
+ dumping=0;
+ else if (IS("-s")) /* strip debug information */
+ stripping=1;
+ else if (IS("-v")) /* show version */
+ ++version;
+ else /* unknown option */
+ usage(argv[i]);
+ }
+ if (i==argc && (listing || !dumping))
+ {
+ dumping=0;
+ argv[--i]=Output;
+ }
+ if (version)
+ {
+ printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT);
+ if (version==argc-1) exit(EXIT_SUCCESS);
+ }
+ return i;
+}
+
+#define toproto(L,i) (clvalue(L->top+(i))->l.p)
+
+static const Proto* combine(lua_State* L, int n)
+{
+ if (n==1)
+ return toproto(L,-1);
+ else
+ {
+ int i,pc;
+ Proto* f=luaF_newproto(L);
+ setptvalue2s(L,L->top,f); incr_top(L);
+ f->source=luaS_newliteral(L,"=(" PROGNAME ")");
+ f->maxstacksize=1;
+ pc=2*n+1;
+ f->code=luaM_newvector(L,pc,Instruction);
+ f->sizecode=pc;
+ f->p=luaM_newvector(L,n,Proto*);
+ f->sizep=n;
+ pc=0;
+ for (i=0; i<n; i++)
+ {
+ f->p[i]=toproto(L,i-n-1);
+ f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
+ f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
+ }
+ f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
+ return f;
+ }
+}
+
+static int writer(lua_State* L, const void* p, size_t size, void* u)
+{
+ UNUSED(L);
+ return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
+}
+
+struct Smain {
+ int argc;
+ char** argv;
+};
+
+static int pmain(lua_State* L)
+{
+ struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
+ int argc=s->argc;
+ char** argv=s->argv;
+ const Proto* f;
+ int i;
+ if (!lua_checkstack(L,argc)) fatal("too many input files");
+ for (i=0; i<argc; i++)
+ {
+ const char* filename=IS("-") ? NULL : argv[i];
+ if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
+ }
+ f=combine(L,argc);
+ if (listing) luaU_print(f,listing>1);
+ if (dumping)
+ {
+ FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
+ if (D==NULL) cannot("open");
+ lua_lock(L);
+ luaU_dump(L,f,writer,D,stripping);
+ lua_unlock(L);
+ if (ferror(D)) cannot("write");
+ if (fclose(D)) cannot("close");
+ }
+ return 0;
+}
+
+/*
+int main(int argc, char* argv[])
+{
+ lua_State* L;
+ struct Smain s;
+ int i=doargs(argc,argv);
+ argc-=i; argv+=i;
+ if (argc<=0) usage("no input files given");
+ L=lua_open();
+ if (L==NULL) fatal("not enough memory for state");
+ s.argc=argc;
+ s.argv=argv;
+ if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
+ lua_close(L);
+ return EXIT_SUCCESS;
+}
+*/
diff --git a/lib/lua/src/luaconf.h b/lib/lua/src/luaconf.h
new file mode 100644
index 000000000..e2cb26163
--- /dev/null
+++ b/lib/lua/src/luaconf.h
@@ -0,0 +1,763 @@
+/*
+** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $
+** Configuration file for Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lconfig_h
+#define lconfig_h
+
+#include <limits.h>
+#include <stddef.h>
+
+
+/*
+** ==================================================================
+** Search for "@@" to find all configurable definitions.
+** ===================================================================
+*/
+
+
+/*
+@@ LUA_ANSI controls the use of non-ansi features.
+** CHANGE it (define it) if you want Lua to avoid the use of any
+** non-ansi feature or library.
+*/
+#if defined(__STRICT_ANSI__)
+#define LUA_ANSI
+#endif
+
+
+#if !defined(LUA_ANSI) && defined(_WIN32)
+#define LUA_WIN
+#endif
+
+#if defined(LUA_USE_LINUX)
+#define LUA_USE_POSIX
+#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
+#define LUA_USE_READLINE /* needs some extra libraries */
+#endif
+
+#if defined(LUA_USE_MACOSX)
+#define LUA_USE_POSIX
+#define LUA_DL_DYLD /* does not need extra library */
+#endif
+
+
+
+/*
+@@ LUA_USE_POSIX includes all functionallity listed as X/Open System
+@* Interfaces Extension (XSI).
+** CHANGE it (define it) if your system is XSI compatible.
+*/
+#if defined(LUA_USE_POSIX)
+#define LUA_USE_MKSTEMP
+#define LUA_USE_ISATTY
+#define LUA_USE_POPEN
+#define LUA_USE_ULONGJMP
+#endif
+
+
+/*
+@@ LUA_PATH and LUA_CPATH are the names of the environment variables that
+@* Lua check to set its paths.
+@@ LUA_INIT is the name of the environment variable that Lua
+@* checks for initialization code.
+** CHANGE them if you want different names.
+*/
+#define LUA_PATH "LUA_PATH"
+#define LUA_CPATH "LUA_CPATH"
+#define LUA_INIT "LUA_INIT"
+
+
+/*
+@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
+@* Lua libraries.
+@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
+@* C libraries.
+** CHANGE them if your machine has a non-conventional directory
+** hierarchy or if you want to install your libraries in
+** non-conventional directories.
+*/
+#if defined(_WIN32)
+/*
+** In Windows, any exclamation mark ('!') in the path is replaced by the
+** path of the directory of the executable file of the current process.
+*/
+#define LUA_LDIR "!\\lua\\"
+#define LUA_CDIR "!\\"
+#define LUA_PATH_DEFAULT \
+ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
+ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
+#define LUA_CPATH_DEFAULT \
+ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
+
+#else
+#define LUA_ROOT "/usr/local/"
+#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
+#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
+#define LUA_PATH_DEFAULT \
+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
+ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
+#define LUA_CPATH_DEFAULT \
+ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
+#endif
+
+
+/*
+@@ LUA_DIRSEP is the directory separator (for submodules).
+** CHANGE it if your machine does not use "/" as the directory separator
+** and is not Windows. (On Windows Lua automatically uses "\".)
+*/
+#if defined(_WIN32)
+#define LUA_DIRSEP "\\"
+#else
+#define LUA_DIRSEP "/"
+#endif
+
+
+/*
+@@ LUA_PATHSEP is the character that separates templates in a path.
+@@ LUA_PATH_MARK is the string that marks the substitution points in a
+@* template.
+@@ LUA_EXECDIR in a Windows path is replaced by the executable's
+@* directory.
+@@ LUA_IGMARK is a mark to ignore all before it when bulding the
+@* luaopen_ function name.
+** CHANGE them if for some reason your system cannot use those
+** characters. (E.g., if one of those characters is a common character
+** in file/directory names.) Probably you do not need to change them.
+*/
+#define LUA_PATHSEP ";"
+#define LUA_PATH_MARK "?"
+#define LUA_EXECDIR "!"
+#define LUA_IGMARK "-"
+
+
+/*
+@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
+** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
+** machines, ptrdiff_t gives a good choice between int or long.)
+*/
+#define LUA_INTEGER ptrdiff_t
+
+
+/*
+@@ LUA_API is a mark for all core API functions.
+@@ LUALIB_API is a mark for all standard library functions.
+** CHANGE them if you need to define those functions in some special way.
+** For instance, if you want to create one Windows DLL with the core and
+** the libraries, you may want to use the following definition (define
+** LUA_BUILD_AS_DLL to get it).
+*/
+#if defined(LUA_BUILD_AS_DLL)
+
+#if defined(LUA_CORE) || defined(LUA_LIB)
+#define LUA_API __declspec(dllexport)
+#else
+#define LUA_API __declspec(dllimport)
+#endif
+
+#else
+
+#define LUA_API extern
+
+#endif
+
+/* more often than not the libs go together with the core */
+#define LUALIB_API LUA_API
+
+
+/*
+@@ LUAI_FUNC is a mark for all extern functions that are not to be
+@* exported to outside modules.
+@@ LUAI_DATA is a mark for all extern (const) variables that are not to
+@* be exported to outside modules.
+** CHANGE them if you need to mark them in some special way. Elf/gcc
+** (versions 3.2 and later) mark them as "hidden" to optimize access
+** when Lua is compiled as a shared library.
+*/
+#if defined(luaall_c)
+#define LUAI_FUNC static
+#define LUAI_DATA /* empty */
+
+#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
+ defined(__ELF__)
+#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
+#define LUAI_DATA LUAI_FUNC
+
+#else
+#define LUAI_FUNC extern
+#define LUAI_DATA extern
+#endif
+
+
+
+/*
+@@ LUA_QL describes how error messages quote program elements.
+** CHANGE it if you want a different appearance.
+*/
+#define LUA_QL(x) "'" x "'"
+#define LUA_QS LUA_QL("%s")
+
+
+/*
+@@ LUA_IDSIZE gives the maximum size for the description of the source
+@* of a function in debug information.
+** CHANGE it if you want a different size.
+*/
+#define LUA_IDSIZE 60
+
+
+/*
+** {==================================================================
+** Stand-alone configuration
+** ===================================================================
+*/
+
+#if defined(lua_c) || defined(luaall_c)
+
+/*
+@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
+@* is, whether we're running lua interactively).
+** CHANGE it if you have a better definition for non-POSIX/non-Windows
+** systems.
+*/
+#if defined(LUA_USE_ISATTY)
+#include <unistd.h>
+#define lua_stdin_is_tty() isatty(0)
+#elif defined(LUA_WIN)
+#include <io.h>
+#include <stdio.h>
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+#else
+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
+#endif
+
+
+/*
+@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
+@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
+** CHANGE them if you want different prompts. (You can also change the
+** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
+*/
+#define LUA_PROMPT "> "
+#define LUA_PROMPT2 ">> "
+
+
+/*
+@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
+** CHANGE it if your stand-alone interpreter has a different name and
+** your system is not able to detect that name automatically.
+*/
+#define LUA_PROGNAME "lua"
+
+
+/*
+@@ LUA_MAXINPUT is the maximum length for an input line in the
+@* stand-alone interpreter.
+** CHANGE it if you need longer lines.
+*/
+#define LUA_MAXINPUT 512
+
+
+/*
+@@ lua_readline defines how to show a prompt and then read a line from
+@* the standard input.
+@@ lua_saveline defines how to "save" a read line in a "history".
+@@ lua_freeline defines how to free a line read by lua_readline.
+** CHANGE them if you want to improve this functionality (e.g., by using
+** GNU readline and history facilities).
+*/
+#if defined(LUA_USE_READLINE)
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
+#define lua_saveline(L,idx) \
+ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
+ add_history(lua_tostring(L, idx)); /* add it to history */
+#define lua_freeline(L,b) ((void)L, free(b))
+#else
+#define lua_readline(L,b,p) \
+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
+#define lua_saveline(L,idx) { (void)L; (void)idx; }
+#define lua_freeline(L,b) { (void)L; (void)b; }
+#endif
+
+#endif
+
+/* }================================================================== */
+
+
+/*
+@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles
+@* as a percentage.
+** CHANGE it if you want the GC to run faster or slower (higher values
+** mean larger pauses which mean slower collection.) You can also change
+** this value dynamically.
+*/
+#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */
+
+
+/*
+@@ LUAI_GCMUL defines the default speed of garbage collection relative to
+@* memory allocation as a percentage.
+** CHANGE it if you want to change the granularity of the garbage
+** collection. (Higher values mean coarser collections. 0 represents
+** infinity, where each step performs a full collection.) You can also
+** change this value dynamically.
+*/
+#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
+
+
+
+/*
+@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.
+** CHANGE it (define it) if you want exact compatibility with the
+** behavior of setn/getn in Lua 5.0.
+*/
+#undef LUA_COMPAT_GETN
+
+/*
+@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.
+** CHANGE it to undefined as soon as you do not need a global 'loadlib'
+** function (the function is still available as 'package.loadlib').
+*/
+#undef LUA_COMPAT_LOADLIB
+
+/*
+@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.
+** CHANGE it to undefined as soon as your programs use only '...' to
+** access vararg parameters (instead of the old 'arg' table).
+*/
+#define LUA_COMPAT_VARARG
+
+/*
+@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.
+** CHANGE it to undefined as soon as your programs use 'math.fmod' or
+** the new '%' operator instead of 'math.mod'.
+*/
+#define LUA_COMPAT_MOD
+
+/*
+@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting
+@* facility.
+** CHANGE it to 2 if you want the old behaviour, or undefine it to turn
+** off the advisory error when nesting [[...]].
+*/
+#define LUA_COMPAT_LSTR 1
+
+/*
+@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.
+** CHANGE it to undefined as soon as you rename 'string.gfind' to
+** 'string.gmatch'.
+*/
+#define LUA_COMPAT_GFIND
+
+/*
+@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'
+@* behavior.
+** CHANGE it to undefined as soon as you replace to 'luaL_register'
+** your uses of 'luaL_openlib'
+*/
+#define LUA_COMPAT_OPENLIB
+
+
+
+/*
+@@ luai_apicheck is the assert macro used by the Lua-C API.
+** CHANGE luai_apicheck if you want Lua to perform some checks in the
+** parameters it gets from API calls. This may slow down the interpreter
+** a bit, but may be quite useful when debugging C code that interfaces
+** with Lua. A useful redefinition is to use assert.h.
+*/
+#if defined(LUA_USE_APICHECK)
+#include <assert.h>
+#define luai_apicheck(L,o) { (void)L; assert(o); }
+#else
+#define luai_apicheck(L,o) { (void)L; }
+#endif
+
+
+/*
+@@ LUAI_BITSINT defines the number of bits in an int.
+** CHANGE here if Lua cannot automatically detect the number of bits of
+** your machine. Probably you do not need to change this.
+*/
+/* avoid overflows in comparison */
+#if INT_MAX-20 < 32760
+#define LUAI_BITSINT 16
+#elif INT_MAX > 2147483640L
+/* int has at least 32 bits */
+#define LUAI_BITSINT 32
+#else
+#error "you must define LUA_BITSINT with number of bits in an integer"
+#endif
+
+
+/*
+@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
+@@ LUAI_INT32 is an signed integer with at least 32 bits.
+@@ LUAI_UMEM is an unsigned integer big enough to count the total
+@* memory used by Lua.
+@@ LUAI_MEM is a signed integer big enough to count the total memory
+@* used by Lua.
+** CHANGE here if for some weird reason the default definitions are not
+** good enough for your machine. (The definitions in the 'else'
+** part always works, but may waste space on machines with 64-bit
+** longs.) Probably you do not need to change this.
+*/
+#if LUAI_BITSINT >= 32
+#define LUAI_UINT32 unsigned int
+#define LUAI_INT32 int
+#define LUAI_MAXINT32 INT_MAX
+#define LUAI_UMEM size_t
+#define LUAI_MEM ptrdiff_t
+#else
+/* 16-bit ints */
+#define LUAI_UINT32 unsigned long
+#define LUAI_INT32 long
+#define LUAI_MAXINT32 LONG_MAX
+#define LUAI_UMEM unsigned long
+#define LUAI_MEM long
+#endif
+
+
+/*
+@@ LUAI_MAXCALLS limits the number of nested calls.
+** CHANGE it if you need really deep recursive calls. This limit is
+** arbitrary; its only purpose is to stop infinite recursion before
+** exhausting memory.
+*/
+#define LUAI_MAXCALLS 20000
+
+
+/*
+@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
+@* can use.
+** CHANGE it if you need lots of (Lua) stack space for your C
+** functions. This limit is arbitrary; its only purpose is to stop C
+** functions to consume unlimited stack space. (must be smaller than
+** -LUA_REGISTRYINDEX)
+*/
+#define LUAI_MAXCSTACK 8000
+
+
+
+/*
+** {==================================================================
+** CHANGE (to smaller values) the following definitions if your system
+** has a small C stack. (Or you may want to change them to larger
+** values if your system has a large C stack and these limits are
+** too rigid for you.) Some of these constants control the size of
+** stack-allocated arrays used by the compiler or the interpreter, while
+** others limit the maximum number of recursive calls that the compiler
+** or the interpreter can perform. Values too large may cause a C stack
+** overflow for some forms of deep constructs.
+** ===================================================================
+*/
+
+
+/*
+@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and
+@* syntactical nested non-terminals in a program.
+*/
+#define LUAI_MAXCCALLS 200
+
+
+/*
+@@ LUAI_MAXVARS is the maximum number of local variables per function
+@* (must be smaller than 250).
+*/
+#define LUAI_MAXVARS 200
+
+
+/*
+@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
+@* (must be smaller than 250).
+*/
+#define LUAI_MAXUPVALUES 60
+
+
+/*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+*/
+#define LUAL_BUFFERSIZE BUFSIZ
+
+/* }================================================================== */
+
+
+
+
+/*
+** {==================================================================
+@@ LUA_NUMBER is the type of numbers in Lua.
+** CHANGE the following definitions only if you want to build Lua
+** with a number type different from double. You may also need to
+** change lua_number2int & lua_number2integer.
+** ===================================================================
+*/
+
+#define LUA_NUMBER_DOUBLE
+#define LUA_NUMBER double
+
+/*
+@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+@* over a number.
+*/
+#define LUAI_UACNUMBER double
+
+
+/*
+@@ LUA_NUMBER_SCAN is the format for reading numbers.
+@@ LUA_NUMBER_FMT is the format for writing numbers.
+@@ lua_number2str converts a number to a string.
+@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+@@ lua_str2number converts a string to a number.
+*/
+#define LUA_NUMBER_SCAN "%lf"
+#define LUA_NUMBER_FMT "%.14g"
+#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
+#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+#define lua_str2number(s,p) strtod((s), (p))
+
+
+/*
+@@ The luai_num* macros define the primitive operations over numbers.
+*/
+#if defined(LUA_CORE)
+#include <math.h>
+#define luai_numadd(a,b) ((a)+(b))
+#define luai_numsub(a,b) ((a)-(b))
+#define luai_nummul(a,b) ((a)*(b))
+#define luai_numdiv(a,b) ((a)/(b))
+#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
+#define luai_numpow(a,b) (pow(a,b))
+#define luai_numunm(a) (-(a))
+#define luai_numeq(a,b) ((a)==(b))
+#define luai_numlt(a,b) ((a)<(b))
+#define luai_numle(a,b) ((a)<=(b))
+#define luai_numisnan(a) (!luai_numeq((a), (a)))
+#endif
+
+
+/*
+@@ lua_number2int is a macro to convert lua_Number to int.
+@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
+** CHANGE them if you know a faster way to convert a lua_Number to
+** int (with any rounding method and without throwing errors) in your
+** system. In Pentium machines, a naive typecast from double to int
+** in C is extremely slow, so any alternative is worth trying.
+*/
+
+/* On a Pentium, resort to a trick */
+#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
+ (defined(__i386) || defined (_M_IX86) || defined(__i386__))
+
+/* On a Microsoft compiler, use assembler */
+#if defined(_MSC_VER)
+
+#define lua_number2int(i,d) __asm fld d __asm fistp i
+#define lua_number2integer(i,n) lua_number2int(i, n)
+
+/* the next trick should work on any Pentium, but sometimes clashes
+ with a DirectX idiosyncrasy */
+#else
+
+union luai_Cast { double l_d; long l_l; };
+#define lua_number2int(i,d) \
+ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
+#define lua_number2integer(i,n) lua_number2int(i, n)
+
+#endif
+
+
+/* this option always works, but may be slow */
+#else
+#define lua_number2int(i,d) ((i)=(int)(d))
+#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
+
+#endif
+
+/* }================================================================== */
+
+
+/*
+@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
+** CHANGE it if your system requires alignments larger than double. (For
+** instance, if your system supports long doubles and they must be
+** aligned in 16-byte boundaries, then you should add long double in the
+** union.) Probably you do not need to change this.
+*/
+#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }
+
+
+/*
+@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.
+** CHANGE them if you prefer to use longjmp/setjmp even with C++
+** or if want/don't to use _longjmp/_setjmp instead of regular
+** longjmp/setjmp. By default, Lua handles errors with exceptions when
+** compiling as C++ code, with _longjmp/_setjmp when asked to use them,
+** and with longjmp/setjmp otherwise.
+*/
+#if defined(__cplusplus)
+/* C++ exceptions */
+#define LUAI_THROW(L,c) throw(c)
+#define LUAI_TRY(L,c,a) try { a } catch(...) \
+ { if ((c)->status == 0) (c)->status = -1; }
+#define luai_jmpbuf int /* dummy variable */
+
+#elif defined(LUA_USE_ULONGJMP)
+/* in Unix, try _longjmp/_setjmp (more efficient) */
+#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
+#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
+#define luai_jmpbuf jmp_buf
+
+#else
+/* default handling with long jumps */
+#define LUAI_THROW(L,c) longjmp((c)->b, 1)
+#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
+#define luai_jmpbuf jmp_buf
+
+#endif
+
+
+/*
+@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern
+@* can do during pattern-matching.
+** CHANGE it if you need more captures. This limit is arbitrary.
+*/
+#define LUA_MAXCAPTURES 32
+
+
+/*
+@@ lua_tmpnam is the function that the OS library uses to create a
+@* temporary name.
+@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.
+** CHANGE them if you have an alternative to tmpnam (which is considered
+** insecure) or if you want the original tmpnam anyway. By default, Lua
+** uses tmpnam except when POSIX is available, where it uses mkstemp.
+*/
+#if defined(loslib_c) || defined(luaall_c)
+
+#if defined(LUA_USE_MKSTEMP)
+#include <unistd.h>
+#define LUA_TMPNAMBUFSIZE 32
+#define lua_tmpnam(b,e) { \
+ strcpy(b, "/tmp/lua_XXXXXX"); \
+ e = mkstemp(b); \
+ if (e != -1) close(e); \
+ e = (e == -1); }
+
+#else
+#define LUA_TMPNAMBUFSIZE L_tmpnam
+#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
+#endif
+
+#endif
+
+
+/*
+@@ lua_popen spawns a new process connected to the current one through
+@* the file streams.
+** CHANGE it if you have a way to implement it in your system.
+*/
+#if defined(LUA_USE_POPEN)
+
+#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m))
+#define lua_pclose(L,file) ((void)L, (pclose(file) != -1))
+
+#elif defined(LUA_WIN)
+
+#define lua_popen(L,c,m) ((void)L, _popen(c,m))
+#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
+
+#else
+
+#define lua_popen(L,c,m) ((void)((void)c, m), \
+ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
+#define lua_pclose(L,file) ((void)((void)L, file), 0)
+
+#endif
+
+/*
+@@ LUA_DL_* define which dynamic-library system Lua should use.
+** CHANGE here if Lua has problems choosing the appropriate
+** dynamic-library system for your platform (either Windows' DLL, Mac's
+** dyld, or Unix's dlopen). If your system is some kind of Unix, there
+** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for
+** it. To use dlopen you also need to adapt the src/Makefile (probably
+** adding -ldl to the linker options), so Lua does not select it
+** automatically. (When you change the makefile to add -ldl, you must
+** also add -DLUA_USE_DLOPEN.)
+** If you do not want any kind of dynamic library, undefine all these
+** options.
+** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.
+*/
+#if defined(LUA_USE_DLOPEN)
+#define LUA_DL_DLOPEN
+#endif
+
+#if defined(LUA_WIN)
+#define LUA_DL_DLL
+#endif
+
+
+/*
+@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State
+@* (the data goes just *before* the lua_State pointer).
+** CHANGE (define) this if you really need that. This value must be
+** a multiple of the maximum alignment required for your machine.
+*/
+#define LUAI_EXTRASPACE 0
+
+
+/*
+@@ luai_userstate* allow user-specific actions on threads.
+** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
+** extra when a thread is created/deleted/resumed/yielded.
+*/
+#define luai_userstateopen(L) ((void)L)
+#define luai_userstateclose(L) ((void)L)
+#define luai_userstatethread(L,L1) ((void)L)
+#define luai_userstatefree(L) ((void)L)
+#define luai_userstateresume(L,n) ((void)L)
+#define luai_userstateyield(L,n) ((void)L)
+
+
+/*
+@@ LUA_INTFRMLEN is the length modifier for integer conversions
+@* in 'string.format'.
+@@ LUA_INTFRM_T is the integer type correspoding to the previous length
+@* modifier.
+** CHANGE them if your system supports long long or does not support long.
+*/
+
+#if defined(LUA_USELONGLONG)
+
+#define LUA_INTFRMLEN "ll"
+#define LUA_INTFRM_T long long
+
+#else
+
+#define LUA_INTFRMLEN "l"
+#define LUA_INTFRM_T long
+
+#endif
+
+
+
+/* =================================================================== */
+
+/*
+** Local configuration. You can use this space to add your redefinitions
+** without modifying the main part of the file.
+*/
+
+
+
+#endif
+
diff --git a/lib/lua/src/lualib.h b/lib/lua/src/lualib.h
new file mode 100644
index 000000000..469417f67
--- /dev/null
+++ b/lib/lua/src/lualib.h
@@ -0,0 +1,53 @@
+/*
+** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua standard libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lualib_h
+#define lualib_h
+
+#include "lua.h"
+
+
+/* Key to file-handle type */
+#define LUA_FILEHANDLE "FILE*"
+
+
+#define LUA_COLIBNAME "coroutine"
+LUALIB_API int (luaopen_base) (lua_State *L);
+
+#define LUA_TABLIBNAME "table"
+LUALIB_API int (luaopen_table) (lua_State *L);
+
+#define LUA_IOLIBNAME "io"
+LUALIB_API int (luaopen_io) (lua_State *L);
+
+#define LUA_OSLIBNAME "os"
+LUALIB_API int (luaopen_os) (lua_State *L);
+
+#define LUA_STRLIBNAME "string"
+LUALIB_API int (luaopen_string) (lua_State *L);
+
+#define LUA_MATHLIBNAME "math"
+LUALIB_API int (luaopen_math) (lua_State *L);
+
+#define LUA_DBLIBNAME "debug"
+LUALIB_API int (luaopen_debug) (lua_State *L);
+
+#define LUA_LOADLIBNAME "package"
+LUALIB_API int (luaopen_package) (lua_State *L);
+
+
+/* open all previous libraries */
+LUALIB_API void (luaL_openlibs) (lua_State *L);
+
+
+
+#ifndef lua_assert
+#define lua_assert(x) ((void)0)
+#endif
+
+
+#endif
diff --git a/lib/lua/src/lundump.c b/lib/lua/src/lundump.c
new file mode 100644
index 000000000..8010a4579
--- /dev/null
+++ b/lib/lua/src/lundump.c
@@ -0,0 +1,227 @@
+/*
+** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $
+** load precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#include <string.h>
+
+#define lundump_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstring.h"
+#include "lundump.h"
+#include "lzio.h"
+
+typedef struct {
+ lua_State* L;
+ ZIO* Z;
+ Mbuffer* b;
+ const char* name;
+} LoadState;
+
+#ifdef LUAC_TRUST_BINARIES
+#define IF(c,s)
+#define error(S,s)
+#else
+#define IF(c,s) if (c) error(S,s)
+
+static void error(LoadState* S, const char* why)
+{
+ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
+ luaD_throw(S->L,LUA_ERRSYNTAX);
+}
+#endif
+
+#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
+#define LoadByte(S) (lu_byte)LoadChar(S)
+#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
+#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
+
+static void LoadBlock(LoadState* S, void* b, size_t size)
+{
+ size_t r=luaZ_read(S->Z,b,size);
+ IF (r!=0, "unexpected end");
+}
+
+static int LoadChar(LoadState* S)
+{
+ char x;
+ LoadVar(S,x);
+ return x;
+}
+
+static int LoadInt(LoadState* S)
+{
+ int x;
+ LoadVar(S,x);
+ IF (x<0, "bad integer");
+ return x;
+}
+
+static lua_Number LoadNumber(LoadState* S)
+{
+ lua_Number x;
+ LoadVar(S,x);
+ return x;
+}
+
+static TString* LoadString(LoadState* S)
+{
+ size_t size;
+ LoadVar(S,size);
+ if (size==0)
+ return NULL;
+ else
+ {
+ char* s=luaZ_openspace(S->L,S->b,size);
+ LoadBlock(S,s,size);
+ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
+ }
+}
+
+static void LoadCode(LoadState* S, Proto* f)
+{
+ int n=LoadInt(S);
+ f->code=luaM_newvector(S->L,n,Instruction);
+ f->sizecode=n;
+ LoadVector(S,f->code,n,sizeof(Instruction));
+}
+
+static Proto* LoadFunction(LoadState* S, TString* p);
+
+static void LoadConstants(LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->k=luaM_newvector(S->L,n,TValue);
+ f->sizek=n;
+ for (i=0; i<n; i++) setnilvalue(&f->k[i]);
+ for (i=0; i<n; i++)
+ {
+ TValue* o=&f->k[i];
+ int t=LoadChar(S);
+ switch (t)
+ {
+ case LUA_TNIL:
+ setnilvalue(o);
+ break;
+ case LUA_TBOOLEAN:
+ setbvalue(o,LoadChar(S)!=0);
+ break;
+ case LUA_TNUMBER:
+ setnvalue(o,LoadNumber(S));
+ break;
+ case LUA_TSTRING:
+ setsvalue2n(S->L,o,LoadString(S));
+ break;
+ default:
+ error(S,"bad constant");
+ break;
+ }
+ }
+ n=LoadInt(S);
+ f->p=luaM_newvector(S->L,n,Proto*);
+ f->sizep=n;
+ for (i=0; i<n; i++) f->p[i]=NULL;
+ for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
+}
+
+static void LoadDebug(LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->lineinfo=luaM_newvector(S->L,n,int);
+ f->sizelineinfo=n;
+ LoadVector(S,f->lineinfo,n,sizeof(int));
+ n=LoadInt(S);
+ f->locvars=luaM_newvector(S->L,n,LocVar);
+ f->sizelocvars=n;
+ for (i=0; i<n; i++) f->locvars[i].varname=NULL;
+ for (i=0; i<n; i++)
+ {
+ f->locvars[i].varname=LoadString(S);
+ f->locvars[i].startpc=LoadInt(S);
+ f->locvars[i].endpc=LoadInt(S);
+ }
+ n=LoadInt(S);
+ f->upvalues=luaM_newvector(S->L,n,TString*);
+ f->sizeupvalues=n;
+ for (i=0; i<n; i++) f->upvalues[i]=NULL;
+ for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
+}
+
+static Proto* LoadFunction(LoadState* S, TString* p)
+{
+ Proto* f;
+ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
+ f=luaF_newproto(S->L);
+ setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
+ f->source=LoadString(S); if (f->source==NULL) f->source=p;
+ f->linedefined=LoadInt(S);
+ f->lastlinedefined=LoadInt(S);
+ f->nups=LoadByte(S);
+ f->numparams=LoadByte(S);
+ f->is_vararg=LoadByte(S);
+ f->maxstacksize=LoadByte(S);
+ LoadCode(S,f);
+ LoadConstants(S,f);
+ LoadDebug(S,f);
+ IF (!luaG_checkcode(f), "bad code");
+ S->L->top--;
+ S->L->nCcalls--;
+ return f;
+}
+
+static void LoadHeader(LoadState* S)
+{
+ char h[LUAC_HEADERSIZE];
+ char s[LUAC_HEADERSIZE];
+ luaU_header(h);
+ LoadBlock(S,s,LUAC_HEADERSIZE);
+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+}
+
+/*
+** load precompiled chunk
+*/
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
+{
+ LoadState S;
+ if (*name=='@' || *name=='=')
+ S.name=name+1;
+ else if (*name==LUA_SIGNATURE[0])
+ S.name="binary string";
+ else
+ S.name=name;
+ S.L=L;
+ S.Z=Z;
+ S.b=buff;
+ LoadHeader(&S);
+ return LoadFunction(&S,luaS_newliteral(L,"=?"));
+}
+
+/*
+* make header
+*/
+void luaU_header (char* h)
+{
+ int x=1;
+ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
+ h+=sizeof(LUA_SIGNATURE)-1;
+ *h++=(char)LUAC_VERSION;
+ *h++=(char)LUAC_FORMAT;
+ *h++=(char)*(char*)&x; /* endianness */
+ *h++=(char)sizeof(int);
+ *h++=(char)sizeof(size_t);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
+}
diff --git a/lib/lua/src/lundump.h b/lib/lua/src/lundump.h
new file mode 100644
index 000000000..c80189dbf
--- /dev/null
+++ b/lib/lua/src/lundump.h
@@ -0,0 +1,36 @@
+/*
+** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
+** load precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lundump_h
+#define lundump_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+/* load one chunk; from lundump.c */
+LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
+
+/* make header; from lundump.c */
+LUAI_FUNC void luaU_header (char* h);
+
+/* dump one chunk; from ldump.c */
+LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+
+#ifdef luac_c
+/* print one chunk; from print.c */
+LUAI_FUNC void luaU_print (const Proto* f, int full);
+#endif
+
+/* for header of binary files -- this is Lua 5.1 */
+#define LUAC_VERSION 0x51
+
+/* for header of binary files -- this is the official format */
+#define LUAC_FORMAT 0
+
+/* size of header of binary files */
+#define LUAC_HEADERSIZE 12
+
+#endif
diff --git a/lib/lua/src/lvm.c b/lib/lua/src/lvm.c
new file mode 100644
index 000000000..ee3256ab9
--- /dev/null
+++ b/lib/lua/src/lvm.c
@@ -0,0 +1,763 @@
+/*
+** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define lvm_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+
+
+/* limit for table tag-method chains (to avoid loops) */
+#define MAXTAGLOOP 100
+
+
+const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
+ lua_Number num;
+ if (ttisnumber(obj)) return obj;
+ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+ setnvalue(n, num);
+ return n;
+ }
+ else
+ return NULL;
+}
+
+
+int luaV_tostring (lua_State *L, StkId obj) {
+ if (!ttisnumber(obj))
+ return 0;
+ else {
+ char s[LUAI_MAXNUMBER2STR];
+ lua_Number n = nvalue(obj);
+ lua_number2str(s, n);
+ setsvalue2s(L, obj, luaS_new(L, s));
+ return 1;
+ }
+}
+
+
+static void traceexec (lua_State *L, const Instruction *pc) {
+ lu_byte mask = L->hookmask;
+ const Instruction *oldpc = L->savedpc;
+ L->savedpc = pc;
+ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
+ resethookcount(L);
+ luaD_callhook(L, LUA_HOOKCOUNT, -1);
+ }
+ if (mask & LUA_MASKLINE) {
+ Proto *p = ci_func(L->ci)->l.p;
+ int npc = pcRel(pc, p);
+ int newline = getline(p, npc);
+ /* call linehook when enter a new function, when jump back (loop),
+ or when enter a new line */
+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
+ luaD_callhook(L, LUA_HOOKLINE, newline);
+ }
+}
+
+
+static void callTMres (lua_State *L, StkId res, const TValue *f,
+ const TValue *p1, const TValue *p2) {
+ ptrdiff_t result = savestack(L, res);
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ luaD_checkstack(L, 3);
+ L->top += 3;
+ luaD_call(L, L->top - 3, 1);
+ res = restorestack(L, result);
+ L->top--;
+ setobjs2s(L, res, L->top);
+}
+
+
+
+static void callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, const TValue *p3) {
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ setobj2s(L, L->top+3, p3); /* 3th argument */
+ luaD_checkstack(L, 4);
+ L->top += 4;
+ luaD_call(L, L->top - 4, 0);
+}
+
+
+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
+ if (ttistable(t)) { /* `t' is a table? */
+ Table *h = hvalue(t);
+ const TValue *res = luaH_get(h, key); /* do a primitive get */
+ if (!ttisnil(res) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
+ setobj2s(L, val, res);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ callTMres(L, val, tm, t, key);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
+ }
+ luaG_runerror(L, "loop in gettable");
+}
+
+
+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
+ if (ttistable(t)) { /* `t' is a table? */
+ Table *h = hvalue(t);
+ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
+ if (!ttisnil(oldval) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
+ setobj2t(L, oldval, val);
+ luaC_barriert(L, h, val);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ callTM(L, tm, t, key, val);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
+ }
+ luaG_runerror(L, "loop in settable");
+}
+
+
+static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event) {
+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
+ if (ttisnil(tm))
+ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
+ if (ttisnil(tm)) return 0;
+ callTMres(L, res, tm, p1, p2);
+ return 1;
+}
+
+
+static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
+ TMS event) {
+ const TValue *tm1 = fasttm(L, mt1, event);
+ const TValue *tm2;
+ if (tm1 == NULL) return NULL; /* no metamethod */
+ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
+ tm2 = fasttm(L, mt2, event);
+ if (tm2 == NULL) return NULL; /* no metamethod */
+ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */
+ return tm1;
+ return NULL;
+}
+
+
+static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
+ TMS event) {
+ const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
+ const TValue *tm2;
+ if (ttisnil(tm1)) return -1; /* no metamethod? */
+ tm2 = luaT_gettmbyobj(L, p2, event);
+ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
+ return -1;
+ callTMres(L, L->top, tm1, p1, p2);
+ return !l_isfalse(L->top);
+}
+
+
+static int l_strcmp (const TString *ls, const TString *rs) {
+ const char *l = getstr(ls);
+ size_t ll = ls->tsv.len;
+ const char *r = getstr(rs);
+ size_t lr = rs->tsv.len;
+ for (;;) {
+ int temp = strcoll(l, r);
+ if (temp != 0) return temp;
+ else { /* strings are equal up to a `\0' */
+ size_t len = strlen(l); /* index of first `\0' in both strings */
+ if (len == lr) /* r is finished? */
+ return (len == ll) ? 0 : 1;
+ else if (len == ll) /* l is finished? */
+ return -1; /* l is smaller than r (because r is not finished) */
+ /* both strings longer than `len'; go on comparing (after the `\0') */
+ len++;
+ l += len; ll -= len; r += len; lr -= len;
+ }
+ }
+}
+
+
+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+ if (ttype(l) != ttype(r))
+ return luaG_ordererror(L, l, r);
+ else if (ttisnumber(l))
+ return luai_numlt(nvalue(l), nvalue(r));
+ else if (ttisstring(l))
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
+ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+ return res;
+ return luaG_ordererror(L, l, r);
+}
+
+
+static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+ if (ttype(l) != ttype(r))
+ return luaG_ordererror(L, l, r);
+ else if (ttisnumber(l))
+ return luai_numle(nvalue(l), nvalue(r));
+ else if (ttisstring(l))
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
+ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
+ return res;
+ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
+ return !res;
+ return luaG_ordererror(L, l, r);
+}
+
+
+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
+ const TValue *tm;
+ lua_assert(ttype(t1) == ttype(t2));
+ switch (ttype(t1)) {
+ case LUA_TNIL: return 1;
+ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
+ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
+ case LUA_TUSERDATA: {
+ if (uvalue(t1) == uvalue(t2)) return 1;
+ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+ TM_EQ);
+ break; /* will try TM */
+ }
+ case LUA_TTABLE: {
+ if (hvalue(t1) == hvalue(t2)) return 1;
+ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+ default: return gcvalue(t1) == gcvalue(t2);
+ }
+ if (tm == NULL) return 0; /* no TM? */
+ callTMres(L, L->top, tm, t1, t2); /* call TM */
+ return !l_isfalse(L->top);
+}
+
+
+void luaV_concat (lua_State *L, int total, int last) {
+ do {
+ StkId top = L->base + last + 1;
+ int n = 2; /* number of elements handled in this pass (at least 2) */
+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
+ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
+ luaG_concaterror(L, top-2, top-1);
+ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
+ (void)tostring(L, top - 2); /* result is first op (as string) */
+ else {
+ /* at least two string values; get as many as possible */
+ size_t tl = tsvalue(top-1)->len;
+ char *buffer;
+ int i;
+ /* collect total length */
+ for (n = 1; n < total && tostring(L, top-n-1); n++) {
+ size_t l = tsvalue(top-n-1)->len;
+ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
+ tl += l;
+ }
+ buffer = luaZ_openspace(L, &G(L)->buff, tl);
+ tl = 0;
+ for (i=n; i>0; i--) { /* concat all strings */
+ size_t l = tsvalue(top-i)->len;
+ memcpy(buffer+tl, svalue(top-i), l);
+ tl += l;
+ }
+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
+ }
+ total -= n-1; /* got `n' strings to create 1 new */
+ last -= n-1;
+ } while (total > 1); /* repeat until only 1 result left */
+}
+
+
+static void Arith (lua_State *L, StkId ra, const TValue *rb,
+ const TValue *rc, TMS op) {
+ TValue tempb, tempc;
+ const TValue *b, *c;
+ if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+ (c = luaV_tonumber(rc, &tempc)) != NULL) {
+ lua_Number nb = nvalue(b), nc = nvalue(c);
+ switch (op) {
+ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
+ default: lua_assert(0); break;
+ }
+ }
+ else if (!call_binTM(L, rb, rc, ra, op))
+ luaG_aritherror(L, rb, rc);
+}
+
+
+
+/*
+** some macros for common tasks in `luaV_execute'
+*/
+
+#define runtime_check(L, c) { if (!(c)) break; }
+
+#define RA(i) (base+GETARG_A(i))
+/* to be used after possible stack reallocation */
+#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
+#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
+#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
+#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
+#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
+
+
+#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);}
+
+
+#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
+
+
+#define arith_op(op,tm) { \
+ TValue *rb = RKB(i); \
+ TValue *rc = RKC(i); \
+ if (ttisnumber(rb) && ttisnumber(rc)) { \
+ lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+ setnvalue(ra, op(nb, nc)); \
+ } \
+ else \
+ Protect(Arith(L, ra, rb, rc, tm)); \
+ }
+
+
+
+void luaV_execute (lua_State *L, int nexeccalls) {
+ LClosure *cl;
+ StkId base;
+ TValue *k;
+ const Instruction *pc;
+ reentry: /* entry point */
+ lua_assert(isLua(L->ci));
+ pc = L->savedpc;
+ cl = &clvalue(L->ci->func)->l;
+ base = L->base;
+ k = cl->p->k;
+ /* main loop of interpreter */
+ for (;;) {
+ const Instruction i = *pc++;
+ StkId ra;
+ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
+ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
+ traceexec(L, pc);
+ if (L->status == LUA_YIELD) { /* did hook yield? */
+ L->savedpc = pc - 1;
+ return;
+ }
+ base = L->base;
+ }
+ /* warning!! several calls may realloc the stack and invalidate `ra' */
+ ra = RA(i);
+ lua_assert(base == L->base && L->base == L->ci->base);
+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
+ switch (GET_OPCODE(i)) {
+ case OP_MOVE: {
+ setobjs2s(L, ra, RB(i));
+ continue;
+ }
+ case OP_LOADK: {
+ setobj2s(L, ra, KBx(i));
+ continue;
+ }
+ case OP_LOADBOOL: {
+ setbvalue(ra, GETARG_B(i));
+ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
+ continue;
+ }
+ case OP_LOADNIL: {
+ TValue *rb = RB(i);
+ do {
+ setnilvalue(rb--);
+ } while (rb >= ra);
+ continue;
+ }
+ case OP_GETUPVAL: {
+ int b = GETARG_B(i);
+ setobj2s(L, ra, cl->upvals[b]->v);
+ continue;
+ }
+ case OP_GETGLOBAL: {
+ TValue g;
+ TValue *rb = KBx(i);
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(rb));
+ Protect(luaV_gettable(L, &g, rb, ra));
+ continue;
+ }
+ case OP_GETTABLE: {
+ Protect(luaV_gettable(L, RB(i), RKC(i), ra));
+ continue;
+ }
+ case OP_SETGLOBAL: {
+ TValue g;
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(KBx(i)));
+ Protect(luaV_settable(L, &g, KBx(i), ra));
+ continue;
+ }
+ case OP_SETUPVAL: {
+ UpVal *uv = cl->upvals[GETARG_B(i)];
+ setobj(L, uv->v, ra);
+ luaC_barrier(L, uv, ra);
+ continue;
+ }
+ case OP_SETTABLE: {
+ Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
+ continue;
+ }
+ case OP_NEWTABLE: {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+ case OP_SELF: {
+ StkId rb = RB(i);
+ setobjs2s(L, ra+1, rb);
+ Protect(luaV_gettable(L, rb, RKC(i), ra));
+ continue;
+ }
+ case OP_ADD: {
+ arith_op(luai_numadd, TM_ADD);
+ continue;
+ }
+ case OP_SUB: {
+ arith_op(luai_numsub, TM_SUB);
+ continue;
+ }
+ case OP_MUL: {
+ arith_op(luai_nummul, TM_MUL);
+ continue;
+ }
+ case OP_DIV: {
+ arith_op(luai_numdiv, TM_DIV);
+ continue;
+ }
+ case OP_MOD: {
+ arith_op(luai_nummod, TM_MOD);
+ continue;
+ }
+ case OP_POW: {
+ arith_op(luai_numpow, TM_POW);
+ continue;
+ }
+ case OP_UNM: {
+ TValue *rb = RB(i);
+ if (ttisnumber(rb)) {
+ lua_Number nb = nvalue(rb);
+ setnvalue(ra, luai_numunm(nb));
+ }
+ else {
+ Protect(Arith(L, ra, rb, rb, TM_UNM));
+ }
+ continue;
+ }
+ case OP_NOT: {
+ int res = l_isfalse(RB(i)); /* next assignment may change this value */
+ setbvalue(ra, res);
+ continue;
+ }
+ case OP_LEN: {
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+ setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
+ break;
+ }
+ case LUA_TSTRING: {
+ setnvalue(ra, cast_num(tsvalue(rb)->len));
+ break;
+ }
+ default: { /* try metamethod */
+ Protect(
+ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
+ luaG_typeerror(L, rb, "get length of");
+ )
+ }
+ }
+ continue;
+ }
+ case OP_CONCAT: {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
+ setobjs2s(L, RA(i), base+b);
+ continue;
+ }
+ case OP_JMP: {
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+ case OP_EQ: {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ Protect(
+ if (equalobj(L, rb, rc) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_LT: {
+ Protect(
+ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_LE: {
+ Protect(
+ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_TEST: {
+ if (l_isfalse(ra) != GETARG_C(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ pc++;
+ continue;
+ }
+ case OP_TESTSET: {
+ TValue *rb = RB(i);
+ if (l_isfalse(rb) != GETARG_C(i)) {
+ setobjs2s(L, ra, rb);
+ dojump(L, pc, GETARG_sBx(*pc));
+ }
+ pc++;
+ continue;
+ }
+ case OP_CALL: {
+ int b = GETARG_B(i);
+ int nresults = GETARG_C(i) - 1;
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+ switch (luaD_precall(L, ra, nresults)) {
+ case PCRLUA: {
+ nexeccalls++;
+ goto reentry; /* restart luaV_execute over new Lua function */
+ }
+ case PCRC: {
+ /* it was a C function (`precall' called it); adjust results */
+ if (nresults >= 0) L->top = L->ci->top;
+ base = L->base;
+ continue;
+ }
+ default: {
+ return; /* yield */
+ }
+ }
+ }
+ case OP_TAILCALL: {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
+ switch (luaD_precall(L, ra, LUA_MULTRET)) {
+ case PCRLUA: {
+ /* tail call: put new frame in place of previous one */
+ CallInfo *ci = L->ci - 1; /* previous frame */
+ int aux;
+ StkId func = ci->func;
+ StkId pfunc = (ci+1)->func; /* previous function index */
+ if (L->openupval) luaF_close(L, ci->base);
+ L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
+ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
+ setobjs2s(L, func+aux, pfunc+aux);
+ ci->top = L->top = func+aux; /* correct top */
+ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
+ ci->savedpc = L->savedpc;
+ ci->tailcalls++; /* one more call lost */
+ L->ci--; /* remove new frame */
+ goto reentry;
+ }
+ case PCRC: { /* it was a C function (`precall' called it) */
+ base = L->base;
+ continue;
+ }
+ default: {
+ return; /* yield */
+ }
+ }
+ }
+ case OP_RETURN: {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b-1;
+ if (L->openupval) luaF_close(L, base);
+ L->savedpc = pc;
+ b = luaD_poscall(L, ra);
+ if (--nexeccalls == 0) /* was previous function running `here'? */
+ return; /* no: return */
+ else { /* yes: continue its execution */
+ if (b) L->top = L->ci->top;
+ lua_assert(isLua(L->ci));
+ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);
+ goto reentry;
+ }
+ }
+ case OP_FORLOOP: {
+ lua_Number step = nvalue(ra+2);
+ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+ lua_Number limit = nvalue(ra+1);
+ if (luai_numlt(0, step) ? luai_numle(idx, limit)
+ : luai_numle(limit, idx)) {
+ dojump(L, pc, GETARG_sBx(i)); /* jump back */
+ setnvalue(ra, idx); /* update internal index... */
+ setnvalue(ra+3, idx); /* ...and external index */
+ }
+ continue;
+ }
+ case OP_FORPREP: {
+ const TValue *init = ra;
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->savedpc = pc; /* next steps may throw errors */
+ if (!tonumber(init, ra))
+ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+ else if (!tonumber(plimit, ra+1))
+ luaG_runerror(L, LUA_QL("for") " limit must be a number");
+ else if (!tonumber(pstep, ra+2))
+ luaG_runerror(L, LUA_QL("for") " step must be a number");
+ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+ case OP_TFORLOOP: {
+ StkId cb = ra + 3; /* call base */
+ setobjs2s(L, cb+2, ra+2);
+ setobjs2s(L, cb+1, ra+1);
+ setobjs2s(L, cb, ra);
+ L->top = cb+3; /* func. + 2 args (state and index) */
+ Protect(luaD_call(L, cb, GETARG_C(i)));
+ L->top = L->ci->top;
+ cb = RA(i) + 3; /* previous call may change the stack */
+ if (!ttisnil(cb)) { /* continue loop? */
+ setobjs2s(L, cb-1, cb); /* save control variable */
+ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */
+ }
+ pc++;
+ continue;
+ }
+ case OP_SETLIST: {
+ int n = GETARG_B(i);
+ int c = GETARG_C(i);
+ int last;
+ Table *h;
+ if (n == 0) {
+ n = cast_int(L->top - ra) - 1;
+ L->top = L->ci->top;
+ }
+ if (c == 0) c = cast_int(*pc++);
+ runtime_check(L, ttistable(ra));
+ h = hvalue(ra);
+ last = ((c-1)*LFIELDS_PER_FLUSH) + n;
+ if (last > h->sizearray) /* needs more space? */
+ luaH_resizearray(L, h, last); /* pre-alloc it at once */
+ for (; n > 0; n--) {
+ TValue *val = ra+n;
+ setobj2t(L, luaH_setnum(L, h, last--), val);
+ luaC_barriert(L, h, val);
+ }
+ continue;
+ }
+ case OP_CLOSE: {
+ luaF_close(L, ra);
+ continue;
+ }
+ case OP_CLOSURE: {
+ Proto *p;
+ Closure *ncl;
+ int nup, j;
+ p = cl->p->p[GETARG_Bx(i)];
+ nup = p->nups;
+ ncl = luaF_newLclosure(L, nup, cl->env);
+ ncl->l.p = p;
+ for (j=0; j<nup; j++, pc++) {
+ if (GET_OPCODE(*pc) == OP_GETUPVAL)
+ ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
+ else {
+ lua_assert(GET_OPCODE(*pc) == OP_MOVE);
+ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
+ }
+ }
+ setclvalue(L, ra, ncl);
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+ case OP_VARARG: {
+ int b = GETARG_B(i) - 1;
+ int j;
+ CallInfo *ci = L->ci;
+ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
+ if (b == LUA_MULTRET) {
+ Protect(luaD_checkstack(L, n));
+ ra = RA(i); /* previous call may change the stack */
+ b = n;
+ L->top = ra + n;
+ }
+ for (j = 0; j < b; j++) {
+ if (j < n) {
+ setobjs2s(L, ra + j, ci->base - n + j);
+ }
+ else {
+ setnilvalue(ra + j);
+ }
+ }
+ continue;
+ }
+ }
+ }
+}
+
diff --git a/lib/lua/src/lvm.h b/lib/lua/src/lvm.h
new file mode 100644
index 000000000..bfe4f5678
--- /dev/null
+++ b/lib/lua/src/lvm.h
@@ -0,0 +1,36 @@
+/*
+** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lvm_h
+#define lvm_h
+
+
+#include "ldo.h"
+#include "lobject.h"
+#include "ltm.h"
+
+
+#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+
+#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
+ (((o) = luaV_tonumber(o,n)) != NULL))
+
+#define equalobj(L,o1,o2) \
+ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
+
+
+LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
+LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
+LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
+LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
+ StkId val);
+LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
+ StkId val);
+LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);
+LUAI_FUNC void luaV_concat (lua_State *L, int total, int last);
+
+#endif
diff --git a/lib/lua/src/lzio.c b/lib/lua/src/lzio.c
new file mode 100644
index 000000000..293edd59b
--- /dev/null
+++ b/lib/lua/src/lzio.c
@@ -0,0 +1,82 @@
+/*
+** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
+** a generic input stream interface
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lzio_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "llimits.h"
+#include "lmem.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+int luaZ_fill (ZIO *z) {
+ size_t size;
+ lua_State *L = z->L;
+ const char *buff;
+ lua_unlock(L);
+ buff = z->reader(L, z->data, &size);
+ lua_lock(L);
+ if (buff == NULL || size == 0) return EOZ;
+ z->n = size - 1;
+ z->p = buff;
+ return char2int(*(z->p++));
+}
+
+
+int luaZ_lookahead (ZIO *z) {
+ if (z->n == 0) {
+ if (luaZ_fill(z) == EOZ)
+ return EOZ;
+ else {
+ z->n++; /* luaZ_fill removed first byte; put back it */
+ z->p--;
+ }
+ }
+ return char2int(*z->p);
+}
+
+
+void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
+ z->L = L;
+ z->reader = reader;
+ z->data = data;
+ z->n = 0;
+ z->p = NULL;
+}
+
+
+/* --------------------------------------------------------------- read --- */
+size_t luaZ_read (ZIO *z, void *b, size_t n) {
+ while (n) {
+ size_t m;
+ if (luaZ_lookahead(z) == EOZ)
+ return n; /* return number of missing bytes */
+ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
+ memcpy(b, z->p, m);
+ z->n -= m;
+ z->p += m;
+ b = (char *)b + m;
+ n -= m;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
+ if (n > buff->buffsize) {
+ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
+ luaZ_resizebuffer(L, buff, n);
+ }
+ return buff->buffer;
+}
+
+
diff --git a/lib/lua/src/lzio.h b/lib/lua/src/lzio.h
new file mode 100644
index 000000000..51d695d8c
--- /dev/null
+++ b/lib/lua/src/lzio.h
@@ -0,0 +1,67 @@
+/*
+** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $
+** Buffered streams
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lzio_h
+#define lzio_h
+
+#include "lua.h"
+
+#include "lmem.h"
+
+
+#define EOZ (-1) /* end of stream */
+
+typedef struct Zio ZIO;
+
+#define char2int(c) cast(int, cast(unsigned char, (c)))
+
+#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
+
+typedef struct Mbuffer {
+ char *buffer;
+ size_t n;
+ size_t buffsize;
+} Mbuffer;
+
+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
+
+#define luaZ_buffer(buff) ((buff)->buffer)
+#define luaZ_sizebuffer(buff) ((buff)->buffsize)
+#define luaZ_bufflen(buff) ((buff)->n)
+
+#define luaZ_resetbuffer(buff) ((buff)->n = 0)
+
+
+#define luaZ_resizebuffer(L, buff, size) \
+ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+ (buff)->buffsize = size)
+
+#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
+
+
+LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
+LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
+ void *data);
+LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
+LUAI_FUNC int luaZ_lookahead (ZIO *z);
+
+
+
+/* --------- Private Part ------------------ */
+
+struct Zio {
+ size_t n; /* bytes still unread */
+ const char *p; /* current position in buffer */
+ lua_Reader reader;
+ void* data; /* additional data */
+ lua_State *L; /* Lua state (for reader) */
+};
+
+
+LUAI_FUNC int luaZ_fill (ZIO *z);
+
+#endif
diff --git a/lib/lua/src/print.c b/lib/lua/src/print.c
new file mode 100644
index 000000000..e240cfc3c
--- /dev/null
+++ b/lib/lua/src/print.c
@@ -0,0 +1,227 @@
+/*
+** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $
+** print bytecodes
+** See Copyright Notice in lua.h
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+
+#define luac_c
+#define LUA_CORE
+
+#include "ldebug.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lundump.h"
+
+#define PrintFunction luaU_print
+
+#define Sizeof(x) ((int)sizeof(x))
+#define VOID(p) ((const void*)(p))
+
+static void PrintString(const TString* ts)
+{
+ const char* s=getstr(ts);
+ size_t i,n=ts->tsv.len;
+ putchar('"');
+ for (i=0; i<n; i++)
+ {
+ int c=s[i];
+ switch (c)
+ {
+ case '"': printf("\\\""); break;
+ case '\\': printf("\\\\"); break;
+ case '\a': printf("\\a"); break;
+ case '\b': printf("\\b"); break;
+ case '\f': printf("\\f"); break;
+ case '\n': printf("\\n"); break;
+ case '\r': printf("\\r"); break;
+ case '\t': printf("\\t"); break;
+ case '\v': printf("\\v"); break;
+ default: if (isprint((unsigned char)c))
+ putchar(c);
+ else
+ printf("\\%03u",(unsigned char)c);
+ }
+ }
+ putchar('"');
+}
+
+static void PrintConstant(const Proto* f, int i)
+{
+ const TValue* o=&f->k[i];
+ switch (ttype(o))
+ {
+ case LUA_TNIL:
+ printf("nil");
+ break;
+ case LUA_TBOOLEAN:
+ printf(bvalue(o) ? "true" : "false");
+ break;
+ case LUA_TNUMBER:
+ printf(LUA_NUMBER_FMT,nvalue(o));
+ break;
+ case LUA_TSTRING:
+ PrintString(rawtsvalue(o));
+ break;
+ default: /* cannot happen */
+ printf("? type=%d",ttype(o));
+ break;
+ }
+}
+
+static void PrintCode(const Proto* f)
+{
+ const Instruction* code=f->code;
+ int pc,n=f->sizecode;
+ for (pc=0; pc<n; pc++)
+ {
+ Instruction i=code[pc];
+ OpCode o=GET_OPCODE(i);
+ int a=GETARG_A(i);
+ int b=GETARG_B(i);
+ int c=GETARG_C(i);
+ int bx=GETARG_Bx(i);
+ int sbx=GETARG_sBx(i);
+ int line=getline(f,pc);
+ printf("\t%d\t",pc+1);
+ if (line>0) printf("[%d]\t",line); else printf("[-]\t");
+ printf("%-9s\t",luaP_opnames[o]);
+ switch (getOpMode(o))
+ {
+ case iABC:
+ printf("%d",a);
+ if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
+ if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
+ break;
+ case iABx:
+ if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
+ break;
+ case iAsBx:
+ if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
+ break;
+ }
+ switch (o)
+ {
+ case OP_LOADK:
+ printf("\t; "); PrintConstant(f,bx);
+ break;
+ case OP_GETUPVAL:
+ case OP_SETUPVAL:
+ printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
+ break;
+ case OP_GETGLOBAL:
+ case OP_SETGLOBAL:
+ printf("\t; %s",svalue(&f->k[bx]));
+ break;
+ case OP_GETTABLE:
+ case OP_SELF:
+ if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
+ break;
+ case OP_SETTABLE:
+ case OP_ADD:
+ case OP_SUB:
+ case OP_MUL:
+ case OP_DIV:
+ case OP_POW:
+ case OP_EQ:
+ case OP_LT:
+ case OP_LE:
+ if (ISK(b) || ISK(c))
+ {
+ printf("\t; ");
+ if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
+ printf(" ");
+ if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
+ }
+ break;
+ case OP_JMP:
+ case OP_FORLOOP:
+ case OP_FORPREP:
+ printf("\t; to %d",sbx+pc+2);
+ break;
+ case OP_CLOSURE:
+ printf("\t; %p",VOID(f->p[bx]));
+ break;
+ case OP_SETLIST:
+ if (c==0) printf("\t; %d",(int)code[++pc]);
+ else printf("\t; %d",c);
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+ }
+}
+
+#define SS(x) (x==1)?"":"s"
+#define S(x) x,SS(x)
+
+static void PrintHeader(const Proto* f)
+{
+ const char* s=getstr(f->source);
+ if (*s=='@' || *s=='=')
+ s++;
+ else if (*s==LUA_SIGNATURE[0])
+ s="(bstring)";
+ else
+ s="(string)";
+ printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n",
+ (f->linedefined==0)?"main":"function",s,
+ f->linedefined,f->lastlinedefined,
+ S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));
+ printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
+ f->numparams,f->is_vararg?"+":"",SS(f->numparams),
+ S(f->maxstacksize),S(f->nups));
+ printf("%d local%s, %d constant%s, %d function%s\n",
+ S(f->sizelocvars),S(f->sizek),S(f->sizep));
+}
+
+static void PrintConstants(const Proto* f)
+{
+ int i,n=f->sizek;
+ printf("constants (%d) for %p:\n",n,VOID(f));
+ for (i=0; i<n; i++)
+ {
+ printf("\t%d\t",i+1);
+ PrintConstant(f,i);
+ printf("\n");
+ }
+}
+
+static void PrintLocals(const Proto* f)
+{
+ int i,n=f->sizelocvars;
+ printf("locals (%d) for %p:\n",n,VOID(f));
+ for (i=0; i<n; i++)
+ {
+ printf("\t%d\t%s\t%d\t%d\n",
+ i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
+ }
+}
+
+static void PrintUpvalues(const Proto* f)
+{
+ int i,n=f->sizeupvalues;
+ printf("upvalues (%d) for %p:\n",n,VOID(f));
+ if (f->upvalues==NULL) return;
+ for (i=0; i<n; i++)
+ {
+ printf("\t%d\t%s\n",i,getstr(f->upvalues[i]));
+ }
+}
+
+void PrintFunction(const Proto* f, int full)
+{
+ int i,n=f->sizep;
+ PrintHeader(f);
+ PrintCode(f);
+ if (full)
+ {
+ PrintConstants(f);
+ PrintLocals(f);
+ PrintUpvalues(f);
+ }
+ for (i=0; i<n; i++) PrintFunction(f->p[i],full);
+}
diff --git a/lib/luaexpat/lxplib.c b/lib/luaexpat/lxplib.c
new file mode 100644
index 000000000..1a36104a8
--- /dev/null
+++ b/lib/luaexpat/lxplib.c
@@ -0,0 +1,599 @@
+/*
+** $Id: lxplib.c,v 1.16 2007/06/05 20:03:12 carregal Exp $
+** LuaExpat: Lua bind for Expat library
+** See Copyright Notice in license.html
+*/
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "expat/expat.h"
+
+#include "lua/src/lua.h"
+#include "lua/src/lauxlib.h"
+
+
+#include "lxplib.h"
+
+
+#if !defined(lua_pushliteral)
+#define lua_pushliteral(L, s) \
+ lua_pushstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+#endif
+
+
+enum XPState {
+ XPSpre, /* parser just initialized */
+ XPSok, /* state while parsing */
+ XPSfinished, /* state after finished parsing */
+ XPSerror,
+ XPSstring /* state while reading a string */
+};
+
+struct lxp_userdata {
+ lua_State *L;
+ XML_Parser parser; /* associated expat parser */
+ int tableref; /* table with callbacks for this parser */
+ enum XPState state;
+ luaL_Buffer *b; /* to concatenate sequences of cdata pieces */
+};
+
+typedef struct lxp_userdata lxp_userdata;
+
+
+static int reporterror (lxp_userdata *xpu) {
+ lua_State *L = xpu->L;
+ XML_Parser p = xpu->parser;
+ lua_pushnil(L);
+ lua_pushstring(L, XML_ErrorString(XML_GetErrorCode(p)));
+ lua_pushnumber(L, XML_GetCurrentLineNumber(p));
+ lua_pushnumber(L, XML_GetCurrentColumnNumber(p) + 1);
+ lua_pushnumber(L, XML_GetCurrentByteIndex(p) + 1);
+ return 5;
+}
+
+
+static lxp_userdata *createlxp (lua_State *L) {
+ lxp_userdata *xpu = (lxp_userdata *)lua_newuserdata(L, sizeof(lxp_userdata));
+ xpu->tableref = LUA_REFNIL; /* in case of errors... */
+ xpu->parser = NULL;
+ xpu->L = NULL;
+ xpu->state = XPSpre;
+ luaL_getmetatable(L, ParserType);
+ lua_setmetatable(L, -2);
+ return xpu;
+}
+
+
+static void lxpclose (lua_State *L, lxp_userdata *xpu) {
+ luaL_unref(L, LUA_REGISTRYINDEX, xpu->tableref);
+ xpu->tableref = LUA_REFNIL;
+ if (xpu->parser)
+ XML_ParserFree(xpu->parser);
+ xpu->parser = NULL;
+}
+
+
+
+
+/*
+** Auxiliary function to call a Lua handle
+*/
+static void docall (lxp_userdata *xpu, int nargs, int nres) {
+ lua_State *L = xpu->L;
+ assert(xpu->state == XPSok);
+ if (lua_pcall(L, nargs + 1, nres, 0) != 0) {
+ xpu->state = XPSerror;
+ luaL_unref(L, LUA_REGISTRYINDEX, xpu->tableref);
+ xpu->tableref = luaL_ref(L, LUA_REGISTRYINDEX); /* error message */
+ }
+}
+
+
+/*
+** Check whether there is pending Cdata, and call its handle if necessary
+*/
+static void dischargestring (lxp_userdata *xpu) {
+ assert(xpu->state == XPSstring);
+ xpu->state = XPSok;
+ luaL_pushresult(xpu->b);
+ docall(xpu, 1, 0);
+}
+
+
+/*
+** Check whether there is a Lua handle for a given event: If so,
+** put it on the stack (to be called later), and also push `self'
+*/
+static int getHandle (lxp_userdata *xpu, const char *handle) {
+ lua_State *L = xpu->L;
+ if (xpu->state == XPSstring) dischargestring(xpu);
+ if (xpu->state == XPSerror)
+ return 0; /* some error happened before; skip all handles */
+ lua_pushstring(L, handle);
+ lua_gettable(L, 3);
+ if (lua_toboolean(L, -1) == 0) {
+ lua_pop(L, 1);
+ return 0;
+ }
+ if (!lua_isfunction(L, -1)) {
+ luaL_error(L, "lxp `%s' callback is not a function", handle);
+ }
+ lua_pushvalue(L, 1); /* first argument in every call (self) */
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** Handles
+** =======================================================
+*/
+
+
+static void f_StartCdata (void *ud) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, StartCdataKey) == 0) return; /* no handle */
+ docall(xpu, 0, 0);
+}
+
+
+static void f_EndCdataKey (void *ud) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, EndCdataKey) == 0) return; /* no handle */
+ docall(xpu, 0, 0);
+}
+
+
+static void f_CharData (void *ud, const char *s, int len) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (xpu->state == XPSok) {
+ if (getHandle(xpu, CharDataKey) == 0) return; /* no handle */
+ xpu->state = XPSstring;
+ luaL_buffinit(xpu->L, xpu->b);
+ }
+ if (xpu->state == XPSstring)
+ luaL_addlstring(xpu->b, s, len);
+}
+
+
+static void f_Comment (void *ud, const char *data) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, CommentKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, data);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_Default (void *ud, const char *data, int len) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, DefaultKey) == 0) return; /* no handle */
+ lua_pushlstring(xpu->L, data, len);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_DefaultExpand (void *ud, const char *data, int len) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, DefaultExpandKey) == 0) return; /* no handle */
+ lua_pushlstring(xpu->L, data, len);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_StartElement (void *ud, const char *name, const char **attrs) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ int lastspec = XML_GetSpecifiedAttributeCount(xpu->parser) / 2;
+ int i = 1;
+ if (getHandle(xpu, StartElementKey) == 0) return; /* no handle */
+ lua_pushstring(L, name);
+ lua_newtable(L);
+ while (*attrs) {
+ if (i <= lastspec) {
+ lua_pushnumber(L, i++);
+ lua_pushstring(L, *attrs);
+ lua_settable(L, -3);
+ }
+ lua_pushstring(L, *attrs++);
+ lua_pushstring(L, *attrs++);
+ lua_settable(L, -3);
+ }
+ docall(xpu, 2, 0); /* call function with self, name, and attributes */
+}
+
+
+static void f_EndElement (void *ud, const char *name) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, EndElementKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, name);
+ docall(xpu, 1, 0);
+}
+
+
+static int f_ExternaEntity (XML_Parser p, const char *context,
+ const char *base,
+ const char *systemId,
+ const char *publicId) {
+ lxp_userdata *xpu = (lxp_userdata *)XML_GetUserData(p);
+ lua_State *L = xpu->L;
+ lxp_userdata *child;
+ int status;
+ if (getHandle(xpu, ExternalEntityKey) == 0) return 1; /* no handle */
+ child = createlxp(L);
+ child->parser = XML_ExternalEntityParserCreate(p, context, NULL);
+ if (!child->parser)
+ luaL_error(L, "XML_ParserCreate failed");
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /*lua_getref(L, xpu->tableref); */ /* child uses the same table of its father */
+ child->tableref = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushstring(L, base);
+ lua_pushstring(L, systemId);
+ lua_pushstring(L, publicId);
+ docall(xpu, 4, 1);
+ status = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ lxpclose(L, child);
+ return status;
+}
+
+
+static void f_StartNamespaceDecl (void *ud, const char *prefix,
+ const char *uri) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, StartNamespaceDeclKey) == 0) return; /* no handle */
+ lua_pushstring(L, prefix);
+ lua_pushstring(L, uri);
+ docall(xpu, 2, 0);
+}
+
+
+static void f_EndNamespaceDecl (void *ud, const char *prefix) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, EndNamespaceDeclKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, prefix);
+ docall(xpu, 1, 0);
+}
+
+
+static void f_NotationDecl (void *ud, const char *notationName,
+ const char *base,
+ const char *systemId,
+ const char *publicId) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, NotationDeclKey) == 0) return; /* no handle */
+ lua_pushstring(L, notationName);
+ lua_pushstring(L, base);
+ lua_pushstring(L, systemId);
+ lua_pushstring(L, publicId);
+ docall(xpu, 4, 0);
+}
+
+
+static int f_NotStandalone (void *ud) {
+ int status;
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, NotStandaloneKey) == 0) return 1; /* no handle */
+ docall(xpu, 0, 1);
+ status = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return status;
+}
+
+
+static void f_ProcessingInstruction (void *ud, const char *target,
+ const char *data) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, ProcessingInstructionKey) == 0) return; /* no handle */
+ lua_pushstring(L, target);
+ lua_pushstring(L, data);
+ docall(xpu, 2, 0);
+}
+
+
+static void f_UnparsedEntityDecl (void *ud, const char *entityName,
+ const char *base,
+ const char *systemId,
+ const char *publicId,
+ const char *notationName) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ lua_State *L = xpu->L;
+ if (getHandle(xpu, UnparsedEntityDeclKey) == 0) return; /* no handle */
+ lua_pushstring(L, entityName);
+ lua_pushstring(L, base);
+ lua_pushstring(L, systemId);
+ lua_pushstring(L, publicId);
+ lua_pushstring(L, notationName);
+ docall(xpu, 5, 0);
+}
+
+static void f_StartDoctypeDecl (void *ud, const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset) {
+ lxp_userdata *xpu = (lxp_userdata *)ud;
+ if (getHandle(xpu, StartDoctypeDeclKey) == 0) return; /* no handle */
+ lua_pushstring(xpu->L, doctypeName);
+ lua_pushstring(xpu->L, sysid);
+ lua_pushstring(xpu->L, pubid);
+ lua_pushboolean(xpu->L, has_internal_subset);
+ docall(xpu, 4, 0);
+}
+
+/* }====================================================== */
+
+
+
+static int hasfield (lua_State *L, const char *fname) {
+ int res;
+ lua_pushstring(L, fname);
+ lua_gettable(L, 1);
+ res = !lua_isnil(L, -1);
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static void checkcallbacks (lua_State *L) {
+ static const char *const validkeys[] = {
+ "StartCdataSection", "EndCdataSection", "CharacterData", "Comment",
+ "Default", "DefaultExpand", "StartElement", "EndElement",
+ "ExternalEntityRef", "StartNamespaceDecl", "EndNamespaceDecl",
+ "NotationDecl", "NotStandalone", "ProcessingInstruction",
+ "UnparsedEntityDecl", "StartDoctypeDecl", NULL};
+ if (hasfield(L, "_nonstrict")) return;
+ lua_pushnil(L);
+ while (lua_next(L, 1)) {
+ lua_pop(L, 1); /* remove value */
+#if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
+ if (lua_type(L, -1) != LUA_TSTRING ||
+ luaL_findstring(lua_tostring(L, -1), validkeys) < 0)
+ luaL_error(L, "invalid key `%s' in callback table", lua_tostring(L, -1));
+#else
+ luaL_checkoption(L, -1, NULL, validkeys);
+#endif
+ }
+}
+
+
+static int lxp_make_parser (lua_State *L) {
+ XML_Parser p;
+ char sep = *luaL_optstring(L, 2, "");
+ lxp_userdata *xpu = createlxp(L);
+ p = xpu->parser = (sep == '\0') ? XML_ParserCreate(NULL) :
+ XML_ParserCreateNS(NULL, sep);
+ if (!p)
+ luaL_error(L, "XML_ParserCreate failed");
+ luaL_checktype(L, 1, LUA_TTABLE);
+ checkcallbacks(L);
+ lua_pushvalue(L, 1);
+ xpu->tableref = luaL_ref(L, LUA_REGISTRYINDEX);
+ XML_SetUserData(p, xpu);
+ if (hasfield(L, StartCdataKey) || hasfield(L, EndCdataKey))
+ XML_SetCdataSectionHandler(p, f_StartCdata, f_EndCdataKey);
+ if (hasfield(L, CharDataKey))
+ XML_SetCharacterDataHandler(p, f_CharData);
+ if (hasfield(L, CommentKey))
+ XML_SetCommentHandler(p, f_Comment);
+ if (hasfield(L, DefaultKey))
+ XML_SetDefaultHandler(p, f_Default);
+ if (hasfield(L, DefaultExpandKey))
+ XML_SetDefaultHandlerExpand(p, f_DefaultExpand);
+ if (hasfield(L, StartElementKey) || hasfield(L, EndElementKey))
+ XML_SetElementHandler(p, f_StartElement, f_EndElement);
+ if (hasfield(L, ExternalEntityKey))
+ XML_SetExternalEntityRefHandler(p, f_ExternaEntity);
+ if (hasfield(L, StartNamespaceDeclKey) || hasfield(L, EndNamespaceDeclKey))
+ XML_SetNamespaceDeclHandler(p, f_StartNamespaceDecl, f_EndNamespaceDecl);
+ if (hasfield(L, NotationDeclKey))
+ XML_SetNotationDeclHandler(p, f_NotationDecl);
+ if (hasfield(L, NotStandaloneKey))
+ XML_SetNotStandaloneHandler(p, f_NotStandalone);
+ if (hasfield(L, ProcessingInstructionKey))
+ XML_SetProcessingInstructionHandler(p, f_ProcessingInstruction);
+ if (hasfield(L, UnparsedEntityDeclKey))
+ XML_SetUnparsedEntityDeclHandler(p, f_UnparsedEntityDecl);
+ if (hasfield(L, StartDoctypeDeclKey))
+ XML_SetStartDoctypeDeclHandler(p, f_StartDoctypeDecl);
+ return 1;
+}
+
+
+static lxp_userdata *checkparser (lua_State *L, int idx) {
+ lxp_userdata *xpu = (lxp_userdata *)luaL_checkudata(L, idx, ParserType);
+ luaL_argcheck(L, xpu, idx, "expat parser expected");
+ luaL_argcheck(L, xpu->parser, idx, "parser is closed");
+ return xpu;
+}
+
+
+static int parser_gc (lua_State *L) {
+ lxp_userdata *xpu = (lxp_userdata *)luaL_checkudata(L, 1, ParserType);
+ luaL_argcheck(L, xpu, 1, "expat parser expected");
+ lxpclose(L, xpu);
+ return 0;
+}
+
+
+static int setbase (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ if (XML_SetBase(xpu->parser, luaL_checkstring(L, 2)) == 0)
+ luaL_error(L, "no memory to store base");
+ return 0;
+}
+
+
+static int getbase (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ lua_pushstring(L, XML_GetBase(xpu->parser));
+ return 1;
+}
+
+
+static int getcallbacks (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref);
+ return 1;
+}
+
+
+static int parse_aux (lua_State *L, lxp_userdata *xpu, const char *s,
+ size_t len) {
+ luaL_Buffer b;
+ int status;
+ xpu->L = L;
+ xpu->state = XPSok;
+ xpu->b = &b;
+ lua_settop(L, 2);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /*lua_getref(L, xpu->tableref);*/ /* to be used by handlers */
+ status = XML_Parse(xpu->parser, s, (int)len, s == NULL);
+ if (xpu->state == XPSstring) dischargestring(xpu);
+ if (xpu->state == XPSerror) { /* callback error? */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /* get original msg. */
+ lua_error(L);
+ }
+ if (s == NULL) xpu->state = XPSfinished;
+ if (status) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else { /* error */
+ return reporterror(xpu);
+ }
+}
+
+
+static int lxp_parse (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ size_t len;
+ const char *s = luaL_optlstring(L, 2, NULL, &len);
+ if (xpu->state == XPSfinished && s != NULL) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "cannot parse - document is finished");
+ return 2;
+ }
+ return parse_aux(L, xpu, s, len);
+}
+
+
+static int lxp_close (lua_State *L) {
+ int status = 1;
+ lxp_userdata *xpu = (lxp_userdata *)luaL_checkudata(L, 1, ParserType);
+ luaL_argcheck(L, xpu, 1, "expat parser expected");
+ if (xpu->state != XPSfinished)
+ status = parse_aux(L, xpu, NULL, 0);
+ lxpclose(L, xpu);
+ if (status > 1) luaL_error(L, "error closing parser: %s",
+ lua_tostring(L, -status+1));
+ return 0;
+}
+
+
+static int lxp_pos (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ XML_Parser p = xpu->parser;
+ lua_pushnumber(L, XML_GetCurrentLineNumber(p));
+ lua_pushnumber(L, XML_GetCurrentColumnNumber(p) + 1);
+ lua_pushnumber(L, XML_GetCurrentByteIndex(p) + 1);
+ return 3;
+}
+
+
+static int lxp_setencoding (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ const char *encoding = luaL_checkstring(L, 2);
+ luaL_argcheck(L, xpu->state == XPSpre, 1, "invalid parser state");
+ XML_SetEncoding(xpu->parser, encoding);
+ return 0;
+}
+
+static int lxp_stop (lua_State *L) {
+ lxp_userdata *xpu = checkparser(L, 1);
+ lua_pushboolean(L, XML_StopParser(xpu->parser, XML_FALSE) == XML_STATUS_OK);
+ return 1;
+}
+
+#if !defined LUA_VERSION_NUM
+/* Lua 5.0 */
+#define luaL_Reg luaL_reg
+#endif
+
+static const struct luaL_Reg lxp_meths[] = {
+ {"parse", lxp_parse},
+ {"close", lxp_close},
+ {"__gc", parser_gc},
+ {"pos", lxp_pos},
+ {"setencoding", lxp_setencoding},
+ {"getcallbacks", getcallbacks},
+ {"getbase", getbase},
+ {"setbase", setbase},
+ {"stop", lxp_stop},
+ {NULL, NULL}
+};
+
+static const struct luaL_Reg lxp_funcs[] = {
+ {"new", lxp_make_parser},
+ {NULL, NULL}
+};
+
+
+/*
+** Assumes the table is on top of the stack.
+*/
+static void set_info (lua_State *L) {
+ lua_pushliteral (L, "_COPYRIGHT");
+ lua_pushliteral (L, "Copyright (C) 2003-2012 Kepler Project");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_DESCRIPTION");
+ lua_pushliteral (L, "LuaExpat is a SAX XML parser based on the Expat library");
+ lua_settable (L, -3);
+ lua_pushliteral (L, "_VERSION");
+ lua_pushliteral (L, "LuaExpat 1.3.0");
+ lua_settable (L, -3);
+}
+
+
+#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501
+/*
+** Adapted from Lua 5.2.0
+*/
+static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+ luaL_checkstack(L, nup, "too many upvalues");
+ for (; l->name != NULL; l++) { /* fill the table with given functions */
+ int i;
+ for (i = 0; i < nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -nup);
+ lua_pushstring(L, l->name);
+ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
+ lua_settable(L, -(nup + 3));
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+#endif
+
+
+int luaopen_lxp (lua_State *L) {
+ luaL_newmetatable(L, ParserType);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2);
+ lua_rawset(L, -3);
+
+ luaL_setfuncs (L, lxp_meths, 0);
+ lua_pop (L, 1); /* remove metatable */
+
+ // _X 2013_04_09: Modified to allow embedding
+ luaL_openlib (L, "lxp", lxp_funcs, 0);
+ /*
+ lua_newtable (L);
+ luaL_setfuncs (L, lxp_funcs, 0);
+ */
+ set_info (L);
+ return 1;
+}
diff --git a/lib/luaexpat/lxplib.h b/lib/luaexpat/lxplib.h
new file mode 100644
index 000000000..9c0be4f78
--- /dev/null
+++ b/lib/luaexpat/lxplib.h
@@ -0,0 +1,24 @@
+/*
+** See Copyright Notice in license.html
+*/
+
+#define ParserType "Expat"
+
+#define StartCdataKey "StartCdataSection"
+#define EndCdataKey "EndCdataSection"
+#define CharDataKey "CharacterData"
+#define CommentKey "Comment"
+#define DefaultKey "Default"
+#define DefaultExpandKey "DefaultExpand"
+#define StartElementKey "StartElement"
+#define EndElementKey "EndElement"
+#define ExternalEntityKey "ExternalEntityRef"
+#define StartNamespaceDeclKey "StartNamespaceDecl"
+#define EndNamespaceDeclKey "EndNamespaceDecl"
+#define NotationDeclKey "NotationDecl"
+#define NotStandaloneKey "NotStandalone"
+#define ProcessingInstructionKey "ProcessingInstruction"
+#define UnparsedEntityDeclKey "UnparsedEntityDecl"
+#define StartDoctypeDeclKey "StartDoctypeDecl"
+
+int luaopen_lxp (lua_State *L);
diff --git a/lib/md5/md5.cpp b/lib/md5/md5.cpp
new file mode 100644
index 000000000..eae0fc3f2
--- /dev/null
+++ b/lib/md5/md5.cpp
@@ -0,0 +1,369 @@
+/* MD5
+ converted to C++ class by Frank Thilo (thilo@unix-ag.org)
+ for bzflag (http://www.bzflag.org)
+
+ based on:
+
+ md5.h and md5.c
+ reference implemantion of RFC 1321
+
+ Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+
+*/
+
+/* interface header */
+#include "md5.h"
+
+/* system implementation headers */
+#include <stdio.h>
+
+#ifndef _WIN32
+ #include <cstring>
+#endif
+
+
+
+
+
+// Constants for MD5Transform routine.
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+///////////////////////////////////////////////
+
+// F, G, H and I are basic MD5 functions.
+inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
+ return x&y | ~x&z;
+}
+
+inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
+ return x&z | y&~z;
+}
+
+inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
+ return x^y^z;
+}
+
+inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
+ return y ^ (x | ~z);
+}
+
+// rotate_left rotates x left n bits.
+inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
+ return (x << n) | (x >> (32-n));
+}
+
+// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+// Rotation is separate from addition to prevent recomputation.
+inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
+ a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;
+}
+
+inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
+ a = rotate_left(a + G(b,c,d) + x + ac, s) + b;
+}
+
+inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
+ a = rotate_left(a + H(b,c,d) + x + ac, s) + b;
+}
+
+inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
+ a = rotate_left(a + I(b,c,d) + x + ac, s) + b;
+}
+
+//////////////////////////////////////////////
+
+// default ctor, just initailize
+MD5::MD5()
+{
+ init();
+}
+
+//////////////////////////////////////////////
+
+// nifty shortcut ctor, compute MD5 for string and finalize it right away
+MD5::MD5(const std::string &text)
+{
+ init();
+ update(text.c_str(), text.length());
+ finalize();
+}
+
+//////////////////////////////
+
+void MD5::init()
+{
+ finalized=false;
+
+ count[0] = 0;
+ count[1] = 0;
+
+ // load magic initialization constants.
+ state[0] = 0x67452301;
+ state[1] = 0xefcdab89;
+ state[2] = 0x98badcfe;
+ state[3] = 0x10325476;
+}
+
+//////////////////////////////
+
+// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
+void MD5::decode(uint4 output[], const uint1 input[], size_type len)
+{
+ for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
+ (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
+}
+
+//////////////////////////////
+
+// encodes input (uint4) into output (unsigned char). Assumes len is
+// a multiple of 4.
+void MD5::encode(uint1 output[], const uint4 input[], size_type len)
+{
+ for (size_type i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = input[i] & 0xff;
+ output[j+1] = (input[i] >> 8) & 0xff;
+ output[j+2] = (input[i] >> 16) & 0xff;
+ output[j+3] = (input[i] >> 24) & 0xff;
+ }
+}
+
+//////////////////////////////
+
+// apply MD5 algo on a block
+void MD5::transform(const uint1 block[blocksize])
+{
+ uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+ decode (x, block, blocksize);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ // Zeroize sensitive information.
+ memset(x, 0, sizeof x);
+}
+
+//////////////////////////////
+
+// MD5 block update operation. Continues an MD5 message-digest
+// operation, processing another message block
+void MD5::update(const unsigned char input[], size_type length)
+{
+ // compute number of bytes mod 64
+ size_type index = count[0] / 8 % blocksize;
+
+ // Update number of bits
+ if ((count[0] += (length << 3)) < (length << 3))
+ count[1]++;
+ count[1] += (length >> 29);
+
+ // number of bytes we need to fill in buffer
+ size_type firstpart = 64 - index;
+
+ size_type i;
+
+ // transform as many times as possible.
+ if (length >= firstpart)
+ {
+ // fill buffer first, transform
+ memcpy(&buffer[index], input, firstpart);
+ transform(buffer);
+
+ // transform chunks of blocksize (64 bytes)
+ for (i = firstpart; i + blocksize <= length; i += blocksize)
+ transform(&input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ // buffer remaining input
+ memcpy(&buffer[index], &input[i], length-i);
+}
+
+//////////////////////////////
+
+// for convenience provide a verson with signed char
+void MD5::update(const char input[], size_type length)
+{
+ update((const unsigned char*)input, length);
+}
+
+//////////////////////////////
+
+// MD5 finalization. Ends an MD5 message-digest operation, writing the
+// the message digest and zeroizing the context.
+MD5& MD5::finalize()
+{
+ static unsigned char padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if (!finalized) {
+ // Save number of bits
+ unsigned char bits[8];
+ encode(bits, count, 8);
+
+ // pad out to 56 mod 64.
+ size_type index = count[0] / 8 % 64;
+ size_type padLen = (index < 56) ? (56 - index) : (120 - index);
+ update(padding, padLen);
+
+ // Append length (before padding)
+ update(bits, 8);
+
+ // Store state in digest
+ encode(digest, state, 16);
+
+ // Zeroize sensitive information.
+ memset(buffer, 0, sizeof buffer);
+ memset(count, 0, sizeof count);
+
+ finalized=true;
+ }
+
+ return *this;
+}
+
+//////////////////////////////
+
+// return hex representation of digest as string
+std::string MD5::hexdigest() const
+{
+ if (!finalized)
+ return "";
+
+ char buf[33];
+ for (int i=0; i<16; i++)
+ sprintf(buf+i*2, "%02x", digest[i]);
+ buf[32]=0;
+
+ return std::string(buf);
+}
+
+//////////////////////////////
+
+std::ostream& operator<<(std::ostream& out, MD5 md5)
+{
+ return out << md5.hexdigest();
+}
+
+//////////////////////////////
+
+std::string md5(const std::string & str)
+{
+ MD5 md5 = MD5(str);
+
+ return md5.hexdigest();
+}
diff --git a/lib/md5/md5.h b/lib/md5/md5.h
new file mode 100644
index 000000000..ad5ad5384
--- /dev/null
+++ b/lib/md5/md5.h
@@ -0,0 +1,93 @@
+/* MD5
+ converted to C++ class by Frank Thilo (thilo@unix-ag.org)
+ for bzflag (http://www.bzflag.org)
+
+ based on:
+
+ md5.h and md5.c
+ reference implementation of RFC 1321
+
+ Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+
+*/
+
+#ifndef BZF_MD5_H
+#define BZF_MD5_H
+
+#include <string>
+#include <iostream>
+
+
+// a small class for calculating MD5 hashes of strings or byte arrays
+// it is not meant to be fast or secure
+//
+// usage: 1) feed it blocks of uchars with update()
+// 2) finalize()
+// 3) get hexdigest() string
+// or
+// MD5(std::string).hexdigest()
+//
+// assumes that char is 8 bit and int is 32 bit
+class MD5
+{
+public:
+ typedef unsigned int size_type; // must be 32bit
+
+ MD5();
+ MD5(const std::string& text);
+ void update(const unsigned char *buf, size_type length);
+ void update(const char *buf, size_type length);
+ MD5& finalize();
+ std::string hexdigest() const;
+ friend std::ostream& operator<<(std::ostream&, MD5 md5);
+
+private:
+ void init();
+ typedef unsigned char uint1; // 8bit
+ typedef unsigned int uint4; // 32bit
+ enum {blocksize = 64}; // VC6 won't eat a const static int here
+
+ void transform(const uint1 block[blocksize]);
+ static void decode(uint4 output[], const uint1 input[], size_type len);
+ static void encode(uint1 output[], const uint4 input[], size_type len);
+
+ bool finalized;
+ uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
+ uint4 count[2]; // 64bit counter for number of bits (lo, hi)
+ uint4 state[4]; // digest so far
+ uint1 digest[16]; // the result
+
+ // low level logic operations
+ static inline uint4 F(uint4 x, uint4 y, uint4 z);
+ static inline uint4 G(uint4 x, uint4 y, uint4 z);
+ static inline uint4 H(uint4 x, uint4 y, uint4 z);
+ static inline uint4 I(uint4 x, uint4 y, uint4 z);
+ static inline uint4 rotate_left(uint4 x, int n);
+ static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
+ static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
+ static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
+ static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
+};
+
+std::string md5(const std::string & str);
+
+#endif \ No newline at end of file
diff --git a/lib/sqlite/lsqlite3.c b/lib/sqlite/lsqlite3.c
new file mode 100644
index 000000000..cf2c62597
--- /dev/null
+++ b/lib/sqlite/lsqlite3.c
@@ -0,0 +1,2175 @@
+/************************************************************************
+* lsqlite3 *
+* Copyright (C) 2002-2013 Tiago Dionizio, Doug Currie *
+* All rights reserved. *
+* Author : Tiago Dionizio <tiago.dionizio@ist.utl.pt> *
+* Author : Doug Currie <doug.currie@alum.mit.edu> *
+* Library : lsqlite3 - a SQLite 3 database binding for Lua 5 *
+* *
+* Permission is hereby granted, free of charge, to any person obtaining *
+* a copy of this software and associated documentation files (the *
+* "Software"), to deal in the Software without restriction, including *
+* without limitation the rights to use, copy, modify, merge, publish, *
+* distribute, sublicense, and/or sell copies of the Software, and to *
+* permit persons to whom the Software is furnished to do so, subject to *
+* the following conditions: *
+* *
+* The above copyright notice and this permission notice shall be *
+* included in all copies or substantial portions of the Software. *
+* *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+************************************************************************/
+// Slightly modified by _Xoft to compile in MSVC
+
+
+
+
+// 2013_04_07 _X: Added the following #define-s so that MSVC doesn't complain about non-secure stuff:
+#define _CRT_SECURE_NO_WARNINGS
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define LUA_LIB
+#include "lua/src/lua.h"
+#include "lua/src/lauxlib.h"
+
+#if LUA_VERSION_NUM > 501
+//
+// Lua 5.2
+//
+#define lua_strlen lua_rawlen
+// luaL_typerror always used with arg at ndx == NULL
+#define luaL_typerror(L,ndx,str) luaL_error(L,"bad argument %d (%s expected, got nil)",ndx,str)
+// luaL_register used once, so below expansion is OK for this case
+#define luaL_register(L,name,reg) lua_newtable(L);luaL_setfuncs(L,reg,0)
+// luaL_openlib always used with name == NULL
+#define luaL_openlib(L,name,reg,nup) luaL_setfuncs(L,reg,nup)
+#endif
+
+#include "sqlite3.h"
+
+/* compile time features */
+#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
+ #define SQLITE_OMIT_PROGRESS_CALLBACK 0
+#endif
+#if !defined(LSQLITE_OMIT_UPDATE_HOOK)
+ #define LSQLITE_OMIT_UPDATE_HOOK 0
+#endif
+
+typedef struct sdb sdb;
+typedef struct sdb_vm sdb_vm;
+typedef struct sdb_func sdb_func;
+
+/* to use as C user data so i know what function sqlite is calling */
+struct sdb_func {
+ /* references to associated lua values */
+ int fn_step;
+ int fn_finalize;
+ int udata;
+
+ sdb *db;
+ char aggregate;
+
+ sdb_func *next;
+};
+
+/* information about database */
+struct sdb {
+ /* associated lua state */
+ lua_State *L;
+ /* sqlite database handle */
+ sqlite3 *db;
+
+ /* sql functions stack usage */
+ sdb_func *func; /* top SQL function being called */
+
+ /* references */
+ int busy_cb; /* busy callback */
+ int busy_udata;
+
+ int progress_cb; /* progress handler */
+ int progress_udata;
+
+ int trace_cb; /* trace callback */
+ int trace_udata;
+
+#if !defined(LSQLITE_OMIT_UPDATE_HOOK) || !LSQLITE_OMIT_UPDATE_HOOK
+
+ int update_hook_cb; /* update_hook callback */
+ int update_hook_udata;
+
+ int commit_hook_cb; /* commit_hook callback */
+ int commit_hook_udata;
+
+ int rollback_hook_cb; /* rollback_hook callback */
+ int rollback_hook_udata;
+
+#endif
+};
+
+static const char *sqlite_meta = ":sqlite3";
+static const char *sqlite_vm_meta = ":sqlite3:vm";
+static const char *sqlite_ctx_meta = ":sqlite3:ctx";
+static int sqlite_ctx_meta_ref;
+
+/*
+** =======================================================
+** Database Virtual Machine Operations
+** =======================================================
+*/
+
+static void vm_push_column(lua_State *L, sqlite3_stmt *vm, int idx) {
+ switch (sqlite3_column_type(vm, idx)) {
+ case SQLITE_INTEGER:
+ {
+ sqlite_int64 i64 = sqlite3_column_int64(vm, idx);
+ lua_Number n = (lua_Number)i64;
+ if (n == i64)
+ lua_pushnumber(L, n);
+ else
+ lua_pushlstring(L, (const char*)sqlite3_column_text(vm, idx), sqlite3_column_bytes(vm, idx));
+ }
+ break;
+ case SQLITE_FLOAT:
+ lua_pushnumber(L, sqlite3_column_double(vm, idx));
+ break;
+ case SQLITE_TEXT:
+ lua_pushlstring(L, (const char*)sqlite3_column_text(vm, idx), sqlite3_column_bytes(vm, idx));
+ break;
+ case SQLITE_BLOB:
+ lua_pushlstring(L, sqlite3_column_blob(vm, idx), sqlite3_column_bytes(vm, idx));
+ break;
+ case SQLITE_NULL:
+ lua_pushnil(L);
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+}
+
+/* virtual machine information */
+struct sdb_vm {
+ sdb *db; /* associated database handle */
+ sqlite3_stmt *vm; /* virtual machine */
+
+ /* sqlite3_step info */
+ int columns; /* number of columns in result */
+ char has_values; /* true when step succeeds */
+
+ char temp; /* temporary vm used in db:rows */
+};
+
+/* called with sql text on the lua stack */
+static sdb_vm *newvm(lua_State *L, sdb *db) {
+ sdb_vm *svm = (sdb_vm*)lua_newuserdata(L, sizeof(sdb_vm));
+
+ luaL_getmetatable(L, sqlite_vm_meta);
+ lua_setmetatable(L, -2); /* set metatable */
+
+ svm->db = db;
+ svm->columns = 0;
+ svm->has_values = 0;
+ svm->vm = NULL;
+ svm->temp = 0;
+
+ /* add an entry on the database table: svm -> sql text */
+ lua_pushlightuserdata(L, db);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, svm);
+ lua_pushvalue(L, -4); /* the sql text */
+ lua_rawset(L, -3);
+ lua_pop(L, 1);
+
+ return svm;
+}
+
+static int cleanupvm(lua_State *L, sdb_vm *svm) {
+ /* remove entry in database table - no harm if not present in the table */
+ lua_pushlightuserdata(L, svm->db);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, svm);
+ lua_pushnil(L);
+ lua_rawset(L, -3);
+ lua_pop(L, 1);
+
+ svm->columns = 0;
+ svm->has_values = 0;
+
+ if (!svm->vm) return 0;
+
+ lua_pushnumber(L, sqlite3_finalize(svm->vm));
+ svm->vm = NULL;
+ return 1;
+}
+
+static int stepvm(lua_State *L, sdb_vm *svm) {
+ int result;
+ int loop_limit = 3;
+ while ( loop_limit-- ) {
+ result = sqlite3_step(svm->vm);
+ if ( result==SQLITE_ERROR ) {
+ result = sqlite3_reset (svm->vm);
+ }
+ if ( result==SQLITE_SCHEMA ) {
+ sqlite3_stmt *vn;
+ const char *sql;
+ /* recover sql text */
+ lua_pushlightuserdata(L, svm->db);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, svm);
+ lua_rawget(L, -2); /* sql text */
+ sql = luaL_checkstring(L, -1);
+ /* re-prepare */
+ result = sqlite3_prepare(svm->db->db, sql, -1, &vn, NULL);
+ if (result != SQLITE_OK) break;
+ sqlite3_transfer_bindings(svm->vm, vn);
+ sqlite3_finalize(svm->vm);
+ svm->vm = vn;
+ lua_pop(L,2);
+ } else {
+ break;
+ }
+ }
+ return result;
+}
+
+static sdb_vm *lsqlite_getvm(lua_State *L, int index) {
+ sdb_vm *svm = (sdb_vm*)luaL_checkudata(L, index, sqlite_vm_meta);
+ if (svm == NULL) luaL_argerror(L, index, "bad sqlite virtual machine");
+ return svm;
+}
+
+static sdb_vm *lsqlite_checkvm(lua_State *L, int index) {
+ sdb_vm *svm = lsqlite_getvm(L, index);
+ if (svm->vm == NULL) luaL_argerror(L, index, "attempt to use closed sqlite virtual machine");
+ return svm;
+}
+
+static int dbvm_isopen(lua_State *L) {
+ sdb_vm *svm = lsqlite_getvm(L, 1);
+ lua_pushboolean(L, svm->vm != NULL ? 1 : 0);
+ return 1;
+}
+
+static int dbvm_tostring(lua_State *L) {
+ char buff[39];
+ sdb_vm *svm = lsqlite_getvm(L, 1);
+ if (svm->vm == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", svm);
+ lua_pushfstring(L, "sqlite virtual machine (%s)", buff);
+ return 1;
+}
+
+static int dbvm_gc(lua_State *L) {
+ sdb_vm *svm = lsqlite_getvm(L, 1);
+ if (svm->vm != NULL) /* ignore closed vms */
+ cleanupvm(L, svm);
+ return 0;
+}
+
+static int dbvm_step(lua_State *L) {
+ int result;
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+
+ result = stepvm(L, svm);
+ svm->has_values = result == SQLITE_ROW ? 1 : 0;
+ svm->columns = sqlite3_data_count(svm->vm);
+
+ lua_pushnumber(L, result);
+ return 1;
+}
+
+static int dbvm_finalize(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ return cleanupvm(L, svm);
+}
+
+static int dbvm_reset(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_reset(svm->vm);
+ lua_pushnumber(L, sqlite3_errcode(svm->db->db));
+ return 1;
+}
+
+static void dbvm_check_contents(lua_State *L, sdb_vm *svm) {
+ if (!svm->has_values) {
+ luaL_error(L, "misuse of function");
+ }
+}
+
+static void dbvm_check_index(lua_State *L, sdb_vm *svm, int index) {
+ if (index < 0 || index >= svm->columns) {
+ luaL_error(L, "index out of range [0..%d]", svm->columns - 1);
+ }
+}
+
+static void dbvm_check_bind_index(lua_State *L, sdb_vm *svm, int index) {
+ if (index < 1 || index > sqlite3_bind_parameter_count(svm->vm)) {
+ luaL_error(L, "bind index out of range [1..%d]", sqlite3_bind_parameter_count(svm->vm));
+ }
+}
+
+/*
+** =======================================================
+** Virtual Machine - generic info
+** =======================================================
+*/
+static int dbvm_columns(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ lua_pushnumber(L, sqlite3_column_count(svm->vm));
+ return 1;
+}
+
+/*
+** =======================================================
+** Virtual Machine - getters
+** =======================================================
+*/
+
+static int dbvm_get_value(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ int index = luaL_checkint(L, 2);
+ dbvm_check_contents(L, svm);
+ dbvm_check_index(L, svm, index);
+ vm_push_column(L, svm->vm, index);
+ return 1;
+}
+
+static int dbvm_get_name(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ int index = (int)luaL_checknumber(L, 2);
+ dbvm_check_index(L, svm, index);
+ lua_pushstring(L, sqlite3_column_name(svm->vm, index));
+ return 1;
+}
+
+static int dbvm_get_type(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ int index = (int)luaL_checknumber(L, 2);
+ dbvm_check_index(L, svm, index);
+ lua_pushstring(L, sqlite3_column_decltype(svm->vm, index));
+ return 1;
+}
+
+static int dbvm_get_values(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = svm->columns;
+ int n;
+ dbvm_check_contents(L, svm);
+
+ lua_newtable(L);
+ for (n = 0; n < columns;) {
+ vm_push_column(L, vm, n++);
+ lua_rawseti(L, -2, n);
+ }
+ return 1;
+}
+
+static int dbvm_get_names(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = sqlite3_column_count(vm); /* valid as soon as statement prepared */
+ int n;
+
+ lua_newtable(L);
+ for (n = 0; n < columns;) {
+ lua_pushstring(L, sqlite3_column_name(vm, n++));
+ lua_rawseti(L, -2, n);
+ }
+ return 1;
+}
+
+static int dbvm_get_types(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = sqlite3_column_count(vm); /* valid as soon as statement prepared */
+ int n;
+
+ lua_newtable(L);
+ for (n = 0; n < columns;) {
+ lua_pushstring(L, sqlite3_column_decltype(vm, n++));
+ lua_rawseti(L, -2, n);
+ }
+ return 1;
+}
+
+static int dbvm_get_uvalues(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = svm->columns;
+ int n;
+ dbvm_check_contents(L, svm);
+
+ lua_checkstack(L, columns);
+ for (n = 0; n < columns; ++n)
+ vm_push_column(L, vm, n);
+ return columns;
+}
+
+static int dbvm_get_unames(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = sqlite3_column_count(vm); /* valid as soon as statement prepared */
+ int n;
+
+ lua_checkstack(L, columns);
+ for (n = 0; n < columns; ++n)
+ lua_pushstring(L, sqlite3_column_name(vm, n));
+ return columns;
+}
+
+static int dbvm_get_utypes(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = sqlite3_column_count(vm); /* valid as soon as statement prepared */
+ int n;
+
+ lua_checkstack(L, columns);
+ for (n = 0; n < columns; ++n)
+ lua_pushstring(L, sqlite3_column_decltype(vm, n));
+ return columns;
+}
+
+static int dbvm_get_named_values(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = svm->columns;
+ int n;
+ dbvm_check_contents(L, svm);
+
+ lua_newtable(L);
+ for (n = 0; n < columns; ++n) {
+ lua_pushstring(L, sqlite3_column_name(vm, n));
+ vm_push_column(L, vm, n);
+ lua_rawset(L, -3);
+ }
+ return 1;
+}
+
+static int dbvm_get_named_types(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int columns = sqlite3_column_count(vm);
+ int n;
+
+ lua_newtable(L);
+ for (n = 0; n < columns; ++n) {
+ lua_pushstring(L, sqlite3_column_name(vm, n));
+ lua_pushstring(L, sqlite3_column_decltype(vm, n));
+ lua_rawset(L, -3);
+ }
+ return 1;
+}
+
+/*
+** =======================================================
+** Virtual Machine - Bind
+** =======================================================
+*/
+
+static int dbvm_bind_index(lua_State *L, sqlite3_stmt *vm, int index, int lindex) {
+ switch (lua_type(L, lindex)) {
+ case LUA_TSTRING:
+ return sqlite3_bind_text(vm, index, lua_tostring(L, lindex), lua_strlen(L, lindex), SQLITE_TRANSIENT);
+ case LUA_TNUMBER:
+ return sqlite3_bind_double(vm, index, lua_tonumber(L, lindex));
+ case LUA_TBOOLEAN:
+ return sqlite3_bind_int(vm, index, lua_toboolean(L, lindex) ? 1 : 0);
+ case LUA_TNONE:
+ case LUA_TNIL:
+ return sqlite3_bind_null(vm, index);
+ default:
+ luaL_error(L, "index (%d) - invalid data type for bind (%s)", index, lua_typename(L, lua_type(L, lindex)));
+ return SQLITE_MISUSE; /*!*/
+ }
+}
+
+
+static int dbvm_bind_parameter_count(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ lua_pushnumber(L, sqlite3_bind_parameter_count(svm->vm));
+ return 1;
+}
+
+static int dbvm_bind_parameter_name(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ int index = (int)luaL_checknumber(L, 2);
+ dbvm_check_bind_index(L, svm, index);
+ lua_pushstring(L, sqlite3_bind_parameter_name(svm->vm, index));
+ return 1;
+}
+
+static int dbvm_bind(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int index = luaL_checkint(L, 2);
+ int result;
+
+ dbvm_check_bind_index(L, svm, index);
+ result = dbvm_bind_index(L, vm, index, 3);
+
+ lua_pushnumber(L, result);
+ return 1;
+}
+
+static int dbvm_bind_blob(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ int index = luaL_checkint(L, 2);
+ const char *value = luaL_checkstring(L, 3);
+ int len = lua_strlen(L, 3);
+
+ lua_pushnumber(L, sqlite3_bind_blob(svm->vm, index, value, len, SQLITE_TRANSIENT));
+ return 1;
+}
+
+static int dbvm_bind_values(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int top = lua_gettop(L);
+ int result, n;
+
+ if (top - 1 != sqlite3_bind_parameter_count(vm))
+ luaL_error(L,
+ "incorrect number of parameters to bind (%d given, %d to bind)",
+ top - 1,
+ sqlite3_bind_parameter_count(vm)
+ );
+
+ for (n = 2; n <= top; ++n) {
+ if ((result = dbvm_bind_index(L, vm, n - 1, n)) != SQLITE_OK) {
+ lua_pushnumber(L, result);
+ return 1;
+ }
+ }
+
+ lua_pushnumber(L, SQLITE_OK);
+ return 1;
+}
+
+static int dbvm_bind_names(lua_State *L) {
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm = svm->vm;
+ int count = sqlite3_bind_parameter_count(vm);
+ const char *name;
+ int result, n;
+ luaL_checktype(L, 2, LUA_TTABLE);
+
+ for (n = 1; n <= count; ++n) {
+ name = sqlite3_bind_parameter_name(vm, n);
+ if (name && (name[0] == ':' || name[0] == '$')) {
+ lua_pushstring(L, ++name);
+ lua_gettable(L, 2);
+ result = dbvm_bind_index(L, vm, n, -1);
+ lua_pop(L, 1);
+ }
+ else {
+ lua_pushnumber(L, n);
+ lua_gettable(L, 2);
+ result = dbvm_bind_index(L, vm, n, -1);
+ lua_pop(L, 1);
+ }
+
+ if (result != SQLITE_OK) {
+ lua_pushnumber(L, result);
+ return 1;
+ }
+ }
+
+ lua_pushnumber(L, SQLITE_OK);
+ return 1;
+}
+
+/*
+** =======================================================
+** Database (internal management)
+** =======================================================
+*/
+
+/*
+** When creating database handles, always creates a `closed' database handle
+** before opening the actual database; so, if there is a memory error, the
+** database is not left opened.
+**
+** Creates a new 'table' and leaves it in the stack
+*/
+static sdb *newdb (lua_State *L) {
+ sdb *db = (sdb*)lua_newuserdata(L, sizeof(sdb));
+ db->L = L;
+ db->db = NULL; /* database handle is currently `closed' */
+ db->func = NULL;
+
+ db->busy_cb =
+ db->busy_udata =
+ db->progress_cb =
+ db->progress_udata =
+ db->trace_cb =
+ db->trace_udata =
+#if !defined(LSQLITE_OMIT_UPDATE_HOOK) || !LSQLITE_OMIT_UPDATE_HOOK
+ db->update_hook_cb =
+ db->update_hook_udata =
+ db->commit_hook_cb =
+ db->commit_hook_udata =
+ db->rollback_hook_cb =
+ db->rollback_hook_udata =
+#endif
+ LUA_NOREF;
+
+ luaL_getmetatable(L, sqlite_meta);
+ lua_setmetatable(L, -2); /* set metatable */
+
+ /* to keep track of 'open' virtual machines */
+ lua_pushlightuserdata(L, db);
+ lua_newtable(L);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+
+ return db;
+}
+
+static int cleanupdb(lua_State *L, sdb *db) {
+ sdb_func *func;
+ sdb_func *func_next;
+ int top;
+ int result;
+
+ /* free associated virtual machines */
+ lua_pushlightuserdata(L, db);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+
+ /* close all used handles */
+ top = lua_gettop(L);
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ sdb_vm *svm = lua_touserdata(L, -2); /* key: vm; val: sql text */
+ cleanupvm(L, svm);
+
+ lua_settop(L, top);
+ lua_pushnil(L);
+ }
+
+ lua_pop(L, 1); /* pop vm table */
+
+ /* remove entry in lua registry table */
+ lua_pushlightuserdata(L, db);
+ lua_pushnil(L);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+
+ /* 'free' all references */
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_udata);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->progress_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->progress_udata);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->trace_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->trace_udata);
+#if !defined(LSQLITE_OMIT_UPDATE_HOOK) || !LSQLITE_OMIT_UPDATE_HOOK
+ luaL_unref(L, LUA_REGISTRYINDEX, db->update_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->update_hook_udata);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->commit_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->commit_hook_udata);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->rollback_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->rollback_hook_udata);
+#endif
+
+ /* close database */
+ result = sqlite3_close(db->db);
+ db->db = NULL;
+
+ /* free associated memory with created functions */
+ func = db->func;
+ while (func) {
+ func_next = func->next;
+ luaL_unref(L, LUA_REGISTRYINDEX, func->fn_step);
+ luaL_unref(L, LUA_REGISTRYINDEX, func->fn_finalize);
+ luaL_unref(L, LUA_REGISTRYINDEX, func->udata);
+ free(func);
+ func = func_next;
+ }
+ db->func = NULL;
+ return result;
+}
+
+static sdb *lsqlite_getdb(lua_State *L, int index) {
+ sdb *db = (sdb*)luaL_checkudata(L, index, sqlite_meta);
+ if (db == NULL) luaL_typerror(L, index, "sqlite database");
+ return db;
+}
+
+static sdb *lsqlite_checkdb(lua_State *L, int index) {
+ sdb *db = lsqlite_getdb(L, index);
+ if (db->db == NULL) luaL_argerror(L, index, "attempt to use closed sqlite database");
+ return db;
+}
+
+
+/*
+** =======================================================
+** User Defined Functions - Context Methods
+** =======================================================
+*/
+typedef struct {
+ sqlite3_context *ctx;
+ int ud;
+} lcontext;
+
+static lcontext *lsqlite_make_context(lua_State *L) {
+ lcontext *ctx = (lcontext*)lua_newuserdata(L, sizeof(lcontext));
+ lua_rawgeti(L, LUA_REGISTRYINDEX, sqlite_ctx_meta_ref);
+ lua_setmetatable(L, -2);
+ ctx->ctx = NULL;
+ ctx->ud = LUA_NOREF;
+ return ctx;
+}
+
+static lcontext *lsqlite_getcontext(lua_State *L, int index) {
+ lcontext *ctx = (lcontext*)luaL_checkudata(L, index, sqlite_ctx_meta);
+ if (ctx == NULL) luaL_typerror(L, index, "sqlite context");
+ return ctx;
+}
+
+static lcontext *lsqlite_checkcontext(lua_State *L, int index) {
+ lcontext *ctx = lsqlite_getcontext(L, index);
+ if (ctx->ctx == NULL) luaL_argerror(L, index, "invalid sqlite context");
+ return ctx;
+}
+
+static int lcontext_tostring(lua_State *L) {
+ char buff[39];
+ lcontext *ctx = lsqlite_getcontext(L, 1);
+ if (ctx->ctx == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", ctx->ctx);
+ lua_pushfstring(L, "sqlite function context (%s)", buff);
+ return 1;
+}
+
+static void lcontext_check_aggregate(lua_State *L, lcontext *ctx) {
+ sdb_func *func = (sdb_func*)sqlite3_user_data(ctx->ctx);
+ if (!func->aggregate) {
+ luaL_error(L, "attempt to call aggregate method from scalar function");
+ }
+}
+
+static int lcontext_user_data(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ sdb_func *func = (sdb_func*)sqlite3_user_data(ctx->ctx);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, func->udata);
+ return 1;
+}
+
+static int lcontext_get_aggregate_context(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ lcontext_check_aggregate(L, ctx);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->ud);
+ return 1;
+}
+
+static int lcontext_set_aggregate_context(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ lcontext_check_aggregate(L, ctx);
+ lua_settop(L, 2);
+ luaL_unref(L, LUA_REGISTRYINDEX, ctx->ud);
+ ctx->ud = luaL_ref(L, LUA_REGISTRYINDEX);
+ return 0;
+}
+
+static int lcontext_aggregate_count(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ lcontext_check_aggregate(L, ctx);
+ lua_pushnumber(L, sqlite3_aggregate_count(ctx->ctx));
+ return 1;
+}
+
+#if 0
+void *sqlite3_get_auxdata(sqlite3_context*, int);
+void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));
+#endif
+
+static int lcontext_result(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ switch (lua_type(L, 2)) {
+ case LUA_TNUMBER:
+ sqlite3_result_double(ctx->ctx, luaL_checknumber(L, 2));
+ break;
+ case LUA_TSTRING:
+ sqlite3_result_text(ctx->ctx, luaL_checkstring(L, 2), lua_strlen(L, 2), SQLITE_TRANSIENT);
+ break;
+ case LUA_TNIL:
+ case LUA_TNONE:
+ sqlite3_result_null(ctx->ctx);
+ break;
+ default:
+ luaL_error(L, "invalid result type %s", lua_typename(L, 2));
+ break;
+ }
+
+ return 0;
+}
+
+static int lcontext_result_blob(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ const char *blob = luaL_checkstring(L, 2);
+ int size = lua_strlen(L, 2);
+ sqlite3_result_blob(ctx->ctx, (const void*)blob, size, SQLITE_TRANSIENT);
+ return 0;
+}
+
+static int lcontext_result_double(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ double d = luaL_checknumber(L, 2);
+ sqlite3_result_double(ctx->ctx, d);
+ return 0;
+}
+
+static int lcontext_result_error(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ const char *err = luaL_checkstring(L, 2);
+ int size = lua_strlen(L, 2);
+ sqlite3_result_error(ctx->ctx, err, size);
+ return 0;
+}
+
+static int lcontext_result_int(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ int i = luaL_checkint(L, 2);
+ sqlite3_result_int(ctx->ctx, i);
+ return 0;
+}
+
+static int lcontext_result_null(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ sqlite3_result_null(ctx->ctx);
+ return 0;
+}
+
+static int lcontext_result_text(lua_State *L) {
+ lcontext *ctx = lsqlite_checkcontext(L, 1);
+ const char *text = luaL_checkstring(L, 2);
+ int size = lua_strlen(L, 2);
+ sqlite3_result_text(ctx->ctx, text, size, SQLITE_TRANSIENT);
+ return 0;
+}
+
+/*
+** =======================================================
+** Database Methods
+** =======================================================
+*/
+
+static int db_isopen(lua_State *L) {
+ sdb *db = lsqlite_getdb(L, 1);
+ lua_pushboolean(L, db->db != NULL ? 1 : 0);
+ return 1;
+}
+
+static int db_last_insert_rowid(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ /* conversion warning: int64 -> luaNumber */
+ sqlite_int64 rowid = sqlite3_last_insert_rowid(db->db);
+ lua_Number n = (lua_Number)rowid;
+ if (n == rowid)
+ lua_pushnumber(L, n);
+ else
+ lua_pushfstring(L, "%ll", rowid);
+ return 1;
+}
+
+static int db_changes(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ lua_pushnumber(L, sqlite3_changes(db->db));
+ return 1;
+}
+
+static int db_total_changes(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ lua_pushnumber(L, sqlite3_total_changes(db->db));
+ return 1;
+}
+
+static int db_errcode(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ lua_pushnumber(L, sqlite3_errcode(db->db));
+ return 1;
+}
+
+static int db_errmsg(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ lua_pushstring(L, sqlite3_errmsg(db->db));
+ return 1;
+}
+
+static int db_interrupt(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ sqlite3_interrupt(db->db);
+ return 0;
+}
+
+/*
+** Registering SQL functions:
+*/
+
+static void db_push_value(lua_State *L, sqlite3_value *value) {
+ switch (sqlite3_value_type(value)) {
+ case SQLITE_TEXT:
+ lua_pushlstring(L, (const char*)sqlite3_value_text(value), sqlite3_value_bytes(value));
+ break;
+
+ case SQLITE_INTEGER:
+ {
+ sqlite_int64 i64 = sqlite3_value_int64(value);
+ lua_Number n = (lua_Number)i64;
+ if (n == i64)
+ lua_pushnumber(L, n);
+ else
+ lua_pushlstring(L, (const char*)sqlite3_value_text(value), sqlite3_value_bytes(value));
+ }
+ break;
+
+ case SQLITE_FLOAT:
+ lua_pushnumber(L, sqlite3_value_double(value));
+ break;
+
+ case SQLITE_BLOB:
+ lua_pushlstring(L, sqlite3_value_blob(value), sqlite3_value_bytes(value));
+ break;
+
+ case SQLITE_NULL:
+ lua_pushnil(L);
+ break;
+
+ default:
+ /* things done properly (SQLite + Lua SQLite)
+ ** this should never happen */
+ lua_pushnil(L);
+ break;
+ }
+}
+
+/*
+** callback functions used when calling registered sql functions
+*/
+
+/* scalar function to be called
+** callback params: context, values... */
+static void db_sql_normal_function(sqlite3_context *context, int argc, sqlite3_value **argv) {
+ sdb_func *func = (sdb_func*)sqlite3_user_data(context);
+ lua_State *L = func->db->L;
+ int n;
+ lcontext *ctx;
+
+ int top = lua_gettop(L);
+
+ /* ensure there is enough space in the stack */
+ lua_checkstack(L, argc + 3);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, func->fn_step); /* function to call */
+
+ if (!func->aggregate) {
+ ctx = lsqlite_make_context(L); /* push context - used to set results */
+ }
+ else {
+ /* reuse context userdata value */
+ void *p = sqlite3_aggregate_context(context, 1);
+ /* i think it is OK to use assume that using a light user data
+ ** as an entry on LUA REGISTRY table will be unique */
+ lua_pushlightuserdata(L, p);
+ lua_rawget(L, LUA_REGISTRYINDEX); /* context table */
+
+ if (lua_isnil(L, -1)) { /* not yet created? */
+ lua_pop(L, 1);
+ ctx = lsqlite_make_context(L);
+ lua_pushlightuserdata(L, p);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+ else
+ ctx = lsqlite_getcontext(L, -1);
+ }
+
+ /* push params */
+ for (n = 0; n < argc; ++n) {
+ db_push_value(L, argv[n]);
+ }
+
+ /* set context */
+ ctx->ctx = context;
+
+ if (lua_pcall(L, argc + 1, 0, 0)) {
+ const char *errmsg = lua_tostring(L, -1);
+ int size = lua_strlen(L, -1);
+ sqlite3_result_error(context, errmsg, size);
+ }
+
+ /* invalidate context */
+ ctx->ctx = NULL;
+
+ if (!func->aggregate) {
+ luaL_unref(L, LUA_REGISTRYINDEX, ctx->ud);
+ }
+
+ lua_settop(L, top);
+}
+
+static void db_sql_finalize_function(sqlite3_context *context) {
+ sdb_func *func = (sdb_func*)sqlite3_user_data(context);
+ lua_State *L = func->db->L;
+ void *p = sqlite3_aggregate_context(context, 1); /* minimal mem usage */
+ lcontext *ctx;
+ int top = lua_gettop(L);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, func->fn_finalize); /* function to call */
+
+ /* i think it is OK to use assume that using a light user data
+ ** as an entry on LUA REGISTRY table will be unique */
+ lua_pushlightuserdata(L, p);
+ lua_rawget(L, LUA_REGISTRYINDEX); /* context table */
+
+ if (lua_isnil(L, -1)) { /* not yet created? - shouldn't happen in finalize function */
+ lua_pop(L, 1);
+ ctx = lsqlite_make_context(L);
+ lua_pushlightuserdata(L, p);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+ else
+ ctx = lsqlite_getcontext(L, -1);
+
+ /* set context */
+ ctx->ctx = context;
+
+ if (lua_pcall(L, 1, 0, 0)) {
+ sqlite3_result_error(context, lua_tostring(L, -1), -1);
+ }
+
+ /* invalidate context */
+ ctx->ctx = NULL;
+
+ /* cleanup context */
+ luaL_unref(L, LUA_REGISTRYINDEX, ctx->ud);
+ /* remove it from registry */
+ lua_pushlightuserdata(L, p);
+ lua_pushnil(L);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+
+ lua_settop(L, top);
+}
+
+/*
+** Register a normal function
+** Params: db, function name, number arguments, [ callback | step, finalize], user data
+** Returns: true on sucess
+**
+** Normal function:
+** Params: context, params
+**
+** Aggregate function:
+** Params of step: context, params
+** Params of finalize: context
+*/
+static int db_register_function(lua_State *L, int aggregate) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ const char *name;
+ int args;
+ int result;
+ sdb_func *func;
+
+ /* safety measure */
+ if (aggregate) aggregate = 1;
+
+ name = luaL_checkstring(L, 2);
+ args = luaL_checkint(L, 3);
+ luaL_checktype(L, 4, LUA_TFUNCTION);
+ if (aggregate) luaL_checktype(L, 5, LUA_TFUNCTION);
+
+ /* maybe an alternative way to allocate memory should be used/avoided */
+ func = (sdb_func*)malloc(sizeof(sdb_func));
+ if (func == NULL) {
+ luaL_error(L, "out of memory");
+ }
+
+ result = sqlite3_create_function(
+ db->db, name, args, SQLITE_UTF8, func,
+ aggregate ? NULL : db_sql_normal_function,
+ aggregate ? db_sql_normal_function : NULL,
+ aggregate ? db_sql_finalize_function : NULL
+ );
+
+ if (result == SQLITE_OK) {
+ /* safety measures for userdata field to be present in the stack */
+ lua_settop(L, 5 + aggregate);
+
+ /* save registered function in db function list */
+ func->db = db;
+ func->aggregate = aggregate;
+ func->next = db->func;
+ db->func = func;
+
+ /* save the setp/normal function callback */
+ lua_pushvalue(L, 4);
+ func->fn_step = luaL_ref(L, LUA_REGISTRYINDEX);
+ /* save user data */
+ lua_pushvalue(L, 5+aggregate);
+ func->udata = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ if (aggregate) {
+ lua_pushvalue(L, 5);
+ func->fn_finalize = luaL_ref(L, LUA_REGISTRYINDEX);
+ }
+ else
+ func->fn_finalize = LUA_NOREF;
+ }
+ else {
+ /* free allocated memory */
+ free(func);
+ }
+
+ lua_pushboolean(L, result == SQLITE_OK ? 1 : 0);
+ return 1;
+}
+
+static int db_create_function(lua_State *L) {
+ return db_register_function(L, 0);
+}
+
+static int db_create_aggregate(lua_State *L) {
+ return db_register_function(L, 1);
+}
+
+/* create_collation; contributed by Thomas Lauer
+*/
+
+typedef struct {
+ lua_State *L;
+ int ref;
+} scc;
+
+static int collwrapper(scc *co,int l1,const void *p1,
+ int l2,const void *p2) {
+ int res=0;
+ lua_State *L=co->L;
+ lua_rawgeti(L,LUA_REGISTRYINDEX,co->ref);
+ lua_pushlstring(L,p1,l1);
+ lua_pushlstring(L,p2,l2);
+ if (lua_pcall(L,2,1,0)==0) res=(int)lua_tonumber(L,-1);
+ lua_pop(L,1);
+ return res;
+}
+
+static void collfree(scc *co) {
+ if (co) {
+ luaL_unref(co->L,LUA_REGISTRYINDEX,co->ref);
+ free(co);
+ }
+}
+
+static int db_create_collation(lua_State *L) {
+ sdb *db=lsqlite_checkdb(L,1);
+ const char *collname=luaL_checkstring(L,2);
+ scc *co=NULL;
+ int (*collfunc)(scc *,int,const void *,int,const void *)=NULL;
+ lua_settop(L,3); /* default args to nil, and exclude extras */
+ if (lua_isfunction(L,3)) collfunc=collwrapper;
+ else if (!lua_isnil(L,3))
+ luaL_error(L,"create_collation: function or nil expected");
+ if (collfunc != NULL) {
+ co=(scc *)malloc(sizeof(scc)); /* userdata is a no-no as it
+ will be garbage-collected */
+ if (co) {
+ co->L=L;
+ /* lua_settop(L,3) above means we don't need: lua_pushvalue(L,3); */
+ co->ref=luaL_ref(L,LUA_REGISTRYINDEX);
+ }
+ else luaL_error(L,"create_collation: could not allocate callback");
+ }
+ sqlite3_create_collation_v2(db->db, collname, SQLITE_UTF8,
+ (void *)co,
+ (int(*)(void*,int,const void*,int,const void*))collfunc,
+ (void(*)(void*))collfree);
+ return 0;
+}
+
+/*
+** trace callback:
+** Params: database, callback function, userdata
+**
+** callback function:
+** Params: userdata, sql
+*/
+static void db_trace_callback(void *user, const char *sql) {
+ sdb *db = (sdb*)user;
+ lua_State *L = db->L;
+ int top = lua_gettop(L);
+
+ /* setup lua callback call */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->trace_cb); /* get callback */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->trace_udata); /* get callback user data */
+ lua_pushstring(L, sql); /* traced sql statement */
+
+ /* call lua function */
+ lua_pcall(L, 2, 0, 0);
+ /* ignore any error generated by this function */
+
+ lua_settop(L, top);
+}
+
+static int db_trace(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+
+ if (lua_gettop(L) < 2 || lua_isnil(L, 2)) {
+ luaL_unref(L, LUA_REGISTRYINDEX, db->trace_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->trace_udata);
+
+ db->trace_cb =
+ db->trace_udata = LUA_NOREF;
+
+ /* clear trace handler */
+ sqlite3_trace(db->db, NULL, NULL);
+ }
+ else {
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ /* make sure we have an userdata field (even if nil) */
+ lua_settop(L, 3);
+
+ luaL_unref(L, LUA_REGISTRYINDEX, db->trace_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->trace_udata);
+
+ db->trace_udata = luaL_ref(L, LUA_REGISTRYINDEX);
+ db->trace_cb = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* set trace handler */
+ sqlite3_trace(db->db, db_trace_callback, db);
+ }
+
+ return 0;
+}
+
+#if !defined(LSQLITE_OMIT_UPDATE_HOOK) || !LSQLITE_OMIT_UPDATE_HOOK
+
+/*
+** update_hook callback:
+** Params: database, callback function, userdata
+**
+** callback function:
+** Params: userdata, {one of SQLITE_INSERT, SQLITE_DELETE, or SQLITE_UPDATE},
+** database name, table name (containing the affected row), rowid of the row
+*/
+static void db_update_hook_callback(void *user, int op, char const *dbname, char const *tblname, sqlite3_int64 rowid) {
+ sdb *db = (sdb*)user;
+ lua_State *L = db->L;
+ int top = lua_gettop(L);
+ lua_Number n = (lua_Number)rowid;
+
+ /* setup lua callback call */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->update_hook_cb); /* get callback */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->update_hook_udata); /* get callback user data */
+ lua_pushnumber(L, (lua_Number )op);
+ lua_pushstring(L, dbname); /* update_hook database name */
+ lua_pushstring(L, tblname); /* update_hook database name */
+ if (n == rowid)
+ lua_pushnumber(L, n);
+ else
+ lua_pushfstring(L, "%ll", rowid);
+
+ /* call lua function */
+ lua_pcall(L, 5, 0, 0);
+ /* ignore any error generated by this function */
+
+ lua_settop(L, top);
+}
+
+static int db_update_hook(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+
+ if (lua_gettop(L) < 2 || lua_isnil(L, 2)) {
+ luaL_unref(L, LUA_REGISTRYINDEX, db->update_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->update_hook_udata);
+
+ db->update_hook_cb =
+ db->update_hook_udata = LUA_NOREF;
+
+ /* clear update_hook handler */
+ sqlite3_update_hook(db->db, NULL, NULL);
+ }
+ else {
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ /* make sure we have an userdata field (even if nil) */
+ lua_settop(L, 3);
+
+ luaL_unref(L, LUA_REGISTRYINDEX, db->update_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->update_hook_udata);
+
+ db->update_hook_udata = luaL_ref(L, LUA_REGISTRYINDEX);
+ db->update_hook_cb = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* set update_hook handler */
+ sqlite3_update_hook(db->db, db_update_hook_callback, db);
+ }
+
+ return 0;
+}
+
+/*
+** commit_hook callback:
+** Params: database, callback function, userdata
+**
+** callback function:
+** Params: userdata
+** Returned value: Return false or nil to continue the COMMIT operation normally.
+** return true (non false, non nil), then the COMMIT is converted into a ROLLBACK.
+*/
+static int db_commit_hook_callback(void *user) {
+ sdb *db = (sdb*)user;
+ lua_State *L = db->L;
+ int top = lua_gettop(L);
+ int rollback = 0;
+
+ /* setup lua callback call */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->commit_hook_cb); /* get callback */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->commit_hook_udata); /* get callback user data */
+
+ /* call lua function */
+ if (!lua_pcall(L, 1, 1, 0))
+ rollback = lua_toboolean(L, -1); /* use result if there was no error */
+
+ lua_settop(L, top);
+ return rollback;
+}
+
+static int db_commit_hook(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+
+ if (lua_gettop(L) < 2 || lua_isnil(L, 2)) {
+ luaL_unref(L, LUA_REGISTRYINDEX, db->commit_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->commit_hook_udata);
+
+ db->commit_hook_cb =
+ db->commit_hook_udata = LUA_NOREF;
+
+ /* clear commit_hook handler */
+ sqlite3_commit_hook(db->db, NULL, NULL);
+ }
+ else {
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ /* make sure we have an userdata field (even if nil) */
+ lua_settop(L, 3);
+
+ luaL_unref(L, LUA_REGISTRYINDEX, db->commit_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->commit_hook_udata);
+
+ db->commit_hook_udata = luaL_ref(L, LUA_REGISTRYINDEX);
+ db->commit_hook_cb = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* set commit_hook handler */
+ sqlite3_commit_hook(db->db, db_commit_hook_callback, db);
+ }
+
+ return 0;
+}
+
+/*
+** rollback hook callback:
+** Params: database, callback function, userdata
+**
+** callback function:
+** Params: userdata
+*/
+static void db_rollback_hook_callback(void *user) {
+ sdb *db = (sdb*)user;
+ lua_State *L = db->L;
+ int top = lua_gettop(L);
+
+ /* setup lua callback call */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->rollback_hook_cb); /* get callback */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->rollback_hook_udata); /* get callback user data */
+
+ /* call lua function */
+ lua_pcall(L, 1, 0, 0);
+ /* ignore any error generated by this function */
+
+ lua_settop(L, top);
+}
+
+static int db_rollback_hook(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+
+ if (lua_gettop(L) < 2 || lua_isnil(L, 2)) {
+ luaL_unref(L, LUA_REGISTRYINDEX, db->rollback_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->rollback_hook_udata);
+
+ db->rollback_hook_cb =
+ db->rollback_hook_udata = LUA_NOREF;
+
+ /* clear rollback_hook handler */
+ sqlite3_rollback_hook(db->db, NULL, NULL);
+ }
+ else {
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ /* make sure we have an userdata field (even if nil) */
+ lua_settop(L, 3);
+
+ luaL_unref(L, LUA_REGISTRYINDEX, db->rollback_hook_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->rollback_hook_udata);
+
+ db->rollback_hook_udata = luaL_ref(L, LUA_REGISTRYINDEX);
+ db->rollback_hook_cb = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* set rollback_hook handler */
+ sqlite3_rollback_hook(db->db, db_rollback_hook_callback, db);
+ }
+
+ return 0;
+}
+
+#endif /* #if !defined(LSQLITE_OMIT_UPDATE_HOOK) || !LSQLITE_OMIT_UPDATE_HOOK */
+
+#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK) || !SQLITE_OMIT_PROGRESS_CALLBACK
+
+/*
+** progress handler:
+** Params: database, number of opcodes, callback function, userdata
+**
+** callback function:
+** Params: userdata
+** returns: 0 to return immediatly and return SQLITE_ABORT, non-zero to continue
+*/
+static int db_progress_callback(void *user) {
+ int result = 1; /* abort by default */
+ sdb *db = (sdb*)user;
+ lua_State *L = db->L;
+ int top = lua_gettop(L);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->progress_cb);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->progress_udata);
+
+ /* call lua function */
+ if (!lua_pcall(L, 1, 1, 0))
+ result = lua_toboolean(L, -1);
+
+ lua_settop(L, top);
+ return result;
+}
+
+static int db_progress_handler(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+
+ if (lua_gettop(L) < 2 || lua_isnil(L, 2)) {
+ luaL_unref(L, LUA_REGISTRYINDEX, db->progress_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->progress_udata);
+
+ db->progress_cb =
+ db->progress_udata = LUA_NOREF;
+
+ /* clear busy handler */
+ sqlite3_progress_handler(db->db, 0, NULL, NULL);
+ }
+ else {
+ int nop = luaL_checkint(L, 2); /* number of opcodes */
+ luaL_checktype(L, 3, LUA_TFUNCTION);
+
+ /* make sure we have an userdata field (even if nil) */
+ lua_settop(L, 4);
+
+ luaL_unref(L, LUA_REGISTRYINDEX, db->progress_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->progress_udata);
+
+ db->progress_udata = luaL_ref(L, LUA_REGISTRYINDEX);
+ db->progress_cb = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* set progress callback */
+ sqlite3_progress_handler(db->db, nop, db_progress_callback, db);
+ }
+
+ return 0;
+}
+
+#else /* #if !defined(SQLITE_OMIT_PROGRESS_CALLBACK) || !SQLITE_OMIT_PROGRESS_CALLBACK */
+
+static int db_progress_handler(lua_State *L) {
+ lua_pushliteral(L, "progress callback support disabled at compile time");
+ lua_error(L);
+ return 0;
+}
+
+#endif /* #if !defined(SQLITE_OMIT_PROGRESS_CALLBACK) || !SQLITE_OMIT_PROGRESS_CALLBACK */
+
+/*
+** busy handler:
+** Params: database, callback function, userdata
+**
+** callback function:
+** Params: userdata, number of tries
+** returns: 0 to return immediatly and return SQLITE_BUSY, non-zero to try again
+*/
+static int db_busy_callback(void *user, int tries) {
+ int retry = 0; /* abort by default */
+ sdb *db = (sdb*)user;
+ lua_State *L = db->L;
+ int top = lua_gettop(L);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->busy_cb);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, db->busy_udata);
+ lua_pushnumber(L, tries);
+
+ /* call lua function */
+ if (!lua_pcall(L, 2, 1, 0))
+ retry = lua_toboolean(L, -1);
+
+ lua_settop(L, top);
+ return retry;
+}
+
+static int db_busy_handler(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+
+ if (lua_gettop(L) < 2 || lua_isnil(L, 2)) {
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_udata);
+
+ db->busy_cb =
+ db->busy_udata = LUA_NOREF;
+
+ /* clear busy handler */
+ sqlite3_busy_handler(db->db, NULL, NULL);
+ }
+ else {
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ /* make sure we have an userdata field (even if nil) */
+ lua_settop(L, 3);
+
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_udata);
+
+ db->busy_udata = luaL_ref(L, LUA_REGISTRYINDEX);
+ db->busy_cb = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* set busy handler */
+ sqlite3_busy_handler(db->db, db_busy_callback, db);
+ }
+
+ return 0;
+}
+
+static int db_busy_timeout(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ int timeout = luaL_checkint(L, 2);
+ sqlite3_busy_timeout(db->db, timeout);
+
+ /* if there was a timeout callback registered, it is now
+ ** invalid/useless. free any references we may have */
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_cb);
+ luaL_unref(L, LUA_REGISTRYINDEX, db->busy_udata);
+ db->busy_cb =
+ db->busy_udata = LUA_NOREF;
+
+ return 0;
+}
+
+/*
+** Params: db, sql, callback, user
+** returns: code [, errmsg]
+**
+** Callback:
+** Params: user, number of columns, values, names
+** Returns: 0 to continue, other value will cause abort
+*/
+static int db_exec_callback(void* user, int columns, char **data, char **names) {
+ int result = SQLITE_ABORT; /* abort by default */
+ lua_State *L = (lua_State*)user;
+ int n;
+
+ int top = lua_gettop(L);
+
+ lua_pushvalue(L, 3); /* function to call */
+ lua_pushvalue(L, 4); /* user data */
+ lua_pushnumber(L, columns); /* total number of rows in result */
+
+ /* column values */
+ lua_pushvalue(L, 6);
+ for (n = 0; n < columns;) {
+ lua_pushstring(L, data[n++]);
+ lua_rawseti(L, -2, n);
+ }
+
+ /* columns names */
+ lua_pushvalue(L, 5);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ lua_pushvalue(L, -1);
+ lua_replace(L, 5);
+ for (n = 0; n < columns;) {
+ lua_pushstring(L, names[n++]);
+ lua_rawseti(L, -2, n);
+ }
+ }
+
+ /* call lua function */
+ if (!lua_pcall(L, 4, 1, 0)) {
+ if (lua_isnumber(L, -1))
+ result = (int)lua_tonumber(L, -1);
+ }
+
+ lua_settop(L, top);
+ return result;
+}
+
+static int db_exec(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ const char *sql = luaL_checkstring(L, 2);
+ int result;
+
+ if (!lua_isnoneornil(L, 3)) {
+ /* stack:
+ ** 3: callback function
+ ** 4: userdata
+ ** 5: column names
+ ** 6: reusable column values
+ */
+ luaL_checktype(L, 3, LUA_TFUNCTION);
+ lua_settop(L, 4); /* 'trap' userdata - nil extra parameters */
+ lua_pushnil(L); /* column names not known at this point */
+ lua_newtable(L); /* column values table */
+
+ result = sqlite3_exec(db->db, sql, db_exec_callback, L, NULL);
+ }
+ else {
+ /* no callbacks */
+ result = sqlite3_exec(db->db, sql, NULL, NULL, NULL);
+ }
+
+ lua_pushnumber(L, result);
+ return 1;
+}
+
+/*
+** Params: db, sql
+** returns: code, compiled length or error message
+*/
+static int db_prepare(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ const char *sql = luaL_checkstring(L, 2);
+ int sql_len = lua_strlen(L, 2);
+ const char *sqltail;
+ sdb_vm *svm;
+ lua_settop(L,2); /* sql is on top of stack for call to newvm */
+ svm = newvm(L, db);
+
+ if (sqlite3_prepare(db->db, sql, sql_len, &svm->vm, &sqltail) != SQLITE_OK) {
+ cleanupvm(L, svm);
+
+ lua_pushnil(L);
+ lua_pushnumber(L, sqlite3_errcode(db->db));
+ return 2;
+ }
+
+ /* vm already in the stack */
+ lua_pushstring(L, sqltail);
+ return 2;
+}
+
+static int db_do_next_row(lua_State *L, int packed) {
+ int result;
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
+ sqlite3_stmt *vm;
+ int columns;
+ int i;
+
+ result = stepvm(L, svm);
+ vm = svm->vm; /* stepvm may change svm->vm if re-prepare is needed */
+ svm->has_values = result == SQLITE_ROW ? 1 : 0;
+ svm->columns = columns = sqlite3_data_count(vm);
+
+ if (result == SQLITE_ROW) {
+ if (packed) {
+ lua_newtable(L);
+ if (packed == 1) {
+ for (i = 0; i < columns;) {
+ vm_push_column(L, vm, i);
+ lua_rawseti(L, -2, ++i);
+ }
+ }
+ else {
+ for (i = 0; i < columns; ++i) {
+ lua_pushstring(L, sqlite3_column_name(vm, i));
+ vm_push_column(L, vm, i);
+ lua_rawset(L, -3);
+ }
+ }
+ return 1;
+ }
+ else {
+ lua_checkstack(L, columns);
+ for (i = 0; i < columns; ++i)
+ vm_push_column(L, vm, i);
+ return svm->columns;
+ }
+ }
+
+ if (svm->temp) {
+ /* finalize and check for errors */
+ result = sqlite3_finalize(vm);
+ svm->vm = NULL;
+ cleanupvm(L, svm);
+ }
+ else if (result == SQLITE_DONE) {
+ result = sqlite3_reset(vm);
+ }
+
+ if (result != SQLITE_OK) {
+ lua_pushstring(L, sqlite3_errmsg(svm->db->db));
+ lua_error(L);
+ }
+ return 0;
+}
+
+static int db_next_row(lua_State *L) {
+ return db_do_next_row(L, 0);
+}
+
+static int db_next_packed_row(lua_State *L) {
+ return db_do_next_row(L, 1);
+}
+
+static int db_next_named_row(lua_State *L) {
+ return db_do_next_row(L, 2);
+}
+
+static int dbvm_do_rows(lua_State *L, int(*f)(lua_State *)) {
+ /* sdb_vm *svm = */
+ lsqlite_checkvm(L, 1);
+ lua_pushvalue(L,1);
+ lua_pushcfunction(L, f);
+ lua_insert(L, -2);
+ return 2;
+}
+
+static int dbvm_rows(lua_State *L) {
+ return dbvm_do_rows(L, db_next_packed_row);
+}
+
+static int dbvm_nrows(lua_State *L) {
+ return dbvm_do_rows(L, db_next_named_row);
+}
+
+static int dbvm_urows(lua_State *L) {
+ return dbvm_do_rows(L, db_next_row);
+}
+
+static int db_do_rows(lua_State *L, int(*f)(lua_State *)) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ const char *sql = luaL_checkstring(L, 2);
+ sdb_vm *svm;
+ lua_settop(L,2); /* sql is on top of stack for call to newvm */
+ svm = newvm(L, db);
+ svm->temp = 1;
+
+ if (sqlite3_prepare(db->db, sql, -1, &svm->vm, NULL) != SQLITE_OK) {
+ cleanupvm(L, svm);
+
+ lua_pushstring(L, sqlite3_errmsg(svm->db->db));
+ lua_error(L);
+ }
+
+ lua_pushcfunction(L, f);
+ lua_insert(L, -2);
+ return 2;
+}
+
+static int db_rows(lua_State *L) {
+ return db_do_rows(L, db_next_packed_row);
+}
+
+static int db_nrows(lua_State *L) {
+ return db_do_rows(L, db_next_named_row);
+}
+
+/* unpacked version of db:rows */
+static int db_urows(lua_State *L) {
+ return db_do_rows(L, db_next_row);
+}
+
+static int db_tostring(lua_State *L) {
+ char buff[32];
+ sdb *db = lsqlite_getdb(L, 1);
+ if (db->db == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", lua_touserdata(L, 1));
+ lua_pushfstring(L, "sqlite database (%s)", buff);
+ return 1;
+}
+
+static int db_close(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ lua_pushnumber(L, cleanupdb(L, db));
+ return 1;
+}
+
+static int db_close_vm(lua_State *L) {
+ sdb *db = lsqlite_checkdb(L, 1);
+ /* cleanup temporary only tables? */
+ int temp = lua_toboolean(L, 2);
+
+ /* free associated virtual machines */
+ lua_pushlightuserdata(L, db);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+
+ /* close all used handles */
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ sdb_vm *svm = lua_touserdata(L, -2); /* key: vm; val: sql text */
+
+ if ((!temp || svm->temp) && svm->vm)
+ {
+ sqlite3_finalize(svm->vm);
+ svm->vm = NULL;
+ }
+
+ /* leave key in the stack */
+ lua_pop(L, 1);
+ }
+ return 0;
+}
+
+static int db_gc(lua_State *L) {
+ sdb *db = lsqlite_getdb(L, 1);
+ if (db->db != NULL) /* ignore closed databases */
+ cleanupdb(L, db);
+ return 0;
+}
+
+/*
+** =======================================================
+** General library functions
+** =======================================================
+*/
+
+static int lsqlite_version(lua_State *L) {
+ lua_pushstring(L, sqlite3_libversion());
+ return 1;
+}
+
+static int lsqlite_complete(lua_State *L) {
+ const char *sql = luaL_checkstring(L, 1);
+ lua_pushboolean(L, sqlite3_complete(sql));
+ return 1;
+}
+
+#ifndef WIN32
+static int lsqlite_temp_directory(lua_State *L) {
+ const char *oldtemp = sqlite3_temp_directory;
+
+ if (!lua_isnone(L, 1)) {
+ const char *temp = luaL_optstring(L, 1, NULL);
+ if (sqlite3_temp_directory) {
+ sqlite3_free((char*)sqlite3_temp_directory);
+ }
+ if (temp) {
+ sqlite3_temp_directory = sqlite3_mprintf("%s", temp);
+ }
+ else {
+ sqlite3_temp_directory = NULL;
+ }
+ }
+ lua_pushstring(L, oldtemp);
+ return 1;
+}
+#endif
+
+static int lsqlite_do_open(lua_State *L, const char *filename) {
+ sdb *db = newdb(L); /* create and leave in stack */
+
+ if (sqlite3_open(filename, &db->db) == SQLITE_OK) {
+ /* database handle already in the stack - return it */
+ return 1;
+ }
+
+ /* failed to open database */
+ lua_pushnil(L); /* push nil */
+ lua_pushnumber(L, sqlite3_errcode(db->db));
+ lua_pushstring(L, sqlite3_errmsg(db->db)); /* push error message */
+
+ /* clean things up */
+ cleanupdb(L, db);
+
+ /* return */
+ return 3;
+}
+
+static int lsqlite_open(lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ return lsqlite_do_open(L, filename);
+}
+
+static int lsqlite_open_memory(lua_State *L) {
+ return lsqlite_do_open(L, ":memory:");
+}
+
+static int lsqlite_newindex(lua_State *L) {
+ lua_pushliteral(L, "attempt to change readonly table");
+ lua_error(L);
+ return 0;
+}
+
+/*
+** =======================================================
+** Register functions
+** =======================================================
+*/
+
+#define SC(s) { #s, SQLITE_ ## s },
+#define LSC(s) { #s, LSQLITE_ ## s },
+
+static const struct {
+ const char* name;
+ int value;
+} sqlite_constants[] = {
+ /* error codes */
+ SC(OK) SC(ERROR) SC(INTERNAL) SC(PERM)
+ SC(ABORT) SC(BUSY) SC(LOCKED) SC(NOMEM)
+ SC(READONLY) SC(INTERRUPT) SC(IOERR) SC(CORRUPT)
+ SC(NOTFOUND) SC(FULL) SC(CANTOPEN) SC(PROTOCOL)
+ SC(EMPTY) SC(SCHEMA) SC(TOOBIG) SC(CONSTRAINT)
+ SC(MISMATCH) SC(MISUSE) SC(NOLFS)
+ SC(FORMAT) SC(NOTADB)
+
+ /* sqlite_step specific return values */
+ SC(RANGE) SC(ROW) SC(DONE)
+
+ /* column types */
+ SC(INTEGER) SC(FLOAT) SC(TEXT) SC(BLOB)
+ SC(NULL)
+
+ /* Authorizer Action Codes */
+ SC(CREATE_INDEX )
+ SC(CREATE_TABLE )
+ SC(CREATE_TEMP_INDEX )
+ SC(CREATE_TEMP_TABLE )
+ SC(CREATE_TEMP_TRIGGER)
+ SC(CREATE_TEMP_VIEW )
+ SC(CREATE_TRIGGER )
+ SC(CREATE_VIEW )
+ SC(DELETE )
+ SC(DROP_INDEX )
+ SC(DROP_TABLE )
+ SC(DROP_TEMP_INDEX )
+ SC(DROP_TEMP_TABLE )
+ SC(DROP_TEMP_TRIGGER )
+ SC(DROP_TEMP_VIEW )
+ SC(DROP_TRIGGER )
+ SC(DROP_VIEW )
+ SC(INSERT )
+ SC(PRAGMA )
+ SC(READ )
+ SC(SELECT )
+ SC(TRANSACTION )
+ SC(UPDATE )
+ SC(ATTACH )
+ SC(DETACH )
+ SC(ALTER_TABLE )
+ SC(REINDEX )
+ SC(ANALYZE )
+ SC(CREATE_VTABLE )
+ SC(DROP_VTABLE )
+ SC(FUNCTION )
+ SC(SAVEPOINT )
+
+ /* terminator */
+ { NULL, 0 }
+};
+
+/* ======================================================= */
+
+static const luaL_Reg dblib[] = {
+ {"isopen", db_isopen },
+ {"last_insert_rowid", db_last_insert_rowid },
+ {"changes", db_changes },
+ {"total_changes", db_total_changes },
+ {"errcode", db_errcode },
+ {"error_code", db_errcode },
+ {"errmsg", db_errmsg },
+ {"error_message", db_errmsg },
+ {"interrupt", db_interrupt },
+
+ {"create_function", db_create_function },
+ {"create_aggregate", db_create_aggregate },
+ {"create_collation", db_create_collation },
+
+ {"trace", db_trace },
+ {"progress_handler", db_progress_handler },
+ {"busy_timeout", db_busy_timeout },
+ {"busy_handler", db_busy_handler },
+#if !defined(LSQLITE_OMIT_UPDATE_HOOK) || !LSQLITE_OMIT_UPDATE_HOOK
+ {"update_hook", db_update_hook },
+ {"commit_hook", db_commit_hook },
+ {"rollback_hook", db_rollback_hook },
+#endif
+
+ {"prepare", db_prepare },
+ {"rows", db_rows },
+ {"urows", db_urows },
+ {"nrows", db_nrows },
+
+ {"exec", db_exec },
+ {"execute", db_exec },
+ {"close", db_close },
+ {"close_vm", db_close_vm },
+
+ {"__tostring", db_tostring },
+ {"__gc", db_gc },
+
+ {NULL, NULL}
+};
+
+static const luaL_Reg vmlib[] = {
+ {"isopen", dbvm_isopen },
+
+ {"step", dbvm_step },
+ {"reset", dbvm_reset },
+ {"finalize", dbvm_finalize },
+
+ {"columns", dbvm_columns },
+
+ {"bind", dbvm_bind },
+ {"bind_values", dbvm_bind_values },
+ {"bind_names", dbvm_bind_names },
+ {"bind_blob", dbvm_bind_blob },
+ {"bind_parameter_count",dbvm_bind_parameter_count},
+ {"bind_parameter_name", dbvm_bind_parameter_name},
+
+ {"get_value", dbvm_get_value },
+ {"get_values", dbvm_get_values },
+ {"get_name", dbvm_get_name },
+ {"get_names", dbvm_get_names },
+ {"get_type", dbvm_get_type },
+ {"get_types", dbvm_get_types },
+ {"get_uvalues", dbvm_get_uvalues },
+ {"get_unames", dbvm_get_unames },
+ {"get_utypes", dbvm_get_utypes },
+
+ {"get_named_values", dbvm_get_named_values },
+ {"get_named_types", dbvm_get_named_types },
+
+ {"rows", dbvm_rows },
+ {"urows", dbvm_urows },
+ {"nrows", dbvm_nrows },
+
+ /* compatibility names (added by request) */
+ {"idata", dbvm_get_values },
+ {"inames", dbvm_get_names },
+ {"itypes", dbvm_get_types },
+ {"data", dbvm_get_named_values },
+ {"type", dbvm_get_named_types },
+
+ {"__tostring", dbvm_tostring },
+ {"__gc", dbvm_gc },
+
+ { NULL, NULL }
+};
+
+static const luaL_Reg ctxlib[] = {
+ {"user_data", lcontext_user_data },
+
+ {"get_aggregate_data", lcontext_get_aggregate_context },
+ {"set_aggregate_data", lcontext_set_aggregate_context },
+ {"aggregate_count", lcontext_aggregate_count },
+
+ {"result", lcontext_result },
+ {"result_null", lcontext_result_null },
+ {"result_number", lcontext_result_double },
+ {"result_double", lcontext_result_double },
+ {"result_int", lcontext_result_int },
+ {"result_text", lcontext_result_text },
+ {"result_blob", lcontext_result_blob },
+ {"result_error", lcontext_result_error },
+
+ {"__tostring", lcontext_tostring },
+ {NULL, NULL}
+};
+
+static const luaL_Reg sqlitelib[] = {
+ {"version", lsqlite_version },
+ {"complete", lsqlite_complete },
+#ifndef WIN32
+ {"temp_directory", lsqlite_temp_directory },
+#endif
+ {"open", lsqlite_open },
+ {"open_memory", lsqlite_open_memory },
+
+ {"__newindex", lsqlite_newindex },
+ {NULL, NULL}
+};
+
+static void create_meta(lua_State *L, const char *name, const luaL_Reg *lib) {
+ luaL_newmetatable(L, name);
+ lua_pushstring(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+
+ /* register metatable functions */
+ luaL_openlib(L, NULL, lib, 0);
+
+ /* remove metatable from stack */
+ lua_pop(L, 1);
+}
+
+LUALIB_API int luaopen_lsqlite3(lua_State *L) {
+ create_meta(L, sqlite_meta, dblib);
+ create_meta(L, sqlite_vm_meta, vmlib);
+ create_meta(L, sqlite_ctx_meta, ctxlib);
+
+ luaL_getmetatable(L, sqlite_ctx_meta);
+ sqlite_ctx_meta_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* register (local) sqlite metatable */
+ luaL_register(L, "sqlite3", sqlitelib);
+
+ {
+ int i = 0;
+ /* add constants to global table */
+ while (sqlite_constants[i].name) {
+ lua_pushstring(L, sqlite_constants[i].name);
+ lua_pushnumber(L, sqlite_constants[i].value);
+ lua_rawset(L, -3);
+ ++i;
+ }
+ }
+
+ /* set sqlite's metatable to itself - set as readonly (__newindex) */
+ lua_pushvalue(L, -1);
+ lua_setmetatable(L, -2);
+
+ return 1;
+}
+
+
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+
+
+
diff --git a/lib/sqlite/sqlite3.c b/lib/sqlite/sqlite3.c
new file mode 100644
index 000000000..37ee4ad38
--- /dev/null
+++ b/lib/sqlite/sqlite3.c
@@ -0,0 +1,138114 @@
+/******************************************************************************
+** This file is an amalgamation of many separate C source files from SQLite
+** version 3.7.16.1. By combining all the individual C code files into this
+** single large file, the entire code can be compiled as a single translation
+** unit. This allows many compilers to do optimizations that would not be
+** possible if the files were compiled separately. Performance improvements
+** of 5% or more are commonly seen when SQLite is compiled as a single
+** translation unit.
+**
+** This file is all you need to compile SQLite. To use SQLite in other
+** programs, you need this file and the "sqlite3.h" header file that defines
+** the programming interface to the SQLite library. (If you do not have
+** the "sqlite3.h" header file at hand, you will find a copy embedded within
+** the text of this file. Search for "Begin file sqlite3.h" to find the start
+** of the embedded sqlite3.h header file.) Additional code files may be needed
+** if you want a wrapper to interface SQLite with your choice of programming
+** language. The code for the "sqlite3" command-line shell is also in a
+** separate file. This file contains only code for the core SQLite library.
+*/
+#define SQLITE_CORE 1
+#define SQLITE_AMALGAMATION 1
+#ifndef SQLITE_PRIVATE
+# define SQLITE_PRIVATE static
+#endif
+#ifndef SQLITE_API
+# define SQLITE_API
+#endif
+/************** Begin file sqliteInt.h ***************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Internal interface definitions for SQLite.
+**
+*/
+#ifndef _SQLITEINT_H_
+#define _SQLITEINT_H_
+
+/*
+** These #defines should enable >2GB file support on POSIX if the
+** underlying operating system supports it. If the OS lacks
+** large file support, or if the OS is windows, these should be no-ops.
+**
+** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
+** system #includes. Hence, this block of code must be the very first
+** code in all source files.
+**
+** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
+** on the compiler command line. This is necessary if you are compiling
+** on a recent machine (ex: Red Hat 7.2) but you want your code to work
+** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
+** without this option, LFS is enable. But LFS does not exist in the kernel
+** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
+** portability you should omit LFS.
+**
+** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
+*/
+#ifndef SQLITE_DISABLE_LFS
+# define _LARGE_FILE 1
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
+# define _LARGEFILE_SOURCE 1
+#endif
+
+/*
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
+*/
+#ifdef _HAVE_SQLITE_CONFIG_H
+#include "config.h"
+#endif
+
+/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
+/************** Begin file sqliteLimit.h *************************************/
+/*
+** 2007 May 7
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file defines various limits of what SQLite can process.
+*/
+
+/*
+** The maximum length of a TEXT or BLOB in bytes. This also
+** limits the size of a row in a table or index.
+**
+** The hard limit is the ability of a 32-bit signed integer
+** to count the size: 2^31-1 or 2147483647.
+*/
+#ifndef SQLITE_MAX_LENGTH
+# define SQLITE_MAX_LENGTH 1000000000
+#endif
+
+/*
+** This is the maximum number of
+**
+** * Columns in a table
+** * Columns in an index
+** * Columns in a view
+** * Terms in the SET clause of an UPDATE statement
+** * Terms in the result set of a SELECT statement
+** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
+** * Terms in the VALUES clause of an INSERT statement
+**
+** The hard upper limit here is 32676. Most database people will
+** tell you that in a well-normalized database, you usually should
+** not have more than a dozen or so columns in any table. And if
+** that is the case, there is no point in having more than a few
+** dozen values in any of the other situations described above.
+*/
+#ifndef SQLITE_MAX_COLUMN
+# define SQLITE_MAX_COLUMN 2000
+#endif
+
+/*
+** The maximum length of a single SQL statement in bytes.
+**
+** It used to be the case that setting this value to zero would
+** turn the limit off. That is no longer true. It is not possible
+** to turn this limit off.
+*/
+#ifndef SQLITE_MAX_SQL_LENGTH
+# define SQLITE_MAX_SQL_LENGTH 1000000000
+#endif
+
+/*
+** The maximum depth of an expression tree. This is limited to
+** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
+** want to place more severe limits on the complexity of an
+** expression.
+**
+** A value of 0 used to mean that the limit was not enforced.
+** But that is no longer true. The limit is now strictly enforced
+** at all times.
+*/
+#ifndef SQLITE_MAX_EXPR_DEPTH
+# define SQLITE_MAX_EXPR_DEPTH 1000
+#endif
+
+/*
+** The maximum number of terms in a compound SELECT statement.
+** The code generator for compound SELECT statements does one
+** level of recursion for each term. A stack overflow can result
+** if the number of terms is too large. In practice, most SQL
+** never has more than 3 or 4 terms. Use a value of 0 to disable
+** any limit on the number of terms in a compount SELECT.
+*/
+#ifndef SQLITE_MAX_COMPOUND_SELECT
+# define SQLITE_MAX_COMPOUND_SELECT 500
+#endif
+
+/*
+** The maximum number of opcodes in a VDBE program.
+** Not currently enforced.
+*/
+#ifndef SQLITE_MAX_VDBE_OP
+# define SQLITE_MAX_VDBE_OP 25000
+#endif
+
+/*
+** The maximum number of arguments to an SQL function.
+*/
+#ifndef SQLITE_MAX_FUNCTION_ARG
+# define SQLITE_MAX_FUNCTION_ARG 127
+#endif
+
+/*
+** The maximum number of in-memory pages to use for the main database
+** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
+*/
+#ifndef SQLITE_DEFAULT_CACHE_SIZE
+# define SQLITE_DEFAULT_CACHE_SIZE 2000
+#endif
+#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
+# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
+#endif
+
+/*
+** The default number of frames to accumulate in the log file before
+** checkpointing the database in WAL mode.
+*/
+#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
+# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
+#endif
+
+/*
+** The maximum number of attached databases. This must be between 0
+** and 62. The upper bound on 62 is because a 64-bit integer bitmap
+** is used internally to track attached databases.
+*/
+#ifndef SQLITE_MAX_ATTACHED
+# define SQLITE_MAX_ATTACHED 10
+#endif
+
+
+/*
+** The maximum value of a ?nnn wildcard that the parser will accept.
+*/
+#ifndef SQLITE_MAX_VARIABLE_NUMBER
+# define SQLITE_MAX_VARIABLE_NUMBER 999
+#endif
+
+/* Maximum page size. The upper bound on this value is 65536. This a limit
+** imposed by the use of 16-bit offsets within each page.
+**
+** Earlier versions of SQLite allowed the user to change this value at
+** compile time. This is no longer permitted, on the grounds that it creates
+** a library that is technically incompatible with an SQLite library
+** compiled with a different limit. If a process operating on a database
+** with a page-size of 65536 bytes crashes, then an instance of SQLite
+** compiled with the default page-size limit will not be able to rollback
+** the aborted transaction. This could lead to database corruption.
+*/
+#ifdef SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_MAX_PAGE_SIZE
+#endif
+#define SQLITE_MAX_PAGE_SIZE 65536
+
+
+/*
+** The default size of a database page.
+*/
+#ifndef SQLITE_DEFAULT_PAGE_SIZE
+# define SQLITE_DEFAULT_PAGE_SIZE 1024
+#endif
+#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_DEFAULT_PAGE_SIZE
+# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
+#endif
+
+/*
+** Ordinarily, if no value is explicitly provided, SQLite creates databases
+** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
+** device characteristics (sector-size and atomic write() support),
+** SQLite may choose a larger value. This constant is the maximum value
+** SQLite will choose on its own.
+*/
+#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
+#endif
+#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
+#endif
+
+
+/*
+** Maximum number of pages in one database file.
+**
+** This is really just the default value for the max_page_count pragma.
+** This value can be lowered (or raised) at run-time using that the
+** max_page_count macro.
+*/
+#ifndef SQLITE_MAX_PAGE_COUNT
+# define SQLITE_MAX_PAGE_COUNT 1073741823
+#endif
+
+/*
+** Maximum length (in bytes) of the pattern in a LIKE or GLOB
+** operator.
+*/
+#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
+# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
+#endif
+
+/*
+** Maximum depth of recursion for triggers.
+**
+** A value of 1 means that a trigger program will not be able to itself
+** fire any triggers. A value of 0 means that no trigger programs at all
+** may be executed.
+*/
+#ifndef SQLITE_MAX_TRIGGER_DEPTH
+# define SQLITE_MAX_TRIGGER_DEPTH 1000
+#endif
+
+/************** End of sqliteLimit.h *****************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+
+/* Disable nuisance warnings on Borland compilers */
+#if defined(__BORLANDC__)
+#pragma warn -rch /* unreachable code */
+#pragma warn -ccc /* Condition is always true or false */
+#pragma warn -aus /* Assigned value is never used */
+#pragma warn -csu /* Comparing signed and unsigned */
+#pragma warn -spa /* Suspicious pointer arithmetic */
+#endif
+
+/* Needed for various definitions... */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
+# define _BSD_SOURCE
+#endif
+
+/*
+** Include standard header files as necessary
+*/
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+/*
+** The following macros are used to cast pointers to integers and
+** integers to pointers. The way you do this varies from one compiler
+** to the next, so we have developed the following set of #if statements
+** to generate appropriate macros for a wide range of compilers.
+**
+** The correct "ANSI" way to do this is to use the intptr_t type.
+** Unfortunately, that typedef is not available on all compilers, or
+** if it is available, it requires an #include of specific headers
+** that vary from one machine to the next.
+**
+** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
+** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
+** So we have to define the macros in different ways depending on the
+** compiler.
+*/
+#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
+# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
+#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
+# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
+# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
+#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
+# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
+#else /* Generates a warning - but it always works */
+# define SQLITE_INT_TO_PTR(X) ((void*)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(X))
+#endif
+
+/*
+** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
+** 0 means mutexes are permanently disable and the library is never
+** threadsafe. 1 means the library is serialized which is the highest
+** level of threadsafety. 2 means the libary is multithreaded - multiple
+** threads can use SQLite as long as no two threads try to use the same
+** database connection at the same time.
+**
+** Older versions of SQLite used an optional THREADSAFE macro.
+** We support that for legacy.
+*/
+#if !defined(SQLITE_THREADSAFE)
+#if defined(THREADSAFE)
+# define SQLITE_THREADSAFE THREADSAFE
+#else
+# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
+#endif
+#endif
+
+/*
+** Powersafe overwrite is on by default. But can be turned off using
+** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
+*/
+#ifndef SQLITE_POWERSAFE_OVERWRITE
+# define SQLITE_POWERSAFE_OVERWRITE 1
+#endif
+
+/*
+** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
+** It determines whether or not the features related to
+** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
+** be overridden at runtime using the sqlite3_config() API.
+*/
+#if !defined(SQLITE_DEFAULT_MEMSTATUS)
+# define SQLITE_DEFAULT_MEMSTATUS 1
+#endif
+
+/*
+** Exactly one of the following macros must be defined in order to
+** specify which memory allocation subsystem to use.
+**
+** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
+** SQLITE_WIN32_MALLOC // Use Win32 native heap API
+** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
+** SQLITE_MEMDEBUG // Debugging version of system malloc()
+**
+** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
+** assert() macro is enabled, each call into the Win32 native heap subsystem
+** will cause HeapValidate to be called. If heap validation should fail, an
+** assertion will be triggered.
+**
+** (Historical note: There used to be several other options, but we've
+** pared it down to just these three.)
+**
+** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
+** the default.
+*/
+#if defined(SQLITE_SYSTEM_MALLOC) \
+ + defined(SQLITE_WIN32_MALLOC) \
+ + defined(SQLITE_ZERO_MALLOC) \
+ + defined(SQLITE_MEMDEBUG)>1
+# error "Two or more of the following compile-time configuration options\
+ are defined but at most one is allowed:\
+ SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
+ SQLITE_ZERO_MALLOC"
+#endif
+#if defined(SQLITE_SYSTEM_MALLOC) \
+ + defined(SQLITE_WIN32_MALLOC) \
+ + defined(SQLITE_ZERO_MALLOC) \
+ + defined(SQLITE_MEMDEBUG)==0
+# define SQLITE_SYSTEM_MALLOC 1
+#endif
+
+/*
+** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
+** sizes of memory allocations below this value where possible.
+*/
+#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
+# define SQLITE_MALLOC_SOFT_LIMIT 1024
+#endif
+
+/*
+** We need to define _XOPEN_SOURCE as follows in order to enable
+** recursive mutexes on most Unix systems. But Mac OS X is different.
+** The _XOPEN_SOURCE define causes problems for Mac OS X we are told,
+** so it is omitted there. See ticket #2673.
+**
+** Later we learn that _XOPEN_SOURCE is poorly or incorrectly
+** implemented on some systems. So we avoid defining it at all
+** if it is already defined or if it is unneeded because we are
+** not doing a threadsafe build. Ticket #2681.
+**
+** See also ticket #2741.
+*/
+#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \
+ && !defined(__APPLE__) && SQLITE_THREADSAFE
+# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
+#endif
+
+/*
+** The TCL headers are only needed when compiling the TCL bindings.
+*/
+#if defined(SQLITE_TCL) || defined(TCLSH)
+# include <tcl.h>
+#endif
+
+/*
+** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
+** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
+** make it true by defining or undefining NDEBUG.
+**
+** Setting NDEBUG makes the code smaller and run faster by disabling the
+** number assert() statements in the code. So we want the default action
+** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
+** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
+** feature.
+*/
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+# define NDEBUG 1
+#endif
+#if defined(NDEBUG) && defined(SQLITE_DEBUG)
+# undef NDEBUG
+#endif
+
+/*
+** The testcase() macro is used to aid in coverage testing. When
+** doing coverage testing, the condition inside the argument to
+** testcase() must be evaluated both true and false in order to
+** get full branch coverage. The testcase() macro is inserted
+** to help ensure adequate test coverage in places where simple
+** condition/decision coverage is inadequate. For example, testcase()
+** can be used to make sure boundary values are tested. For
+** bitmask tests, testcase() can be used to make sure each bit
+** is significant and used at least once. On switch statements
+** where multiple cases go to the same block of code, testcase()
+** can insure that all cases are evaluated.
+**
+*/
+#ifdef SQLITE_COVERAGE_TEST
+SQLITE_PRIVATE void sqlite3Coverage(int);
+# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
+#else
+# define testcase(X)
+#endif
+
+/*
+** The TESTONLY macro is used to enclose variable declarations or
+** other bits of code that are needed to support the arguments
+** within testcase() and assert() macros.
+*/
+#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
+# define TESTONLY(X) X
+#else
+# define TESTONLY(X)
+#endif
+
+/*
+** Sometimes we need a small amount of code such as a variable initialization
+** to setup for a later assert() statement. We do not want this code to
+** appear when assert() is disabled. The following macro is therefore
+** used to contain that setup code. The "VVA" acronym stands for
+** "Verification, Validation, and Accreditation". In other words, the
+** code within VVA_ONLY() will only run during verification processes.
+*/
+#ifndef NDEBUG
+# define VVA_ONLY(X) X
+#else
+# define VVA_ONLY(X)
+#endif
+
+/*
+** The ALWAYS and NEVER macros surround boolean expressions which
+** are intended to always be true or false, respectively. Such
+** expressions could be omitted from the code completely. But they
+** are included in a few cases in order to enhance the resilience
+** of SQLite to unexpected behavior - to make the code "self-healing"
+** or "ductile" rather than being "brittle" and crashing at the first
+** hint of unplanned behavior.
+**
+** In other words, ALWAYS and NEVER are added for defensive code.
+**
+** When doing coverage testing ALWAYS and NEVER are hard-coded to
+** be true and false so that the unreachable code then specify will
+** not be counted as untested code.
+*/
+#if defined(SQLITE_COVERAGE_TEST)
+# define ALWAYS(X) (1)
+# define NEVER(X) (0)
+#elif !defined(NDEBUG)
+# define ALWAYS(X) ((X)?1:(assert(0),0))
+# define NEVER(X) ((X)?(assert(0),1):0)
+#else
+# define ALWAYS(X) (X)
+# define NEVER(X) (X)
+#endif
+
+/*
+** Return true (non-zero) if the input is a integer that is too large
+** to fit in 32-bits. This macro is used inside of various testcase()
+** macros to verify that we have tested SQLite for large-file support.
+*/
+#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
+
+/*
+** The macro unlikely() is a hint that surrounds a boolean
+** expression that is usually false. Macro likely() surrounds
+** a boolean expression that is usually true. GCC is able to
+** use these hints to generate better code, sometimes.
+*/
+#if defined(__GNUC__) && 0
+# define likely(X) __builtin_expect((X),1)
+# define unlikely(X) __builtin_expect((X),0)
+#else
+# define likely(X) !!(X)
+# define unlikely(X) !!(X)
+#endif
+
+/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
+/************** Begin file sqlite3.h *****************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the SQLite library
+** presents to client programs. If a C-function, structure, datatype,
+** or constant definition does not appear in this file, then it is
+** not a published API of SQLite, is subject to change without
+** notice, and should not be referenced by programs that use SQLite.
+**
+** Some of the definitions that are in this file are marked as
+** "experimental". Experimental interfaces are normally new
+** features recently added to SQLite. We do not anticipate changes
+** to experimental interfaces but reserve the right to make minor changes
+** if experience from use "in the wild" suggest such changes are prudent.
+**
+** The official C-language API documentation for SQLite is derived
+** from comments in this file. This file is the authoritative source
+** on how SQLite interfaces are suppose to operate.
+**
+** The name of this file under configuration management is "sqlite.h.in".
+** The makefile makes some minor changes to this file (such as inserting
+** the version number) and changes its name to "sqlite3.h" as
+** part of the build process.
+*/
+#ifndef _SQLITE3_H_
+#define _SQLITE3_H_
+#include <stdarg.h> /* Needed for the definition of va_list */
+
+/*
+** Make sure we can call this stuff from C++.
+*/
+#if 0
+extern "C" {
+#endif
+
+
+/*
+** Add the ability to override 'extern'
+*/
+#ifndef SQLITE_EXTERN
+# define SQLITE_EXTERN extern
+#endif
+
+#ifndef SQLITE_API
+# define SQLITE_API
+#endif
+
+
+/*
+** These no-op macros are used in front of interfaces to mark those
+** interfaces as either deprecated or experimental. New applications
+** should not use deprecated interfaces - they are support for backwards
+** compatibility only. Application writers should be aware that
+** experimental interfaces are subject to change in point releases.
+**
+** These macros used to resolve to various kinds of compiler magic that
+** would generate warning messages when they were used. But that
+** compiler magic ended up generating such a flurry of bug reports
+** that we have taken it all out and gone back to using simple
+** noop macros.
+*/
+#define SQLITE_DEPRECATED
+#define SQLITE_EXPERIMENTAL
+
+/*
+** Ensure these symbols were not defined by some previous header file.
+*/
+#ifdef SQLITE_VERSION
+# undef SQLITE_VERSION
+#endif
+#ifdef SQLITE_VERSION_NUMBER
+# undef SQLITE_VERSION_NUMBER
+#endif
+
+/*
+** CAPI3REF: Compile-Time Library Version Numbers
+**
+** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header
+** evaluates to a string literal that is the SQLite version in the
+** format "X.Y.Z" where X is the major version number (always 3 for
+** SQLite3) and Y is the minor version number and Z is the release number.)^
+** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer
+** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
+** numbers used in [SQLITE_VERSION].)^
+** The SQLITE_VERSION_NUMBER for any given release of SQLite will also
+** be larger than the release from which it is derived. Either Y will
+** be held constant and Z will be incremented or else Y will be incremented
+** and Z will be reset to zero.
+**
+** Since version 3.6.18, SQLite source code has been stored in the
+** <a href="http://www.fossil-scm.org/">Fossil configuration management
+** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
+** a string which identifies a particular check-in of SQLite
+** within its configuration management system. ^The SQLITE_SOURCE_ID
+** string contains the date and time of the check-in (UTC) and an SHA1
+** hash of the entire source tree.
+**
+** See also: [sqlite3_libversion()],
+** [sqlite3_libversion_number()], [sqlite3_sourceid()],
+** [sqlite_version()] and [sqlite_source_id()].
+*/
+#define SQLITE_VERSION "3.7.16.1"
+#define SQLITE_VERSION_NUMBER 3007016
+#define SQLITE_SOURCE_ID "2013-03-29 13:44:34 527231bc67285f01fb18d4451b28f61da3c4e39d"
+
+/*
+** CAPI3REF: Run-Time Library Version Numbers
+** KEYWORDS: sqlite3_version, sqlite3_sourceid
+**
+** These interfaces provide the same information as the [SQLITE_VERSION],
+** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
+** but are associated with the library instead of the header file. ^(Cautious
+** programmers might include assert() statements in their application to
+** verify that values returned by these interfaces match the macros in
+** the header, and thus insure that the application is
+** compiled with matching library and header files.
+**
+** <blockquote><pre>
+** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
+** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
+** </pre></blockquote>)^
+**
+** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
+** macro. ^The sqlite3_libversion() function returns a pointer to the
+** to the sqlite3_version[] string constant. The sqlite3_libversion()
+** function is provided for use in DLLs since DLL users usually do not have
+** direct access to string constants within the DLL. ^The
+** sqlite3_libversion_number() function returns an integer equal to
+** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
+** a pointer to a string constant whose value is the same as the
+** [SQLITE_SOURCE_ID] C preprocessor macro.
+**
+** See also: [sqlite_version()] and [sqlite_source_id()].
+*/
+SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
+SQLITE_API const char *sqlite3_libversion(void);
+SQLITE_API const char *sqlite3_sourceid(void);
+SQLITE_API int sqlite3_libversion_number(void);
+
+/*
+** CAPI3REF: Run-Time Library Compilation Options Diagnostics
+**
+** ^The sqlite3_compileoption_used() function returns 0 or 1
+** indicating whether the specified option was defined at
+** compile time. ^The SQLITE_ prefix may be omitted from the
+** option name passed to sqlite3_compileoption_used().
+**
+** ^The sqlite3_compileoption_get() function allows iterating
+** over the list of options that were defined at compile time by
+** returning the N-th compile time option string. ^If N is out of range,
+** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
+** prefix is omitted from any strings returned by
+** sqlite3_compileoption_get().
+**
+** ^Support for the diagnostic functions sqlite3_compileoption_used()
+** and sqlite3_compileoption_get() may be omitted by specifying the
+** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
+**
+** See also: SQL functions [sqlite_compileoption_used()] and
+** [sqlite_compileoption_get()] and the [compile_options pragma].
+*/
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
+SQLITE_API const char *sqlite3_compileoption_get(int N);
+#endif
+
+/*
+** CAPI3REF: Test To See If The Library Is Threadsafe
+**
+** ^The sqlite3_threadsafe() function returns zero if and only if
+** SQLite was compiled with mutexing code omitted due to the
+** [SQLITE_THREADSAFE] compile-time option being set to 0.
+**
+** SQLite can be compiled with or without mutexes. When
+** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
+** are enabled and SQLite is threadsafe. When the
+** [SQLITE_THREADSAFE] macro is 0,
+** the mutexes are omitted. Without the mutexes, it is not safe
+** to use SQLite concurrently from more than one thread.
+**
+** Enabling mutexes incurs a measurable performance penalty.
+** So if speed is of utmost importance, it makes sense to disable
+** the mutexes. But for maximum safety, mutexes should be enabled.
+** ^The default behavior is for mutexes to be enabled.
+**
+** This interface can be used by an application to make sure that the
+** version of SQLite that it is linking against was compiled with
+** the desired setting of the [SQLITE_THREADSAFE] macro.
+**
+** This interface only reports on the compile-time mutex setting
+** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
+** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
+** can be fully or partially disabled using a call to [sqlite3_config()]
+** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
+** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the
+** sqlite3_threadsafe() function shows only the compile-time setting of
+** thread safety, not any run-time changes to that setting made by
+** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
+** is unchanged by calls to sqlite3_config().)^
+**
+** See the [threading mode] documentation for additional information.
+*/
+SQLITE_API int sqlite3_threadsafe(void);
+
+/*
+** CAPI3REF: Database Connection Handle
+** KEYWORDS: {database connection} {database connections}
+**
+** Each open SQLite database is represented by a pointer to an instance of
+** the opaque structure named "sqlite3". It is useful to think of an sqlite3
+** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and
+** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
+** and [sqlite3_close_v2()] are its destructors. There are many other
+** interfaces (such as
+** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
+** [sqlite3_busy_timeout()] to name but three) that are methods on an
+** sqlite3 object.
+*/
+typedef struct sqlite3 sqlite3;
+
+/*
+** CAPI3REF: 64-Bit Integer Types
+** KEYWORDS: sqlite_int64 sqlite_uint64
+**
+** Because there is no cross-platform way to specify 64-bit integer types
+** SQLite includes typedefs for 64-bit signed and unsigned integers.
+**
+** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions.
+** The sqlite_int64 and sqlite_uint64 types are supported for backwards
+** compatibility only.
+**
+** ^The sqlite3_int64 and sqlite_int64 types can store integer values
+** between -9223372036854775808 and +9223372036854775807 inclusive. ^The
+** sqlite3_uint64 and sqlite_uint64 types can store integer values
+** between 0 and +18446744073709551615 inclusive.
+*/
+#ifdef SQLITE_INT64_TYPE
+ typedef SQLITE_INT64_TYPE sqlite_int64;
+ typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef __int64 sqlite_int64;
+ typedef unsigned __int64 sqlite_uint64;
+#else
+ typedef long long int sqlite_int64;
+ typedef unsigned long long int sqlite_uint64;
+#endif
+typedef sqlite_int64 sqlite3_int64;
+typedef sqlite_uint64 sqlite3_uint64;
+
+/*
+** If compiling for a processor that lacks floating point support,
+** substitute integer for floating-point.
+*/
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# define double sqlite3_int64
+#endif
+
+/*
+** CAPI3REF: Closing A Database Connection
+**
+** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
+** for the [sqlite3] object.
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
+** the [sqlite3] object is successfully destroyed and all associated
+** resources are deallocated.
+**
+** ^If the database connection is associated with unfinalized prepared
+** statements or unfinished sqlite3_backup objects then sqlite3_close()
+** will leave the database connection open and return [SQLITE_BUSY].
+** ^If sqlite3_close_v2() is called with unfinalized prepared statements
+** and unfinished sqlite3_backups, then the database connection becomes
+** an unusable "zombie" which will automatically be deallocated when the
+** last prepared statement is finalized or the last sqlite3_backup is
+** finished. The sqlite3_close_v2() interface is intended for use with
+** host languages that are garbage collected, and where the order in which
+** destructors are called is arbitrary.
+**
+** Applications should [sqlite3_finalize | finalize] all [prepared statements],
+** [sqlite3_blob_close | close] all [BLOB handles], and
+** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
+** with the [sqlite3] object prior to attempting to close the object. ^If
+** sqlite3_close_v2() is called on a [database connection] that still has
+** outstanding [prepared statements], [BLOB handles], and/or
+** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
+** of resources is deferred until all [prepared statements], [BLOB handles],
+** and [sqlite3_backup] objects are also destroyed.
+**
+** ^If an [sqlite3] object is destroyed while a transaction is open,
+** the transaction is automatically rolled back.
+**
+** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
+** must be either a NULL
+** pointer or an [sqlite3] object pointer obtained
+** from [sqlite3_open()], [sqlite3_open16()], or
+** [sqlite3_open_v2()], and not previously closed.
+** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
+** argument is a harmless no-op.
+*/
+SQLITE_API int sqlite3_close(sqlite3*);
+SQLITE_API int sqlite3_close_v2(sqlite3*);
+
+/*
+** The type for a callback function.
+** This is legacy and deprecated. It is included for historical
+** compatibility and is not documented.
+*/
+typedef int (*sqlite3_callback)(void*,int,char**, char**);
+
+/*
+** CAPI3REF: One-Step Query Execution Interface
+**
+** The sqlite3_exec() interface is a convenience wrapper around
+** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
+** that allows an application to run multiple statements of SQL
+** without having to use a lot of C code.
+**
+** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
+** semicolon-separate SQL statements passed into its 2nd argument,
+** in the context of the [database connection] passed in as its 1st
+** argument. ^If the callback function of the 3rd argument to
+** sqlite3_exec() is not NULL, then it is invoked for each result row
+** coming out of the evaluated SQL statements. ^The 4th argument to
+** sqlite3_exec() is relayed through to the 1st argument of each
+** callback invocation. ^If the callback pointer to sqlite3_exec()
+** is NULL, then no callback is ever invoked and result rows are
+** ignored.
+**
+** ^If an error occurs while evaluating the SQL statements passed into
+** sqlite3_exec(), then execution of the current statement stops and
+** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec()
+** is not NULL then any error message is written into memory obtained
+** from [sqlite3_malloc()] and passed back through the 5th parameter.
+** To avoid memory leaks, the application should invoke [sqlite3_free()]
+** on error message strings returned through the 5th parameter of
+** of sqlite3_exec() after the error message string is no longer needed.
+** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors
+** occur, then sqlite3_exec() sets the pointer in its 5th parameter to
+** NULL before returning.
+**
+** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec()
+** routine returns SQLITE_ABORT without invoking the callback again and
+** without running any subsequent SQL statements.
+**
+** ^The 2nd argument to the sqlite3_exec() callback function is the
+** number of columns in the result. ^The 3rd argument to the sqlite3_exec()
+** callback is an array of pointers to strings obtained as if from
+** [sqlite3_column_text()], one for each column. ^If an element of a
+** result row is NULL then the corresponding string pointer for the
+** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the
+** sqlite3_exec() callback is an array of pointers to strings where each
+** entry represents the name of corresponding result column as obtained
+** from [sqlite3_column_name()].
+**
+** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
+** to an empty string, or a pointer that contains only whitespace and/or
+** SQL comments, then no SQL statements are evaluated and the database
+** is not changed.
+**
+** Restrictions:
+**
+** <ul>
+** <li> The application must insure that the 1st parameter to sqlite3_exec()
+** is a valid and open [database connection].
+** <li> The application must not close [database connection] specified by
+** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
+** <li> The application must not modify the SQL statement text passed into
+** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+** </ul>
+*/
+SQLITE_API int sqlite3_exec(
+ sqlite3*, /* An open database */
+ const char *sql, /* SQL to be evaluated */
+ int (*callback)(void*,int,char**,char**), /* Callback function */
+ void *, /* 1st argument to callback */
+ char **errmsg /* Error msg written here */
+);
+
+/*
+** CAPI3REF: Result Codes
+** KEYWORDS: SQLITE_OK {error code} {error codes}
+** KEYWORDS: {result code} {result codes}
+**
+** Many SQLite functions return an integer result code from the set shown
+** here in order to indicate success or failure.
+**
+** New error codes may be added in future versions of SQLite.
+**
+** See also: [SQLITE_IOERR_READ | extended result codes],
+** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
+*/
+#define SQLITE_OK 0 /* Successful result */
+/* beginning-of-error-codes */
+#define SQLITE_ERROR 1 /* SQL error or missing database */
+#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
+#define SQLITE_PERM 3 /* Access permission denied */
+#define SQLITE_ABORT 4 /* Callback routine requested an abort */
+#define SQLITE_BUSY 5 /* The database file is locked */
+#define SQLITE_LOCKED 6 /* A table in the database is locked */
+#define SQLITE_NOMEM 7 /* A malloc() failed */
+#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
+#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
+#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
+#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
+#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */
+#define SQLITE_FULL 13 /* Insertion failed because database is full */
+#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
+#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
+#define SQLITE_EMPTY 16 /* Database is empty */
+#define SQLITE_SCHEMA 17 /* The database schema changed */
+#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
+#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
+#define SQLITE_MISMATCH 20 /* Data type mismatch */
+#define SQLITE_MISUSE 21 /* Library used incorrectly */
+#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
+#define SQLITE_AUTH 23 /* Authorization denied */
+#define SQLITE_FORMAT 24 /* Auxiliary database format error */
+#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
+#define SQLITE_NOTADB 26 /* File opened that is not a database file */
+#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
+#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
+/* end-of-error-codes */
+
+/*
+** CAPI3REF: Extended Result Codes
+** KEYWORDS: {extended error code} {extended error codes}
+** KEYWORDS: {extended result code} {extended result codes}
+**
+** In its default configuration, SQLite API routines return one of 26 integer
+** [SQLITE_OK | result codes]. However, experience has shown that many of
+** these result codes are too coarse-grained. They do not provide as
+** much information about problems as programmers might like. In an effort to
+** address this, newer versions of SQLite (version 3.3.8 and later) include
+** support for additional result codes that provide more detailed information
+** about errors. The extended result codes are enabled or disabled
+** on a per database connection basis using the
+** [sqlite3_extended_result_codes()] API.
+**
+** Some of the available extended result codes are listed here.
+** One may expect the number of extended result codes will be expand
+** over time. Software that uses extended result codes should expect
+** to see new result codes in future releases of SQLite.
+**
+** The SQLITE_OK result code will never be extended. It will always
+** be exactly zero.
+*/
+#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
+#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
+#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
+#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
+#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8))
+#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8))
+#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8))
+#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8))
+#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8))
+#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8))
+#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8))
+#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
+#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
+#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
+#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
+#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
+#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
+#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
+#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
+#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
+#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
+#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
+#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
+#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
+#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
+#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
+#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
+#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
+#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
+#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
+
+/*
+** CAPI3REF: Flags For File Open Operations
+**
+** These bit values are intended for use in the
+** 3rd parameter to the [sqlite3_open_v2()] interface and
+** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
+*/
+#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
+#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
+#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
+#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
+#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
+#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
+#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
+#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
+#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */
+#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
+#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
+
+/* Reserved: 0x00F00000 */
+
+/*
+** CAPI3REF: Device Characteristics
+**
+** The xDeviceCharacteristics method of the [sqlite3_io_methods]
+** object returns an integer which is a vector of these
+** bit values expressing I/O characteristics of the mass storage
+** device that holds the file that the [sqlite3_io_methods]
+** refers to.
+**
+** The SQLITE_IOCAP_ATOMIC property means that all writes of
+** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
+** mean that writes of blocks that are nnn bytes in size and
+** are aligned to an address which is an integer multiple of
+** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
+** that when data is appended to a file, the data is appended
+** first then the size of the file is extended, never the other
+** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
+** information is written to disk in the same order as calls
+** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that
+** after reboot following a crash or power loss, the only bytes in a
+** file that were written at the application level might have changed
+** and that adjacent bytes, even bytes within the same sector are
+** guaranteed to be unchanged.
+*/
+#define SQLITE_IOCAP_ATOMIC 0x00000001
+#define SQLITE_IOCAP_ATOMIC512 0x00000002
+#define SQLITE_IOCAP_ATOMIC1K 0x00000004
+#define SQLITE_IOCAP_ATOMIC2K 0x00000008
+#define SQLITE_IOCAP_ATOMIC4K 0x00000010
+#define SQLITE_IOCAP_ATOMIC8K 0x00000020
+#define SQLITE_IOCAP_ATOMIC16K 0x00000040
+#define SQLITE_IOCAP_ATOMIC32K 0x00000080
+#define SQLITE_IOCAP_ATOMIC64K 0x00000100
+#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
+#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
+#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
+#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
+
+/*
+** CAPI3REF: File Locking Levels
+**
+** SQLite uses one of these integer values as the second
+** argument to calls it makes to the xLock() and xUnlock() methods
+** of an [sqlite3_io_methods] object.
+*/
+#define SQLITE_LOCK_NONE 0
+#define SQLITE_LOCK_SHARED 1
+#define SQLITE_LOCK_RESERVED 2
+#define SQLITE_LOCK_PENDING 3
+#define SQLITE_LOCK_EXCLUSIVE 4
+
+/*
+** CAPI3REF: Synchronization Type Flags
+**
+** When SQLite invokes the xSync() method of an
+** [sqlite3_io_methods] object it uses a combination of
+** these integer values as the second argument.
+**
+** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
+** sync operation only needs to flush data to mass storage. Inode
+** information need not be flushed. If the lower four bits of the flag
+** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics.
+** If the lower four bits equal SQLITE_SYNC_FULL, that means
+** to use Mac OS X style fullsync instead of fsync().
+**
+** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags
+** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL
+** settings. The [synchronous pragma] determines when calls to the
+** xSync VFS method occur and applies uniformly across all platforms.
+** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how
+** energetic or rigorous or forceful the sync operations are and
+** only make a difference on Mac OSX for the default SQLite code.
+** (Third-party VFS implementations might also make the distinction
+** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the
+** operating systems natively supported by SQLite, only Mac OSX
+** cares about the difference.)
+*/
+#define SQLITE_SYNC_NORMAL 0x00002
+#define SQLITE_SYNC_FULL 0x00003
+#define SQLITE_SYNC_DATAONLY 0x00010
+
+/*
+** CAPI3REF: OS Interface Open File Handle
+**
+** An [sqlite3_file] object represents an open file in the
+** [sqlite3_vfs | OS interface layer]. Individual OS interface
+** implementations will
+** want to subclass this object by appending additional fields
+** for their own use. The pMethods entry is a pointer to an
+** [sqlite3_io_methods] object that defines methods for performing
+** I/O operations on the open file.
+*/
+typedef struct sqlite3_file sqlite3_file;
+struct sqlite3_file {
+ const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
+};
+
+/*
+** CAPI3REF: OS Interface File Virtual Methods Object
+**
+** Every file opened by the [sqlite3_vfs.xOpen] method populates an
+** [sqlite3_file] object (or, more commonly, a subclass of the
+** [sqlite3_file] object) with a pointer to an instance of this object.
+** This object defines the methods used to perform various operations
+** against the open file represented by the [sqlite3_file] object.
+**
+** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
+** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
+** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
+** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
+** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
+** to NULL.
+**
+** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
+** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
+** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
+** flag may be ORed in to indicate that only the data of the file
+** and not its inode needs to be synced.
+**
+** The integer values to xLock() and xUnlock() are one of
+** <ul>
+** <li> [SQLITE_LOCK_NONE],
+** <li> [SQLITE_LOCK_SHARED],
+** <li> [SQLITE_LOCK_RESERVED],
+** <li> [SQLITE_LOCK_PENDING], or
+** <li> [SQLITE_LOCK_EXCLUSIVE].
+** </ul>
+** xLock() increases the lock. xUnlock() decreases the lock.
+** The xCheckReservedLock() method checks whether any database connection,
+** either in this process or in some other process, is holding a RESERVED,
+** PENDING, or EXCLUSIVE lock on the file. It returns true
+** if such a lock exists and false otherwise.
+**
+** The xFileControl() method is a generic interface that allows custom
+** VFS implementations to directly control an open file using the
+** [sqlite3_file_control()] interface. The second "op" argument is an
+** integer opcode. The third argument is a generic pointer intended to
+** point to a structure that may contain arguments or space in which to
+** write return values. Potential uses for xFileControl() might be
+** functions to enable blocking locks with timeouts, to change the
+** locking strategy (for example to use dot-file locks), to inquire
+** about the status of a lock, or to break stale locks. The SQLite
+** core reserves all opcodes less than 100 for its own use.
+** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
+** Applications that define a custom xFileControl method should use opcodes
+** greater than 100 to avoid conflicts. VFS implementations should
+** return [SQLITE_NOTFOUND] for file control opcodes that they do not
+** recognize.
+**
+** The xSectorSize() method returns the sector size of the
+** device that underlies the file. The sector size is the
+** minimum write that can be performed without disturbing
+** other bytes in the file. The xDeviceCharacteristics()
+** method returns a bit vector describing behaviors of the
+** underlying device:
+**
+** <ul>
+** <li> [SQLITE_IOCAP_ATOMIC]
+** <li> [SQLITE_IOCAP_ATOMIC512]
+** <li> [SQLITE_IOCAP_ATOMIC1K]
+** <li> [SQLITE_IOCAP_ATOMIC2K]
+** <li> [SQLITE_IOCAP_ATOMIC4K]
+** <li> [SQLITE_IOCAP_ATOMIC8K]
+** <li> [SQLITE_IOCAP_ATOMIC16K]
+** <li> [SQLITE_IOCAP_ATOMIC32K]
+** <li> [SQLITE_IOCAP_ATOMIC64K]
+** <li> [SQLITE_IOCAP_SAFE_APPEND]
+** <li> [SQLITE_IOCAP_SEQUENTIAL]
+** </ul>
+**
+** The SQLITE_IOCAP_ATOMIC property means that all writes of
+** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
+** mean that writes of blocks that are nnn bytes in size and
+** are aligned to an address which is an integer multiple of
+** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
+** that when data is appended to a file, the data is appended
+** first then the size of the file is extended, never the other
+** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
+** information is written to disk in the same order as calls
+** to xWrite().
+**
+** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill
+** in the unread portions of the buffer with zeros. A VFS that
+** fails to zero-fill short reads might seem to work. However,
+** failure to zero-fill short reads will eventually lead to
+** database corruption.
+*/
+typedef struct sqlite3_io_methods sqlite3_io_methods;
+struct sqlite3_io_methods {
+ int iVersion;
+ int (*xClose)(sqlite3_file*);
+ int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+ int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
+ int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
+ int (*xSync)(sqlite3_file*, int flags);
+ int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
+ int (*xLock)(sqlite3_file*, int);
+ int (*xUnlock)(sqlite3_file*, int);
+ int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
+ int (*xFileControl)(sqlite3_file*, int op, void *pArg);
+ int (*xSectorSize)(sqlite3_file*);
+ int (*xDeviceCharacteristics)(sqlite3_file*);
+ /* Methods above are valid for version 1 */
+ int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
+ int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
+ void (*xShmBarrier)(sqlite3_file*);
+ int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
+ /* Methods above are valid for version 2 */
+ /* Additional methods may be added in future releases */
+};
+
+/*
+** CAPI3REF: Standard File Control Opcodes
+**
+** These integer constants are opcodes for the xFileControl method
+** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
+** interface.
+**
+** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
+** opcode causes the xFileControl method to write the current state of
+** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
+** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
+** into an integer that the pArg argument points to. This capability
+** is used during testing and only needs to be supported when SQLITE_TEST
+** is defined.
+** <ul>
+** <li>[[SQLITE_FCNTL_SIZE_HINT]]
+** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
+** layer a hint of how large the database file will grow to be during the
+** current transaction. This hint is not guaranteed to be accurate but it
+** is often close. The underlying VFS might choose to preallocate database
+** file space based on this hint in order to help writes to the database
+** file run faster.
+**
+** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
+** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
+** extends and truncates the database file in chunks of a size specified
+** by the user. The fourth argument to [sqlite3_file_control()] should
+** point to an integer (type int) containing the new chunk-size to use
+** for the nominated database. Allocating database file space in large
+** chunks (say 1MB at a time), may reduce file-system fragmentation and
+** improve performance on some systems.
+**
+** <li>[[SQLITE_FCNTL_FILE_POINTER]]
+** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
+** to the [sqlite3_file] object associated with a particular database
+** connection. See the [sqlite3_file_control()] documentation for
+** additional information.
+**
+** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
+** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
+** SQLite and sent to all VFSes in place of a call to the xSync method
+** when the database connection has [PRAGMA synchronous] set to OFF.)^
+** Some specialized VFSes need this signal in order to operate correctly
+** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
+** VFSes do not need this signal and should silently ignore this opcode.
+** Applications should not call [sqlite3_file_control()] with this
+** opcode as doing so may disrupt the operation of the specialized VFSes
+** that do require it.
+**
+** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
+** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
+** retry counts and intervals for certain disk I/O operations for the
+** windows [VFS] in order to provide robustness in the presence of
+** anti-virus programs. By default, the windows VFS will retry file read,
+** file write, and file delete operations up to 10 times, with a delay
+** of 25 milliseconds before the first retry and with the delay increasing
+** by an additional 25 milliseconds with each subsequent retry. This
+** opcode allows these two values (10 retries and 25 milliseconds of delay)
+** to be adjusted. The values are changed for all database connections
+** within the same process. The argument is a pointer to an array of two
+** integers where the first integer i the new retry count and the second
+** integer is the delay. If either integer is negative, then the setting
+** is not changed but instead the prior value of that setting is written
+** into the array entry, allowing the current retry settings to be
+** interrogated. The zDbName parameter is ignored.
+**
+** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
+** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
+** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
+** write ahead log and shared memory files used for transaction control
+** are automatically deleted when the latest connection to the database
+** closes. Setting persistent WAL mode causes those files to persist after
+** close. Persisting the files is useful when other processes that do not
+** have write permission on the directory containing the database file want
+** to read the database file, as the WAL and shared memory files must exist
+** in order for the database to be readable. The fourth parameter to
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
+** WAL mode. If the integer is -1, then it is overwritten with the current
+** WAL persistence setting.
+**
+** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
+** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
+** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
+** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
+** xDeviceCharacteristics methods. The fourth parameter to
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
+** mode. If the integer is -1, then it is overwritten with the current
+** zero-damage mode setting.
+**
+** <li>[[SQLITE_FCNTL_OVERWRITE]]
+** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
+** a write transaction to indicate that, unless it is rolled back for some
+** reason, the entire database file will be overwritten by the current
+** transaction. This is used by VACUUM operations.
+**
+** <li>[[SQLITE_FCNTL_VFSNAME]]
+** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
+** all [VFSes] in the VFS stack. The names are of all VFS shims and the
+** final bottom-level VFS are written into memory obtained from
+** [sqlite3_malloc()] and the result is stored in the char* variable
+** that the fourth parameter of [sqlite3_file_control()] points to.
+** The caller is responsible for freeing the memory when done. As with
+** all file-control actions, there is no guarantee that this will actually
+** do anything. Callers should initialize the char* variable to a NULL
+** pointer in case this file-control is not implemented. This file-control
+** is intended for diagnostic use only.
+**
+** <li>[[SQLITE_FCNTL_PRAGMA]]
+** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
+** file control is sent to the open [sqlite3_file] object corresponding
+** to the database file to which the pragma statement refers. ^The argument
+** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
+** pointers to strings (char**) in which the second element of the array
+** is the name of the pragma and the third element is the argument to the
+** pragma or NULL if the pragma has no argument. ^The handler for an
+** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
+** of the char** argument point to a string obtained from [sqlite3_mprintf()]
+** or the equivalent and that string will become the result of the pragma or
+** the error message if the pragma fails. ^If the
+** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
+** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
+** file control returns [SQLITE_OK], then the parser assumes that the
+** VFS has handled the PRAGMA itself and the parser generates a no-op
+** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
+** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
+** that the VFS encountered an error while handling the [PRAGMA] and the
+** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
+** file control occurs at the beginning of pragma statement analysis and so
+** it is able to override built-in [PRAGMA] statements.
+**
+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
+** ^This file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke this file-control to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses. The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()]. The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
+** </ul>
+*/
+#define SQLITE_FCNTL_LOCKSTATE 1
+#define SQLITE_GET_LOCKPROXYFILE 2
+#define SQLITE_SET_LOCKPROXYFILE 3
+#define SQLITE_LAST_ERRNO 4
+#define SQLITE_FCNTL_SIZE_HINT 5
+#define SQLITE_FCNTL_CHUNK_SIZE 6
+#define SQLITE_FCNTL_FILE_POINTER 7
+#define SQLITE_FCNTL_SYNC_OMITTED 8
+#define SQLITE_FCNTL_WIN32_AV_RETRY 9
+#define SQLITE_FCNTL_PERSIST_WAL 10
+#define SQLITE_FCNTL_OVERWRITE 11
+#define SQLITE_FCNTL_VFSNAME 12
+#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
+#define SQLITE_FCNTL_PRAGMA 14
+#define SQLITE_FCNTL_BUSYHANDLER 15
+#define SQLITE_FCNTL_TEMPFILENAME 16
+
+/*
+** CAPI3REF: Mutex Handle
+**
+** The mutex module within SQLite defines [sqlite3_mutex] to be an
+** abstract type for a mutex object. The SQLite core never looks
+** at the internal representation of an [sqlite3_mutex]. It only
+** deals with pointers to the [sqlite3_mutex] object.
+**
+** Mutexes are created using [sqlite3_mutex_alloc()].
+*/
+typedef struct sqlite3_mutex sqlite3_mutex;
+
+/*
+** CAPI3REF: OS Interface Object
+**
+** An instance of the sqlite3_vfs object defines the interface between
+** the SQLite core and the underlying operating system. The "vfs"
+** in the name of the object stands for "virtual file system". See
+** the [VFS | VFS documentation] for further information.
+**
+** The value of the iVersion field is initially 1 but may be larger in
+** future versions of SQLite. Additional fields may be appended to this
+** object when the iVersion value is increased. Note that the structure
+** of the sqlite3_vfs object changes in the transaction between
+** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not
+** modified.
+**
+** The szOsFile field is the size of the subclassed [sqlite3_file]
+** structure used by this VFS. mxPathname is the maximum length of
+** a pathname in this VFS.
+**
+** Registered sqlite3_vfs objects are kept on a linked list formed by
+** the pNext pointer. The [sqlite3_vfs_register()]
+** and [sqlite3_vfs_unregister()] interfaces manage this list
+** in a thread-safe way. The [sqlite3_vfs_find()] interface
+** searches the list. Neither the application code nor the VFS
+** implementation should use the pNext pointer.
+**
+** The pNext field is the only field in the sqlite3_vfs
+** structure that SQLite will ever modify. SQLite will only access
+** or modify this field while holding a particular static mutex.
+** The application should never modify anything within the sqlite3_vfs
+** object once the object has been registered.
+**
+** The zName field holds the name of the VFS module. The name must
+** be unique across all VFS modules.
+**
+** [[sqlite3_vfs.xOpen]]
+** ^SQLite guarantees that the zFilename parameter to xOpen
+** is either a NULL pointer or string obtained
+** from xFullPathname() with an optional suffix added.
+** ^If a suffix is added to the zFilename parameter, it will
+** consist of a single "-" character followed by no more than
+** 11 alphanumeric and/or "-" characters.
+** ^SQLite further guarantees that
+** the string will be valid and unchanged until xClose() is
+** called. Because of the previous sentence,
+** the [sqlite3_file] can safely store a pointer to the
+** filename if it needs to remember the filename for some reason.
+** If the zFilename parameter to xOpen is a NULL pointer then xOpen
+** must invent its own temporary name for the file. ^Whenever the
+** xFilename parameter is NULL it will also be the case that the
+** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
+**
+** The flags argument to xOpen() includes all bits set in
+** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
+** or [sqlite3_open16()] is used, then flags includes at least
+** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
+** If xOpen() opens a file read-only then it sets *pOutFlags to
+** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
+**
+** ^(SQLite will also add one of the following flags to the xOpen()
+** call, depending on the object being opened:
+**
+** <ul>
+** <li> [SQLITE_OPEN_MAIN_DB]
+** <li> [SQLITE_OPEN_MAIN_JOURNAL]
+** <li> [SQLITE_OPEN_TEMP_DB]
+** <li> [SQLITE_OPEN_TEMP_JOURNAL]
+** <li> [SQLITE_OPEN_TRANSIENT_DB]
+** <li> [SQLITE_OPEN_SUBJOURNAL]
+** <li> [SQLITE_OPEN_MASTER_JOURNAL]
+** <li> [SQLITE_OPEN_WAL]
+** </ul>)^
+**
+** The file I/O implementation can use the object type flags to
+** change the way it deals with files. For example, an application
+** that does not care about crash recovery or rollback might make
+** the open of a journal file a no-op. Writes to this journal would
+** also be no-ops, and any attempt to read the journal would return
+** SQLITE_IOERR. Or the implementation might recognize that a database
+** file will be doing page-aligned sector reads and writes in a random
+** order and set up its I/O subsystem accordingly.
+**
+** SQLite might also add one of the following flags to the xOpen method:
+**
+** <ul>
+** <li> [SQLITE_OPEN_DELETEONCLOSE]
+** <li> [SQLITE_OPEN_EXCLUSIVE]
+** </ul>
+**
+** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
+** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE]
+** will be set for TEMP databases and their journals, transient
+** databases, and subjournals.
+**
+** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
+** with the [SQLITE_OPEN_CREATE] flag, which are both directly
+** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
+** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
+** SQLITE_OPEN_CREATE, is used to indicate that file should always
+** be created, and that it is an error if it already exists.
+** It is <i>not</i> used to indicate the file should be opened
+** for exclusive access.
+**
+** ^At least szOsFile bytes of memory are allocated by SQLite
+** to hold the [sqlite3_file] structure passed as the third
+** argument to xOpen. The xOpen method does not have to
+** allocate the structure; it should just fill it in. Note that
+** the xOpen method must set the sqlite3_file.pMethods to either
+** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
+** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
+** element will be valid after xOpen returns regardless of the success
+** or failure of the xOpen call.
+**
+** [[sqlite3_vfs.xAccess]]
+** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
+** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
+** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
+** to test whether a file is at least readable. The file can be a
+** directory.
+**
+** ^SQLite will always allocate at least mxPathname+1 bytes for the
+** output buffer xFullPathname. The exact size of the output buffer
+** is also passed as a parameter to both methods. If the output buffer
+** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
+** handled as a fatal error by SQLite, vfs implementations should endeavor
+** to prevent this by setting mxPathname to a sufficiently large value.
+**
+** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
+** interfaces are not strictly a part of the filesystem, but they are
+** included in the VFS structure for completeness.
+** The xRandomness() function attempts to return nBytes bytes
+** of good-quality randomness into zOut. The return value is
+** the actual number of bytes of randomness obtained.
+** The xSleep() method causes the calling thread to sleep for at
+** least the number of microseconds given. ^The xCurrentTime()
+** method returns a Julian Day Number for the current date and time as
+** a floating point value.
+** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
+** Day Number multiplied by 86400000 (the number of milliseconds in
+** a 24-hour day).
+** ^SQLite will use the xCurrentTimeInt64() method to get the current
+** date and time if that method is available (if iVersion is 2 or
+** greater and the function pointer is not NULL) and will fall back
+** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
+**
+** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
+** are not used by the SQLite core. These optional interfaces are provided
+** by some VFSes to facilitate testing of the VFS code. By overriding
+** system calls with functions under its control, a test program can
+** simulate faults and error conditions that would otherwise be difficult
+** or impossible to induce. The set of system calls that can be overridden
+** varies from one VFS to another, and from one version of the same VFS to the
+** next. Applications that use these interfaces must be prepared for any
+** or all of these interfaces to be NULL or for their behavior to change
+** from one release to the next. Applications must not attempt to access
+** any of these methods if the iVersion of the VFS is less than 3.
+*/
+typedef struct sqlite3_vfs sqlite3_vfs;
+typedef void (*sqlite3_syscall_ptr)(void);
+struct sqlite3_vfs {
+ int iVersion; /* Structure version number (currently 3) */
+ int szOsFile; /* Size of subclassed sqlite3_file */
+ int mxPathname; /* Maximum file pathname length */
+ sqlite3_vfs *pNext; /* Next registered VFS */
+ const char *zName; /* Name of this virtual file system */
+ void *pAppData; /* Pointer to application-specific data */
+ int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
+ int flags, int *pOutFlags);
+ int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
+ int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
+ int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
+ void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
+ void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
+ void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
+ void (*xDlClose)(sqlite3_vfs*, void*);
+ int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
+ int (*xSleep)(sqlite3_vfs*, int microseconds);
+ int (*xCurrentTime)(sqlite3_vfs*, double*);
+ int (*xGetLastError)(sqlite3_vfs*, int, char *);
+ /*
+ ** The methods above are in version 1 of the sqlite_vfs object
+ ** definition. Those that follow are added in version 2 or later
+ */
+ int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
+ /*
+ ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
+ ** Those below are for version 3 and greater.
+ */
+ int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
+ sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
+ const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
+ /*
+ ** The methods above are in versions 1 through 3 of the sqlite_vfs object.
+ ** New fields may be appended in figure versions. The iVersion
+ ** value will increment whenever this happens.
+ */
+};
+
+/*
+** CAPI3REF: Flags for the xAccess VFS method
+**
+** These integer constants can be used as the third parameter to
+** the xAccess method of an [sqlite3_vfs] object. They determine
+** what kind of permissions the xAccess method is looking for.
+** With SQLITE_ACCESS_EXISTS, the xAccess method
+** simply checks whether the file exists.
+** With SQLITE_ACCESS_READWRITE, the xAccess method
+** checks whether the named directory is both readable and writable
+** (in other words, if files can be added, removed, and renamed within
+** the directory).
+** The SQLITE_ACCESS_READWRITE constant is currently used only by the
+** [temp_store_directory pragma], though this could change in a future
+** release of SQLite.
+** With SQLITE_ACCESS_READ, the xAccess method
+** checks whether the file is readable. The SQLITE_ACCESS_READ constant is
+** currently unused, though it might be used in a future release of
+** SQLite.
+*/
+#define SQLITE_ACCESS_EXISTS 0
+#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */
+#define SQLITE_ACCESS_READ 2 /* Unused */
+
+/*
+** CAPI3REF: Flags for the xShmLock VFS method
+**
+** These integer constants define the various locking operations
+** allowed by the xShmLock method of [sqlite3_io_methods]. The
+** following are the only legal combinations of flags to the
+** xShmLock method:
+**
+** <ul>
+** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
+** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
+** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
+** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
+** </ul>
+**
+** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
+** was given no the corresponding lock.
+**
+** The xShmLock method can transition between unlocked and SHARED or
+** between unlocked and EXCLUSIVE. It cannot transition between SHARED
+** and EXCLUSIVE.
+*/
+#define SQLITE_SHM_UNLOCK 1
+#define SQLITE_SHM_LOCK 2
+#define SQLITE_SHM_SHARED 4
+#define SQLITE_SHM_EXCLUSIVE 8
+
+/*
+** CAPI3REF: Maximum xShmLock index
+**
+** The xShmLock method on [sqlite3_io_methods] may use values
+** between 0 and this upper bound as its "offset" argument.
+** The SQLite core will never attempt to acquire or release a
+** lock outside of this range
+*/
+#define SQLITE_SHM_NLOCK 8
+
+
+/*
+** CAPI3REF: Initialize The SQLite Library
+**
+** ^The sqlite3_initialize() routine initializes the
+** SQLite library. ^The sqlite3_shutdown() routine
+** deallocates any resources that were allocated by sqlite3_initialize().
+** These routines are designed to aid in process initialization and
+** shutdown on embedded systems. Workstation applications using
+** SQLite normally do not need to invoke either of these routines.
+**
+** A call to sqlite3_initialize() is an "effective" call if it is
+** the first time sqlite3_initialize() is invoked during the lifetime of
+** the process, or if it is the first time sqlite3_initialize() is invoked
+** following a call to sqlite3_shutdown(). ^(Only an effective call
+** of sqlite3_initialize() does any initialization. All other calls
+** are harmless no-ops.)^
+**
+** A call to sqlite3_shutdown() is an "effective" call if it is the first
+** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only
+** an effective call to sqlite3_shutdown() does any deinitialization.
+** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^
+**
+** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown()
+** is not. The sqlite3_shutdown() interface must only be called from a
+** single thread. All open [database connections] must be closed and all
+** other SQLite resources must be deallocated prior to invoking
+** sqlite3_shutdown().
+**
+** Among other things, ^sqlite3_initialize() will invoke
+** sqlite3_os_init(). Similarly, ^sqlite3_shutdown()
+** will invoke sqlite3_os_end().
+**
+** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success.
+** ^If for some reason, sqlite3_initialize() is unable to initialize
+** the library (perhaps it is unable to allocate a needed resource such
+** as a mutex) it returns an [error code] other than [SQLITE_OK].
+**
+** ^The sqlite3_initialize() routine is called internally by many other
+** SQLite interfaces so that an application usually does not need to
+** invoke sqlite3_initialize() directly. For example, [sqlite3_open()]
+** calls sqlite3_initialize() so the SQLite library will be automatically
+** initialized when [sqlite3_open()] is called if it has not be initialized
+** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT]
+** compile-time option, then the automatic calls to sqlite3_initialize()
+** are omitted and the application must call sqlite3_initialize() directly
+** prior to using any other SQLite interface. For maximum portability,
+** it is recommended that applications always invoke sqlite3_initialize()
+** directly prior to using any other SQLite interface. Future releases
+** of SQLite may require this. In other words, the behavior exhibited
+** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the
+** default behavior in some future release of SQLite.
+**
+** The sqlite3_os_init() routine does operating-system specific
+** initialization of the SQLite library. The sqlite3_os_end()
+** routine undoes the effect of sqlite3_os_init(). Typical tasks
+** performed by these routines include allocation or deallocation
+** of static resources, initialization of global variables,
+** setting up a default [sqlite3_vfs] module, or setting up
+** a default configuration using [sqlite3_config()].
+**
+** The application should never invoke either sqlite3_os_init()
+** or sqlite3_os_end() directly. The application should only invoke
+** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init()
+** interface is called automatically by sqlite3_initialize() and
+** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate
+** implementations for sqlite3_os_init() and sqlite3_os_end()
+** are built into SQLite when it is compiled for Unix, Windows, or OS/2.
+** When [custom builds | built for other platforms]
+** (using the [SQLITE_OS_OTHER=1] compile-time
+** option) the application must supply a suitable implementation for
+** sqlite3_os_init() and sqlite3_os_end(). An application-supplied
+** implementation of sqlite3_os_init() or sqlite3_os_end()
+** must return [SQLITE_OK] on success and some other [error code] upon
+** failure.
+*/
+SQLITE_API int sqlite3_initialize(void);
+SQLITE_API int sqlite3_shutdown(void);
+SQLITE_API int sqlite3_os_init(void);
+SQLITE_API int sqlite3_os_end(void);
+
+/*
+** CAPI3REF: Configuring The SQLite Library
+**
+** The sqlite3_config() interface is used to make global configuration
+** changes to SQLite in order to tune SQLite to the specific needs of
+** the application. The default configuration is recommended for most
+** applications and so this routine is usually not necessary. It is
+** provided to support rare applications with unusual needs.
+**
+** The sqlite3_config() interface is not threadsafe. The application
+** must insure that no other SQLite interfaces are invoked by other
+** threads while sqlite3_config() is running. Furthermore, sqlite3_config()
+** may only be invoked prior to library initialization using
+** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
+** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
+** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
+** Note, however, that ^sqlite3_config() can be called as part of the
+** implementation of an application-defined [sqlite3_os_init()].
+**
+** The first argument to sqlite3_config() is an integer
+** [configuration option] that determines
+** what property of SQLite is to be configured. Subsequent arguments
+** vary depending on the [configuration option]
+** in the first argument.
+**
+** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
+** ^If the option is unknown or SQLite is unable to set the option
+** then this routine returns a non-zero [error code].
+*/
+SQLITE_API int sqlite3_config(int, ...);
+
+/*
+** CAPI3REF: Configure database connections
+**
+** The sqlite3_db_config() interface is used to make configuration
+** changes to a [database connection]. The interface is similar to
+** [sqlite3_config()] except that the changes apply to a single
+** [database connection] (specified in the first argument).
+**
+** The second argument to sqlite3_db_config(D,V,...) is the
+** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code
+** that indicates what aspect of the [database connection] is being configured.
+** Subsequent arguments vary depending on the configuration verb.
+**
+** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
+** the call is considered successful.
+*/
+SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+
+/*
+** CAPI3REF: Memory Allocation Routines
+**
+** An instance of this object defines the interface between SQLite
+** and low-level memory allocation routines.
+**
+** This object is used in only one place in the SQLite interface.
+** A pointer to an instance of this object is the argument to
+** [sqlite3_config()] when the configuration option is
+** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
+** By creating an instance of this object
+** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
+** during configuration, an application can specify an alternative
+** memory allocation subsystem for SQLite to use for all of its
+** dynamic memory needs.
+**
+** Note that SQLite comes with several [built-in memory allocators]
+** that are perfectly adequate for the overwhelming majority of applications
+** and that this object is only useful to a tiny minority of applications
+** with specialized memory allocation requirements. This object is
+** also used during testing of SQLite in order to specify an alternative
+** memory allocator that simulates memory out-of-memory conditions in
+** order to verify that SQLite recovers gracefully from such
+** conditions.
+**
+** The xMalloc, xRealloc, and xFree methods must work like the
+** malloc(), realloc() and free() functions from the standard C library.
+** ^SQLite guarantees that the second argument to
+** xRealloc is always a value returned by a prior call to xRoundup.
+**
+** xSize should return the allocated size of a memory allocation
+** previously obtained from xMalloc or xRealloc. The allocated size
+** is always at least as big as the requested size but may be larger.
+**
+** The xRoundup method returns what would be the allocated size of
+** a memory allocation given a particular requested size. Most memory
+** allocators round up memory allocations at least to the next multiple
+** of 8. Some allocators round up to a larger multiple or to a power of 2.
+** Every memory allocation request coming in through [sqlite3_malloc()]
+** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
+** that causes the corresponding memory allocation to fail.
+**
+** The xInit method initializes the memory allocator. (For example,
+** it might allocate any require mutexes or initialize internal data
+** structures. The xShutdown method is invoked (indirectly) by
+** [sqlite3_shutdown()] and should deallocate any resources acquired
+** by xInit. The pAppData pointer is used as the only parameter to
+** xInit and xShutdown.
+**
+** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes
+** the xInit method, so the xInit method need not be threadsafe. The
+** xShutdown method is only called from [sqlite3_shutdown()] so it does
+** not need to be threadsafe either. For all other methods, SQLite
+** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the
+** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which
+** it is by default) and so the methods are automatically serialized.
+** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other
+** methods must be threadsafe or else make their own arrangements for
+** serialization.
+**
+** SQLite will never invoke xInit() more than once without an intervening
+** call to xShutdown().
+*/
+typedef struct sqlite3_mem_methods sqlite3_mem_methods;
+struct sqlite3_mem_methods {
+ void *(*xMalloc)(int); /* Memory allocation function */
+ void (*xFree)(void*); /* Free a prior allocation */
+ void *(*xRealloc)(void*,int); /* Resize an allocation */
+ int (*xSize)(void*); /* Return the size of an allocation */
+ int (*xRoundup)(int); /* Round up request size to allocation size */
+ int (*xInit)(void*); /* Initialize the memory allocator */
+ void (*xShutdown)(void*); /* Deinitialize the memory allocator */
+ void *pAppData; /* Argument to xInit() and xShutdown() */
+};
+
+/*
+** CAPI3REF: Configuration Options
+** KEYWORDS: {configuration option}
+**
+** These constants are the available integer configuration options that
+** can be passed as the first argument to the [sqlite3_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_config()] to make sure that
+** the call worked. The [sqlite3_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
+**
+** <dl>
+** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
+** <dd>There are no arguments to this option. ^This option sets the
+** [threading mode] to Single-thread. In other words, it disables
+** all mutexing and puts SQLite into a mode where it can only be used
+** by a single thread. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** it is not possible to change the [threading mode] from its default
+** value of Single-thread and so [sqlite3_config()] will return
+** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
+** configuration option.</dd>
+**
+** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
+** <dd>There are no arguments to this option. ^This option sets the
+** [threading mode] to Multi-thread. In other words, it disables
+** mutexing on [database connection] and [prepared statement] objects.
+** The application is responsible for serializing access to
+** [database connections] and [prepared statements]. But other mutexes
+** are enabled so that SQLite will be safe to use in a multi-threaded
+** environment as long as no two threads attempt to use the same
+** [database connection] at the same time. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** it is not possible to set the Multi-thread [threading mode] and
+** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
+** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
+**
+** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
+** <dd>There are no arguments to this option. ^This option sets the
+** [threading mode] to Serialized. In other words, this option enables
+** all mutexes including the recursive
+** mutexes on [database connection] and [prepared statement] objects.
+** In this mode (which is the default when SQLite is compiled with
+** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access
+** to [database connections] and [prepared statements] so that the
+** application is free to use the same [database connection] or the
+** same [prepared statement] in different threads at the same time.
+** ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** it is not possible to set the Serialized [threading mode] and
+** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
+** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
+**
+** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mem_methods] structure. The argument specifies
+** alternative low-level memory allocation routines to be used in place of
+** the memory allocation routines built into SQLite.)^ ^SQLite makes
+** its own private copy of the content of the [sqlite3_mem_methods] structure
+** before the [sqlite3_config()] call returns.</dd>
+**
+** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
+** structure is filled with the currently defined memory allocation routines.)^
+** This option can be used to overload the default memory allocation
+** routines with a wrapper that simulations memory allocation failure or
+** tracks memory usage, for example. </dd>
+**
+** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
+** <dd> ^This option takes single argument of type int, interpreted as a
+** boolean, which enables or disables the collection of memory allocation
+** statistics. ^(When memory allocation statistics are disabled, the
+** following SQLite interfaces become non-operational:
+** <ul>
+** <li> [sqlite3_memory_used()]
+** <li> [sqlite3_memory_highwater()]
+** <li> [sqlite3_soft_heap_limit64()]
+** <li> [sqlite3_status()]
+** </ul>)^
+** ^Memory allocation statistics are enabled by default unless SQLite is
+** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
+** allocation statistics are disabled by default.
+** </dd>
+**
+** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
+** <dd> ^This option specifies a static memory buffer that SQLite can use for
+** scratch memory. There are three arguments: A pointer an 8-byte
+** aligned memory buffer from which the scratch allocations will be
+** drawn, the size of each scratch allocation (sz),
+** and the maximum number of scratch allocations (N). The sz
+** argument must be a multiple of 16.
+** The first argument must be a pointer to an 8-byte aligned buffer
+** of at least sz*N bytes of memory.
+** ^SQLite will use no more than two scratch buffers per thread. So
+** N should be set to twice the expected maximum number of threads.
+** ^SQLite will never require a scratch buffer that is more than 6
+** times the database page size. ^If SQLite needs needs additional
+** scratch memory beyond what is provided by this configuration option, then
+** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
+**
+** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
+** <dd> ^This option specifies a static memory buffer that SQLite can use for
+** the database page cache with the default page cache implementation.
+** This configuration should not be used if an application-define page
+** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option.
+** There are three arguments to this option: A pointer to 8-byte aligned
+** memory, the size of each page buffer (sz), and the number of pages (N).
+** The sz argument should be the size of the largest database page
+** (a power of two between 512 and 32768) plus a little extra for each
+** page header. ^The page header size is 20 to 40 bytes depending on
+** the host architecture. ^It is harmless, apart from the wasted memory,
+** to make sz a little too large. The first
+** argument should point to an allocation of at least sz*N bytes of memory.
+** ^SQLite will use the memory provided by the first argument to satisfy its
+** memory needs for the first N pages that it adds to cache. ^If additional
+** page cache memory is needed beyond what is provided by this option, then
+** SQLite goes to [sqlite3_malloc()] for the additional storage space.
+** The pointer in the first argument must
+** be aligned to an 8-byte boundary or subsequent behavior of SQLite
+** will be undefined.</dd>
+**
+** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
+** <dd> ^This option specifies a static memory buffer that SQLite will use
+** for all of its dynamic memory allocation needs beyond those provided
+** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
+** There are three arguments: An 8-byte aligned pointer to the memory,
+** the number of bytes in the memory buffer, and the minimum allocation size.
+** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts
+** to using its default memory allocator (the system malloc() implementation),
+** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the
+** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or
+** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory
+** allocator is engaged to handle all of SQLites memory allocation needs.
+** The first pointer (the memory pointer) must be aligned to an 8-byte
+** boundary or subsequent behavior of SQLite will be undefined.
+** The minimum allocation size is capped at 2**12. Reasonable values
+** for the minimum allocation size are 2**5 through 2**8.</dd>
+**
+** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mutex_methods] structure. The argument specifies
+** alternative low-level mutex routines to be used in place
+** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
+** content of the [sqlite3_mutex_methods] structure before the call to
+** [sqlite3_config()] returns. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** the entire mutexing subsystem is omitted from the build and hence calls to
+** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
+** return [SQLITE_ERROR].</dd>
+**
+** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mutex_methods] structure. The
+** [sqlite3_mutex_methods]
+** structure is filled with the currently defined mutex routines.)^
+** This option can be used to overload the default mutex allocation
+** routines with a wrapper used to track mutex usage for performance
+** profiling or testing, for example. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** the entire mutexing subsystem is omitted from the build and hence calls to
+** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
+** return [SQLITE_ERROR].</dd>
+**
+** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
+** <dd> ^(This option takes two arguments that determine the default
+** memory allocation for the lookaside memory allocator on each
+** [database connection]. The first argument is the
+** size of each lookaside buffer slot and the second is the number of
+** slots allocated to each database connection.)^ ^(This option sets the
+** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
+** verb to [sqlite3_db_config()] can be used to change the lookaside
+** configuration on individual connections.)^ </dd>
+**
+** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
+** <dd> ^(This option takes a single argument which is a pointer to
+** an [sqlite3_pcache_methods2] object. This object specifies the interface
+** to a custom page cache implementation.)^ ^SQLite makes a copy of the
+** object and uses it for page cache memory allocations.</dd>
+**
+** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** [sqlite3_pcache_methods2] object. SQLite copies of the current
+** page cache implementation into that object.)^ </dd>
+**
+** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
+** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
+** function with a call signature of void(*)(void*,int,const char*),
+** and a pointer to void. ^If the function pointer is not NULL, it is
+** invoked by [sqlite3_log()] to process each logging event. ^If the
+** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
+** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
+** passed through as the first parameter to the application-defined logger
+** function whenever that function is invoked. ^The second parameter to
+** the logger function is a copy of the first parameter to the corresponding
+** [sqlite3_log()] call and is intended to be a [result code] or an
+** [extended result code]. ^The third parameter passed to the logger is
+** log message after formatting via [sqlite3_snprintf()].
+** The SQLite logging interface is not reentrant; the logger function
+** supplied by the application must not invoke any SQLite interface.
+** In a multi-threaded application, the application-defined logger
+** function must be threadsafe. </dd>
+**
+** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
+** <dd> This option takes a single argument of type int. If non-zero, then
+** URI handling is globally enabled. If the parameter is zero, then URI handling
+** is globally disabled. If URI handling is globally enabled, all filenames
+** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
+** specified as part of [ATTACH] commands are interpreted as URIs, regardless
+** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
+** connection is opened. If it is globally disabled, filenames are
+** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
+** database connection is opened. By default, URI handling is globally
+** disabled. The default value may be changed by compiling with the
+** [SQLITE_USE_URI] symbol defined.
+**
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd> This option takes a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer. The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** malfunction when the optimization is enabled. Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
+** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
+** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
+** <dd> These options are obsolete and should not be used by new code.
+** They are retained for backwards compatibility but are now no-ops.
+** </dl>
+**
+** [[SQLITE_CONFIG_SQLLOG]]
+** <dt>SQLITE_CONFIG_SQLLOG
+** <dd>This option is only available if sqlite is compiled with the
+** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
+** The second should be of type (void*). The callback is invoked by the library
+** in three separate circumstances, identified by the value passed as the
+** fourth parameter. If the fourth parameter is 0, then the database connection
+** passed as the second argument has just been opened. The third argument
+** points to a buffer containing the name of the main database file. If the
+** fourth parameter is 1, then the SQL statement that the third parameter
+** points to has just been executed. Or, if the fourth parameter is 2, then
+** the connection being passed as the second parameter is being closed. The
+** third parameter is passed NULL In this case.
+** </dl>
+*/
+#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
+#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
+#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
+#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */
+#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
+#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
+#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
+#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
+#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
+/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
+#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
+#define SQLITE_CONFIG_PCACHE 14 /* no-op */
+#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */
+#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
+#define SQLITE_CONFIG_URI 17 /* int */
+#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
+#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
+
+/*
+** CAPI3REF: Database Connection Configuration Options
+**
+** These constants are the available integer configuration options that
+** can be passed as the second argument to the [sqlite3_db_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_db_config()] to make sure that
+** the call worked. ^The [sqlite3_db_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
+**
+** <dl>
+** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
+** <dd> ^This option takes three additional arguments that determine the
+** [lookaside memory allocator] configuration for the [database connection].
+** ^The first argument (the third parameter to [sqlite3_db_config()] is a
+** pointer to a memory buffer to use for lookaside memory.
+** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
+** may be NULL in which case SQLite will allocate the
+** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
+** size of each lookaside buffer slot. ^The third argument is the number of
+** slots. The size of the buffer in the first argument must be greater than
+** or equal to the product of the second and third arguments. The buffer
+** must be aligned to an 8-byte boundary. ^If the second argument to
+** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
+** rounded down to the next smaller multiple of 8. ^(The lookaside memory
+** configuration for a database connection can only be changed when that
+** connection is not currently using lookaside memory, or in other words
+** when the "current value" returned by
+** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero.
+** Any attempt to change the lookaside memory configuration when lookaside
+** memory is in use leaves the configuration unchanged and returns
+** [SQLITE_BUSY].)^</dd>
+**
+** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
+** <dd> ^This option is used to enable or disable the enforcement of
+** [foreign key constraints]. There should be two additional arguments.
+** The first argument is an integer which is 0 to disable FK enforcement,
+** positive to enable FK enforcement or negative to leave FK enforcement
+** unchanged. The second parameter is a pointer to an integer into which
+** is written 0 or 1 to indicate whether FK enforcement is off or on
+** following this call. The second parameter may be a NULL pointer, in
+** which case the FK enforcement setting is not reported back. </dd>
+**
+** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
+** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
+** There should be two additional arguments.
+** The first argument is an integer which is 0 to disable triggers,
+** positive to enable triggers or negative to leave the setting unchanged.
+** The second parameter is a pointer to an integer into which
+** is written 0 or 1 to indicate whether triggers are disabled or enabled
+** following this call. The second parameter may be a NULL pointer, in
+** which case the trigger setting is not reported back. </dd>
+**
+** </dl>
+*/
+#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
+#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
+
+
+/*
+** CAPI3REF: Enable Or Disable Extended Result Codes
+**
+** ^The sqlite3_extended_result_codes() routine enables or disables the
+** [extended result codes] feature of SQLite. ^The extended result
+** codes are disabled by default for historical compatibility.
+*/
+SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
+
+/*
+** CAPI3REF: Last Insert Rowid
+**
+** ^Each entry in an SQLite table has a unique 64-bit signed
+** integer key called the [ROWID | "rowid"]. ^The rowid is always available
+** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
+** names are not also used by explicitly declared columns. ^If
+** the table has a column of type [INTEGER PRIMARY KEY] then that column
+** is another alias for the rowid.
+**
+** ^This routine returns the [rowid] of the most recent
+** successful [INSERT] into the database from the [database connection]
+** in the first argument. ^As of SQLite version 3.7.7, this routines
+** records the last insert rowid of both ordinary tables and [virtual tables].
+** ^If no successful [INSERT]s
+** have ever occurred on that database connection, zero is returned.
+**
+** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
+** method, then this routine will return the [rowid] of the inserted
+** row as long as the trigger or virtual table method is running.
+** But once the trigger or virtual table method ends, the value returned
+** by this routine reverts to what it was before the trigger or virtual
+** table method began.)^
+**
+** ^An [INSERT] that fails due to a constraint violation is not a
+** successful [INSERT] and does not change the value returned by this
+** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
+** and INSERT OR ABORT make no changes to the return value of this
+** routine when their insertion fails. ^(When INSERT OR REPLACE
+** encounters a constraint violation, it does not fail. The
+** INSERT continues to completion after deleting rows that caused
+** the constraint problem so INSERT OR REPLACE will always change
+** the return value of this interface.)^
+**
+** ^For the purposes of this routine, an [INSERT] is considered to
+** be successful even if it is subsequently rolled back.
+**
+** This function is accessible to SQL statements via the
+** [last_insert_rowid() SQL function].
+**
+** If a separate thread performs a new [INSERT] on the same
+** database connection while the [sqlite3_last_insert_rowid()]
+** function is running and thus changes the last insert [rowid],
+** then the value returned by [sqlite3_last_insert_rowid()] is
+** unpredictable and might not equal either the old or the new
+** last insert [rowid].
+*/
+SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+
+/*
+** CAPI3REF: Count The Number Of Rows Modified
+**
+** ^This function returns the number of database rows that were changed
+** or inserted or deleted by the most recently completed SQL statement
+** on the [database connection] specified by the first parameter.
+** ^(Only changes that are directly specified by the [INSERT], [UPDATE],
+** or [DELETE] statement are counted. Auxiliary changes caused by
+** triggers or [foreign key actions] are not counted.)^ Use the
+** [sqlite3_total_changes()] function to find the total number of changes
+** including changes caused by triggers and foreign key actions.
+**
+** ^Changes to a view that are simulated by an [INSTEAD OF trigger]
+** are not counted. Only real table changes are counted.
+**
+** ^(A "row change" is a change to a single row of a single table
+** caused by an INSERT, DELETE, or UPDATE statement. Rows that
+** are changed as side effects of [REPLACE] constraint resolution,
+** rollback, ABORT processing, [DROP TABLE], or by any other
+** mechanisms do not count as direct row changes.)^
+**
+** A "trigger context" is a scope of execution that begins and
+** ends with the script of a [CREATE TRIGGER | trigger].
+** Most SQL statements are
+** evaluated outside of any trigger. This is the "top level"
+** trigger context. If a trigger fires from the top level, a
+** new trigger context is entered for the duration of that one
+** trigger. Subtriggers create subcontexts for their duration.
+**
+** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does
+** not create a new trigger context.
+**
+** ^This function returns the number of direct row changes in the
+** most recent INSERT, UPDATE, or DELETE statement within the same
+** trigger context.
+**
+** ^Thus, when called from the top level, this function returns the
+** number of changes in the most recent INSERT, UPDATE, or DELETE
+** that also occurred at the top level. ^(Within the body of a trigger,
+** the sqlite3_changes() interface can be called to find the number of
+** changes in the most recently completed INSERT, UPDATE, or DELETE
+** statement within the body of the same trigger.
+** However, the number returned does not include changes
+** caused by subtriggers since those have their own context.)^
+**
+** See also the [sqlite3_total_changes()] interface, the
+** [count_changes pragma], and the [changes() SQL function].
+**
+** If a separate thread makes changes on the same database connection
+** while [sqlite3_changes()] is running then the value returned
+** is unpredictable and not meaningful.
+*/
+SQLITE_API int sqlite3_changes(sqlite3*);
+
+/*
+** CAPI3REF: Total Number Of Rows Modified
+**
+** ^This function returns the number of row changes caused by [INSERT],
+** [UPDATE] or [DELETE] statements since the [database connection] was opened.
+** ^(The count returned by sqlite3_total_changes() includes all changes
+** from all [CREATE TRIGGER | trigger] contexts and changes made by
+** [foreign key actions]. However,
+** the count does not include changes used to implement [REPLACE] constraints,
+** do rollbacks or ABORT processing, or [DROP TABLE] processing. The
+** count does not include rows of views that fire an [INSTEAD OF trigger],
+** though if the INSTEAD OF trigger makes changes of its own, those changes
+** are counted.)^
+** ^The sqlite3_total_changes() function counts the changes as soon as
+** the statement that makes them is completed (when the statement handle
+** is passed to [sqlite3_reset()] or [sqlite3_finalize()]).
+**
+** See also the [sqlite3_changes()] interface, the
+** [count_changes pragma], and the [total_changes() SQL function].
+**
+** If a separate thread makes changes on the same database connection
+** while [sqlite3_total_changes()] is running then the value
+** returned is unpredictable and not meaningful.
+*/
+SQLITE_API int sqlite3_total_changes(sqlite3*);
+
+/*
+** CAPI3REF: Interrupt A Long-Running Query
+**
+** ^This function causes any pending database operation to abort and
+** return at its earliest opportunity. This routine is typically
+** called in response to a user action such as pressing "Cancel"
+** or Ctrl-C where the user wants a long query operation to halt
+** immediately.
+**
+** ^It is safe to call this routine from a thread different from the
+** thread that is currently running the database operation. But it
+** is not safe to call this routine with a [database connection] that
+** is closed or might close before sqlite3_interrupt() returns.
+**
+** ^If an SQL operation is very nearly finished at the time when
+** sqlite3_interrupt() is called, then it might not have an opportunity
+** to be interrupted and might continue to completion.
+**
+** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT].
+** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE
+** that is inside an explicit transaction, then the entire transaction
+** will be rolled back automatically.
+**
+** ^The sqlite3_interrupt(D) call is in effect until all currently running
+** SQL statements on [database connection] D complete. ^Any new SQL statements
+** that are started after the sqlite3_interrupt() call and before the
+** running statements reaches zero are interrupted as if they had been
+** running prior to the sqlite3_interrupt() call. ^New SQL statements
+** that are started after the running statement count reaches zero are
+** not effected by the sqlite3_interrupt().
+** ^A call to sqlite3_interrupt(D) that occurs when there are no running
+** SQL statements is a no-op and has no effect on SQL statements
+** that are started after the sqlite3_interrupt() call returns.
+**
+** If the database connection closes while [sqlite3_interrupt()]
+** is running then bad things will likely happen.
+*/
+SQLITE_API void sqlite3_interrupt(sqlite3*);
+
+/*
+** CAPI3REF: Determine If An SQL Statement Is Complete
+**
+** These routines are useful during command-line input to determine if the
+** currently entered text seems to form a complete SQL statement or
+** if additional input is needed before sending the text into
+** SQLite for parsing. ^These routines return 1 if the input string
+** appears to be a complete SQL statement. ^A statement is judged to be
+** complete if it ends with a semicolon token and is not a prefix of a
+** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within
+** string literals or quoted identifier names or comments are not
+** independent tokens (they are part of the token in which they are
+** embedded) and thus do not count as a statement terminator. ^Whitespace
+** and comments that follow the final semicolon are ignored.
+**
+** ^These routines return 0 if the statement is incomplete. ^If a
+** memory allocation fails, then SQLITE_NOMEM is returned.
+**
+** ^These routines do not parse the SQL statements thus
+** will not detect syntactically incorrect SQL.
+**
+** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
+** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
+** automatically by sqlite3_complete16(). If that initialization fails,
+** then the return value from sqlite3_complete16() will be non-zero
+** regardless of whether or not the input SQL is complete.)^
+**
+** The input to [sqlite3_complete()] must be a zero-terminated
+** UTF-8 string.
+**
+** The input to [sqlite3_complete16()] must be a zero-terminated
+** UTF-16 string in native byte order.
+*/
+SQLITE_API int sqlite3_complete(const char *sql);
+SQLITE_API int sqlite3_complete16(const void *sql);
+
+/*
+** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
+**
+** ^This routine sets a callback function that might be invoked whenever
+** an attempt is made to open a database table that another thread
+** or process has locked.
+**
+** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
+** is returned immediately upon encountering the lock. ^If the busy callback
+** is not NULL, then the callback might be invoked with two arguments.
+**
+** ^The first argument to the busy handler is a copy of the void* pointer which
+** is the third argument to sqlite3_busy_handler(). ^The second argument to
+** the busy handler callback is the number of times that the busy handler has
+** been invoked for this locking event. ^If the
+** busy callback returns 0, then no additional attempts are made to
+** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
+** ^If the callback returns non-zero, then another attempt
+** is made to open the database for reading and the cycle repeats.
+**
+** The presence of a busy handler does not guarantee that it will be invoked
+** when there is lock contention. ^If SQLite determines that invoking the busy
+** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
+** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
+** Consider a scenario where one process is holding a read lock that
+** it is trying to promote to a reserved lock and
+** a second process is holding a reserved lock that it is trying
+** to promote to an exclusive lock. The first process cannot proceed
+** because it is blocked by the second and the second process cannot
+** proceed because it is blocked by the first. If both processes
+** invoke the busy handlers, neither will make any progress. Therefore,
+** SQLite returns [SQLITE_BUSY] for the first process, hoping that this
+** will induce the first process to release its read lock and allow
+** the second process to proceed.
+**
+** ^The default busy callback is NULL.
+**
+** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
+** when SQLite is in the middle of a large transaction where all the
+** changes will not fit into the in-memory cache. SQLite will
+** already hold a RESERVED lock on the database file, but it needs
+** to promote this lock to EXCLUSIVE so that it can spill cache
+** pages into the database file without harm to concurrent
+** readers. ^If it is unable to promote the lock, then the in-memory
+** cache will be left in an inconsistent state and so the error
+** code is promoted from the relatively benign [SQLITE_BUSY] to
+** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
+** forces an automatic rollback of the changes. See the
+** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
+** CorruptionFollowingBusyError</a> wiki page for a discussion of why
+** this is important.
+**
+** ^(There can only be a single busy handler defined for each
+** [database connection]. Setting a new busy handler clears any
+** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
+** will also set or clear the busy handler.
+**
+** The busy callback should not take any actions which modify the
+** database connection that invoked the busy handler. Any such actions
+** result in undefined behavior.
+**
+** A busy handler must not close the database connection
+** or [prepared statement] that invoked the busy handler.
+*/
+SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
+
+/*
+** CAPI3REF: Set A Busy Timeout
+**
+** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
+** for a specified amount of time when a table is locked. ^The handler
+** will sleep multiple times until at least "ms" milliseconds of sleeping
+** have accumulated. ^After at least "ms" milliseconds of sleeping,
+** the handler returns 0 which causes [sqlite3_step()] to return
+** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
+**
+** ^Calling this routine with an argument less than or equal to zero
+** turns off all busy handlers.
+**
+** ^(There can only be a single busy handler for a particular
+** [database connection] any any given moment. If another busy handler
+** was defined (using [sqlite3_busy_handler()]) prior to calling
+** this routine, that other busy handler is cleared.)^
+*/
+SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
+
+/*
+** CAPI3REF: Convenience Routines For Running Queries
+**
+** This is a legacy interface that is preserved for backwards compatibility.
+** Use of this interface is not recommended.
+**
+** Definition: A <b>result table</b> is memory data structure created by the
+** [sqlite3_get_table()] interface. A result table records the
+** complete query results from one or more queries.
+**
+** The table conceptually has a number of rows and columns. But
+** these numbers are not part of the result table itself. These
+** numbers are obtained separately. Let N be the number of rows
+** and M be the number of columns.
+**
+** A result table is an array of pointers to zero-terminated UTF-8 strings.
+** There are (N+1)*M elements in the array. The first M pointers point
+** to zero-terminated strings that contain the names of the columns.
+** The remaining entries all point to query results. NULL values result
+** in NULL pointers. All other values are in their UTF-8 zero-terminated
+** string representation as returned by [sqlite3_column_text()].
+**
+** A result table might consist of one or more memory allocations.
+** It is not safe to pass a result table directly to [sqlite3_free()].
+** A result table should be deallocated using [sqlite3_free_table()].
+**
+** ^(As an example of the result table format, suppose a query result
+** is as follows:
+**
+** <blockquote><pre>
+** Name | Age
+** -----------------------
+** Alice | 43
+** Bob | 28
+** Cindy | 21
+** </pre></blockquote>
+**
+** There are two column (M==2) and three rows (N==3). Thus the
+** result table has 8 entries. Suppose the result table is stored
+** in an array names azResult. Then azResult holds this content:
+**
+** <blockquote><pre>
+** azResult&#91;0] = "Name";
+** azResult&#91;1] = "Age";
+** azResult&#91;2] = "Alice";
+** azResult&#91;3] = "43";
+** azResult&#91;4] = "Bob";
+** azResult&#91;5] = "28";
+** azResult&#91;6] = "Cindy";
+** azResult&#91;7] = "21";
+** </pre></blockquote>)^
+**
+** ^The sqlite3_get_table() function evaluates one or more
+** semicolon-separated SQL statements in the zero-terminated UTF-8
+** string of its 2nd parameter and returns a result table to the
+** pointer given in its 3rd parameter.
+**
+** After the application has finished with the result from sqlite3_get_table(),
+** it must pass the result table pointer to sqlite3_free_table() in order to
+** release the memory that was malloced. Because of the way the
+** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling
+** function must not try to call [sqlite3_free()] directly. Only
+** [sqlite3_free_table()] is able to release the memory properly and safely.
+**
+** The sqlite3_get_table() interface is implemented as a wrapper around
+** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access
+** to any internal data structures of SQLite. It uses only the public
+** interface defined here. As a consequence, errors that occur in the
+** wrapper layer outside of the internal [sqlite3_exec()] call are not
+** reflected in subsequent calls to [sqlite3_errcode()] or
+** [sqlite3_errmsg()].
+*/
+SQLITE_API int sqlite3_get_table(
+ sqlite3 *db, /* An open database */
+ const char *zSql, /* SQL to be evaluated */
+ char ***pazResult, /* Results of the query */
+ int *pnRow, /* Number of result rows written here */
+ int *pnColumn, /* Number of result columns written here */
+ char **pzErrmsg /* Error msg written here */
+);
+SQLITE_API void sqlite3_free_table(char **result);
+
+/*
+** CAPI3REF: Formatted String Printing Functions
+**
+** These routines are work-alikes of the "printf()" family of functions
+** from the standard C library.
+**
+** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
+** results into memory obtained from [sqlite3_malloc()].
+** The strings returned by these two routines should be
+** released by [sqlite3_free()]. ^Both routines return a
+** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
+** memory to hold the resulting string.
+**
+** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
+** the standard C library. The result is written into the
+** buffer supplied as the second parameter whose size is given by
+** the first parameter. Note that the order of the
+** first two parameters is reversed from snprintf().)^ This is an
+** historical accident that cannot be fixed without breaking
+** backwards compatibility. ^(Note also that sqlite3_snprintf()
+** returns a pointer to its buffer instead of the number of
+** characters actually written into the buffer.)^ We admit that
+** the number of characters written would be a more useful return
+** value but we cannot change the implementation of sqlite3_snprintf()
+** now without breaking compatibility.
+**
+** ^As long as the buffer size is greater than zero, sqlite3_snprintf()
+** guarantees that the buffer is always zero-terminated. ^The first
+** parameter "n" is the total size of the buffer, including space for
+** the zero terminator. So the longest string that can be completely
+** written will be n-1 characters.
+**
+** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
+**
+** These routines all implement some additional formatting
+** options that are useful for constructing SQL statements.
+** All of the usual printf() formatting options apply. In addition, there
+** is are "%q", "%Q", and "%z" options.
+**
+** ^(The %q option works like %s in that it substitutes a nul-terminated
+** string from the argument list. But %q also doubles every '\'' character.
+** %q is designed for use inside a string literal.)^ By doubling each '\''
+** character it escapes that character and allows it to be inserted into
+** the string.
+**
+** For example, assume the string variable zText contains text as follows:
+**
+** <blockquote><pre>
+** char *zText = "It's a happy day!";
+** </pre></blockquote>
+**
+** One can use this text in an SQL statement as follows:
+**
+** <blockquote><pre>
+** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+** sqlite3_exec(db, zSQL, 0, 0, 0);
+** sqlite3_free(zSQL);
+** </pre></blockquote>
+**
+** Because the %q format string is used, the '\'' character in zText
+** is escaped and the SQL generated is as follows:
+**
+** <blockquote><pre>
+** INSERT INTO table1 VALUES('It''s a happy day!')
+** </pre></blockquote>
+**
+** This is correct. Had we used %s instead of %q, the generated SQL
+** would have looked like this:
+**
+** <blockquote><pre>
+** INSERT INTO table1 VALUES('It's a happy day!');
+** </pre></blockquote>
+**
+** This second example is an SQL syntax error. As a general rule you should
+** always use %q instead of %s when inserting text into a string literal.
+**
+** ^(The %Q option works like %q except it also adds single quotes around
+** the outside of the total string. Additionally, if the parameter in the
+** argument list is a NULL pointer, %Q substitutes the text "NULL" (without
+** single quotes).)^ So, for example, one could say:
+**
+** <blockquote><pre>
+** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+** sqlite3_exec(db, zSQL, 0, 0, 0);
+** sqlite3_free(zSQL);
+** </pre></blockquote>
+**
+** The code above will render a correct SQL statement in the zSQL
+** variable even if the zText variable is a NULL pointer.
+**
+** ^(The "%z" formatting option works like "%s" but with the
+** addition that after the string has been read and copied into
+** the result, [sqlite3_free()] is called on the input string.)^
+*/
+SQLITE_API char *sqlite3_mprintf(const char*,...);
+SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
+SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
+SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
+
+/*
+** CAPI3REF: Memory Allocation Subsystem
+**
+** The SQLite core uses these three routines for all of its own
+** internal memory allocation needs. "Core" in the previous sentence
+** does not include operating-system specific VFS implementation. The
+** Windows VFS uses native malloc() and free() for some operations.
+**
+** ^The sqlite3_malloc() routine returns a pointer to a block
+** of memory at least N bytes in length, where N is the parameter.
+** ^If sqlite3_malloc() is unable to obtain sufficient free
+** memory, it returns a NULL pointer. ^If the parameter N to
+** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
+** a NULL pointer.
+**
+** ^Calling sqlite3_free() with a pointer previously returned
+** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
+** that it might be reused. ^The sqlite3_free() routine is
+** a no-op if is called with a NULL pointer. Passing a NULL pointer
+** to sqlite3_free() is harmless. After being freed, memory
+** should neither be read nor written. Even reading previously freed
+** memory might result in a segmentation fault or other severe error.
+** Memory corruption, a segmentation fault, or other severe error
+** might result if sqlite3_free() is called with a non-NULL pointer that
+** was not obtained from sqlite3_malloc() or sqlite3_realloc().
+**
+** ^(The sqlite3_realloc() interface attempts to resize a
+** prior memory allocation to be at least N bytes, where N is the
+** second parameter. The memory allocation to be resized is the first
+** parameter.)^ ^ If the first parameter to sqlite3_realloc()
+** is a NULL pointer then its behavior is identical to calling
+** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc().
+** ^If the second parameter to sqlite3_realloc() is zero or
+** negative then the behavior is exactly the same as calling
+** sqlite3_free(P) where P is the first parameter to sqlite3_realloc().
+** ^sqlite3_realloc() returns a pointer to a memory allocation
+** of at least N bytes in size or NULL if sufficient memory is unavailable.
+** ^If M is the size of the prior allocation, then min(N,M) bytes
+** of the prior allocation are copied into the beginning of buffer returned
+** by sqlite3_realloc() and the prior allocation is freed.
+** ^If sqlite3_realloc() returns NULL, then the prior allocation
+** is not freed.
+**
+** ^The memory returned by sqlite3_malloc() and sqlite3_realloc()
+** is always aligned to at least an 8 byte boundary, or to a
+** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
+** option is used.
+**
+** In SQLite version 3.5.0 and 3.5.1, it was possible to define
+** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
+** implementation of these routines to be omitted. That capability
+** is no longer provided. Only built-in memory allocators can be used.
+**
+** Prior to SQLite version 3.7.10, the Windows OS interface layer called
+** the system malloc() and free() directly when converting
+** filenames between the UTF-8 encoding used by SQLite
+** and whatever filename encoding is used by the particular Windows
+** installation. Memory allocation errors were detected, but
+** they were reported back as [SQLITE_CANTOPEN] or
+** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
+**
+** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
+** must be either NULL or else pointers obtained from a prior
+** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
+** not yet been released.
+**
+** The application must not read or write any part of
+** a block of memory after it has been released using
+** [sqlite3_free()] or [sqlite3_realloc()].
+*/
+SQLITE_API void *sqlite3_malloc(int);
+SQLITE_API void *sqlite3_realloc(void*, int);
+SQLITE_API void sqlite3_free(void*);
+
+/*
+** CAPI3REF: Memory Allocator Statistics
+**
+** SQLite provides these two interfaces for reporting on the status
+** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
+** routines, which form the built-in memory allocation subsystem.
+**
+** ^The [sqlite3_memory_used()] routine returns the number of bytes
+** of memory currently outstanding (malloced but not freed).
+** ^The [sqlite3_memory_highwater()] routine returns the maximum
+** value of [sqlite3_memory_used()] since the high-water mark
+** was last reset. ^The values returned by [sqlite3_memory_used()] and
+** [sqlite3_memory_highwater()] include any overhead
+** added by SQLite in its implementation of [sqlite3_malloc()],
+** but not overhead added by the any underlying system library
+** routines that [sqlite3_malloc()] may call.
+**
+** ^The memory high-water mark is reset to the current value of
+** [sqlite3_memory_used()] if and only if the parameter to
+** [sqlite3_memory_highwater()] is true. ^The value returned
+** by [sqlite3_memory_highwater(1)] is the high-water mark
+** prior to the reset.
+*/
+SQLITE_API sqlite3_int64 sqlite3_memory_used(void);
+SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
+
+/*
+** CAPI3REF: Pseudo-Random Number Generator
+**
+** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
+** select random [ROWID | ROWIDs] when inserting new records into a table that
+** already uses the largest possible [ROWID]. The PRNG is also used for
+** the build-in random() and randomblob() SQL functions. This interface allows
+** applications to access the same PRNG for other purposes.
+**
+** ^A call to this routine stores N bytes of randomness into buffer P.
+**
+** ^The first time this routine is invoked (either internally or by
+** the application) the PRNG is seeded using randomness obtained
+** from the xRandomness method of the default [sqlite3_vfs] object.
+** ^On all subsequent invocations, the pseudo-randomness is generated
+** internally and without recourse to the [sqlite3_vfs] xRandomness
+** method.
+*/
+SQLITE_API void sqlite3_randomness(int N, void *P);
+
+/*
+** CAPI3REF: Compile-Time Authorization Callbacks
+**
+** ^This routine registers an authorizer callback with a particular
+** [database connection], supplied in the first argument.
+** ^The authorizer callback is invoked as SQL statements are being compiled
+** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
+** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various
+** points during the compilation process, as logic is being created
+** to perform various actions, the authorizer callback is invoked to
+** see if those actions are allowed. ^The authorizer callback should
+** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the
+** specific action but allow the SQL statement to continue to be
+** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be
+** rejected with an error. ^If the authorizer callback returns
+** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY]
+** then the [sqlite3_prepare_v2()] or equivalent call that triggered
+** the authorizer will fail with an error message.
+**
+** When the callback returns [SQLITE_OK], that means the operation
+** requested is ok. ^When the callback returns [SQLITE_DENY], the
+** [sqlite3_prepare_v2()] or equivalent call that triggered the
+** authorizer will fail with an error message explaining that
+** access is denied.
+**
+** ^The first parameter to the authorizer callback is a copy of the third
+** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
+** to the callback is an integer [SQLITE_COPY | action code] that specifies
+** the particular action to be authorized. ^The third through sixth parameters
+** to the callback are zero-terminated strings that contain additional
+** details about the action to be authorized.
+**
+** ^If the action code is [SQLITE_READ]
+** and the callback returns [SQLITE_IGNORE] then the
+** [prepared statement] statement is constructed to substitute
+** a NULL value in place of the table column that would have
+** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
+** return can be used to deny an untrusted user access to individual
+** columns of a table.
+** ^If the action code is [SQLITE_DELETE] and the callback returns
+** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
+** [truncate optimization] is disabled and all rows are deleted individually.
+**
+** An authorizer is used when [sqlite3_prepare | preparing]
+** SQL statements from an untrusted source, to ensure that the SQL statements
+** do not try to access data they are not allowed to see, or that they do not
+** try to execute malicious statements that damage the database. For
+** example, an application may allow a user to enter arbitrary
+** SQL queries for evaluation by a database. But the application does
+** not want the user to be able to make arbitrary changes to the
+** database. An authorizer could then be put in place while the
+** user-entered SQL is being [sqlite3_prepare | prepared] that
+** disallows everything except [SELECT] statements.
+**
+** Applications that need to process SQL from untrusted sources
+** might also consider lowering resource limits using [sqlite3_limit()]
+** and limiting database size using the [max_page_count] [PRAGMA]
+** in addition to using an authorizer.
+**
+** ^(Only a single authorizer can be in place on a database connection
+** at a time. Each call to sqlite3_set_authorizer overrides the
+** previous call.)^ ^Disable the authorizer by installing a NULL callback.
+** The authorizer is disabled by default.
+**
+** The authorizer callback must not do anything that will modify
+** the database connection that invoked the authorizer callback.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
+** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the
+** statement might be re-prepared during [sqlite3_step()] due to a
+** schema change. Hence, the application should ensure that the
+** correct authorizer callback remains in place during the [sqlite3_step()].
+**
+** ^Note that the authorizer callback is invoked only during
+** [sqlite3_prepare()] or its variants. Authorization is not
+** performed during statement evaluation in [sqlite3_step()], unless
+** as stated in the previous paragraph, sqlite3_step() invokes
+** sqlite3_prepare_v2() to reprepare a statement after a schema change.
+*/
+SQLITE_API int sqlite3_set_authorizer(
+ sqlite3*,
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
+ void *pUserData
+);
+
+/*
+** CAPI3REF: Authorizer Return Codes
+**
+** The [sqlite3_set_authorizer | authorizer callback function] must
+** return either [SQLITE_OK] or one of these two constants in order
+** to signal SQLite whether or not the action is permitted. See the
+** [sqlite3_set_authorizer | authorizer documentation] for additional
+** information.
+**
+** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
+** from the [sqlite3_vtab_on_conflict()] interface.
+*/
+#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
+#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
+
+/*
+** CAPI3REF: Authorizer Action Codes
+**
+** The [sqlite3_set_authorizer()] interface registers a callback function
+** that is invoked to authorize certain SQL statement actions. The
+** second parameter to the callback is an integer code that specifies
+** what action is being authorized. These are the integer action codes that
+** the authorizer callback may be passed.
+**
+** These action code values signify what kind of operation is to be
+** authorized. The 3rd and 4th parameters to the authorization
+** callback function will be parameters or NULL depending on which of these
+** codes is used as the second parameter. ^(The 5th parameter to the
+** authorizer callback is the name of the database ("main", "temp",
+** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback
+** is the name of the inner-most trigger or view that is responsible for
+** the access attempt or NULL if this access attempt is directly from
+** top-level SQL code.
+*/
+/******************************************* 3rd ************ 4th ***********/
+#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */
+#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */
+#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
+#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */
+#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
+#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */
+#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */
+#define SQLITE_CREATE_VIEW 8 /* View Name NULL */
+#define SQLITE_DELETE 9 /* Table Name NULL */
+#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */
+#define SQLITE_DROP_TABLE 11 /* Table Name NULL */
+#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */
+#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */
+#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
+#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */
+#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */
+#define SQLITE_DROP_VIEW 17 /* View Name NULL */
+#define SQLITE_INSERT 18 /* Table Name NULL */
+#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */
+#define SQLITE_READ 20 /* Table Name Column Name */
+#define SQLITE_SELECT 21 /* NULL NULL */
+#define SQLITE_TRANSACTION 22 /* Operation NULL */
+#define SQLITE_UPDATE 23 /* Table Name Column Name */
+#define SQLITE_ATTACH 24 /* Filename NULL */
+#define SQLITE_DETACH 25 /* Database Name NULL */
+#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
+#define SQLITE_REINDEX 27 /* Index Name NULL */
+#define SQLITE_ANALYZE 28 /* Table Name NULL */
+#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */
+#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
+#define SQLITE_FUNCTION 31 /* NULL Function Name */
+#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
+#define SQLITE_COPY 0 /* No longer used */
+
+/*
+** CAPI3REF: Tracing And Profiling Functions
+**
+** These routines register callback functions that can be used for
+** tracing and profiling the execution of SQL statements.
+**
+** ^The callback function registered by sqlite3_trace() is invoked at
+** various times when an SQL statement is being run by [sqlite3_step()].
+** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the
+** SQL statement text as the statement first begins executing.
+** ^(Additional sqlite3_trace() callbacks might occur
+** as each triggered subprogram is entered. The callbacks for triggers
+** contain a UTF-8 SQL comment that identifies the trigger.)^
+**
+** ^The callback function registered by sqlite3_profile() is invoked
+** as each SQL statement finishes. ^The profile callback contains
+** the original statement text and an estimate of wall-clock time
+** of how long that statement took to run. ^The profile callback
+** time is in units of nanoseconds, however the current implementation
+** is only capable of millisecond resolution so the six least significant
+** digits in the time are meaningless. Future versions of SQLite
+** might provide greater resolution on the profiler callback. The
+** sqlite3_profile() function is considered experimental and is
+** subject to change in future versions of SQLite.
+*/
+SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
+ void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
+
+/*
+** CAPI3REF: Query Progress Callbacks
+**
+** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
+** function X to be invoked periodically during long running calls to
+** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for
+** database connection D. An example use for this
+** interface is to keep a GUI updated during a large query.
+**
+** ^The parameter P is passed through as the only parameter to the
+** callback function X. ^The parameter N is the number of
+** [virtual machine instructions] that are evaluated between successive
+** invocations of the callback X.
+**
+** ^Only a single progress handler may be defined at one time per
+** [database connection]; setting a new progress handler cancels the
+** old one. ^Setting parameter X to NULL disables the progress handler.
+** ^The progress handler is also disabled by setting N to a value less
+** than 1.
+**
+** ^If the progress callback returns non-zero, the operation is
+** interrupted. This feature can be used to implement a
+** "Cancel" button on a GUI progress dialog box.
+**
+** The progress handler callback must not do anything that will modify
+** the database connection that invoked the progress handler.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
+*/
+SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+
+/*
+** CAPI3REF: Opening A New Database Connection
+**
+** ^These routines open an SQLite database file as specified by the
+** filename argument. ^The filename argument is interpreted as UTF-8 for
+** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
+** order for sqlite3_open16(). ^(A [database connection] handle is usually
+** returned in *ppDb, even if an error occurs. The only exception is that
+** if SQLite is unable to allocate memory to hold the [sqlite3] object,
+** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
+** object.)^ ^(If the database is opened (and/or created) successfully, then
+** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The
+** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain
+** an English language description of the error following a failure of any
+** of the sqlite3_open() routines.
+**
+** ^The default encoding for the database will be UTF-8 if
+** sqlite3_open() or sqlite3_open_v2() is called and
+** UTF-16 in the native byte order if sqlite3_open16() is used.
+**
+** Whether or not an error occurs when it is opened, resources
+** associated with the [database connection] handle should be released by
+** passing it to [sqlite3_close()] when it is no longer required.
+**
+** The sqlite3_open_v2() interface works like sqlite3_open()
+** except that it accepts two additional parameters for additional control
+** over the new database connection. ^(The flags parameter to
+** sqlite3_open_v2() can take one of
+** the following three values, optionally combined with the
+** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
+** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
+**
+** <dl>
+** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
+** <dd>The database is opened in read-only mode. If the database does not
+** already exist, an error is returned.</dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_READWRITE]</dt>
+** <dd>The database is opened for reading and writing if possible, or reading
+** only if the file is write protected by the operating system. In either
+** case the database must already exist, otherwise an error is returned.</dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
+** <dd>The database is opened for reading and writing, and is created if
+** it does not already exist. This is the behavior that is always used for
+** sqlite3_open() and sqlite3_open16().</dd>)^
+** </dl>
+**
+** If the 3rd parameter to sqlite3_open_v2() is not one of the
+** combinations shown above optionally combined with other
+** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
+** then the behavior is undefined.
+**
+** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
+** opens in the multi-thread [threading mode] as long as the single-thread
+** mode has not been set at compile-time or start-time. ^If the
+** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
+** in the serialized [threading mode] unless single-thread was
+** previously selected at compile-time or start-time.
+** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
+** eligible to use [shared cache mode], regardless of whether or not shared
+** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
+** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
+** participate in [shared cache mode] even if it is enabled.
+**
+** ^The fourth parameter to sqlite3_open_v2() is the name of the
+** [sqlite3_vfs] object that defines the operating system interface that
+** the new database connection should use. ^If the fourth parameter is
+** a NULL pointer then the default [sqlite3_vfs] object is used.
+**
+** ^If the filename is ":memory:", then a private, temporary in-memory database
+** is created for the connection. ^This in-memory database will vanish when
+** the database connection is closed. Future versions of SQLite might
+** make use of additional special filenames that begin with the ":" character.
+** It is recommended that when a database filename actually does begin with
+** a ":" character you should prefix the filename with a pathname such as
+** "./" to avoid ambiguity.
+**
+** ^If the filename is an empty string, then a private, temporary
+** on-disk database will be created. ^This private database will be
+** automatically deleted as soon as the database connection is closed.
+**
+** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
+**
+** ^If [URI filename] interpretation is enabled, and the filename argument
+** begins with "file:", then the filename is interpreted as a URI. ^URI
+** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
+** set in the fourth argument to sqlite3_open_v2(), or if it has
+** been enabled globally using the [SQLITE_CONFIG_URI] option with the
+** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
+** As of SQLite version 3.7.7, URI filename interpretation is turned off
+** by default, but future releases of SQLite might enable URI filename
+** interpretation by default. See "[URI filenames]" for additional
+** information.
+**
+** URI filenames are parsed according to RFC 3986. ^If the URI contains an
+** authority, then it must be either an empty string or the string
+** "localhost". ^If the authority is not an empty string or "localhost", an
+** error is returned to the caller. ^The fragment component of a URI, if
+** present, is ignored.
+**
+** ^SQLite uses the path component of the URI as the name of the disk file
+** which contains the database. ^If the path begins with a '/' character,
+** then it is interpreted as an absolute path. ^If the path does not begin
+** with a '/' (meaning that the authority section is omitted from the URI)
+** then the path is interpreted as a relative path.
+** ^On windows, the first component of an absolute path
+** is a drive specification (e.g. "C:").
+**
+** [[core URI query parameters]]
+** The query component of a URI may contain parameters that are interpreted
+** either by SQLite itself, or by a [VFS | custom VFS implementation].
+** SQLite interprets the following three query parameters:
+**
+** <ul>
+** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
+** a VFS object that provides the operating system interface that should
+** be used to access the database file on disk. ^If this option is set to
+** an empty string the default VFS object is used. ^Specifying an unknown
+** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
+** present, then the VFS specified by the option takes precedence over
+** the value passed as the fourth parameter to sqlite3_open_v2().
+**
+** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
+** "rwc", or "memory". Attempting to set it to any other value is
+** an error)^.
+** ^If "ro" is specified, then the database is opened for read-only
+** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
+** third argument to sqlite3_open_v2(). ^If the mode option is set to
+** "rw", then the database is opened for read-write (but not create)
+** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
+** been set. ^Value "rwc" is equivalent to setting both
+** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is
+** set to "memory" then a pure [in-memory database] that never reads
+** or writes from disk is used. ^It is an error to specify a value for
+** the mode parameter that is less restrictive than that specified by
+** the flags passed in the third parameter to sqlite3_open_v2().
+**
+** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
+** "private". ^Setting it to "shared" is equivalent to setting the
+** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
+** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
+** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
+** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
+** a URI filename, its value overrides any behavior requested by setting
+** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+** </ul>
+**
+** ^Specifying an unknown parameter in the query component of a URI is not an
+** error. Future versions of SQLite might understand additional query
+** parameters. See "[query parameters with special meaning to SQLite]" for
+** additional information.
+**
+** [[URI filename examples]] <h3>URI filename examples</h3>
+**
+** <table border="1" align=center cellpadding=5>
+** <tr><th> URI filenames <th> Results
+** <tr><td> file:data.db <td>
+** Open the file "data.db" in the current directory.
+** <tr><td> file:/home/fred/data.db<br>
+** file:///home/fred/data.db <br>
+** file://localhost/home/fred/data.db <br> <td>
+** Open the database file "/home/fred/data.db".
+** <tr><td> file://darkstar/home/fred/data.db <td>
+** An error. "darkstar" is not a recognized authority.
+** <tr><td style="white-space:nowrap">
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
+** <td> Windows only: Open the file "data.db" on fred's desktop on drive
+** C:. Note that the %20 escaping in this example is not strictly
+** necessary - space characters can be used literally
+** in URI filenames.
+** <tr><td> file:data.db?mode=ro&cache=private <td>
+** Open file "data.db" in the current directory for read-only access.
+** Regardless of whether or not shared-cache mode is enabled by
+** default, use a private cache.
+** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
+** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+** <tr><td> file:data.db?mode=readonly <td>
+** An error. "readonly" is not a valid option for the "mode" parameter.
+** </table>
+**
+** ^URI hexadecimal escape sequences (%HH) are supported within the path and
+** query components of a URI. A hexadecimal escape sequence consists of a
+** percent sign - "%" - followed by exactly two hexadecimal digits
+** specifying an octet value. ^Before the path or query components of a
+** URI filename are interpreted, they are encoded using UTF-8 and all
+** hexadecimal escape sequences replaced by a single byte containing the
+** corresponding octet. If this process generates an invalid UTF-8 encoding,
+** the results are undefined.
+**
+** <b>Note to Windows users:</b> The encoding used for the filename argument
+** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
+** codepage is currently defined. Filenames containing international
+** characters must be converted to UTF-8 prior to passing them into
+** sqlite3_open() or sqlite3_open_v2().
+**
+** <b>Note to Windows Runtime users:</b> The temporary directory must be set
+** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various
+** features that require the use of temporary files may fail.
+**
+** See also: [sqlite3_temp_directory]
+*/
+SQLITE_API int sqlite3_open(
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
+);
+SQLITE_API int sqlite3_open16(
+ const void *filename, /* Database filename (UTF-16) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
+);
+SQLITE_API int sqlite3_open_v2(
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb, /* OUT: SQLite db handle */
+ int flags, /* Flags */
+ const char *zVfs /* Name of VFS module to use */
+);
+
+/*
+** CAPI3REF: Obtain Values For URI Parameters
+**
+** These are utility routines, useful to VFS implementations, that check
+** to see if a database file was a URI that contained a specific query
+** parameter, and if so obtains the value of that query parameter.
+**
+** If F is the database filename pointer passed into the xOpen() method of
+** a VFS implementation when the flags parameter to xOpen() has one or
+** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
+** P is the name of the query parameter, then
+** sqlite3_uri_parameter(F,P) returns the value of the P
+** parameter if it exists or a NULL pointer if P does not appear as a
+** query parameter on F. If P is a query parameter of F
+** has no explicit value, then sqlite3_uri_parameter(F,P) returns
+** a pointer to an empty string.
+**
+** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
+** parameter and returns true (1) or false (0) according to the value
+** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
+** value of query parameter P is one of "yes", "true", or "on" in any
+** case or if the value begins with a non-zero number. The
+** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
+** query parameter P is one of "no", "false", or "off" in any case or
+** if the value begins with a numeric zero. If P is not a query
+** parameter on F or if the value of P is does not match any of the
+** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
+**
+** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
+** 64-bit signed integer and returns that integer, or D if P does not
+** exist. If the value of P is something other than an integer, then
+** zero is returned.
+**
+** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
+** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
+** is not a database file pathname pointer that SQLite passed into the xOpen
+** VFS method, then the behavior of this routine is undefined and probably
+** undesirable.
+*/
+SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
+SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+
+
+/*
+** CAPI3REF: Error Codes And Messages
+**
+** ^The sqlite3_errcode() interface returns the numeric [result code] or
+** [extended result code] for the most recent failed sqlite3_* API call
+** associated with a [database connection]. If a prior API call failed
+** but the most recent API call succeeded, the return value from
+** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
+** interface is the same except that it always returns the
+** [extended result code] even when extended result codes are
+** disabled.
+**
+** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
+** text that describes the error, as either UTF-8 or UTF-16 respectively.
+** ^(Memory to hold the error message string is managed internally.
+** The application does not need to worry about freeing the result.
+** However, the error string might be overwritten or deallocated by
+** subsequent calls to other SQLite interface functions.)^
+**
+** ^The sqlite3_errstr() interface returns the English-language text
+** that describes the [result code], as UTF-8.
+** ^(Memory to hold the error message string is managed internally
+** and must not be freed by the application)^.
+**
+** When the serialized [threading mode] is in use, it might be the
+** case that a second error occurs on a separate thread in between
+** the time of the first error and the call to these interfaces.
+** When that happens, the second error will be reported since these
+** interfaces always report the most recent result. To avoid
+** this, each thread can obtain exclusive use of the [database connection] D
+** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
+** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
+** all calls to the interfaces listed here are completed.
+**
+** If an interface fails with SQLITE_MISUSE, that means the interface
+** was invoked incorrectly by the application. In that case, the
+** error code and message may or may not be set.
+*/
+SQLITE_API int sqlite3_errcode(sqlite3 *db);
+SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
+SQLITE_API const char *sqlite3_errmsg(sqlite3*);
+SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errstr(int);
+
+/*
+** CAPI3REF: SQL Statement Object
+** KEYWORDS: {prepared statement} {prepared statements}
+**
+** An instance of this object represents a single SQL statement.
+** This object is variously known as a "prepared statement" or a
+** "compiled SQL statement" or simply as a "statement".
+**
+** The life of a statement object goes something like this:
+**
+** <ol>
+** <li> Create the object using [sqlite3_prepare_v2()] or a related
+** function.
+** <li> Bind values to [host parameters] using the sqlite3_bind_*()
+** interfaces.
+** <li> Run the SQL by calling [sqlite3_step()] one or more times.
+** <li> Reset the statement using [sqlite3_reset()] then go back
+** to step 2. Do this zero or more times.
+** <li> Destroy the object using [sqlite3_finalize()].
+** </ol>
+**
+** Refer to documentation on individual methods above for additional
+** information.
+*/
+typedef struct sqlite3_stmt sqlite3_stmt;
+
+/*
+** CAPI3REF: Run-time Limits
+**
+** ^(This interface allows the size of various constructs to be limited
+** on a connection by connection basis. The first parameter is the
+** [database connection] whose limit is to be set or queried. The
+** second parameter is one of the [limit categories] that define a
+** class of constructs to be size limited. The third parameter is the
+** new limit for that construct.)^
+**
+** ^If the new limit is a negative number, the limit is unchanged.
+** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a
+** [limits | hard upper bound]
+** set at compile-time by a C preprocessor macro called
+** [limits | SQLITE_MAX_<i>NAME</i>].
+** (The "_LIMIT_" in the name is changed to "_MAX_".))^
+** ^Attempts to increase a limit above its hard upper bound are
+** silently truncated to the hard upper bound.
+**
+** ^Regardless of whether or not the limit was changed, the
+** [sqlite3_limit()] interface returns the prior value of the limit.
+** ^Hence, to find the current value of a limit without changing it,
+** simply invoke this interface with the third parameter set to -1.
+**
+** Run-time limits are intended for use in applications that manage
+** both their own internal database and also databases that are controlled
+** by untrusted external sources. An example application might be a
+** web browser that has its own databases for storing history and
+** separate databases controlled by JavaScript applications downloaded
+** off the Internet. The internal databases can be given the
+** large, default limits. Databases managed by external sources can
+** be given much smaller limits designed to prevent a denial of service
+** attack. Developers might also want to use the [sqlite3_set_authorizer()]
+** interface to further control untrusted SQL. The size of the database
+** created by an untrusted script can be contained using the
+** [max_page_count] [PRAGMA].
+**
+** New run-time limit categories may be added in future releases.
+*/
+SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
+
+/*
+** CAPI3REF: Run-Time Limit Categories
+** KEYWORDS: {limit category} {*limit categories}
+**
+** These constants define various performance limits
+** that can be lowered at run-time using [sqlite3_limit()].
+** The synopsis of the meanings of the various limits is shown below.
+** Additional information is available at [limits | Limits in SQLite].
+**
+** <dl>
+** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
+** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
+**
+** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
+** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
+**
+** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
+** <dd>The maximum number of columns in a table definition or in the
+** result set of a [SELECT] or the maximum number of columns in an index
+** or in an ORDER BY or GROUP BY clause.</dd>)^
+**
+** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
+** <dd>The maximum depth of the parse tree on any expression.</dd>)^
+**
+** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
+** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
+**
+** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
+** <dd>The maximum number of instructions in a virtual machine program
+** used to implement an SQL statement. This limit is not currently
+** enforced, though that might be added in some future release of
+** SQLite.</dd>)^
+**
+** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
+** <dd>The maximum number of arguments on a function.</dd>)^
+**
+** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
+** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
+**
+** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
+** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
+** <dd>The maximum length of the pattern argument to the [LIKE] or
+** [GLOB] operators.</dd>)^
+**
+** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
+** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
+** <dd>The maximum index number of any [parameter] in an SQL statement.)^
+**
+** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
+** <dd>The maximum depth of recursion for triggers.</dd>)^
+** </dl>
+*/
+#define SQLITE_LIMIT_LENGTH 0
+#define SQLITE_LIMIT_SQL_LENGTH 1
+#define SQLITE_LIMIT_COLUMN 2
+#define SQLITE_LIMIT_EXPR_DEPTH 3
+#define SQLITE_LIMIT_COMPOUND_SELECT 4
+#define SQLITE_LIMIT_VDBE_OP 5
+#define SQLITE_LIMIT_FUNCTION_ARG 6
+#define SQLITE_LIMIT_ATTACHED 7
+#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
+#define SQLITE_LIMIT_VARIABLE_NUMBER 9
+#define SQLITE_LIMIT_TRIGGER_DEPTH 10
+
+/*
+** CAPI3REF: Compiling An SQL Statement
+** KEYWORDS: {SQL statement compiler}
+**
+** To execute an SQL query, it must first be compiled into a byte-code
+** program using one of these routines.
+**
+** The first argument, "db", is a [database connection] obtained from a
+** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
+** [sqlite3_open16()]. The database connection must not have been closed.
+**
+** The second argument, "zSql", is the statement to be compiled, encoded
+** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
+** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
+** use UTF-16.
+**
+** ^If the nByte argument is less than zero, then zSql is read up to the
+** first zero terminator. ^If nByte is non-negative, then it is the maximum
+** number of bytes read from zSql. ^When nByte is non-negative, the
+** zSql string ends at either the first '\000' or '\u0000' character or
+** the nByte-th byte, whichever comes first. If the caller knows
+** that the supplied string is nul-terminated, then there is a small
+** performance advantage to be gained by passing an nByte parameter that
+** is equal to the number of bytes in the input string <i>including</i>
+** the nul-terminator bytes as this saves SQLite from having to
+** make a copy of the input string.
+**
+** ^If pzTail is not NULL then *pzTail is made to point to the first byte
+** past the end of the first SQL statement in zSql. These routines only
+** compile the first statement in zSql, so *pzTail is left pointing to
+** what remains uncompiled.
+**
+** ^*ppStmt is left pointing to a compiled [prepared statement] that can be
+** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set
+** to NULL. ^If the input text contains no SQL (if the input is an empty
+** string or a comment) then *ppStmt is set to NULL.
+** The calling procedure is responsible for deleting the compiled
+** SQL statement using [sqlite3_finalize()] after it has finished with it.
+** ppStmt may not be NULL.
+**
+** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK];
+** otherwise an [error code] is returned.
+**
+** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
+** recommended for all new programs. The two older interfaces are retained
+** for backwards compatibility, but their use is discouraged.
+** ^In the "v2" interfaces, the prepared statement
+** that is returned (the [sqlite3_stmt] object) contains a copy of the
+** original SQL text. This causes the [sqlite3_step()] interface to
+** behave differently in three ways:
+**
+** <ol>
+** <li>
+** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it
+** always used to do, [sqlite3_step()] will automatically recompile the SQL
+** statement and try to run it again.
+** </li>
+**
+** <li>
+** ^When an error occurs, [sqlite3_step()] will return one of the detailed
+** [error codes] or [extended error codes]. ^The legacy behavior was that
+** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code
+** and the application would have to make a second call to [sqlite3_reset()]
+** in order to find the underlying cause of the problem. With the "v2" prepare
+** interfaces, the underlying reason for the error is returned immediately.
+** </li>
+**
+** <li>
+** ^If the specific value bound to [parameter | host parameter] in the
+** WHERE clause might influence the choice of query plan for a statement,
+** then the statement will be automatically recompiled, as if there had been
+** a schema change, on the first [sqlite3_step()] call following any change
+** to the [sqlite3_bind_text | bindings] of that [parameter].
+** ^The specific value of WHERE-clause [parameter] might influence the
+** choice of query plan if the parameter is the left-hand side of a [LIKE]
+** or [GLOB] operator or if the parameter is compared to an indexed column
+** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
+** the
+** </li>
+** </ol>
+*/
+SQLITE_API int sqlite3_prepare(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+SQLITE_API int sqlite3_prepare_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+SQLITE_API int sqlite3_prepare16(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+SQLITE_API int sqlite3_prepare16_v2(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+
+/*
+** CAPI3REF: Retrieving Statement SQL
+**
+** ^This interface can be used to retrieve a saved copy of the original
+** SQL text used to create a [prepared statement] if that statement was
+** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
+*/
+SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Determine If An SQL Statement Writes The Database
+**
+** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
+** and only if the [prepared statement] X makes no direct changes to
+** the content of the database file.
+**
+** Note that [application-defined SQL functions] or
+** [virtual tables] might change the database indirectly as a side effect.
+** ^(For example, if an application defines a function "eval()" that
+** calls [sqlite3_exec()], then the following SQL statement would
+** change the database file through side-effects:
+**
+** <blockquote><pre>
+** SELECT eval('DELETE FROM t1') FROM t2;
+** </pre></blockquote>
+**
+** But because the [SELECT] statement does not change the database file
+** directly, sqlite3_stmt_readonly() would still return true.)^
+**
+** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
+** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
+** since the statements themselves do not actually modify the database but
+** rather they control the timing of when other statements modify the
+** database. ^The [ATTACH] and [DETACH] statements also cause
+** sqlite3_stmt_readonly() to return true since, while those statements
+** change the configuration of a database connection, they do not make
+** changes to the content of the database files on disk.
+*/
+SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Determine If A Prepared Statement Has Been Reset
+**
+** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
+** [prepared statement] S has been stepped at least once using
+** [sqlite3_step(S)] but has not run to completion and/or has not
+** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
+** interface returns false if S is a NULL pointer. If S is not a
+** NULL pointer and is not a pointer to a valid [prepared statement]
+** object, then the behavior is undefined and probably undesirable.
+**
+** This interface can be used in combination [sqlite3_next_stmt()]
+** to locate all prepared statements associated with a database
+** connection that are in need of being reset. This can be used,
+** for example, in diagnostic routines to search for prepared
+** statements that are holding a transaction open.
+*/
+SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Dynamically Typed Value Object
+** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
+**
+** SQLite uses the sqlite3_value object to represent all values
+** that can be stored in a database table. SQLite uses dynamic typing
+** for the values it stores. ^Values stored in sqlite3_value objects
+** can be integers, floating point values, strings, BLOBs, or NULL.
+**
+** An sqlite3_value object may be either "protected" or "unprotected".
+** Some interfaces require a protected sqlite3_value. Other interfaces
+** will accept either a protected or an unprotected sqlite3_value.
+** Every interface that accepts sqlite3_value arguments specifies
+** whether or not it requires a protected sqlite3_value.
+**
+** The terms "protected" and "unprotected" refer to whether or not
+** a mutex is held. An internal mutex is held for a protected
+** sqlite3_value object but no mutex is held for an unprotected
+** sqlite3_value object. If SQLite is compiled to be single-threaded
+** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
+** or if SQLite is run in one of reduced mutex modes
+** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
+** then there is no distinction between protected and unprotected
+** sqlite3_value objects and they can be used interchangeably. However,
+** for maximum code portability it is recommended that applications
+** still make the distinction between protected and unprotected
+** sqlite3_value objects even when not strictly required.
+**
+** ^The sqlite3_value objects that are passed as parameters into the
+** implementation of [application-defined SQL functions] are protected.
+** ^The sqlite3_value object returned by
+** [sqlite3_column_value()] is unprotected.
+** Unprotected sqlite3_value objects may only be used with
+** [sqlite3_result_value()] and [sqlite3_bind_value()].
+** The [sqlite3_value_blob | sqlite3_value_type()] family of
+** interfaces require protected sqlite3_value objects.
+*/
+typedef struct Mem sqlite3_value;
+
+/*
+** CAPI3REF: SQL Function Context Object
+**
+** The context in which an SQL function executes is stored in an
+** sqlite3_context object. ^A pointer to an sqlite3_context object
+** is always first parameter to [application-defined SQL functions].
+** The application-defined SQL function implementation will pass this
+** pointer through into calls to [sqlite3_result_int | sqlite3_result()],
+** [sqlite3_aggregate_context()], [sqlite3_user_data()],
+** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()],
+** and/or [sqlite3_set_auxdata()].
+*/
+typedef struct sqlite3_context sqlite3_context;
+
+/*
+** CAPI3REF: Binding Values To Prepared Statements
+** KEYWORDS: {host parameter} {host parameters} {host parameter name}
+** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
+**
+** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
+** literals may be replaced by a [parameter] that matches one of following
+** templates:
+**
+** <ul>
+** <li> ?
+** <li> ?NNN
+** <li> :VVV
+** <li> @VVV
+** <li> $VVV
+** </ul>
+**
+** In the templates above, NNN represents an integer literal,
+** and VVV represents an alphanumeric identifier.)^ ^The values of these
+** parameters (also called "host parameter names" or "SQL parameters")
+** can be set using the sqlite3_bind_*() routines defined here.
+**
+** ^The first argument to the sqlite3_bind_*() routines is always
+** a pointer to the [sqlite3_stmt] object returned from
+** [sqlite3_prepare_v2()] or its variants.
+**
+** ^The second argument is the index of the SQL parameter to be set.
+** ^The leftmost SQL parameter has an index of 1. ^When the same named
+** SQL parameter is used more than once, second and subsequent
+** occurrences have the same index as the first occurrence.
+** ^The index for named parameters can be looked up using the
+** [sqlite3_bind_parameter_index()] API if desired. ^The index
+** for "?NNN" parameters is the value of NNN.
+** ^The NNN value must be between 1 and the [sqlite3_limit()]
+** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
+**
+** ^The third argument is the value to bind to the parameter.
+**
+** ^(In those routines that have a fourth argument, its value is the
+** number of bytes in the parameter. To be clear: the value is the
+** number of <u>bytes</u> in the value, not the number of characters.)^
+** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** is negative, then the length of the string is
+** the number of bytes up to the first zero terminator.
+** If the fourth parameter to sqlite3_bind_blob() is negative, then
+** the behavior is undefined.
+** If a non-negative fourth parameter is provided to sqlite3_bind_text()
+** or sqlite3_bind_text16() then that parameter must be the byte offset
+** where the NUL terminator would occur assuming the string were NUL
+** terminated. If any NUL characters occur at byte offsets less than
+** the value of the fourth parameter then the resulting string value will
+** contain embedded NULs. The result of expressions involving strings
+** with embedded NULs is undefined.
+**
+** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
+** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
+** string after SQLite has finished with it. ^The destructor is called
+** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
+** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
+** ^If the fifth argument is
+** the special value [SQLITE_STATIC], then SQLite assumes that the
+** information is in static, unmanaged space and does not need to be freed.
+** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
+** SQLite makes its own private copy of the data immediately, before
+** the sqlite3_bind_*() routine returns.
+**
+** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
+** is filled with zeroes. ^A zeroblob uses a fixed amount of memory
+** (just an integer to hold its size) while it is being processed.
+** Zeroblobs are intended to serve as placeholders for BLOBs whose
+** content is later written using
+** [sqlite3_blob_open | incremental BLOB I/O] routines.
+** ^A negative value for the zeroblob results in a zero-length BLOB.
+**
+** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
+** for the [prepared statement] or with a prepared statement for which
+** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
+** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_()
+** routine is passed a [prepared statement] that has been finalized, the
+** result is undefined and probably harmful.
+**
+** ^Bindings are not cleared by the [sqlite3_reset()] routine.
+** ^Unbound parameters are interpreted as NULL.
+**
+** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
+** [error code] if anything goes wrong.
+** ^[SQLITE_RANGE] is returned if the parameter
+** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails.
+**
+** See also: [sqlite3_bind_parameter_count()],
+** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
+SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
+SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
+SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
+SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
+SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
+SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
+SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+
+/*
+** CAPI3REF: Number Of SQL Parameters
+**
+** ^This routine can be used to find the number of [SQL parameters]
+** in a [prepared statement]. SQL parameters are tokens of the
+** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
+** placeholders for values that are [sqlite3_bind_blob | bound]
+** to the parameters at a later time.
+**
+** ^(This routine actually returns the index of the largest (rightmost)
+** parameter. For all forms except ?NNN, this will correspond to the
+** number of unique parameters. If parameters of the ?NNN form are used,
+** there may be gaps in the list.)^
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_name()], and
+** [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Name Of A Host Parameter
+**
+** ^The sqlite3_bind_parameter_name(P,N) interface returns
+** the name of the N-th [SQL parameter] in the [prepared statement] P.
+** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** respectively.
+** In other words, the initial ":" or "$" or "@" or "?"
+** is included as part of the name.)^
+** ^Parameters of the form "?" without a following integer have no name
+** and are referred to as "nameless" or "anonymous parameters".
+**
+** ^The first host parameter has an index of 1, not 0.
+**
+** ^If the value N is out of range or if the N-th parameter is
+** nameless, then NULL is returned. ^The returned string is
+** always in UTF-8 encoding even if the named parameter was
+** originally specified as UTF-16 in [sqlite3_prepare16()] or
+** [sqlite3_prepare16_v2()].
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_count()], and
+** [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+
+/*
+** CAPI3REF: Index Of A Parameter With A Given Name
+**
+** ^Return the index of an SQL parameter given its name. ^The
+** index value returned is suitable for use as the second
+** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero
+** is returned if no matching parameter is found. ^The parameter
+** name must be given in UTF-8 even if the original statement
+** was prepared from UTF-16 text using [sqlite3_prepare16_v2()].
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_count()], and
+** [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+
+/*
+** CAPI3REF: Reset All Bindings On A Prepared Statement
+**
+** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
+** the [sqlite3_bind_blob | bindings] on a [prepared statement].
+** ^Use this routine to reset all host parameters to NULL.
+*/
+SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Number Of Columns In A Result Set
+**
+** ^Return the number of columns in the result set returned by the
+** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
+** statement that does not return data (for example an [UPDATE]).
+**
+** See also: [sqlite3_data_count()]
+*/
+SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Column Names In A Result Set
+**
+** ^These routines return the name assigned to a particular column
+** in the result set of a [SELECT] statement. ^The sqlite3_column_name()
+** interface returns a pointer to a zero-terminated UTF-8 string
+** and sqlite3_column_name16() returns a pointer to a zero-terminated
+** UTF-16 string. ^The first parameter is the [prepared statement]
+** that implements the [SELECT] statement. ^The second parameter is the
+** column number. ^The leftmost column is number 0.
+**
+** ^The returned string pointer is valid until either the [prepared statement]
+** is destroyed by [sqlite3_finalize()] or until the statement is automatically
+** reprepared by the first call to [sqlite3_step()] for a particular run
+** or until the next call to
+** sqlite3_column_name() or sqlite3_column_name16() on the same column.
+**
+** ^If sqlite3_malloc() fails during the processing of either routine
+** (for example during a conversion from UTF-8 to UTF-16) then a
+** NULL pointer is returned.
+**
+** ^The name of a result column is the value of the "AS" clause for
+** that column, if there is an AS clause. If there is no AS clause
+** then the name of the column is unspecified and may change from
+** one release of SQLite to the next.
+*/
+SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
+SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+
+/*
+** CAPI3REF: Source Of Data In A Query Result
+**
+** ^These routines provide a means to determine the database, table, and
+** table column that is the origin of a particular result column in
+** [SELECT] statement.
+** ^The name of the database or table or column can be returned as
+** either a UTF-8 or UTF-16 string. ^The _database_ routines return
+** the database name, the _table_ routines return the table name, and
+** the origin_ routines return the column name.
+** ^The returned string is valid until the [prepared statement] is destroyed
+** using [sqlite3_finalize()] or until the statement is automatically
+** reprepared by the first call to [sqlite3_step()] for a particular run
+** or until the same information is requested
+** again in a different encoding.
+**
+** ^The names returned are the original un-aliased names of the
+** database, table, and column.
+**
+** ^The first argument to these interfaces is a [prepared statement].
+** ^These functions return information about the Nth result column returned by
+** the statement, where N is the second function argument.
+** ^The left-most column is column 0 for these routines.
+**
+** ^If the Nth column returned by the statement is an expression or
+** subquery and is not a column value, then all of these functions return
+** NULL. ^These routine might also return NULL if a memory allocation error
+** occurs. ^Otherwise, they return the name of the attached database, table,
+** or column that query result column was extracted from.
+**
+** ^As with all other SQLite APIs, those whose names end with "16" return
+** UTF-16 encoded strings and the other functions return UTF-8.
+**
+** ^These APIs are only available if the library was compiled with the
+** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
+**
+** If two or more threads call one or more of these routines against the same
+** prepared statement and column at the same time then the results are
+** undefined.
+**
+** If two or more threads call one or more
+** [sqlite3_column_database_name | column metadata interfaces]
+** for the same [prepared statement] and result column
+** at the same time then the results are undefined.
+*/
+SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+
+/*
+** CAPI3REF: Declared Datatype Of A Query Result
+**
+** ^(The first parameter is a [prepared statement].
+** If this statement is a [SELECT] statement and the Nth column of the
+** returned result set of that [SELECT] is a table column (not an
+** expression or subquery) then the declared type of the table
+** column is returned.)^ ^If the Nth column of the result set is an
+** expression or subquery, then a NULL pointer is returned.
+** ^The returned string is always UTF-8 encoded.
+**
+** ^(For example, given the database schema:
+**
+** CREATE TABLE t1(c1 VARIANT);
+**
+** and the following statement to be compiled:
+**
+** SELECT c1 + 1, c1 FROM t1;
+**
+** this routine would return the string "VARIANT" for the second result
+** column (i==1), and a NULL pointer for the first result column (i==0).)^
+**
+** ^SQLite uses dynamic run-time typing. ^So just because a column
+** is declared to contain a particular type does not mean that the
+** data stored in that column is of the declared type. SQLite is
+** strongly typed, but the typing is dynamic not static. ^Type
+** is associated with individual values, not with the containers
+** used to hold those values.
+*/
+SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+
+/*
+** CAPI3REF: Evaluate An SQL Statement
+**
+** After a [prepared statement] has been prepared using either
+** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
+** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
+** must be called one or more times to evaluate the statement.
+**
+** The details of the behavior of the sqlite3_step() interface depend
+** on whether the statement was prepared using the newer "v2" interface
+** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy
+** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
+** new "v2" interface is recommended for new applications but the legacy
+** interface will continue to be supported.
+**
+** ^In the legacy interface, the return value will be either [SQLITE_BUSY],
+** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE].
+** ^With the "v2" interface, any of the other [result codes] or
+** [extended result codes] might be returned as well.
+**
+** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
+** database locks it needs to do its job. ^If the statement is a [COMMIT]
+** or occurs outside of an explicit transaction, then you can retry the
+** statement. If the statement is not a [COMMIT] and occurs within an
+** explicit transaction then you should rollback the transaction before
+** continuing.
+**
+** ^[SQLITE_DONE] means that the statement has finished executing
+** successfully. sqlite3_step() should not be called again on this virtual
+** machine without first calling [sqlite3_reset()] to reset the virtual
+** machine back to its initial state.
+**
+** ^If the SQL statement being executed returns any data, then [SQLITE_ROW]
+** is returned each time a new row of data is ready for processing by the
+** caller. The values may be accessed using the [column access functions].
+** sqlite3_step() is called again to retrieve the next row of data.
+**
+** ^[SQLITE_ERROR] means that a run-time error (such as a constraint
+** violation) has occurred. sqlite3_step() should not be called again on
+** the VM. More information may be found by calling [sqlite3_errmsg()].
+** ^With the legacy interface, a more specific error code (for example,
+** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth)
+** can be obtained by calling [sqlite3_reset()] on the
+** [prepared statement]. ^In the "v2" interface,
+** the more specific error code is returned directly by sqlite3_step().
+**
+** [SQLITE_MISUSE] means that the this routine was called inappropriately.
+** Perhaps it was called on a [prepared statement] that has
+** already been [sqlite3_finalize | finalized] or on one that had
+** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could
+** be the case that the same database connection is being used by two or
+** more threads at the same moment in time.
+**
+** For all versions of SQLite up to and including 3.6.23.1, a call to
+** [sqlite3_reset()] was required after sqlite3_step() returned anything
+** other than [SQLITE_ROW] before any subsequent invocation of
+** sqlite3_step(). Failure to reset the prepared statement using
+** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
+** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began
+** calling [sqlite3_reset()] automatically in this circumstance rather
+** than returning [SQLITE_MISUSE]. This is not considered a compatibility
+** break because any application that ever receives an SQLITE_MISUSE error
+** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
+** can be used to restore the legacy behavior.
+**
+** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
+** API always returns a generic error code, [SQLITE_ERROR], following any
+** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
+** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the
+** specific [error codes] that better describes the error.
+** We admit that this is a goofy design. The problem has been fixed
+** with the "v2" interface. If you prepare all of your SQL statements
+** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead
+** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
+** then the more specific [error codes] are returned directly
+** by sqlite3_step(). The use of the "v2" interface is recommended.
+*/
+SQLITE_API int sqlite3_step(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Number of columns in a result set
+**
+** ^The sqlite3_data_count(P) interface returns the number of columns in the
+** current row of the result set of [prepared statement] P.
+** ^If prepared statement P does not have results ready to return
+** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
+** interfaces) then sqlite3_data_count(P) returns 0.
+** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
+** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
+** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P)
+** will return non-zero if previous call to [sqlite3_step](P) returned
+** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
+** where it always returns zero since each step of that multi-step
+** pragma returns 0 columns of data.
+**
+** See also: [sqlite3_column_count()]
+*/
+SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Fundamental Datatypes
+** KEYWORDS: SQLITE_TEXT
+**
+** ^(Every value in SQLite has one of five fundamental datatypes:
+**
+** <ul>
+** <li> 64-bit signed integer
+** <li> 64-bit IEEE floating point number
+** <li> string
+** <li> BLOB
+** <li> NULL
+** </ul>)^
+**
+** These constants are codes for each of those types.
+**
+** Note that the SQLITE_TEXT constant was also used in SQLite version 2
+** for a completely different meaning. Software that links against both
+** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not
+** SQLITE_TEXT.
+*/
+#define SQLITE_INTEGER 1
+#define SQLITE_FLOAT 2
+#define SQLITE_BLOB 4
+#define SQLITE_NULL 5
+#ifdef SQLITE_TEXT
+# undef SQLITE_TEXT
+#else
+# define SQLITE_TEXT 3
+#endif
+#define SQLITE3_TEXT 3
+
+/*
+** CAPI3REF: Result Values From A Query
+** KEYWORDS: {column access functions}
+**
+** These routines form the "result set" interface.
+**
+** ^These routines return information about a single column of the current
+** result row of a query. ^In every case the first argument is a pointer
+** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
+** that was returned from [sqlite3_prepare_v2()] or one of its variants)
+** and the second argument is the index of the column for which information
+** should be returned. ^The leftmost column of the result set has the index 0.
+** ^The number of columns in the result can be determined using
+** [sqlite3_column_count()].
+**
+** If the SQL statement does not currently point to a valid row, or if the
+** column index is out of range, the result is undefined.
+** These routines may only be called when the most recent call to
+** [sqlite3_step()] has returned [SQLITE_ROW] and neither
+** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently.
+** If any of these routines are called after [sqlite3_reset()] or
+** [sqlite3_finalize()] or after [sqlite3_step()] has returned
+** something other than [SQLITE_ROW], the results are undefined.
+** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()]
+** are called from a different thread while any of these routines
+** are pending, then the results are undefined.
+**
+** ^The sqlite3_column_type() routine returns the
+** [SQLITE_INTEGER | datatype code] for the initial data type
+** of the result column. ^The returned value is one of [SQLITE_INTEGER],
+** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value
+** returned by sqlite3_column_type() is only meaningful if no type
+** conversions have occurred as described below. After a type conversion,
+** the value returned by sqlite3_column_type() is undefined. Future
+** versions of SQLite may change the behavior of sqlite3_column_type()
+** following a type conversion.
+**
+** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes()
+** routine returns the number of bytes in that BLOB or string.
+** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts
+** the string to UTF-8 and then returns the number of bytes.
+** ^If the result is a numeric value then sqlite3_column_bytes() uses
+** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns
+** the number of bytes in that string.
+** ^If the result is NULL, then sqlite3_column_bytes() returns zero.
+**
+** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16()
+** routine returns the number of bytes in that BLOB or string.
+** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts
+** the string to UTF-16 and then returns the number of bytes.
+** ^If the result is a numeric value then sqlite3_column_bytes16() uses
+** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns
+** the number of bytes in that string.
+** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
+**
+** ^The values returned by [sqlite3_column_bytes()] and
+** [sqlite3_column_bytes16()] do not include the zero terminators at the end
+** of the string. ^For clarity: the values returned by
+** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
+** bytes in the string, not the number of characters.
+**
+** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
+** even empty strings, are always zero-terminated. ^The return
+** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
+**
+** ^The object returned by [sqlite3_column_value()] is an
+** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
+** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
+** If the [unprotected sqlite3_value] object returned by
+** [sqlite3_column_value()] is used in any other way, including calls
+** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
+** or [sqlite3_value_bytes()], then the behavior is undefined.
+**
+** These routines attempt to convert the value where appropriate. ^For
+** example, if the internal representation is FLOAT and a text result
+** is requested, [sqlite3_snprintf()] is used internally to perform the
+** conversion automatically. ^(The following table details the conversions
+** that are applied:
+**
+** <blockquote>
+** <table border="1">
+** <tr><th> Internal<br>Type <th> Requested<br>Type <th> Conversion
+**
+** <tr><td> NULL <td> INTEGER <td> Result is 0
+** <tr><td> NULL <td> FLOAT <td> Result is 0.0
+** <tr><td> NULL <td> TEXT <td> Result is NULL pointer
+** <tr><td> NULL <td> BLOB <td> Result is NULL pointer
+** <tr><td> INTEGER <td> FLOAT <td> Convert from integer to float
+** <tr><td> INTEGER <td> TEXT <td> ASCII rendering of the integer
+** <tr><td> INTEGER <td> BLOB <td> Same as INTEGER->TEXT
+** <tr><td> FLOAT <td> INTEGER <td> Convert from float to integer
+** <tr><td> FLOAT <td> TEXT <td> ASCII rendering of the float
+** <tr><td> FLOAT <td> BLOB <td> Same as FLOAT->TEXT
+** <tr><td> TEXT <td> INTEGER <td> Use atoi()
+** <tr><td> TEXT <td> FLOAT <td> Use atof()
+** <tr><td> TEXT <td> BLOB <td> No change
+** <tr><td> BLOB <td> INTEGER <td> Convert to TEXT then use atoi()
+** <tr><td> BLOB <td> FLOAT <td> Convert to TEXT then use atof()
+** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
+** </table>
+** </blockquote>)^
+**
+** The table above makes reference to standard C library functions atoi()
+** and atof(). SQLite does not really use these functions. It has its
+** own equivalent internal routines. The atoi() and atof() names are
+** used in the table for brevity and because they are familiar to most
+** C programmers.
+**
+** Note that when type conversions occur, pointers returned by prior
+** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
+** sqlite3_column_text16() may be invalidated.
+** Type conversions and pointer invalidations might occur
+** in the following cases:
+**
+** <ul>
+** <li> The initial content is a BLOB and sqlite3_column_text() or
+** sqlite3_column_text16() is called. A zero-terminator might
+** need to be added to the string.</li>
+** <li> The initial content is UTF-8 text and sqlite3_column_bytes16() or
+** sqlite3_column_text16() is called. The content must be converted
+** to UTF-16.</li>
+** <li> The initial content is UTF-16 text and sqlite3_column_bytes() or
+** sqlite3_column_text() is called. The content must be converted
+** to UTF-8.</li>
+** </ul>
+**
+** ^Conversions between UTF-16be and UTF-16le are always done in place and do
+** not invalidate a prior pointer, though of course the content of the buffer
+** that the prior pointer references will have been modified. Other kinds
+** of conversion are done in place when it is possible, but sometimes they
+** are not possible and in those cases prior pointers are invalidated.
+**
+** The safest and easiest to remember policy is to invoke these routines
+** in one of the following ways:
+**
+** <ul>
+** <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li>
+** <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li>
+** <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li>
+** </ul>
+**
+** In other words, you should call sqlite3_column_text(),
+** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result
+** into the desired format, then invoke sqlite3_column_bytes() or
+** sqlite3_column_bytes16() to find the size of the result. Do not mix calls
+** to sqlite3_column_text() or sqlite3_column_blob() with calls to
+** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16()
+** with calls to sqlite3_column_bytes().
+**
+** ^The pointers returned are valid until a type conversion occurs as
+** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
+** [sqlite3_finalize()] is called. ^The memory space used to hold strings
+** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
+** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
+** [sqlite3_free()].
+**
+** ^(If a memory allocation error occurs during the evaluation of any
+** of these routines, a default value is returned. The default value
+** is either the integer 0, the floating point number 0.0, or a NULL
+** pointer. Subsequent calls to [sqlite3_errcode()] will return
+** [SQLITE_NOMEM].)^
+*/
+SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
+SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
+SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+
+/*
+** CAPI3REF: Destroy A Prepared Statement Object
+**
+** ^The sqlite3_finalize() function is called to delete a [prepared statement].
+** ^If the most recent evaluation of the statement encountered no errors
+** or if the statement is never been evaluated, then sqlite3_finalize() returns
+** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
+** sqlite3_finalize(S) returns the appropriate [error code] or
+** [extended error code].
+**
+** ^The sqlite3_finalize(S) routine can be called at any point during
+** the life cycle of [prepared statement] S:
+** before statement S is ever evaluated, after
+** one or more calls to [sqlite3_reset()], or after any call
+** to [sqlite3_step()] regardless of whether or not the statement has
+** completed execution.
+**
+** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
+**
+** The application must finalize every [prepared statement] in order to avoid
+** resource leaks. It is a grievous error for the application to try to use
+** a prepared statement after it has been finalized. Any use of a prepared
+** statement after it has been finalized can result in undefined and
+** undesirable behavior such as segfaults and heap corruption.
+*/
+SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Reset A Prepared Statement Object
+**
+** The sqlite3_reset() function is called to reset a [prepared statement]
+** object back to its initial state, ready to be re-executed.
+** ^Any SQL statement variables that had values bound to them using
+** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values.
+** Use [sqlite3_clear_bindings()] to reset the bindings.
+**
+** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
+** back to the beginning of its program.
+**
+** ^If the most recent call to [sqlite3_step(S)] for the
+** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
+** or if [sqlite3_step(S)] has never before been called on S,
+** then [sqlite3_reset(S)] returns [SQLITE_OK].
+**
+** ^If the most recent call to [sqlite3_step(S)] for the
+** [prepared statement] S indicated an error, then
+** [sqlite3_reset(S)] returns an appropriate [error code].
+**
+** ^The [sqlite3_reset(S)] interface does not change the values
+** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
+*/
+SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Create Or Redefine SQL Functions
+** KEYWORDS: {function creation routines}
+** KEYWORDS: {application-defined SQL function}
+** KEYWORDS: {application-defined SQL functions}
+**
+** ^These functions (collectively known as "function creation routines")
+** are used to add SQL functions or aggregates or to redefine the behavior
+** of existing SQL functions or aggregates. The only differences between
+** these routines are the text encoding expected for
+** the second parameter (the name of the function being created)
+** and the presence or absence of a destructor callback for
+** the application data pointer.
+**
+** ^The first parameter is the [database connection] to which the SQL
+** function is to be added. ^If an application uses more than one database
+** connection then application-defined SQL functions must be added
+** to each database connection separately.
+**
+** ^The second parameter is the name of the SQL function to be created or
+** redefined. ^The length of the name is limited to 255 bytes in a UTF-8
+** representation, exclusive of the zero-terminator. ^Note that the name
+** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
+** ^Any attempt to create a function with a longer name
+** will result in [SQLITE_MISUSE] being returned.
+**
+** ^The third parameter (nArg)
+** is the number of arguments that the SQL function or
+** aggregate takes. ^If this parameter is -1, then the SQL function or
+** aggregate may take any number of arguments between 0 and the limit
+** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third
+** parameter is less than -1 or greater than 127 then the behavior is
+** undefined.
+**
+** ^The fourth parameter, eTextRep, specifies what
+** [SQLITE_UTF8 | text encoding] this SQL function prefers for
+** its parameters. Every SQL function implementation must be able to work
+** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be
+** more efficient with one encoding than another. ^An application may
+** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
+** times with the same function but with different values of eTextRep.
+** ^When multiple implementations of the same function are available, SQLite
+** will pick the one that involves the least amount of data conversion.
+** If there is only a single implementation which does not care what text
+** encoding is used, then the fourth argument should be [SQLITE_ANY].
+**
+** ^(The fifth parameter is an arbitrary pointer. The implementation of the
+** function can gain access to this pointer using [sqlite3_user_data()].)^
+**
+** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are
+** pointers to C-language functions that implement the SQL function or
+** aggregate. ^A scalar SQL function requires an implementation of the xFunc
+** callback only; NULL pointers must be passed as the xStep and xFinal
+** parameters. ^An aggregate SQL function requires an implementation of xStep
+** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing
+** SQL function or aggregate, pass NULL pointers for all three function
+** callbacks.
+**
+** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
+** then it is destructor for the application data pointer.
+** The destructor is invoked when the function is deleted, either by being
+** overloaded or when the database connection closes.)^
+** ^The destructor is also invoked if the call to
+** sqlite3_create_function_v2() fails.
+** ^When the destructor callback of the tenth parameter is invoked, it
+** is passed a single argument which is a copy of the application data
+** pointer which was the fifth parameter to sqlite3_create_function_v2().
+**
+** ^It is permitted to register multiple implementations of the same
+** functions with the same name but with either differing numbers of
+** arguments or differing preferred text encodings. ^SQLite will use
+** the implementation that most closely matches the way in which the
+** SQL function is used. ^A function implementation with a non-negative
+** nArg parameter is a better match than a function implementation with
+** a negative nArg. ^A function where the preferred text encoding
+** matches the database encoding is a better
+** match than a function where the encoding is different.
+** ^A function where the encoding difference is between UTF16le and UTF16be
+** is a closer match than a function where the encoding difference is
+** between UTF8 and UTF16.
+**
+** ^Built-in functions may be overloaded by new application-defined functions.
+**
+** ^An application-defined function is permitted to call other
+** SQLite interfaces. However, such calls must not
+** close the database connection nor finalize or reset the prepared
+** statement in which the function is running.
+*/
+SQLITE_API int sqlite3_create_function(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*)
+);
+SQLITE_API int sqlite3_create_function16(
+ sqlite3 *db,
+ const void *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*)
+);
+SQLITE_API int sqlite3_create_function_v2(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*),
+ void(*xDestroy)(void*)
+);
+
+/*
+** CAPI3REF: Text Encodings
+**
+** These constant define integer codes that represent the various
+** text encodings supported by SQLite.
+*/
+#define SQLITE_UTF8 1
+#define SQLITE_UTF16LE 2
+#define SQLITE_UTF16BE 3
+#define SQLITE_UTF16 4 /* Use native byte order */
+#define SQLITE_ANY 5 /* sqlite3_create_function only */
+#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
+
+/*
+** CAPI3REF: Deprecated Functions
+** DEPRECATED
+**
+** These functions are [deprecated]. In order to maintain
+** backwards compatibility with older code, these functions continue
+** to be supported. However, new applications should avoid
+** the use of these functions. To help encourage people to avoid
+** using these functions, we are not going to tell you what they do.
+*/
+#ifndef SQLITE_OMIT_DEPRECATED
+SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
+SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+ void*,sqlite3_int64);
+#endif
+
+/*
+** CAPI3REF: Obtaining SQL Function Parameter Values
+**
+** The C-language implementation of SQL functions and aggregates uses
+** this set of interface routines to access the parameter values on
+** the function or aggregate.
+**
+** The xFunc (for scalar functions) or xStep (for aggregates) parameters
+** to [sqlite3_create_function()] and [sqlite3_create_function16()]
+** define callbacks that implement the SQL functions and aggregates.
+** The 3rd parameter to these callbacks is an array of pointers to
+** [protected sqlite3_value] objects. There is one [sqlite3_value] object for
+** each parameter to the SQL function. These routines are used to
+** extract values from the [sqlite3_value] objects.
+**
+** These routines work only with [protected sqlite3_value] objects.
+** Any attempt to use these routines on an [unprotected sqlite3_value]
+** object results in undefined behavior.
+**
+** ^These routines work just like the corresponding [column access functions]
+** except that these routines take a single [protected sqlite3_value] object
+** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
+**
+** ^The sqlite3_value_text16() interface extracts a UTF-16 string
+** in the native byte-order of the host machine. ^The
+** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
+** extract UTF-16 strings as big-endian and little-endian respectively.
+**
+** ^(The sqlite3_value_numeric_type() interface attempts to apply
+** numeric affinity to the value. This means that an attempt is
+** made to convert the value to an integer or floating point. If
+** such a conversion is possible without loss of information (in other
+** words, if the value is a string that looks like a number)
+** then the conversion is performed. Otherwise no conversion occurs.
+** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
+**
+** Please pay particular attention to the fact that the pointer returned
+** from [sqlite3_value_blob()], [sqlite3_value_text()], or
+** [sqlite3_value_text16()] can be invalidated by a subsequent call to
+** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
+** or [sqlite3_value_text16()].
+**
+** These routines must be called from the same thread as
+** the SQL function that supplied the [sqlite3_value*] parameters.
+*/
+SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
+SQLITE_API double sqlite3_value_double(sqlite3_value*);
+SQLITE_API int sqlite3_value_int(sqlite3_value*);
+SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
+SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
+SQLITE_API int sqlite3_value_type(sqlite3_value*);
+SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
+
+/*
+** CAPI3REF: Obtain Aggregate Function Context
+**
+** Implementations of aggregate SQL functions use this
+** routine to allocate memory for storing their state.
+**
+** ^The first time the sqlite3_aggregate_context(C,N) routine is called
+** for a particular aggregate function, SQLite
+** allocates N of memory, zeroes out that memory, and returns a pointer
+** to the new memory. ^On second and subsequent calls to
+** sqlite3_aggregate_context() for the same aggregate function instance,
+** the same buffer is returned. Sqlite3_aggregate_context() is normally
+** called once for each invocation of the xStep callback and then one
+** last time when the xFinal callback is invoked. ^(When no rows match
+** an aggregate query, the xStep() callback of the aggregate function
+** implementation is never called and xFinal() is called exactly once.
+** In those cases, sqlite3_aggregate_context() might be called for the
+** first time from within xFinal().)^
+**
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
+** when first called if N is less than or equal to zero or if a memory
+** allocate error occurs.
+**
+** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
+** determined by the N parameter on first successful call. Changing the
+** value of N in subsequent call to sqlite3_aggregate_context() within
+** the same aggregate function instance will not resize the memory
+** allocation.)^ Within the xFinal callback, it is customary to set
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
+** pointless memory allocations occur.
+**
+** ^SQLite automatically frees the memory allocated by
+** sqlite3_aggregate_context() when the aggregate query concludes.
+**
+** The first parameter must be a copy of the
+** [sqlite3_context | SQL function context] that is the first parameter
+** to the xStep or xFinal callback routine that implements the aggregate
+** function.
+**
+** This routine must be called from the same thread in which
+** the aggregate SQL function is running.
+*/
+SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+
+/*
+** CAPI3REF: User Data For Functions
+**
+** ^The sqlite3_user_data() interface returns a copy of
+** the pointer that was the pUserData parameter (the 5th parameter)
+** of the [sqlite3_create_function()]
+** and [sqlite3_create_function16()] routines that originally
+** registered the application defined function.
+**
+** This routine must be called from the same thread in which
+** the application-defined function is running.
+*/
+SQLITE_API void *sqlite3_user_data(sqlite3_context*);
+
+/*
+** CAPI3REF: Database Connection For Functions
+**
+** ^The sqlite3_context_db_handle() interface returns a copy of
+** the pointer to the [database connection] (the 1st parameter)
+** of the [sqlite3_create_function()]
+** and [sqlite3_create_function16()] routines that originally
+** registered the application defined function.
+*/
+SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+
+/*
+** CAPI3REF: Function Auxiliary Data
+**
+** The following two functions may be used by scalar SQL functions to
+** associate metadata with argument values. If the same value is passed to
+** multiple invocations of the same SQL function during query execution, under
+** some circumstances the associated metadata may be preserved. This may
+** be used, for example, to add a regular-expression matching scalar
+** function. The compiled version of the regular expression is stored as
+** metadata associated with the SQL value passed as the regular expression
+** pattern. The compiled regular expression can be reused on multiple
+** invocations of the same function so that the original pattern string
+** does not need to be recompiled on each invocation.
+**
+** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
+** associated by the sqlite3_set_auxdata() function with the Nth argument
+** value to the application-defined function. ^If no metadata has been ever
+** been set for the Nth argument of the function, or if the corresponding
+** function parameter has changed since the meta-data was set,
+** then sqlite3_get_auxdata() returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata() interface saves the metadata
+** pointed to by its 3rd parameter as the metadata for the N-th
+** argument of the application-defined function. Subsequent
+** calls to sqlite3_get_auxdata() might return this data, if it has
+** not been destroyed.
+** ^If it is not NULL, SQLite will invoke the destructor
+** function given by the 4th parameter to sqlite3_set_auxdata() on
+** the metadata when the corresponding function parameter changes
+** or when the SQL statement completes, whichever comes first.
+**
+** SQLite is free to call the destructor and drop metadata on any
+** parameter of any function at any time. ^The only guarantee is that
+** the destructor will be called before the metadata is dropped.
+**
+** ^(In practice, metadata is preserved between function calls for
+** expressions that are constant at compile time. This includes literal
+** values and [parameters].)^
+**
+** These routines must be called from the same thread in which
+** the SQL function is running.
+*/
+SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
+SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+
+
+/*
+** CAPI3REF: Constants Defining Special Destructor Behavior
+**
+** These are special values for the destructor that is passed in as the
+** final argument to routines like [sqlite3_result_blob()]. ^If the destructor
+** argument is SQLITE_STATIC, it means that the content pointer is constant
+** and will never change. It does not need to be destroyed. ^The
+** SQLITE_TRANSIENT value means that the content will likely change in
+** the near future and that SQLite should make its own private copy of
+** the content before returning.
+**
+** The typedef is necessary to work around problems in certain
+** C++ compilers. See ticket #2191.
+*/
+typedef void (*sqlite3_destructor_type)(void*);
+#define SQLITE_STATIC ((sqlite3_destructor_type)0)
+#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
+
+/*
+** CAPI3REF: Setting The Result Of An SQL Function
+**
+** These routines are used by the xFunc or xFinal callbacks that
+** implement SQL functions and aggregates. See
+** [sqlite3_create_function()] and [sqlite3_create_function16()]
+** for additional information.
+**
+** These functions work very much like the [parameter binding] family of
+** functions used to bind values to host parameters in prepared statements.
+** Refer to the [SQL parameter] documentation for additional information.
+**
+** ^The sqlite3_result_blob() interface sets the result from
+** an application-defined function to be the BLOB whose content is pointed
+** to by the second parameter and which is N bytes long where N is the
+** third parameter.
+**
+** ^The sqlite3_result_zeroblob() interfaces set the result of
+** the application-defined function to be a BLOB containing all zero
+** bytes and N bytes in size, where N is the value of the 2nd parameter.
+**
+** ^The sqlite3_result_double() interface sets the result from
+** an application-defined function to be a floating point value specified
+** by its 2nd argument.
+**
+** ^The sqlite3_result_error() and sqlite3_result_error16() functions
+** cause the implemented SQL function to throw an exception.
+** ^SQLite uses the string pointed to by the
+** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
+** as the text of an error message. ^SQLite interprets the error
+** message string from sqlite3_result_error() as UTF-8. ^SQLite
+** interprets the string from sqlite3_result_error16() as UTF-16 in native
+** byte order. ^If the third parameter to sqlite3_result_error()
+** or sqlite3_result_error16() is negative then SQLite takes as the error
+** message all text up through the first zero character.
+** ^If the third parameter to sqlite3_result_error() or
+** sqlite3_result_error16() is non-negative then SQLite takes that many
+** bytes (not characters) from the 2nd parameter as the error message.
+** ^The sqlite3_result_error() and sqlite3_result_error16()
+** routines make a private copy of the error message text before
+** they return. Hence, the calling function can deallocate or
+** modify the text after they return without harm.
+** ^The sqlite3_result_error_code() function changes the error code
+** returned by SQLite as a result of an error in a function. ^By default,
+** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error()
+** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
+**
+** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
+** error indicating that a string or BLOB is too long to represent.
+**
+** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
+** error indicating that a memory allocation failed.
+**
+** ^The sqlite3_result_int() interface sets the return value
+** of the application-defined function to be the 32-bit signed integer
+** value given in the 2nd argument.
+** ^The sqlite3_result_int64() interface sets the return value
+** of the application-defined function to be the 64-bit signed integer
+** value given in the 2nd argument.
+**
+** ^The sqlite3_result_null() interface sets the return value
+** of the application-defined function to be NULL.
+**
+** ^The sqlite3_result_text(), sqlite3_result_text16(),
+** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
+** set the return value of the application-defined function to be
+** a text string which is represented as UTF-8, UTF-16 native byte order,
+** UTF-16 little endian, or UTF-16 big endian, respectively.
+** ^SQLite takes the text result from the application from
+** the 2nd parameter of the sqlite3_result_text* interfaces.
+** ^If the 3rd parameter to the sqlite3_result_text* interfaces
+** is negative, then SQLite takes result text from the 2nd parameter
+** through the first zero character.
+** ^If the 3rd parameter to the sqlite3_result_text* interfaces
+** is non-negative, then as many bytes (not characters) of the text
+** pointed to by the 2nd parameter are taken as the application-defined
+** function result. If the 3rd parameter is non-negative, then it
+** must be the byte offset into the string where the NUL terminator would
+** appear if the string where NUL terminated. If any NUL characters occur
+** in the string at a byte offset that is less than the value of the 3rd
+** parameter, then the resulting string will contain embedded NULs and the
+** result of expressions operating on strings with embedded NULs is undefined.
+** ^If the 4th parameter to the sqlite3_result_text* interfaces
+** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
+** function as the destructor on the text or BLOB result when it has
+** finished using that result.
+** ^If the 4th parameter to the sqlite3_result_text* interfaces or to
+** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite
+** assumes that the text or BLOB result is in constant space and does not
+** copy the content of the parameter nor call a destructor on the content
+** when it has finished using that result.
+** ^If the 4th parameter to the sqlite3_result_text* interfaces
+** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
+** then SQLite makes a copy of the result into space obtained from
+** from [sqlite3_malloc()] before it returns.
+**
+** ^The sqlite3_result_value() interface sets the result of
+** the application-defined function to be a copy the
+** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
+** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
+** so that the [sqlite3_value] specified in the parameter may change or
+** be deallocated after sqlite3_result_value() returns without harm.
+** ^A [protected sqlite3_value] object may always be used where an
+** [unprotected sqlite3_value] object is required, so either
+** kind of [sqlite3_value] object can be used with this interface.
+**
+** If these routines are called from within the different thread
+** than the one containing the application-defined function that received
+** the [sqlite3_context] pointer, the results are undefined.
+*/
+SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
+SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
+SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
+SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
+SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
+SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
+SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
+SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
+SQLITE_API void sqlite3_result_null(sqlite3_context*);
+SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
+SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
+
+/*
+** CAPI3REF: Define New Collating Sequences
+**
+** ^These functions add, remove, or modify a [collation] associated
+** with the [database connection] specified as the first argument.
+**
+** ^The name of the collation is a UTF-8 string
+** for sqlite3_create_collation() and sqlite3_create_collation_v2()
+** and a UTF-16 string in native byte order for sqlite3_create_collation16().
+** ^Collation names that compare equal according to [sqlite3_strnicmp()] are
+** considered to be the same name.
+**
+** ^(The third argument (eTextRep) must be one of the constants:
+** <ul>
+** <li> [SQLITE_UTF8],
+** <li> [SQLITE_UTF16LE],
+** <li> [SQLITE_UTF16BE],
+** <li> [SQLITE_UTF16], or
+** <li> [SQLITE_UTF16_ALIGNED].
+** </ul>)^
+** ^The eTextRep argument determines the encoding of strings passed
+** to the collating function callback, xCallback.
+** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
+** force strings to be UTF16 with native byte order.
+** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
+** on an even byte address.
+**
+** ^The fourth argument, pArg, is an application data pointer that is passed
+** through as the first argument to the collating function callback.
+**
+** ^The fifth argument, xCallback, is a pointer to the collating function.
+** ^Multiple collating functions can be registered using the same name but
+** with different eTextRep parameters and SQLite will use whichever
+** function requires the least amount of data transformation.
+** ^If the xCallback argument is NULL then the collating function is
+** deleted. ^When all collating functions having the same name are deleted,
+** that collation is no longer usable.
+**
+** ^The collating function callback is invoked with a copy of the pArg
+** application data pointer and with two strings in the encoding specified
+** by the eTextRep argument. The collating function must return an
+** integer that is negative, zero, or positive
+** if the first string is less than, equal to, or greater than the second,
+** respectively. A collating function must always return the same answer
+** given the same inputs. If two or more collating functions are registered
+** to the same collation name (using different eTextRep values) then all
+** must give an equivalent answer when invoked with equivalent strings.
+** The collating function must obey the following properties for all
+** strings A, B, and C:
+**
+** <ol>
+** <li> If A==B then B==A.
+** <li> If A==B and B==C then A==C.
+** <li> If A&lt;B THEN B&gt;A.
+** <li> If A&lt;B and B&lt;C then A&lt;C.
+** </ol>
+**
+** If a collating function fails any of the above constraints and that
+** collating function is registered and used, then the behavior of SQLite
+** is undefined.
+**
+** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
+** with the addition that the xDestroy callback is invoked on pArg when
+** the collating function is deleted.
+** ^Collating functions are deleted when they are overridden by later
+** calls to the collation creation functions or when the
+** [database connection] is closed using [sqlite3_close()].
+**
+** ^The xDestroy callback is <u>not</u> called if the
+** sqlite3_create_collation_v2() function fails. Applications that invoke
+** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
+** check the return code and dispose of the application data pointer
+** themselves rather than expecting SQLite to deal with it for them.
+** This is different from every other SQLite interface. The inconsistency
+** is unfortunate but cannot be changed without breaking backwards
+** compatibility.
+**
+** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
+*/
+SQLITE_API int sqlite3_create_collation(
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
+ void *pArg,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+);
+SQLITE_API int sqlite3_create_collation_v2(
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
+ void *pArg,
+ int(*xCompare)(void*,int,const void*,int,const void*),
+ void(*xDestroy)(void*)
+);
+SQLITE_API int sqlite3_create_collation16(
+ sqlite3*,
+ const void *zName,
+ int eTextRep,
+ void *pArg,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+);
+
+/*
+** CAPI3REF: Collation Needed Callbacks
+**
+** ^To avoid having to register all collation sequences before a database
+** can be used, a single callback function may be registered with the
+** [database connection] to be invoked whenever an undefined collation
+** sequence is required.
+**
+** ^If the function is registered using the sqlite3_collation_needed() API,
+** then it is passed the names of undefined collation sequences as strings
+** encoded in UTF-8. ^If sqlite3_collation_needed16() is used,
+** the names are passed as UTF-16 in machine native byte order.
+** ^A call to either function replaces the existing collation-needed callback.
+**
+** ^(When the callback is invoked, the first argument passed is a copy
+** of the second argument to sqlite3_collation_needed() or
+** sqlite3_collation_needed16(). The second argument is the database
+** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE],
+** or [SQLITE_UTF16LE], indicating the most desirable form of the collation
+** sequence function required. The fourth parameter is the name of the
+** required collation sequence.)^
+**
+** The callback function should register the desired collation using
+** [sqlite3_create_collation()], [sqlite3_create_collation16()], or
+** [sqlite3_create_collation_v2()].
+*/
+SQLITE_API int sqlite3_collation_needed(
+ sqlite3*,
+ void*,
+ void(*)(void*,sqlite3*,int eTextRep,const char*)
+);
+SQLITE_API int sqlite3_collation_needed16(
+ sqlite3*,
+ void*,
+ void(*)(void*,sqlite3*,int eTextRep,const void*)
+);
+
+#ifdef SQLITE_HAS_CODEC
+/*
+** Specify the key for an encrypted database. This routine should be
+** called right after sqlite3_open().
+**
+** The code to implement this API is not available in the public release
+** of SQLite.
+*/
+SQLITE_API int sqlite3_key(
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The key */
+);
+
+/*
+** Change the key on an open database. If the current database is not
+** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
+** database is decrypted.
+**
+** The code to implement this API is not available in the public release
+** of SQLite.
+*/
+SQLITE_API int sqlite3_rekey(
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The new key */
+);
+
+/*
+** Specify the activation key for a SEE database. Unless
+** activated, none of the SEE routines will work.
+*/
+SQLITE_API void sqlite3_activate_see(
+ const char *zPassPhrase /* Activation phrase */
+);
+#endif
+
+#ifdef SQLITE_ENABLE_CEROD
+/*
+** Specify the activation key for a CEROD database. Unless
+** activated, none of the CEROD routines will work.
+*/
+SQLITE_API void sqlite3_activate_cerod(
+ const char *zPassPhrase /* Activation phrase */
+);
+#endif
+
+/*
+** CAPI3REF: Suspend Execution For A Short Time
+**
+** The sqlite3_sleep() function causes the current thread to suspend execution
+** for at least a number of milliseconds specified in its parameter.
+**
+** If the operating system does not support sleep requests with
+** millisecond time resolution, then the time will be rounded up to
+** the nearest second. The number of milliseconds of sleep actually
+** requested from the operating system is returned.
+**
+** ^SQLite implements this interface by calling the xSleep()
+** method of the default [sqlite3_vfs] object. If the xSleep() method
+** of the default VFS is not implemented correctly, or not implemented at
+** all, then the behavior of sqlite3_sleep() may deviate from the description
+** in the previous paragraphs.
+*/
+SQLITE_API int sqlite3_sleep(int);
+
+/*
+** CAPI3REF: Name Of The Folder Holding Temporary Files
+**
+** ^(If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all temporary files
+** created by SQLite when using a built-in [sqlite3_vfs | VFS]
+** will be placed in that directory.)^ ^If this variable
+** is a NULL pointer, then SQLite performs a search for an appropriate
+** temporary file directory.
+**
+** It is not safe to read or modify this variable in more than one
+** thread at a time. It is not safe to read or modify this variable
+** if a [database connection] is being used at the same time in a separate
+** thread.
+** It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been called and that this variable remain unchanged
+** thereafter.
+**
+** ^The [temp_store_directory pragma] may modify this variable and cause
+** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
+** the [temp_store_directory pragma] always assumes that any string
+** that this variable points to is held in memory obtained from
+** [sqlite3_malloc] and the pragma may attempt to free that memory
+** using [sqlite3_free].
+** Hence, if this variable is modified directly, either it should be
+** made NULL or made to point to memory obtained from [sqlite3_malloc]
+** or else the use of the [temp_store_directory pragma] should be avoided.
+**
+** <b>Note to Windows Runtime users:</b> The temporary directory must be set
+** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
+** features that require the use of temporary files may fail. Here is an
+** example of how to do this using C++ with the Windows Runtime:
+**
+** <blockquote><pre>
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+** &nbsp; TemporaryFolder->Path->Data();
+** char zPathBuf&#91;MAX_PATH + 1&#93;;
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+** &nbsp; NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** </pre></blockquote>
+*/
+SQLITE_API char *sqlite3_temp_directory;
+
+/*
+** CAPI3REF: Name Of The Folder Holding Database Files
+**
+** ^(If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all database files
+** specified with a relative pathname and created or accessed by
+** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
+** to be relative to that directory.)^ ^If this variable is a NULL
+** pointer, then SQLite assumes that all database files specified
+** with a relative pathname are relative to the current directory
+** for the process. Only the windows VFS makes use of this global
+** variable; it is ignored by the unix VFS.
+**
+** Changing the value of this variable while a database connection is
+** open can result in a corrupt database.
+**
+** It is not safe to read or modify this variable in more than one
+** thread at a time. It is not safe to read or modify this variable
+** if a [database connection] is being used at the same time in a separate
+** thread.
+** It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been called and that this variable remain unchanged
+** thereafter.
+**
+** ^The [data_store_directory pragma] may modify this variable and cause
+** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
+** the [data_store_directory pragma] always assumes that any string
+** that this variable points to is held in memory obtained from
+** [sqlite3_malloc] and the pragma may attempt to free that memory
+** using [sqlite3_free].
+** Hence, if this variable is modified directly, either it should be
+** made NULL or made to point to memory obtained from [sqlite3_malloc]
+** or else the use of the [data_store_directory pragma] should be avoided.
+*/
+SQLITE_API char *sqlite3_data_directory;
+
+/*
+** CAPI3REF: Test For Auto-Commit Mode
+** KEYWORDS: {autocommit mode}
+**
+** ^The sqlite3_get_autocommit() interface returns non-zero or
+** zero if the given database connection is or is not in autocommit mode,
+** respectively. ^Autocommit mode is on by default.
+** ^Autocommit mode is disabled by a [BEGIN] statement.
+** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK].
+**
+** If certain kinds of errors occur on a statement within a multi-statement
+** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR],
+** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the
+** transaction might be rolled back automatically. The only way to
+** find out whether SQLite automatically rolled back the transaction after
+** an error is to use this function.
+**
+** If another thread changes the autocommit status of the database
+** connection while this routine is running, then the return value
+** is undefined.
+*/
+SQLITE_API int sqlite3_get_autocommit(sqlite3*);
+
+/*
+** CAPI3REF: Find The Database Handle Of A Prepared Statement
+**
+** ^The sqlite3_db_handle interface returns the [database connection] handle
+** to which a [prepared statement] belongs. ^The [database connection]
+** returned by sqlite3_db_handle is the same [database connection]
+** that was the first argument
+** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
+** create the statement in the first place.
+*/
+SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Return The Filename For A Database Connection
+**
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
+** associated with database N of connection D. ^The main database file
+** has the name "main". If there is no attached database N on the database
+** connection D, or if database N is a temporary or in-memory database, then
+** a NULL pointer is returned.
+**
+** ^The filename returned by this function is the output of the
+** xFullPathname method of the [VFS]. ^In other words, the filename
+** will be an absolute pathname, even if the filename used
+** to open the database originally was a URI or relative pathname.
+*/
+SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+
+/*
+** CAPI3REF: Determine if a database is read-only
+**
+** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
+** of connection D is read-only, 0 if it is read/write, or -1 if N is not
+** the name of a database on connection D.
+*/
+SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
+
+/*
+** CAPI3REF: Find the next prepared statement
+**
+** ^This interface returns a pointer to the next [prepared statement] after
+** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
+** then this interface returns a pointer to the first prepared statement
+** associated with the database connection pDb. ^If no prepared statement
+** satisfies the conditions of this routine, it returns NULL.
+**
+** The [database connection] pointer D in a call to
+** [sqlite3_next_stmt(D,S)] must refer to an open database
+** connection and in particular must not be a NULL pointer.
+*/
+SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Commit And Rollback Notification Callbacks
+**
+** ^The sqlite3_commit_hook() interface registers a callback
+** function to be invoked whenever a transaction is [COMMIT | committed].
+** ^Any callback set by a previous call to sqlite3_commit_hook()
+** for the same database connection is overridden.
+** ^The sqlite3_rollback_hook() interface registers a callback
+** function to be invoked whenever a transaction is [ROLLBACK | rolled back].
+** ^Any callback set by a previous call to sqlite3_rollback_hook()
+** for the same database connection is overridden.
+** ^The pArg argument is passed through to the callback.
+** ^If the callback on a commit hook function returns non-zero,
+** then the commit is converted into a rollback.
+**
+** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions
+** return the P argument from the previous call of the same function
+** on the same [database connection] D, or NULL for
+** the first call for each function on D.
+**
+** The commit and rollback hook callbacks are not reentrant.
+** The callback implementation must not do anything that will modify
+** the database connection that invoked the callback. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the commit
+** or rollback hook in the first place.
+** Note that running any other SQL statements, including SELECT statements,
+** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify
+** the database connections for the meaning of "modify" in this paragraph.
+**
+** ^Registering a NULL function disables the callback.
+**
+** ^When the commit hook callback routine returns zero, the [COMMIT]
+** operation is allowed to continue normally. ^If the commit hook
+** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK].
+** ^The rollback hook is invoked on a rollback that results from a commit
+** hook returning non-zero, just as it would be with any other rollback.
+**
+** ^For the purposes of this API, a transaction is said to have been
+** rolled back if an explicit "ROLLBACK" statement is executed, or
+** an error or constraint causes an implicit rollback to occur.
+** ^The rollback callback is not invoked if a transaction is
+** automatically rolled back because the database connection is closed.
+**
+** See also the [sqlite3_update_hook()] interface.
+*/
+SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
+SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+
+/*
+** CAPI3REF: Data Change Notification Callbacks
+**
+** ^The sqlite3_update_hook() interface registers a callback function
+** with the [database connection] identified by the first argument
+** to be invoked whenever a row is updated, inserted or deleted.
+** ^Any callback set by a previous call to this function
+** for the same database connection is overridden.
+**
+** ^The second argument is a pointer to the function to invoke when a
+** row is updated, inserted or deleted.
+** ^The first argument to the callback is a copy of the third argument
+** to sqlite3_update_hook().
+** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
+** or [SQLITE_UPDATE], depending on the operation that caused the callback
+** to be invoked.
+** ^The third and fourth arguments to the callback contain pointers to the
+** database and table name containing the affected row.
+** ^The final callback parameter is the [rowid] of the row.
+** ^In the case of an update, this is the [rowid] after the update takes place.
+**
+** ^(The update hook is not invoked when internal system tables are
+** modified (i.e. sqlite_master and sqlite_sequence).)^
+**
+** ^In the current implementation, the update hook
+** is not invoked when duplication rows are deleted because of an
+** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
+** invoked when rows are deleted using the [truncate optimization].
+** The exceptions defined in this paragraph might change in a future
+** release of SQLite.
+**
+** The update hook implementation must not do anything that will modify
+** the database connection that invoked the update hook. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the update hook.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
+** ^The sqlite3_update_hook(D,C,P) function
+** returns the P argument from the previous call
+** on the same [database connection] D, or NULL for
+** the first call on D.
+**
+** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()]
+** interfaces.
+*/
+SQLITE_API void *sqlite3_update_hook(
+ sqlite3*,
+ void(*)(void *,int ,char const *,char const *,sqlite3_int64),
+ void*
+);
+
+/*
+** CAPI3REF: Enable Or Disable Shared Pager Cache
+**
+** ^(This routine enables or disables the sharing of the database cache
+** and schema data structures between [database connection | connections]
+** to the same database. Sharing is enabled if the argument is true
+** and disabled if the argument is false.)^
+**
+** ^Cache sharing is enabled and disabled for an entire process.
+** This is a change as of SQLite version 3.5.0. In prior versions of SQLite,
+** sharing was enabled or disabled for each thread separately.
+**
+** ^(The cache sharing mode set by this interface effects all subsequent
+** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
+** Existing database connections continue use the sharing mode
+** that was in effect at the time they were opened.)^
+**
+** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
+** successfully. An [error code] is returned otherwise.)^
+**
+** ^Shared cache is disabled by default. But this might change in
+** future releases of SQLite. Applications that care about shared
+** cache setting should set it explicitly.
+**
+** This interface is threadsafe on processors where writing a
+** 32-bit integer is atomic.
+**
+** See Also: [SQLite Shared-Cache Mode]
+*/
+SQLITE_API int sqlite3_enable_shared_cache(int);
+
+/*
+** CAPI3REF: Attempt To Free Heap Memory
+**
+** ^The sqlite3_release_memory() interface attempts to free N bytes
+** of heap memory by deallocating non-essential memory allocations
+** held by the database library. Memory used to cache database
+** pages to improve performance is an example of non-essential memory.
+** ^sqlite3_release_memory() returns the number of bytes actually freed,
+** which might be more or less than the amount requested.
+** ^The sqlite3_release_memory() routine is a no-op returning zero
+** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT].
+**
+** See also: [sqlite3_db_release_memory()]
+*/
+SQLITE_API int sqlite3_release_memory(int);
+
+/*
+** CAPI3REF: Free Memory Used By A Database Connection
+**
+** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
+** memory as possible from database connection D. Unlike the
+** [sqlite3_release_memory()] interface, this interface is effect even
+** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
+** omitted.
+**
+** See also: [sqlite3_release_memory()]
+*/
+SQLITE_API int sqlite3_db_release_memory(sqlite3*);
+
+/*
+** CAPI3REF: Impose A Limit On Heap Size
+**
+** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
+** soft limit on the amount of heap memory that may be allocated by SQLite.
+** ^SQLite strives to keep heap memory utilization below the soft heap
+** limit by reducing the number of pages held in the page cache
+** as heap memory usages approaches the limit.
+** ^The soft heap limit is "soft" because even though SQLite strives to stay
+** below the limit, it will exceed the limit rather than generate
+** an [SQLITE_NOMEM] error. In other words, the soft heap limit
+** is advisory only.
+**
+** ^The return value from sqlite3_soft_heap_limit64() is the size of
+** the soft heap limit prior to the call, or negative in the case of an
+** error. ^If the argument N is negative
+** then no change is made to the soft heap limit. Hence, the current
+** size of the soft heap limit can be determined by invoking
+** sqlite3_soft_heap_limit64() with a negative argument.
+**
+** ^If the argument N is zero then the soft heap limit is disabled.
+**
+** ^(The soft heap limit is not enforced in the current implementation
+** if one or more of following conditions are true:
+**
+** <ul>
+** <li> The soft heap limit is set to zero.
+** <li> Memory accounting is disabled using a combination of the
+** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
+** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
+** <li> An alternative page cache implementation is specified using
+** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...).
+** <li> The page cache allocates from its own memory pool supplied
+** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
+** from the heap.
+** </ul>)^
+**
+** Beginning with SQLite version 3.7.3, the soft heap limit is enforced
+** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
+** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
+** the soft heap limit is enforced on every memory allocation. Without
+** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
+** when memory is allocated by the page cache. Testing suggests that because
+** the page cache is the predominate memory user in SQLite, most
+** applications will achieve adequate soft heap limit enforcement without
+** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
+**
+** The circumstances under which SQLite will enforce the soft heap limit may
+** changes in future releases of SQLite.
+*/
+SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+
+/*
+** CAPI3REF: Deprecated Soft Heap Limit Interface
+** DEPRECATED
+**
+** This is a deprecated version of the [sqlite3_soft_heap_limit64()]
+** interface. This routine is provided for historical compatibility
+** only. All new applications should use the
+** [sqlite3_soft_heap_limit64()] interface rather than this one.
+*/
+SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
+
+
+/*
+** CAPI3REF: Extract Metadata About A Column Of A Table
+**
+** ^This routine returns metadata about a specific column of a specific
+** database table accessible using the [database connection] handle
+** passed as the first function argument.
+**
+** ^The column is identified by the second, third and fourth parameters to
+** this function. ^The second parameter is either the name of the database
+** (i.e. "main", "temp", or an attached database) containing the specified
+** table or NULL. ^If it is NULL, then all attached databases are searched
+** for the table using the same algorithm used by the database engine to
+** resolve unqualified table references.
+**
+** ^The third and fourth parameters to this function are the table and column
+** name of the desired column, respectively. Neither of these parameters
+** may be NULL.
+**
+** ^Metadata is returned by writing to the memory locations passed as the 5th
+** and subsequent parameters to this function. ^Any of these arguments may be
+** NULL, in which case the corresponding element of metadata is omitted.
+**
+** ^(<blockquote>
+** <table border="1">
+** <tr><th> Parameter <th> Output<br>Type <th> Description
+**
+** <tr><td> 5th <td> const char* <td> Data type
+** <tr><td> 6th <td> const char* <td> Name of default collation sequence
+** <tr><td> 7th <td> int <td> True if column has a NOT NULL constraint
+** <tr><td> 8th <td> int <td> True if column is part of the PRIMARY KEY
+** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
+** </table>
+** </blockquote>)^
+**
+** ^The memory pointed to by the character pointers returned for the
+** declaration type and collation sequence is valid only until the next
+** call to any SQLite API function.
+**
+** ^If the specified table is actually a view, an [error code] is returned.
+**
+** ^If the specified column is "rowid", "oid" or "_rowid_" and an
+** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
+** parameters are set for the explicitly declared column. ^(If there is no
+** explicitly declared [INTEGER PRIMARY KEY] column, then the output
+** parameters are set as follows:
+**
+** <pre>
+** data type: "INTEGER"
+** collation sequence: "BINARY"
+** not null: 0
+** primary key: 1
+** auto increment: 0
+** </pre>)^
+**
+** ^(This function may load one or more schemas from database files. If an
+** error occurs during this process, or if the requested table or column
+** cannot be found, an [error code] is returned and an error message left
+** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^
+**
+** ^This API is only available if the library was compiled with the
+** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
+*/
+SQLITE_API int sqlite3_table_column_metadata(
+ sqlite3 *db, /* Connection handle */
+ const char *zDbName, /* Database name or NULL */
+ const char *zTableName, /* Table name */
+ const char *zColumnName, /* Column name */
+ char const **pzDataType, /* OUTPUT: Declared data type */
+ char const **pzCollSeq, /* OUTPUT: Collation sequence name */
+ int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
+ int *pPrimaryKey, /* OUTPUT: True if column part of PK */
+ int *pAutoinc /* OUTPUT: True if column is auto-increment */
+);
+
+/*
+** CAPI3REF: Load An Extension
+**
+** ^This interface loads an SQLite extension library from the named file.
+**
+** ^The sqlite3_load_extension() interface attempts to load an
+** SQLite extension library contained in the file zFile.
+**
+** ^The entry point is zProc.
+** ^zProc may be 0, in which case the name of the entry point
+** defaults to "sqlite3_extension_init".
+** ^The sqlite3_load_extension() interface returns
+** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
+** ^If an error occurs and pzErrMsg is not 0, then the
+** [sqlite3_load_extension()] interface shall attempt to
+** fill *pzErrMsg with error message text stored in memory
+** obtained from [sqlite3_malloc()]. The calling function
+** should free this memory by calling [sqlite3_free()].
+**
+** ^Extension loading must be enabled using
+** [sqlite3_enable_load_extension()] prior to calling this API,
+** otherwise an error will be returned.
+**
+** See also the [load_extension() SQL function].
+*/
+SQLITE_API int sqlite3_load_extension(
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Derived from zFile if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
+);
+
+/*
+** CAPI3REF: Enable Or Disable Extension Loading
+**
+** ^So as not to open security holes in older applications that are
+** unprepared to deal with extension loading, and as a means of disabling
+** extension loading while evaluating user-entered SQL, the following API
+** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
+**
+** ^Extension loading is off by default. See ticket #1863.
+** ^Call the sqlite3_enable_load_extension() routine with onoff==1
+** to turn extension loading on and call it with onoff==0 to turn
+** it back off again.
+*/
+SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+
+/*
+** CAPI3REF: Automatically Load Statically Linked Extensions
+**
+** ^This interface causes the xEntryPoint() function to be invoked for
+** each new [database connection] that is created. The idea here is that
+** xEntryPoint() is the entry point for a statically linked SQLite extension
+** that is to be automatically loaded into all new database connections.
+**
+** ^(Even though the function prototype shows that xEntryPoint() takes
+** no arguments and returns void, SQLite invokes xEntryPoint() with three
+** arguments and expects and integer result as if the signature of the
+** entry point where as follows:
+**
+** <blockquote><pre>
+** &nbsp; int xEntryPoint(
+** &nbsp; sqlite3 *db,
+** &nbsp; const char **pzErrMsg,
+** &nbsp; const struct sqlite3_api_routines *pThunk
+** &nbsp; );
+** </pre></blockquote>)^
+**
+** If the xEntryPoint routine encounters an error, it should make *pzErrMsg
+** point to an appropriate error message (obtained from [sqlite3_mprintf()])
+** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg
+** is NULL before calling the xEntryPoint(). ^SQLite will invoke
+** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any
+** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()],
+** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail.
+**
+** ^Calling sqlite3_auto_extension(X) with an entry point X that is already
+** on the list of automatic extensions is a harmless no-op. ^No entry point
+** will be called more than once for each database connection that is opened.
+**
+** See also: [sqlite3_reset_auto_extension()].
+*/
+SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
+
+/*
+** CAPI3REF: Reset Automatic Extension Loading
+**
+** ^This interface disables all automatic extensions previously
+** registered using [sqlite3_auto_extension()].
+*/
+SQLITE_API void sqlite3_reset_auto_extension(void);
+
+/*
+** The interface to the virtual-table mechanism is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stabilizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+*/
+
+/*
+** Structures used by the virtual table interface
+*/
+typedef struct sqlite3_vtab sqlite3_vtab;
+typedef struct sqlite3_index_info sqlite3_index_info;
+typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
+typedef struct sqlite3_module sqlite3_module;
+
+/*
+** CAPI3REF: Virtual Table Object
+** KEYWORDS: sqlite3_module {virtual table module}
+**
+** This structure, sometimes called a "virtual table module",
+** defines the implementation of a [virtual tables].
+** This structure consists mostly of methods for the module.
+**
+** ^A virtual table module is created by filling in a persistent
+** instance of this structure and passing a pointer to that instance
+** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
+** ^The registration remains valid until it is replaced by a different
+** module or until the [database connection] closes. The content
+** of this structure must not change while it is registered with
+** any database connection.
+*/
+struct sqlite3_module {
+ int iVersion;
+ int (*xCreate)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xConnect)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
+ int (*xDisconnect)(sqlite3_vtab *pVTab);
+ int (*xDestroy)(sqlite3_vtab *pVTab);
+ int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
+ int (*xClose)(sqlite3_vtab_cursor*);
+ int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv);
+ int (*xNext)(sqlite3_vtab_cursor*);
+ int (*xEof)(sqlite3_vtab_cursor*);
+ int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
+ int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
+ int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
+ int (*xBegin)(sqlite3_vtab *pVTab);
+ int (*xSync)(sqlite3_vtab *pVTab);
+ int (*xCommit)(sqlite3_vtab *pVTab);
+ int (*xRollback)(sqlite3_vtab *pVTab);
+ int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
+ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+ void **ppArg);
+ int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
+ /* The methods above are in version 1 of the sqlite_module object. Those
+ ** below are for version 2 and greater. */
+ int (*xSavepoint)(sqlite3_vtab *pVTab, int);
+ int (*xRelease)(sqlite3_vtab *pVTab, int);
+ int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+};
+
+/*
+** CAPI3REF: Virtual Table Indexing Information
+** KEYWORDS: sqlite3_index_info
+**
+** The sqlite3_index_info structure and its substructures is used as part
+** of the [virtual table] interface to
+** pass information into and receive the reply from the [xBestIndex]
+** method of a [virtual table module]. The fields under **Inputs** are the
+** inputs to xBestIndex and are read-only. xBestIndex inserts its
+** results into the **Outputs** fields.
+**
+** ^(The aConstraint[] array records WHERE clause constraints of the form:
+**
+** <blockquote>column OP expr</blockquote>
+**
+** where OP is =, &lt;, &lt;=, &gt;, or &gt;=.)^ ^(The particular operator is
+** stored in aConstraint[].op using one of the
+** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^
+** ^(The index of the column is stored in
+** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the
+** expr on the right-hand side can be evaluated (and thus the constraint
+** is usable) and false if it cannot.)^
+**
+** ^The optimizer automatically inverts terms of the form "expr OP column"
+** and makes other simplifications to the WHERE clause in an attempt to
+** get as many WHERE clause terms into the form shown above as possible.
+** ^The aConstraint[] array only reports WHERE clause terms that are
+** relevant to the particular virtual table being queried.
+**
+** ^Information about the ORDER BY clause is stored in aOrderBy[].
+** ^Each term of aOrderBy records a column of the ORDER BY clause.
+**
+** The [xBestIndex] method must fill aConstraintUsage[] with information
+** about what parameters to pass to xFilter. ^If argvIndex>0 then
+** the right-hand side of the corresponding aConstraint[] is evaluated
+** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
+** is true, then the constraint is assumed to be fully handled by the
+** virtual table and is not checked again by SQLite.)^
+**
+** ^The idxNum and idxPtr values are recorded and passed into the
+** [xFilter] method.
+** ^[sqlite3_free()] is used to free idxPtr if and only if
+** needToFreeIdxPtr is true.
+**
+** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in
+** the correct order to satisfy the ORDER BY clause so that no separate
+** sorting step is required.
+**
+** ^The estimatedCost value is an estimate of the cost of doing the
+** particular lookup. A full scan of a table with N entries should have
+** a cost of N. A binary search of a table of N entries should have a
+** cost of approximately log(N).
+*/
+struct sqlite3_index_info {
+ /* Inputs */
+ int nConstraint; /* Number of entries in aConstraint */
+ struct sqlite3_index_constraint {
+ int iColumn; /* Column on left-hand side of constraint */
+ unsigned char op; /* Constraint operator */
+ unsigned char usable; /* True if this constraint is usable */
+ int iTermOffset; /* Used internally - xBestIndex should ignore */
+ } *aConstraint; /* Table of WHERE clause constraints */
+ int nOrderBy; /* Number of terms in the ORDER BY clause */
+ struct sqlite3_index_orderby {
+ int iColumn; /* Column number */
+ unsigned char desc; /* True for DESC. False for ASC. */
+ } *aOrderBy; /* The ORDER BY clause */
+ /* Outputs */
+ struct sqlite3_index_constraint_usage {
+ int argvIndex; /* if >0, constraint is part of argv to xFilter */
+ unsigned char omit; /* Do not code a test for this constraint */
+ } *aConstraintUsage;
+ int idxNum; /* Number used to identify the index */
+ char *idxStr; /* String, possibly obtained from sqlite3_malloc */
+ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
+ int orderByConsumed; /* True if output is already ordered */
+ double estimatedCost; /* Estimated cost of using this index */
+};
+
+/*
+** CAPI3REF: Virtual Table Constraint Operator Codes
+**
+** These macros defined the allowed values for the
+** [sqlite3_index_info].aConstraint[].op field. Each value represents
+** an operator that is part of a constraint term in the wHERE clause of
+** a query that uses a [virtual table].
+*/
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+
+/*
+** CAPI3REF: Register A Virtual Table Implementation
+**
+** ^These routines are used to register a new [virtual table module] name.
+** ^Module names must be registered before
+** creating a new [virtual table] using the module and before using a
+** preexisting [virtual table] for the module.
+**
+** ^The module name is registered on the [database connection] specified
+** by the first parameter. ^The name of the module is given by the
+** second parameter. ^The third parameter is a pointer to
+** the implementation of the [virtual table module]. ^The fourth
+** parameter is an arbitrary client data pointer that is passed through
+** into the [xCreate] and [xConnect] methods of the virtual table module
+** when a new virtual table is be being created or reinitialized.
+**
+** ^The sqlite3_create_module_v2() interface has a fifth parameter which
+** is a pointer to a destructor for the pClientData. ^SQLite will
+** invoke the destructor function (if it is not NULL) when SQLite
+** no longer needs the pClientData pointer. ^The destructor will also
+** be invoked if the call to sqlite3_create_module_v2() fails.
+** ^The sqlite3_create_module()
+** interface is equivalent to sqlite3_create_module_v2() with a NULL
+** destructor.
+*/
+SQLITE_API int sqlite3_create_module(
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData /* Client data for xCreate/xConnect */
+);
+SQLITE_API int sqlite3_create_module_v2(
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData, /* Client data for xCreate/xConnect */
+ void(*xDestroy)(void*) /* Module destructor function */
+);
+
+/*
+** CAPI3REF: Virtual Table Instance Object
+** KEYWORDS: sqlite3_vtab
+**
+** Every [virtual table module] implementation uses a subclass
+** of this object to describe a particular instance
+** of the [virtual table]. Each subclass will
+** be tailored to the specific needs of the module implementation.
+** The purpose of this superclass is to define certain fields that are
+** common to all module implementations.
+**
+** ^Virtual tables methods can set an error message by assigning a
+** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should
+** take care that any prior string is freed by a call to [sqlite3_free()]
+** prior to assigning a new string to zErrMsg. ^After the error message
+** is delivered up to the client application, the string will be automatically
+** freed by sqlite3_free() and the zErrMsg field will be zeroed.
+*/
+struct sqlite3_vtab {
+ const sqlite3_module *pModule; /* The module for this virtual table */
+ int nRef; /* NO LONGER USED */
+ char *zErrMsg; /* Error message from sqlite3_mprintf() */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/*
+** CAPI3REF: Virtual Table Cursor Object
+** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
+**
+** Every [virtual table module] implementation uses a subclass of the
+** following structure to describe cursors that point into the
+** [virtual table] and are used
+** to loop through the virtual table. Cursors are created using the
+** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed
+** by the [sqlite3_module.xClose | xClose] method. Cursors are used
+** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
+** of the module. Each module implementation will define
+** the content of a cursor structure to suit its own needs.
+**
+** This superclass exists in order to define fields of the cursor that
+** are common to all implementations.
+*/
+struct sqlite3_vtab_cursor {
+ sqlite3_vtab *pVtab; /* Virtual table of this cursor */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/*
+** CAPI3REF: Declare The Schema Of A Virtual Table
+**
+** ^The [xCreate] and [xConnect] methods of a
+** [virtual table module] call this interface
+** to declare the format (the names and datatypes of the columns) of
+** the virtual tables they implement.
+*/
+SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+
+/*
+** CAPI3REF: Overload A Function For A Virtual Table
+**
+** ^(Virtual tables can provide alternative implementations of functions
+** using the [xFindFunction] method of the [virtual table module].
+** But global versions of those functions
+** must exist in order to be overloaded.)^
+**
+** ^(This API makes sure a global version of a function with a particular
+** name and number of parameters exists. If no such function exists
+** before this API is called, a new function is created.)^ ^The implementation
+** of the new function always causes an exception to be thrown. So
+** the new function is not good for anything by itself. Its only
+** purpose is to be a placeholder function that can be overloaded
+** by a [virtual table].
+*/
+SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+
+/*
+** The interface to the virtual-table mechanism defined above (back up
+** to a comment remarkably similar to this one) is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stabilizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+*/
+
+/*
+** CAPI3REF: A Handle To An Open BLOB
+** KEYWORDS: {BLOB handle} {BLOB handles}
+**
+** An instance of this object represents an open BLOB on which
+** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
+** ^Objects of this type are created by [sqlite3_blob_open()]
+** and destroyed by [sqlite3_blob_close()].
+** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces
+** can be used to read or write small subsections of the BLOB.
+** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes.
+*/
+typedef struct sqlite3_blob sqlite3_blob;
+
+/*
+** CAPI3REF: Open A BLOB For Incremental I/O
+**
+** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
+** in row iRow, column zColumn, table zTable in database zDb;
+** in other words, the same BLOB that would be selected by:
+**
+** <pre>
+** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
+** </pre>)^
+**
+** ^If the flags parameter is non-zero, then the BLOB is opened for read
+** and write access. ^If it is zero, the BLOB is opened for read access.
+** ^It is not possible to open a column that is part of an index or primary
+** key for writing. ^If [foreign key constraints] are enabled, it is
+** not possible to open a column that is part of a [child key] for writing.
+**
+** ^Note that the database name is not the filename that contains
+** the database but rather the symbolic name of the database that
+** appears after the AS keyword when the database is connected using [ATTACH].
+** ^For the main database file, the database name is "main".
+** ^For TEMP tables, the database name is "temp".
+**
+** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written
+** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set
+** to be a null pointer.)^
+** ^This function sets the [database connection] error code and message
+** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related
+** functions. ^Note that the *ppBlob variable is always initialized in a
+** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob
+** regardless of the success or failure of this routine.
+**
+** ^(If the row that a BLOB handle points to is modified by an
+** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
+** then the BLOB handle is marked as "expired".
+** This is true if any column of the row is changed, even a column
+** other than the one the BLOB handle is open on.)^
+** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for
+** an expired BLOB handle fail with a return code of [SQLITE_ABORT].
+** ^(Changes written into a BLOB prior to the BLOB expiring are not
+** rolled back by the expiration of the BLOB. Such changes will eventually
+** commit if the transaction continues to completion.)^
+**
+** ^Use the [sqlite3_blob_bytes()] interface to determine the size of
+** the opened blob. ^The size of a blob may not be changed by this
+** interface. Use the [UPDATE] SQL command to change the size of a
+** blob.
+**
+** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
+** and the built-in [zeroblob] SQL function can be used, if desired,
+** to create an empty, zero-filled blob in which to read or write using
+** this interface.
+**
+** To avoid a resource leak, every open [BLOB handle] should eventually
+** be released by a call to [sqlite3_blob_close()].
+*/
+SQLITE_API int sqlite3_blob_open(
+ sqlite3*,
+ const char *zDb,
+ const char *zTable,
+ const char *zColumn,
+ sqlite3_int64 iRow,
+ int flags,
+ sqlite3_blob **ppBlob
+);
+
+/*
+** CAPI3REF: Move a BLOB Handle to a New Row
+**
+** ^This function is used to move an existing blob handle so that it points
+** to a different row of the same database table. ^The new row is identified
+** by the rowid value passed as the second argument. Only the row can be
+** changed. ^The database, table and column on which the blob handle is open
+** remain the same. Moving an existing blob handle to a new row can be
+** faster than closing the existing handle and opening a new one.
+**
+** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
+** it must exist and there must be either a blob or text value stored in
+** the nominated column.)^ ^If the new row is not present in the table, or if
+** it does not contain a blob or text value, or if another error occurs, an
+** SQLite error code is returned and the blob handle is considered aborted.
+** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or
+** [sqlite3_blob_reopen()] on an aborted blob handle immediately return
+** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle
+** always returns zero.
+**
+** ^This function sets the database handle error code and message.
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
+
+/*
+** CAPI3REF: Close A BLOB Handle
+**
+** ^Closes an open [BLOB handle].
+**
+** ^Closing a BLOB shall cause the current transaction to commit
+** if there are no other BLOBs, no pending prepared statements, and the
+** database connection is in [autocommit mode].
+** ^If any writes were made to the BLOB, they might be held in cache
+** until the close operation if they will fit.
+**
+** ^(Closing the BLOB often forces the changes
+** out to disk and so if any I/O errors occur, they will likely occur
+** at the time when the BLOB is closed. Any errors that occur during
+** closing are reported as a non-zero return value.)^
+**
+** ^(The BLOB is closed unconditionally. Even if this routine returns
+** an error code, the BLOB is still closed.)^
+**
+** ^Calling this routine with a null pointer (such as would be returned
+** by a failed call to [sqlite3_blob_open()]) is a harmless no-op.
+*/
+SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
+
+/*
+** CAPI3REF: Return The Size Of An Open BLOB
+**
+** ^Returns the size in bytes of the BLOB accessible via the
+** successfully opened [BLOB handle] in its only argument. ^The
+** incremental blob I/O routines can only read or overwriting existing
+** blob content; they cannot change the size of a blob.
+**
+** This routine only works on a [BLOB handle] which has been created
+** by a prior successful call to [sqlite3_blob_open()] and which has not
+** been closed by [sqlite3_blob_close()]. Passing any other pointer in
+** to this routine results in undefined and probably undesirable behavior.
+*/
+SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
+
+/*
+** CAPI3REF: Read Data From A BLOB Incrementally
+**
+** ^(This function is used to read data from an open [BLOB handle] into a
+** caller-supplied buffer. N bytes of data are copied into buffer Z
+** from the open BLOB, starting at offset iOffset.)^
+**
+** ^If offset iOffset is less than N bytes from the end of the BLOB,
+** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is
+** less than zero, [SQLITE_ERROR] is returned and no data is read.
+** ^The size of the blob (and hence the maximum value of N+iOffset)
+** can be determined using the [sqlite3_blob_bytes()] interface.
+**
+** ^An attempt to read from an expired [BLOB handle] fails with an
+** error code of [SQLITE_ABORT].
+**
+** ^(On success, sqlite3_blob_read() returns SQLITE_OK.
+** Otherwise, an [error code] or an [extended error code] is returned.)^
+**
+** This routine only works on a [BLOB handle] which has been created
+** by a prior successful call to [sqlite3_blob_open()] and which has not
+** been closed by [sqlite3_blob_close()]. Passing any other pointer in
+** to this routine results in undefined and probably undesirable behavior.
+**
+** See also: [sqlite3_blob_write()].
+*/
+SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
+
+/*
+** CAPI3REF: Write Data Into A BLOB Incrementally
+**
+** ^This function is used to write data into an open [BLOB handle] from a
+** caller-supplied buffer. ^N bytes of data are copied from the buffer Z
+** into the open BLOB, starting at offset iOffset.
+**
+** ^If the [BLOB handle] passed as the first argument was not opened for
+** writing (the flags parameter to [sqlite3_blob_open()] was zero),
+** this function returns [SQLITE_READONLY].
+**
+** ^This function may only modify the contents of the BLOB; it is
+** not possible to increase the size of a BLOB using this API.
+** ^If offset iOffset is less than N bytes from the end of the BLOB,
+** [SQLITE_ERROR] is returned and no data is written. ^If N is
+** less than zero [SQLITE_ERROR] is returned and no data is written.
+** The size of the BLOB (and hence the maximum value of N+iOffset)
+** can be determined using the [sqlite3_blob_bytes()] interface.
+**
+** ^An attempt to write to an expired [BLOB handle] fails with an
+** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred
+** before the [BLOB handle] expired are not rolled back by the
+** expiration of the handle, though of course those changes might
+** have been overwritten by the statement that expired the BLOB handle
+** or by other independent statements.
+**
+** ^(On success, sqlite3_blob_write() returns SQLITE_OK.
+** Otherwise, an [error code] or an [extended error code] is returned.)^
+**
+** This routine only works on a [BLOB handle] which has been created
+** by a prior successful call to [sqlite3_blob_open()] and which has not
+** been closed by [sqlite3_blob_close()]. Passing any other pointer in
+** to this routine results in undefined and probably undesirable behavior.
+**
+** See also: [sqlite3_blob_read()].
+*/
+SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
+
+/*
+** CAPI3REF: Virtual File System Objects
+**
+** A virtual filesystem (VFS) is an [sqlite3_vfs] object
+** that SQLite uses to interact
+** with the underlying operating system. Most SQLite builds come with a
+** single default VFS that is appropriate for the host computer.
+** New VFSes can be registered and existing VFSes can be unregistered.
+** The following interfaces are provided.
+**
+** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name.
+** ^Names are case sensitive.
+** ^Names are zero-terminated UTF-8 strings.
+** ^If there is no match, a NULL pointer is returned.
+** ^If zVfsName is NULL then the default VFS is returned.
+**
+** ^New VFSes are registered with sqlite3_vfs_register().
+** ^Each new VFS becomes the default VFS if the makeDflt flag is set.
+** ^The same VFS can be registered multiple times without injury.
+** ^To make an existing VFS into the default VFS, register it again
+** with the makeDflt flag set. If two different VFSes with the
+** same name are registered, the behavior is undefined. If a
+** VFS is registered with a name that is NULL or an empty string,
+** then the behavior is undefined.
+**
+** ^Unregister a VFS with the sqlite3_vfs_unregister() interface.
+** ^(If the default VFS is unregistered, another VFS is chosen as
+** the default. The choice for the new VFS is arbitrary.)^
+*/
+SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
+SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
+SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
+
+/*
+** CAPI3REF: Mutexes
+**
+** The SQLite core uses these routines for thread
+** synchronization. Though they are intended for internal
+** use by SQLite, code that links against SQLite is
+** permitted to use any of these routines.
+**
+** The SQLite source code contains multiple implementations
+** of these mutex routines. An appropriate implementation
+** is selected automatically at compile-time. ^(The following
+** implementations are available in the SQLite core:
+**
+** <ul>
+** <li> SQLITE_MUTEX_PTHREADS
+** <li> SQLITE_MUTEX_W32
+** <li> SQLITE_MUTEX_NOOP
+** </ul>)^
+**
+** ^The SQLITE_MUTEX_NOOP implementation is a set of routines
+** that does no real locking and is appropriate for use in
+** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and
+** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
+** and Windows.
+**
+** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
+** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
+** implementation is included with the library. In this case the
+** application must supply a custom mutex implementation using the
+** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
+** before calling sqlite3_initialize() or any other public sqlite3_
+** function that calls sqlite3_initialize().)^
+**
+** ^The sqlite3_mutex_alloc() routine allocates a new
+** mutex and returns a pointer to it. ^If it returns NULL
+** that means that a mutex could not be allocated. ^SQLite
+** will unwind its stack and return an error. ^(The argument
+** to sqlite3_mutex_alloc() is one of these integer constants:
+**
+** <ul>
+** <li> SQLITE_MUTEX_FAST
+** <li> SQLITE_MUTEX_RECURSIVE
+** <li> SQLITE_MUTEX_STATIC_MASTER
+** <li> SQLITE_MUTEX_STATIC_MEM
+** <li> SQLITE_MUTEX_STATIC_MEM2
+** <li> SQLITE_MUTEX_STATIC_PRNG
+** <li> SQLITE_MUTEX_STATIC_LRU
+** <li> SQLITE_MUTEX_STATIC_LRU2
+** </ul>)^
+**
+** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
+** cause sqlite3_mutex_alloc() to create
+** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
+** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
+** The mutex implementation does not need to make a distinction
+** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
+** not want to. ^SQLite will only request a recursive mutex in
+** cases where it really needs one. ^If a faster non-recursive mutex
+** implementation is available on the host platform, the mutex subsystem
+** might return such a mutex in response to SQLITE_MUTEX_FAST.
+**
+** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other
+** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
+** a pointer to a static preexisting mutex. ^Six static mutexes are
+** used by the current version of SQLite. Future versions of SQLite
+** may add additional static mutexes. Static mutexes are for internal
+** use by SQLite only. Applications that use SQLite mutexes should
+** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
+** SQLITE_MUTEX_RECURSIVE.
+**
+** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
+** returns a different mutex on every call. ^But for the static
+** mutex types, the same mutex is returned on every call that has
+** the same type number.
+**
+** ^The sqlite3_mutex_free() routine deallocates a previously
+** allocated dynamic mutex. ^SQLite is careful to deallocate every
+** dynamic mutex that it allocates. The dynamic mutexes must not be in
+** use when they are deallocated. Attempting to deallocate a static
+** mutex results in undefined behavior. ^SQLite never deallocates
+** a static mutex.
+**
+** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+** to enter a mutex. ^If another thread is already within the mutex,
+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK]
+** upon successful entry. ^(Mutexes created using
+** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread.
+** In such cases the,
+** mutex must be exited an equal number of times before another thread
+** can enter.)^ ^(If the same thread tries to enter any other
+** kind of mutex more than once, the behavior is undefined.
+** SQLite will never exhibit
+** such behavior in its own use of mutexes.)^
+**
+** ^(Some systems (for example, Windows 95) do not support the operation
+** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
+** will always return SQLITE_BUSY. The SQLite core only ever uses
+** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^
+**
+** ^The sqlite3_mutex_leave() routine exits a mutex that was
+** previously entered by the same thread. ^(The behavior
+** is undefined if the mutex is not currently entered by the
+** calling thread or is not currently allocated. SQLite will
+** never do either.)^
+**
+** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
+** sqlite3_mutex_leave() is a NULL pointer, then all three routines
+** behave as no-ops.
+**
+** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
+*/
+SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
+SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
+SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
+SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
+SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
+
+/*
+** CAPI3REF: Mutex Methods Object
+**
+** An instance of this structure defines the low-level routines
+** used to allocate and use mutexes.
+**
+** Usually, the default mutex implementations provided by SQLite are
+** sufficient, however the user has the option of substituting a custom
+** implementation for specialized deployments or systems for which SQLite
+** does not provide a suitable implementation. In this case, the user
+** creates and populates an instance of this structure to pass
+** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option.
+** Additionally, an instance of this structure can be used as an
+** output variable when querying the system for the current mutex
+** implementation, using the [SQLITE_CONFIG_GETMUTEX] option.
+**
+** ^The xMutexInit method defined by this structure is invoked as
+** part of system initialization by the sqlite3_initialize() function.
+** ^The xMutexInit routine is called by SQLite exactly once for each
+** effective call to [sqlite3_initialize()].
+**
+** ^The xMutexEnd method defined by this structure is invoked as
+** part of system shutdown by the sqlite3_shutdown() function. The
+** implementation of this method is expected to release all outstanding
+** resources obtained by the mutex methods implementation, especially
+** those obtained by the xMutexInit method. ^The xMutexEnd()
+** interface is invoked exactly once for each call to [sqlite3_shutdown()].
+**
+** ^(The remaining seven methods defined by this structure (xMutexAlloc,
+** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and
+** xMutexNotheld) implement the following interfaces (respectively):
+**
+** <ul>
+** <li> [sqlite3_mutex_alloc()] </li>
+** <li> [sqlite3_mutex_free()] </li>
+** <li> [sqlite3_mutex_enter()] </li>
+** <li> [sqlite3_mutex_try()] </li>
+** <li> [sqlite3_mutex_leave()] </li>
+** <li> [sqlite3_mutex_held()] </li>
+** <li> [sqlite3_mutex_notheld()] </li>
+** </ul>)^
+**
+** The only difference is that the public sqlite3_XXX functions enumerated
+** above silently ignore any invocations that pass a NULL pointer instead
+** of a valid mutex handle. The implementations of the methods defined
+** by this structure are not required to handle this case, the results
+** of passing a NULL pointer instead of a valid mutex handle are undefined
+** (i.e. it is acceptable to provide an implementation that segfaults if
+** it is passed a NULL pointer).
+**
+** The xMutexInit() method must be threadsafe. ^It must be harmless to
+** invoke xMutexInit() multiple times within the same process and without
+** intervening calls to xMutexEnd(). Second and subsequent calls to
+** xMutexInit() must be no-ops.
+**
+** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()]
+** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory
+** allocation for a static mutex. ^However xMutexAlloc() may use SQLite
+** memory allocation for a fast or recursive mutex.
+**
+** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is
+** called, but only if the prior call to xMutexInit returned SQLITE_OK.
+** If xMutexInit fails in any way, it is expected to clean up after itself
+** prior to returning.
+*/
+typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
+struct sqlite3_mutex_methods {
+ int (*xMutexInit)(void);
+ int (*xMutexEnd)(void);
+ sqlite3_mutex *(*xMutexAlloc)(int);
+ void (*xMutexFree)(sqlite3_mutex *);
+ void (*xMutexEnter)(sqlite3_mutex *);
+ int (*xMutexTry)(sqlite3_mutex *);
+ void (*xMutexLeave)(sqlite3_mutex *);
+ int (*xMutexHeld)(sqlite3_mutex *);
+ int (*xMutexNotheld)(sqlite3_mutex *);
+};
+
+/*
+** CAPI3REF: Mutex Verification Routines
+**
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines
+** are intended for use inside assert() statements. ^The SQLite core
+** never uses these routines except inside an assert() and applications
+** are advised to follow the lead of the core. ^The SQLite core only
+** provides implementations for these routines when it is compiled
+** with the SQLITE_DEBUG flag. ^External mutex implementations
+** are only required to provide these routines if SQLITE_DEBUG is
+** defined and if NDEBUG is not defined.
+**
+** ^These routines should return true if the mutex in their argument
+** is held or not held, respectively, by the calling thread.
+**
+** ^The implementation is not required to provide versions of these
+** routines that actually work. If the implementation does not provide working
+** versions of these routines, it should at least provide stubs that always
+** return true so that one does not get spurious assertion failures.
+**
+** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
+** the routine should return 1. This seems counter-intuitive since
+** clearly the mutex cannot be held if it does not exist. But
+** the reason the mutex does not exist is because the build is not
+** using mutexes. And we do not want the assert() containing the
+** call to sqlite3_mutex_held() to fail, so a non-zero return is
+** the appropriate thing to do. ^The sqlite3_mutex_notheld()
+** interface should also return 1 when given a NULL pointer.
+*/
+#ifndef NDEBUG
+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
+SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
+#endif
+
+/*
+** CAPI3REF: Mutex Types
+**
+** The [sqlite3_mutex_alloc()] interface takes a single argument
+** which is one of these integer constants.
+**
+** The set of static mutexes may change from one SQLite release to the
+** next. Applications that override the built-in mutex logic must be
+** prepared to accommodate additional static mutexes.
+*/
+#define SQLITE_MUTEX_FAST 0
+#define SQLITE_MUTEX_RECURSIVE 1
+#define SQLITE_MUTEX_STATIC_MASTER 2
+#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
+#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
+#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
+#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
+#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
+#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
+#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
+
+/*
+** CAPI3REF: Retrieve the mutex for a database connection
+**
+** ^This interface returns a pointer the [sqlite3_mutex] object that
+** serializes access to the [database connection] given in the argument
+** when the [threading mode] is Serialized.
+** ^If the [threading mode] is Single-thread or Multi-thread then this
+** routine returns a NULL pointer.
+*/
+SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+
+/*
+** CAPI3REF: Low-Level Control Of Database Files
+**
+** ^The [sqlite3_file_control()] interface makes a direct call to the
+** xFileControl method for the [sqlite3_io_methods] object associated
+** with a particular database identified by the second argument. ^The
+** name of the database is "main" for the main database or "temp" for the
+** TEMP database, or the name that appears after the AS keyword for
+** databases that are added using the [ATTACH] SQL command.
+** ^A NULL pointer can be used in place of "main" to refer to the
+** main database file.
+** ^The third and fourth parameters to this routine
+** are passed directly through to the second and third parameters of
+** the xFileControl method. ^The return value of the xFileControl
+** method becomes the return value of this routine.
+**
+** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes
+** a pointer to the underlying [sqlite3_file] object to be written into
+** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER
+** case is a short-circuit path which does not actually invoke the
+** underlying sqlite3_io_methods.xFileControl method.
+**
+** ^If the second parameter (zDbName) does not match the name of any
+** open database file, then SQLITE_ERROR is returned. ^This error
+** code is not remembered and will not be recalled by [sqlite3_errcode()]
+** or [sqlite3_errmsg()]. The underlying xFileControl method might
+** also return SQLITE_ERROR. There is no way to distinguish between
+** an incorrect zDbName and an SQLITE_ERROR return from the underlying
+** xFileControl method.
+**
+** See also: [SQLITE_FCNTL_LOCKSTATE]
+*/
+SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+
+/*
+** CAPI3REF: Testing Interface
+**
+** ^The sqlite3_test_control() interface is used to read out internal
+** state of SQLite and to inject faults into SQLite for testing
+** purposes. ^The first parameter is an operation code that determines
+** the number, meaning, and operation of all subsequent parameters.
+**
+** This interface is not for use by applications. It exists solely
+** for verifying the correct operation of the SQLite library. Depending
+** on how the SQLite library is compiled, this interface might not exist.
+**
+** The details of the operation codes, their meanings, the parameters
+** they take, and what they do are all subject to change without notice.
+** Unlike most of the SQLite API, this function is not guaranteed to
+** operate consistently from one release to the next.
+*/
+SQLITE_API int sqlite3_test_control(int op, ...);
+
+/*
+** CAPI3REF: Testing Interface Operation Codes
+**
+** These constants are the valid operation code parameters used
+** as the first argument to [sqlite3_test_control()].
+**
+** These parameters and their meanings are subject to change
+** without notice. These values are for testing purposes only.
+** Applications should not use any of these parameters or the
+** [sqlite3_test_control()] interface.
+*/
+#define SQLITE_TESTCTRL_FIRST 5
+#define SQLITE_TESTCTRL_PRNG_SAVE 5
+#define SQLITE_TESTCTRL_PRNG_RESTORE 6
+#define SQLITE_TESTCTRL_PRNG_RESET 7
+#define SQLITE_TESTCTRL_BITVEC_TEST 8
+#define SQLITE_TESTCTRL_FAULT_INSTALL 9
+#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
+#define SQLITE_TESTCTRL_PENDING_BYTE 11
+#define SQLITE_TESTCTRL_ASSERT 12
+#define SQLITE_TESTCTRL_ALWAYS 13
+#define SQLITE_TESTCTRL_RESERVE 14
+#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
+#define SQLITE_TESTCTRL_ISKEYWORD 16
+#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
+#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
+#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
+#define SQLITE_TESTCTRL_LAST 19
+
+/*
+** CAPI3REF: SQLite Runtime Status
+**
+** ^This interface is used to retrieve runtime status information
+** about the performance of SQLite, and optionally to reset various
+** highwater marks. ^The first argument is an integer code for
+** the specific parameter to measure. ^(Recognized integer codes
+** are of the form [status parameters | SQLITE_STATUS_...].)^
+** ^The current value of the parameter is returned into *pCurrent.
+** ^The highest recorded value is returned in *pHighwater. ^If the
+** resetFlag is true, then the highest record value is reset after
+** *pHighwater is written. ^(Some parameters do not record the highest
+** value. For those parameters
+** nothing is written into *pHighwater and the resetFlag is ignored.)^
+** ^(Other parameters record only the highwater mark and not the current
+** value. For these latter parameters nothing is written into *pCurrent.)^
+**
+** ^The sqlite3_status() routine returns SQLITE_OK on success and a
+** non-zero [error code] on failure.
+**
+** This routine is threadsafe but is not atomic. This routine can be
+** called while other threads are running the same or different SQLite
+** interfaces. However the values returned in *pCurrent and
+** *pHighwater reflect the status of SQLite at different points in time
+** and it is possible that another thread might change the parameter
+** in between the times when *pCurrent and *pHighwater are written.
+**
+** See also: [sqlite3_db_status()]
+*/
+SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+
+
+/*
+** CAPI3REF: Status Parameters
+** KEYWORDS: {status parameters}
+**
+** These integer constants designate various run-time status parameters
+** that can be returned by [sqlite3_status()].
+**
+** <dl>
+** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
+** <dd>This parameter is the current amount of memory checked out
+** using [sqlite3_malloc()], either directly or indirectly. The
+** figure includes calls made to [sqlite3_malloc()] by the application
+** and internal memory usage by the SQLite library. Scratch memory
+** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
+** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
+** this parameter. The amount returned is the sum of the allocation
+** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
+**
+** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
+** internal equivalents). Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>)^
+**
+** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
+** <dd>This parameter records the number of separate memory allocations
+** currently checked out.</dd>)^
+**
+** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
+** <dd>This parameter returns the number of pages used out of the
+** [pagecache memory allocator] that was configured using
+** [SQLITE_CONFIG_PAGECACHE]. The
+** value returned is in pages, not in bytes.</dd>)^
+**
+** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
+** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
+** <dd>This parameter returns the number of bytes of page cache
+** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
+** buffer and where forced to overflow to [sqlite3_malloc()]. The
+** returned value includes allocations that overflowed because they
+** where too large (they were larger than the "sz" parameter to
+** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
+** no space was left in the page cache.</dd>)^
+**
+** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [pagecache memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>)^
+**
+** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
+** <dd>This parameter returns the number of allocations used out of the
+** [scratch memory allocator] configured using
+** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
+** in bytes. Since a single thread may only have one scratch allocation
+** outstanding at time, this parameter also reports the number of threads
+** using scratch memory at the same time.</dd>)^
+**
+** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
+** <dd>This parameter returns the number of bytes of scratch memory
+** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
+** buffer and where forced to overflow to [sqlite3_malloc()]. The values
+** returned include overflows because the requested allocation was too
+** larger (that is, because the requested allocation was larger than the
+** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
+** slots were available.
+** </dd>)^
+**
+** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [scratch memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>)^
+**
+** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
+** <dd>This parameter records the deepest parser stack. It is only
+** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
+** </dl>
+**
+** New status parameters may be added from time to time.
+*/
+#define SQLITE_STATUS_MEMORY_USED 0
+#define SQLITE_STATUS_PAGECACHE_USED 1
+#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
+#define SQLITE_STATUS_SCRATCH_USED 3
+#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
+#define SQLITE_STATUS_MALLOC_SIZE 5
+#define SQLITE_STATUS_PARSER_STACK 6
+#define SQLITE_STATUS_PAGECACHE_SIZE 7
+#define SQLITE_STATUS_SCRATCH_SIZE 8
+#define SQLITE_STATUS_MALLOC_COUNT 9
+
+/*
+** CAPI3REF: Database Connection Status
+**
+** ^This interface is used to retrieve runtime status information
+** about a single [database connection]. ^The first argument is the
+** database connection object to be interrogated. ^The second argument
+** is an integer constant, taken from the set of
+** [SQLITE_DBSTATUS options], that
+** determines the parameter to interrogate. The set of
+** [SQLITE_DBSTATUS options] is likely
+** to grow in future releases of SQLite.
+**
+** ^The current value of the requested parameter is written into *pCur
+** and the highest instantaneous value is written into *pHiwtr. ^If
+** the resetFlg is true, then the highest instantaneous value is
+** reset back down to the current value.
+**
+** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a
+** non-zero [error code] on failure.
+**
+** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
+*/
+SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters for database connections
+** KEYWORDS: {SQLITE_DBSTATUS options}
+**
+** These constants are the available integer "verbs" that can be passed as
+** the second argument to the [sqlite3_db_status()] interface.
+**
+** New verbs may be added in future releases of SQLite. Existing verbs
+** might be discontinued. Applications should check the return code from
+** [sqlite3_db_status()] to make sure that the call worked.
+** The [sqlite3_db_status()] interface will return a non-zero error code
+** if a discontinued or unsupported verb is invoked.
+**
+** <dl>
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
+** <dd>This parameter returns the number of lookaside memory slots currently
+** checked out.</dd>)^
+**
+** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
+** <dd>This parameter returns the number malloc attempts that were
+** satisfied using lookaside memory. Only the high-water value is meaningful;
+** the current value is always zero.)^
+**
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
+** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
+** <dd>This parameter returns the number malloc attempts that might have
+** been satisfied using lookaside memory but failed due to the amount of
+** memory requested being larger than the lookaside slot size.
+** Only the high-water value is meaningful;
+** the current value is always zero.)^
+**
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
+** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
+** <dd>This parameter returns the number malloc attempts that might have
+** been satisfied using lookaside memory but failed due to all lookaside
+** memory already being in use.
+** Only the high-water value is meaningful;
+** the current value is always zero.)^
+**
+** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
+** <dd>This parameter returns the approximate number of of bytes of heap
+** memory used by all pager caches associated with the database connection.)^
+** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
+**
+** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
+** <dd>This parameter returns the approximate number of of bytes of heap
+** memory used to store the schema for all databases associated
+** with the connection - main, temp, and any [ATTACH]-ed databases.)^
+** ^The full amount of memory used by the schemas is reported, even if the
+** schema memory is shared with other database connections due to
+** [shared cache mode] being enabled.
+** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
+**
+** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
+** <dd>This parameter returns the approximate number of of bytes of heap
+** and lookaside memory used by all prepared statements associated with
+** the database connection.)^
+** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
+** <dd>This parameter returns the number of pager cache hits that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
+** is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
+** <dd>This parameter returns the number of pager cache misses that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
+** is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
+** <dd>This parameter returns the number of dirty cache entries that have
+** been written to disk. Specifically, the number of pages written to the
+** wal file in wal mode databases, or the number of pages written to the
+** database file in rollback mode databases. Any pages written as part of
+** transaction rollback or database recovery operations are not included.
+** If an IO or other error occurs while writing a page to disk, the effect
+** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
+** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
+** </dd>
+** </dl>
+*/
+#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
+#define SQLITE_DBSTATUS_CACHE_USED 1
+#define SQLITE_DBSTATUS_SCHEMA_USED 2
+#define SQLITE_DBSTATUS_STMT_USED 3
+#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
+#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
+#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
+#define SQLITE_DBSTATUS_CACHE_HIT 7
+#define SQLITE_DBSTATUS_CACHE_MISS 8
+#define SQLITE_DBSTATUS_CACHE_WRITE 9
+#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
+
+
+/*
+** CAPI3REF: Prepared Statement Status
+**
+** ^(Each prepared statement maintains various
+** [SQLITE_STMTSTATUS counters] that measure the number
+** of times it has performed specific operations.)^ These counters can
+** be used to monitor the performance characteristics of the prepared
+** statements. For example, if the number of table steps greatly exceeds
+** the number of table searches or result rows, that would tend to indicate
+** that the prepared statement is using a full table scan rather than
+** an index.
+**
+** ^(This interface is used to retrieve and reset counter values from
+** a [prepared statement]. The first argument is the prepared statement
+** object to be interrogated. The second argument
+** is an integer code for a specific [SQLITE_STMTSTATUS counter]
+** to be interrogated.)^
+** ^The current value of the requested counter is returned.
+** ^If the resetFlg is true, then the counter is reset to zero after this
+** interface call returns.
+**
+** See also: [sqlite3_status()] and [sqlite3_db_status()].
+*/
+SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters for prepared statements
+** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
+**
+** These preprocessor macros define integer codes that name counter
+** values associated with the [sqlite3_stmt_status()] interface.
+** The meanings of the various counters are as follows:
+**
+** <dl>
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
+** <dd>^This is the number of times that SQLite has stepped forward in
+** a table as part of a full table scan. Large numbers for this counter
+** may indicate opportunities for performance improvement through
+** careful use of indices.</dd>
+**
+** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
+** <dd>^This is the number of sort operations that have occurred.
+** A non-zero value in this counter may indicate an opportunity to
+** improvement performance through careful use of indices.</dd>
+**
+** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
+** <dd>^This is the number of rows inserted into transient indices that
+** were created automatically in order to help joins run faster.
+** A non-zero value in this counter may indicate an opportunity to
+** improvement performance by adding permanent indices that do not
+** need to be reinitialized each time the statement is run.</dd>
+** </dl>
+*/
+#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
+#define SQLITE_STMTSTATUS_SORT 2
+#define SQLITE_STMTSTATUS_AUTOINDEX 3
+
+/*
+** CAPI3REF: Custom Page Cache Object
+**
+** The sqlite3_pcache type is opaque. It is implemented by
+** the pluggable module. The SQLite core has no knowledge of
+** its size or internal structure and never deals with the
+** sqlite3_pcache object except by holding and passing pointers
+** to the object.
+**
+** See [sqlite3_pcache_methods2] for additional information.
+*/
+typedef struct sqlite3_pcache sqlite3_pcache;
+
+/*
+** CAPI3REF: Custom Page Cache Object
+**
+** The sqlite3_pcache_page object represents a single page in the
+** page cache. The page cache will allocate instances of this
+** object. Various methods of the page cache use pointers to instances
+** of this object as parameters or as their return value.
+**
+** See [sqlite3_pcache_methods2] for additional information.
+*/
+typedef struct sqlite3_pcache_page sqlite3_pcache_page;
+struct sqlite3_pcache_page {
+ void *pBuf; /* The content of the page */
+ void *pExtra; /* Extra information associated with the page */
+};
+
+/*
+** CAPI3REF: Application Defined Page Cache.
+** KEYWORDS: {page cache}
+**
+** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
+** register an alternative page cache implementation by passing in an
+** instance of the sqlite3_pcache_methods2 structure.)^
+** In many applications, most of the heap memory allocated by
+** SQLite is used for the page cache.
+** By implementing a
+** custom page cache using this API, an application can better control
+** the amount of memory consumed by SQLite, the way in which
+** that memory is allocated and released, and the policies used to
+** determine exactly which parts of a database file are cached and for
+** how long.
+**
+** The alternative page cache mechanism is an
+** extreme measure that is only needed by the most demanding applications.
+** The built-in page cache is recommended for most uses.
+**
+** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an
+** internal buffer by SQLite within the call to [sqlite3_config]. Hence
+** the application may discard the parameter after the call to
+** [sqlite3_config()] returns.)^
+**
+** [[the xInit() page cache method]]
+** ^(The xInit() method is called once for each effective
+** call to [sqlite3_initialize()])^
+** (usually only once during the lifetime of the process). ^(The xInit()
+** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
+** The intent of the xInit() method is to set up global data structures
+** required by the custom page cache implementation.
+** ^(If the xInit() method is NULL, then the
+** built-in default page cache is used instead of the application defined
+** page cache.)^
+**
+** [[the xShutdown() page cache method]]
+** ^The xShutdown() method is called by [sqlite3_shutdown()].
+** It can be used to clean up
+** any outstanding resources before process shutdown, if required.
+** ^The xShutdown() method may be NULL.
+**
+** ^SQLite automatically serializes calls to the xInit method,
+** so the xInit method need not be threadsafe. ^The
+** xShutdown method is only called from [sqlite3_shutdown()] so it does
+** not need to be threadsafe either. All other methods must be threadsafe
+** in multithreaded applications.
+**
+** ^SQLite will never invoke xInit() more than once without an intervening
+** call to xShutdown().
+**
+** [[the xCreate() page cache methods]]
+** ^SQLite invokes the xCreate() method to construct a new cache instance.
+** SQLite will typically create one cache instance for each open database file,
+** though this is not guaranteed. ^The
+** first parameter, szPage, is the size in bytes of the pages that must
+** be allocated by the cache. ^szPage will always a power of two. ^The
+** second parameter szExtra is a number of bytes of extra storage
+** associated with each page cache entry. ^The szExtra parameter will
+** a number less than 250. SQLite will use the
+** extra szExtra bytes on each page to store metadata about the underlying
+** database page on disk. The value passed into szExtra depends
+** on the SQLite version, the target platform, and how SQLite was compiled.
+** ^The third argument to xCreate(), bPurgeable, is true if the cache being
+** created will be used to cache database pages of a file stored on disk, or
+** false if it is used for an in-memory database. The cache implementation
+** does not have to do anything special based with the value of bPurgeable;
+** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
+** never invoke xUnpin() except to deliberately delete a page.
+** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
+** false will always have the "discard" flag set to true.
+** ^Hence, a cache created with bPurgeable false will
+** never contain any unpinned pages.
+**
+** [[the xCachesize() page cache method]]
+** ^(The xCachesize() method may be called at any time by SQLite to set the
+** suggested maximum cache-size (number of pages stored by) the cache
+** instance passed as the first argument. This is the value configured using
+** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
+** parameter, the implementation is not required to do anything with this
+** value; it is advisory only.
+**
+** [[the xPagecount() page cache methods]]
+** The xPagecount() method must return the number of pages currently
+** stored in the cache, both pinned and unpinned.
+**
+** [[the xFetch() page cache methods]]
+** The xFetch() method locates a page in the cache and returns a pointer to
+** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
+** The pBuf element of the returned sqlite3_pcache_page object will be a
+** pointer to a buffer of szPage bytes used to store the content of a
+** single database page. The pExtra element of sqlite3_pcache_page will be
+** a pointer to the szExtra bytes of extra storage that SQLite has requested
+** for each entry in the page cache.
+**
+** The page to be fetched is determined by the key. ^The minimum key value
+** is 1. After it has been retrieved using xFetch, the page is considered
+** to be "pinned".
+**
+** If the requested page is already in the page cache, then the page cache
+** implementation must return a pointer to the page buffer with its content
+** intact. If the requested page is not already in the cache, then the
+** cache implementation should use the value of the createFlag
+** parameter to help it determined what action to take:
+**
+** <table border=1 width=85% align=center>
+** <tr><th> createFlag <th> Behavior when page is not already in cache
+** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
+** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
+** Otherwise return NULL.
+** <tr><td> 2 <td> Make every effort to allocate a new page. Only return
+** NULL if allocating a new page is effectively impossible.
+** </table>
+**
+** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
+** will only use a createFlag of 2 after a prior call with a createFlag of 1
+** failed.)^ In between the to xFetch() calls, SQLite may
+** attempt to unpin one or more cache pages by spilling the content of
+** pinned pages to disk and synching the operating system disk cache.
+**
+** [[the xUnpin() page cache method]]
+** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
+** as its second argument. If the third parameter, discard, is non-zero,
+** then the page must be evicted from the cache.
+** ^If the discard parameter is
+** zero, then the page may be discarded or retained at the discretion of
+** page cache implementation. ^The page cache implementation
+** may choose to evict unpinned pages at any time.
+**
+** The cache must not perform any reference counting. A single
+** call to xUnpin() unpins the page regardless of the number of prior calls
+** to xFetch().
+**
+** [[the xRekey() page cache methods]]
+** The xRekey() method is used to change the key value associated with the
+** page passed as the second argument. If the cache
+** previously contains an entry associated with newKey, it must be
+** discarded. ^Any prior cache entry associated with newKey is guaranteed not
+** to be pinned.
+**
+** When SQLite calls the xTruncate() method, the cache must discard all
+** existing cache entries with page numbers (keys) greater than or equal
+** to the value of the iLimit parameter passed to xTruncate(). If any
+** of these pages are pinned, they are implicitly unpinned, meaning that
+** they can be safely discarded.
+**
+** [[the xDestroy() page cache method]]
+** ^The xDestroy() method is used to delete a cache allocated by xCreate().
+** All resources associated with the specified cache should be freed. ^After
+** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
+** handle invalid, and will not use it with any other sqlite3_pcache_methods2
+** functions.
+**
+** [[the xShrink() page cache method]]
+** ^SQLite invokes the xShrink() method when it wants the page cache to
+** free up as much of heap memory as possible. The page cache implementation
+** is not obligated to free any memory, but well-behaved implementations should
+** do their best.
+*/
+typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
+struct sqlite3_pcache_methods2 {
+ int iVersion;
+ void *pArg;
+ int (*xInit)(void*);
+ void (*xShutdown)(void*);
+ sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
+ void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+ int (*xPagecount)(sqlite3_pcache*);
+ sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+ void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
+ void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
+ unsigned oldKey, unsigned newKey);
+ void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+ void (*xDestroy)(sqlite3_pcache*);
+ void (*xShrink)(sqlite3_pcache*);
+};
+
+/*
+** This is the obsolete pcache_methods object that has now been replaced
+** by sqlite3_pcache_methods2. This object is not used by SQLite. It is
+** retained in the header file for backwards compatibility only.
+*/
+typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
+struct sqlite3_pcache_methods {
+ void *pArg;
+ int (*xInit)(void*);
+ void (*xShutdown)(void*);
+ sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
+ void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+ int (*xPagecount)(sqlite3_pcache*);
+ void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+ void (*xUnpin)(sqlite3_pcache*, void*, int discard);
+ void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
+ void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+ void (*xDestroy)(sqlite3_pcache*);
+};
+
+
+/*
+** CAPI3REF: Online Backup Object
+**
+** The sqlite3_backup object records state information about an ongoing
+** online backup operation. ^The sqlite3_backup object is created by
+** a call to [sqlite3_backup_init()] and is destroyed by a call to
+** [sqlite3_backup_finish()].
+**
+** See Also: [Using the SQLite Online Backup API]
+*/
+typedef struct sqlite3_backup sqlite3_backup;
+
+/*
+** CAPI3REF: Online Backup API.
+**
+** The backup API copies the content of one database into another.
+** It is useful either for creating backups of databases or
+** for copying in-memory databases to or from persistent files.
+**
+** See Also: [Using the SQLite Online Backup API]
+**
+** ^SQLite holds a write transaction open on the destination database file
+** for the duration of the backup operation.
+** ^The source database is read-locked only while it is being read;
+** it is not locked continuously for the entire backup operation.
+** ^Thus, the backup may be performed on a live source database without
+** preventing other database connections from
+** reading or writing to the source database while the backup is underway.
+**
+** ^(To perform a backup operation:
+** <ol>
+** <li><b>sqlite3_backup_init()</b> is called once to initialize the
+** backup,
+** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
+** the data between the two databases, and finally
+** <li><b>sqlite3_backup_finish()</b> is called to release all resources
+** associated with the backup operation.
+** </ol>)^
+** There should be exactly one call to sqlite3_backup_finish() for each
+** successful call to sqlite3_backup_init().
+**
+** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
+**
+** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
+** [database connection] associated with the destination database
+** and the database name, respectively.
+** ^The database name is "main" for the main database, "temp" for the
+** temporary database, or the name specified after the AS keyword in
+** an [ATTACH] statement for an attached database.
+** ^The S and M arguments passed to
+** sqlite3_backup_init(D,N,S,M) identify the [database connection]
+** and database name of the source database, respectively.
+** ^The source and destination [database connections] (parameters S and D)
+** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
+** an error.
+**
+** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is
+** returned and an error code and error message are stored in the
+** destination [database connection] D.
+** ^The error code and message for the failed call to sqlite3_backup_init()
+** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or
+** [sqlite3_errmsg16()] functions.
+** ^A successful call to sqlite3_backup_init() returns a pointer to an
+** [sqlite3_backup] object.
+** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
+** sqlite3_backup_finish() functions to perform the specified backup
+** operation.
+**
+** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
+**
+** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
+** the source and destination databases specified by [sqlite3_backup] object B.
+** ^If N is negative, all remaining source pages are copied.
+** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
+** are still more pages to be copied, then the function returns [SQLITE_OK].
+** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
+** from source to destination, then it returns [SQLITE_DONE].
+** ^If an error occurs while running sqlite3_backup_step(B,N),
+** then an [error code] is returned. ^As well as [SQLITE_OK] and
+** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY],
+** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an
+** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code.
+**
+** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if
+** <ol>
+** <li> the destination database was opened read-only, or
+** <li> the destination database is using write-ahead-log journaling
+** and the destination and source page sizes differ, or
+** <li> the destination database is an in-memory database and the
+** destination and source page sizes differ.
+** </ol>)^
+**
+** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
+** the [sqlite3_busy_handler | busy-handler function]
+** is invoked (if one is specified). ^If the
+** busy-handler returns non-zero before the lock is available, then
+** [SQLITE_BUSY] is returned to the caller. ^In this case the call to
+** sqlite3_backup_step() can be retried later. ^If the source
+** [database connection]
+** is being used to write to the source database when sqlite3_backup_step()
+** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this
+** case the call to sqlite3_backup_step() can be retried later on. ^(If
+** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or
+** [SQLITE_READONLY] is returned, then
+** there is no point in retrying the call to sqlite3_backup_step(). These
+** errors are considered fatal.)^ The application must accept
+** that the backup operation has failed and pass the backup operation handle
+** to the sqlite3_backup_finish() to release associated resources.
+**
+** ^The first call to sqlite3_backup_step() obtains an exclusive lock
+** on the destination file. ^The exclusive lock is not released until either
+** sqlite3_backup_finish() is called or the backup operation is complete
+** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to
+** sqlite3_backup_step() obtains a [shared lock] on the source database that
+** lasts for the duration of the sqlite3_backup_step() call.
+** ^Because the source database is not locked between calls to
+** sqlite3_backup_step(), the source database may be modified mid-way
+** through the backup process. ^If the source database is modified by an
+** external process or via a database connection other than the one being
+** used by the backup operation, then the backup will be automatically
+** restarted by the next call to sqlite3_backup_step(). ^If the source
+** database is modified by the using the same database connection as is used
+** by the backup operation, then the backup database is automatically
+** updated at the same time.
+**
+** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
+**
+** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
+** application wishes to abandon the backup operation, the application
+** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
+** ^The sqlite3_backup_finish() interfaces releases all
+** resources associated with the [sqlite3_backup] object.
+** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any
+** active write-transaction on the destination database is rolled back.
+** The [sqlite3_backup] object is invalid
+** and may not be used following a call to sqlite3_backup_finish().
+**
+** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
+** sqlite3_backup_step() errors occurred, regardless or whether or not
+** sqlite3_backup_step() completed.
+** ^If an out-of-memory condition or IO error occurred during any prior
+** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
+** sqlite3_backup_finish() returns the corresponding [error code].
+**
+** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
+** is not a permanent error and does not affect the return value of
+** sqlite3_backup_finish().
+**
+** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
+** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
+**
+** ^Each call to sqlite3_backup_step() sets two values inside
+** the [sqlite3_backup] object: the number of pages still to be backed
+** up and the total number of pages in the source database file.
+** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
+** retrieve these two values, respectively.
+**
+** ^The values returned by these functions are only updated by
+** sqlite3_backup_step(). ^If the source database is modified during a backup
+** operation, then the values are not updated to account for any extra
+** pages that need to be updated or the size of the source database file
+** changing.
+**
+** <b>Concurrent Usage of Database Handles</b>
+**
+** ^The source [database connection] may be used by the application for other
+** purposes while a backup operation is underway or being initialized.
+** ^If SQLite is compiled and configured to support threadsafe database
+** connections, then the source database connection may be used concurrently
+** from within other threads.
+**
+** However, the application must guarantee that the destination
+** [database connection] is not passed to any other API (by any thread) after
+** sqlite3_backup_init() is called and before the corresponding call to
+** sqlite3_backup_finish(). SQLite does not currently check to see
+** if the application incorrectly accesses the destination [database connection]
+** and so no error code is reported, but the operations may malfunction
+** nevertheless. Use of the destination database connection while a
+** backup is in progress might also also cause a mutex deadlock.
+**
+** If running in [shared cache mode], the application must
+** guarantee that the shared cache used by the destination database
+** is not accessed while the backup is running. In practice this means
+** that the application must guarantee that the disk file being
+** backed up to is not accessed by any connection within the process,
+** not just the specific connection that was passed to sqlite3_backup_init().
+**
+** The [sqlite3_backup] object itself is partially threadsafe. Multiple
+** threads may safely make multiple concurrent calls to sqlite3_backup_step().
+** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount()
+** APIs are not strictly speaking threadsafe. If they are invoked at the
+** same time as another thread is invoking sqlite3_backup_step() it is
+** possible that they return invalid values.
+*/
+SQLITE_API sqlite3_backup *sqlite3_backup_init(
+ sqlite3 *pDest, /* Destination database handle */
+ const char *zDestName, /* Destination database name */
+ sqlite3 *pSource, /* Source database handle */
+ const char *zSourceName /* Source database name */
+);
+SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage);
+SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p);
+SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p);
+SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
+
+/*
+** CAPI3REF: Unlock Notification
+**
+** ^When running in shared-cache mode, a database operation may fail with
+** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
+** individual tables within the shared-cache cannot be obtained. See
+** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
+** ^This API may be used to register a callback that SQLite will invoke
+** when the connection currently holding the required lock relinquishes it.
+** ^This API is only available if the library was compiled with the
+** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
+**
+** See Also: [Using the SQLite Unlock Notification Feature].
+**
+** ^Shared-cache locks are released when a database connection concludes
+** its current transaction, either by committing it or rolling it back.
+**
+** ^When a connection (known as the blocked connection) fails to obtain a
+** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
+** identity of the database connection (the blocking connection) that
+** has locked the required resource is stored internally. ^After an
+** application receives an SQLITE_LOCKED error, it may call the
+** sqlite3_unlock_notify() method with the blocked connection handle as
+** the first argument to register for a callback that will be invoked
+** when the blocking connections current transaction is concluded. ^The
+** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
+** call that concludes the blocking connections transaction.
+**
+** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
+** there is a chance that the blocking connection will have already
+** concluded its transaction by the time sqlite3_unlock_notify() is invoked.
+** If this happens, then the specified callback is invoked immediately,
+** from within the call to sqlite3_unlock_notify().)^
+**
+** ^If the blocked connection is attempting to obtain a write-lock on a
+** shared-cache table, and more than one other connection currently holds
+** a read-lock on the same table, then SQLite arbitrarily selects one of
+** the other connections to use as the blocking connection.
+**
+** ^(There may be at most one unlock-notify callback registered by a
+** blocked connection. If sqlite3_unlock_notify() is called when the
+** blocked connection already has a registered unlock-notify callback,
+** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
+** called with a NULL pointer as its second argument, then any existing
+** unlock-notify callback is canceled. ^The blocked connections
+** unlock-notify callback may also be canceled by closing the blocked
+** connection using [sqlite3_close()].
+**
+** The unlock-notify callback is not reentrant. If an application invokes
+** any sqlite3_xxx API functions from within an unlock-notify callback, a
+** crash or deadlock may be the result.
+**
+** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always
+** returns SQLITE_OK.
+**
+** <b>Callback Invocation Details</b>
+**
+** When an unlock-notify callback is registered, the application provides a
+** single void* pointer that is passed to the callback when it is invoked.
+** However, the signature of the callback function allows SQLite to pass
+** it an array of void* context pointers. The first argument passed to
+** an unlock-notify callback is a pointer to an array of void* pointers,
+** and the second is the number of entries in the array.
+**
+** When a blocking connections transaction is concluded, there may be
+** more than one blocked connection that has registered for an unlock-notify
+** callback. ^If two or more such blocked connections have specified the
+** same callback function, then instead of invoking the callback function
+** multiple times, it is invoked once with the set of void* context pointers
+** specified by the blocked connections bundled together into an array.
+** This gives the application an opportunity to prioritize any actions
+** related to the set of unblocked database connections.
+**
+** <b>Deadlock Detection</b>
+**
+** Assuming that after registering for an unlock-notify callback a
+** database waits for the callback to be issued before taking any further
+** action (a reasonable assumption), then using this API may cause the
+** application to deadlock. For example, if connection X is waiting for
+** connection Y's transaction to be concluded, and similarly connection
+** Y is waiting on connection X's transaction, then neither connection
+** will proceed and the system may remain deadlocked indefinitely.
+**
+** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock
+** detection. ^If a given call to sqlite3_unlock_notify() would put the
+** system in a deadlocked state, then SQLITE_LOCKED is returned and no
+** unlock-notify callback is registered. The system is said to be in
+** a deadlocked state if connection A has registered for an unlock-notify
+** callback on the conclusion of connection B's transaction, and connection
+** B has itself registered for an unlock-notify callback when connection
+** A's transaction is concluded. ^Indirect deadlock is also detected, so
+** the system is also considered to be deadlocked if connection B has
+** registered for an unlock-notify callback on the conclusion of connection
+** C's transaction, where connection C is waiting on connection A. ^Any
+** number of levels of indirection are allowed.
+**
+** <b>The "DROP TABLE" Exception</b>
+**
+** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
+** always appropriate to call sqlite3_unlock_notify(). There is however,
+** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
+** SQLite checks if there are any currently executing SELECT statements
+** that belong to the same connection. If there are, SQLITE_LOCKED is
+** returned. In this case there is no "blocking connection", so invoking
+** sqlite3_unlock_notify() results in the unlock-notify callback being
+** invoked immediately. If the application then re-attempts the "DROP TABLE"
+** or "DROP INDEX" query, an infinite loop might be the result.
+**
+** One way around this problem is to check the extended error code returned
+** by an sqlite3_step() call. ^(If there is a blocking connection, then the
+** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
+** the special "DROP TABLE/INDEX" case, the extended error code is just
+** SQLITE_LOCKED.)^
+*/
+SQLITE_API int sqlite3_unlock_notify(
+ sqlite3 *pBlocked, /* Waiting connection */
+ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
+ void *pNotifyArg /* Argument to pass to xNotify */
+);
+
+
+/*
+** CAPI3REF: String Comparison
+**
+** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
+** and extensions to compare the contents of two buffers containing UTF-8
+** strings in a case-independent fashion, using the same definition of "case
+** independence" that SQLite uses internally when comparing identifiers.
+*/
+SQLITE_API int sqlite3_stricmp(const char *, const char *);
+SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
+
+/*
+** CAPI3REF: Error Logging Interface
+**
+** ^The [sqlite3_log()] interface writes a message into the error log
+** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
+** ^If logging is enabled, the zFormat string and subsequent arguments are
+** used with [sqlite3_snprintf()] to generate the final output string.
+**
+** The sqlite3_log() interface is intended for use by extensions such as
+** virtual tables, collating functions, and SQL functions. While there is
+** nothing to prevent an application from calling sqlite3_log(), doing so
+** is considered bad form.
+**
+** The zFormat string must not be NULL.
+**
+** To avoid deadlocks and other threading problems, the sqlite3_log() routine
+** will not use dynamically allocated memory. The log message is stored in
+** a fixed-length buffer on the stack. If the log message is longer than
+** a few hundred characters, it will be truncated to the length of the
+** buffer.
+*/
+SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
+
+/*
+** CAPI3REF: Write-Ahead Log Commit Hook
+**
+** ^The [sqlite3_wal_hook()] function is used to register a callback that
+** will be invoked each time a database connection commits data to a
+** [write-ahead log] (i.e. whenever a transaction is committed in
+** [journal_mode | journal_mode=WAL mode]).
+**
+** ^The callback is invoked by SQLite after the commit has taken place and
+** the associated write-lock on the database released, so the implementation
+** may read, write or [checkpoint] the database as required.
+**
+** ^The first parameter passed to the callback function when it is invoked
+** is a copy of the third parameter passed to sqlite3_wal_hook() when
+** registering the callback. ^The second is a copy of the database handle.
+** ^The third parameter is the name of the database that was written to -
+** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
+** is the number of pages currently in the write-ahead log file,
+** including those that were just committed.
+**
+** The callback function should normally return [SQLITE_OK]. ^If an error
+** code is returned, that error will propagate back up through the
+** SQLite code base to cause the statement that provoked the callback
+** to report an error, though the commit will have still occurred. If the
+** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
+** that does not correspond to any valid SQLite error code, the results
+** are undefined.
+**
+** A single database handle may have at most a single write-ahead log callback
+** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
+** previously registered write-ahead log callback. ^Note that the
+** [sqlite3_wal_autocheckpoint()] interface and the
+** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
+** those overwrite any prior [sqlite3_wal_hook()] settings.
+*/
+SQLITE_API void *sqlite3_wal_hook(
+ sqlite3*,
+ int(*)(void *,sqlite3*,const char*,int),
+ void*
+);
+
+/*
+** CAPI3REF: Configure an auto-checkpoint
+**
+** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
+** [sqlite3_wal_hook()] that causes any database on [database connection] D
+** to automatically [checkpoint]
+** after committing a transaction if there are N or
+** more frames in the [write-ahead log] file. ^Passing zero or
+** a negative value as the nFrame parameter disables automatic
+** checkpoints entirely.
+**
+** ^The callback registered by this function replaces any existing callback
+** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback
+** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
+** configured by this function.
+**
+** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
+** from SQL.
+**
+** ^Every new [database connection] defaults to having the auto-checkpoint
+** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
+** pages. The use of this interface
+** is only necessary if the default setting is found to be suboptimal
+** for a particular application.
+*/
+SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
+
+/*
+** CAPI3REF: Checkpoint a database
+**
+** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
+** on [database connection] D to be [checkpointed]. ^If X is NULL or an
+** empty string, then a checkpoint is run on all databases of
+** connection D. ^If the database connection D is not in
+** [WAL | write-ahead log mode] then this interface is a harmless no-op.
+**
+** ^The [wal_checkpoint pragma] can be used to invoke this interface
+** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
+** [wal_autocheckpoint pragma] can be used to cause this interface to be
+** run whenever the WAL reaches a certain size threshold.
+**
+** See also: [sqlite3_wal_checkpoint_v2()]
+*/
+SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
+
+/*
+** CAPI3REF: Checkpoint a database
+**
+** Run a checkpoint operation on WAL database zDb attached to database
+** handle db. The specific operation is determined by the value of the
+** eMode parameter:
+**
+** <dl>
+** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
+** Checkpoint as many frames as possible without waiting for any database
+** readers or writers to finish. Sync the db file if all frames in the log
+** are checkpointed. This mode is the same as calling
+** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
+**
+** <dt>SQLITE_CHECKPOINT_FULL<dd>
+** This mode blocks (calls the busy-handler callback) until there is no
+** database writer and all readers are reading from the most recent database
+** snapshot. It then checkpoints all frames in the log file and syncs the
+** database file. This call blocks database writers while it is running,
+** but not database readers.
+**
+** <dt>SQLITE_CHECKPOINT_RESTART<dd>
+** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
+** checkpointing the log file it blocks (calls the busy-handler callback)
+** until all readers are reading from the database file only. This ensures
+** that the next client to write to the database file restarts the log file
+** from the beginning. This call blocks database writers while it is running,
+** but not database readers.
+** </dl>
+**
+** If pnLog is not NULL, then *pnLog is set to the total number of frames in
+** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to
+** the total number of checkpointed frames (including any that were already
+** checkpointed when this function is called). *pnLog and *pnCkpt may be
+** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK.
+** If no values are available because of an error, they are both set to -1
+** before returning to communicate this to the caller.
+**
+** All calls obtain an exclusive "checkpoint" lock on the database file. If
+** any other process is running a checkpoint operation at the same time, the
+** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a
+** busy-handler configured, it will not be invoked in this case.
+**
+** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive
+** "writer" lock on the database file. If the writer lock cannot be obtained
+** immediately, and a busy-handler is configured, it is invoked and the writer
+** lock retried until either the busy-handler returns 0 or the lock is
+** successfully obtained. The busy-handler is also invoked while waiting for
+** database readers as described above. If the busy-handler returns 0 before
+** the writer lock is obtained or while waiting for database readers, the
+** checkpoint operation proceeds from that point in the same way as
+** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
+** without blocking any further. SQLITE_BUSY is returned in this case.
+**
+** If parameter zDb is NULL or points to a zero length string, then the
+** specified operation is attempted on all WAL databases. In this case the
+** values written to output parameters *pnLog and *pnCkpt are undefined. If
+** an SQLITE_BUSY error is encountered when processing one or more of the
+** attached WAL databases, the operation is still attempted on any remaining
+** attached databases and SQLITE_BUSY is returned to the caller. If any other
+** error occurs while processing an attached database, processing is abandoned
+** and the error code returned to the caller immediately. If no error
+** (SQLITE_BUSY or otherwise) is encountered while processing the attached
+** databases, SQLITE_OK is returned.
+**
+** If database zDb is the name of an attached database that is not in WAL
+** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If
+** zDb is not NULL (or a zero length string) and is not the name of any
+** attached database, SQLITE_ERROR is returned to the caller.
+*/
+SQLITE_API int sqlite3_wal_checkpoint_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of attached database (or NULL) */
+ int eMode, /* SQLITE_CHECKPOINT_* value */
+ int *pnLog, /* OUT: Size of WAL log in frames */
+ int *pnCkpt /* OUT: Total number of frames checkpointed */
+);
+
+/*
+** CAPI3REF: Checkpoint operation parameters
+**
+** These constants can be used as the 3rd parameter to
+** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()]
+** documentation for additional information about the meaning and use of
+** each of these values.
+*/
+#define SQLITE_CHECKPOINT_PASSIVE 0
+#define SQLITE_CHECKPOINT_FULL 1
+#define SQLITE_CHECKPOINT_RESTART 2
+
+/*
+** CAPI3REF: Virtual Table Interface Configuration
+**
+** This function may be called by either the [xConnect] or [xCreate] method
+** of a [virtual table] implementation to configure
+** various facets of the virtual table interface.
+**
+** If this interface is invoked outside the context of an xConnect or
+** xCreate virtual table method then the behavior is undefined.
+**
+** At present, there is only one option that may be configured using
+** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
+** may be added in the future.
+*/
+SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+
+/*
+** CAPI3REF: Virtual Table Configuration Options
+**
+** These macros define the various options to the
+** [sqlite3_vtab_config()] interface that [virtual table] implementations
+** can use to customize and optimize their behavior.
+**
+** <dl>
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
+** <dd>Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
+** where X is an integer. If X is zero, then the [virtual table] whose
+** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
+** support constraints. In this configuration (which is the default) if
+** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
+** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
+** specified as part of the users SQL statement, regardless of the actual
+** ON CONFLICT mode specified.
+**
+** If X is non-zero, then the virtual table implementation guarantees
+** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
+** any modifications to internal or persistent data structures have been made.
+** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
+** is able to roll back a statement or database transaction, and abandon
+** or continue processing the current SQL statement as appropriate.
+** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
+** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
+** had been ABORT.
+**
+** Virtual table implementations that are required to handle OR REPLACE
+** must do so within the [xUpdate] method. If a call to the
+** [sqlite3_vtab_on_conflict()] function indicates that the current ON
+** CONFLICT policy is REPLACE, the virtual table implementation should
+** silently replace the appropriate rows within the xUpdate callback and
+** return SQLITE_OK. Or, if this is not possible, it may return
+** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
+** constraint handling.
+** </dl>
+*/
+#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+
+/*
+** CAPI3REF: Determine The Virtual Table Conflict Policy
+**
+** This function may only be called from within a call to the [xUpdate] method
+** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
+** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
+** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
+** of the SQL statement that triggered the call to the [xUpdate] method of the
+** [virtual table].
+*/
+SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
+
+/*
+** CAPI3REF: Conflict resolution modes
+**
+** These constants are returned by [sqlite3_vtab_on_conflict()] to
+** inform a [virtual table] implementation what the [ON CONFLICT] mode
+** is for the SQL statement being evaluated.
+**
+** Note that the [SQLITE_IGNORE] constant is also used as a potential
+** return value from the [sqlite3_set_authorizer()] callback and that
+** [SQLITE_ABORT] is also a [result code].
+*/
+#define SQLITE_ROLLBACK 1
+/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
+#define SQLITE_FAIL 3
+/* #define SQLITE_ABORT 4 // Also an error code */
+#define SQLITE_REPLACE 5
+
+
+
+/*
+** Undo the hack that converts floating point types to integer for
+** builds on processors without floating point support.
+*/
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# undef double
+#endif
+
+#if 0
+} /* End of the 'extern "C"' block */
+#endif
+#endif
+
+/*
+** 2010 August 30
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+*/
+
+#ifndef _SQLITE3RTREE_H_
+#define _SQLITE3RTREE_H_
+
+
+#if 0
+extern "C" {
+#endif
+
+typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
+
+/*
+** Register a geometry callback named zGeom that can be used as part of an
+** R-Tree geometry query as follows:
+**
+** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
+*/
+SQLITE_API int sqlite3_rtree_geometry_callback(
+ sqlite3 *db,
+ const char *zGeom,
+#ifdef SQLITE_RTREE_INT_ONLY
+ int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
+#else
+ int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
+#endif
+ void *pContext
+);
+
+
+/*
+** A pointer to a structure of the following type is passed as the first
+** argument to callbacks registered using rtree_geometry_callback().
+*/
+struct sqlite3_rtree_geometry {
+ void *pContext; /* Copy of pContext passed to s_r_g_c() */
+ int nParam; /* Size of array aParam[] */
+ double *aParam; /* Parameters passed to SQL geom function */
+ void *pUser; /* Callback implementation user data */
+ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
+};
+
+
+#if 0
+} /* end of the 'extern "C"' block */
+#endif
+
+#endif /* ifndef _SQLITE3RTREE_H_ */
+
+
+/************** End of sqlite3.h *********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include hash.h in the middle of sqliteInt.h ******************/
+/************** Begin file hash.h ********************************************/
+/*
+** 2001 September 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This is the header file for the generic hash-table implementation
+** used in SQLite.
+*/
+#ifndef _SQLITE_HASH_H_
+#define _SQLITE_HASH_H_
+
+/* Forward declarations of structures. */
+typedef struct Hash Hash;
+typedef struct HashElem HashElem;
+
+/* A complete hash table is an instance of the following structure.
+** The internals of this structure are intended to be opaque -- client
+** code should not attempt to access or modify the fields of this structure
+** directly. Change this structure only by using the routines below.
+** However, some of the "procedures" and "functions" for modifying and
+** accessing this structure are really macros, so we can't really make
+** this structure opaque.
+**
+** All elements of the hash table are on a single doubly-linked list.
+** Hash.first points to the head of this list.
+**
+** There are Hash.htsize buckets. Each bucket points to a spot in
+** the global doubly-linked list. The contents of the bucket are the
+** element pointed to plus the next _ht.count-1 elements in the list.
+**
+** Hash.htsize and Hash.ht may be zero. In that case lookup is done
+** by a linear search of the global list. For small tables, the
+** Hash.ht table is never allocated because if there are few elements
+** in the table, it is faster to do a linear search than to manage
+** the hash table.
+*/
+struct Hash {
+ unsigned int htsize; /* Number of buckets in the hash table */
+ unsigned int count; /* Number of entries in this table */
+ HashElem *first; /* The first element of the array */
+ struct _ht { /* the hash table */
+ int count; /* Number of entries with this hash */
+ HashElem *chain; /* Pointer to first entry with this hash */
+ } *ht;
+};
+
+/* Each element in the hash table is an instance of the following
+** structure. All elements are stored on a single doubly-linked list.
+**
+** Again, this structure is intended to be opaque, but it can't really
+** be opaque because it is used by macros.
+*/
+struct HashElem {
+ HashElem *next, *prev; /* Next and previous elements in the table */
+ void *data; /* Data associated with this element */
+ const char *pKey; int nKey; /* Key associated with this element */
+};
+
+/*
+** Access routines. To delete, insert a NULL pointer.
+*/
+SQLITE_PRIVATE void sqlite3HashInit(Hash*);
+SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData);
+SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey);
+SQLITE_PRIVATE void sqlite3HashClear(Hash*);
+
+/*
+** Macros for looping over all elements of a hash table. The idiom is
+** like this:
+**
+** Hash h;
+** HashElem *p;
+** ...
+** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
+** SomeStructure *pData = sqliteHashData(p);
+** // do something with pData
+** }
+*/
+#define sqliteHashFirst(H) ((H)->first)
+#define sqliteHashNext(E) ((E)->next)
+#define sqliteHashData(E) ((E)->data)
+/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */
+/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */
+
+/*
+** Number of entries in a hash table
+*/
+/* #define sqliteHashCount(H) ((H)->count) // NOT USED */
+
+#endif /* _SQLITE_HASH_H_ */
+
+/************** End of hash.h ************************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include parse.h in the middle of sqliteInt.h *****************/
+/************** Begin file parse.h *******************************************/
+#define TK_SEMI 1
+#define TK_EXPLAIN 2
+#define TK_QUERY 3
+#define TK_PLAN 4
+#define TK_BEGIN 5
+#define TK_TRANSACTION 6
+#define TK_DEFERRED 7
+#define TK_IMMEDIATE 8
+#define TK_EXCLUSIVE 9
+#define TK_COMMIT 10
+#define TK_END 11
+#define TK_ROLLBACK 12
+#define TK_SAVEPOINT 13
+#define TK_RELEASE 14
+#define TK_TO 15
+#define TK_TABLE 16
+#define TK_CREATE 17
+#define TK_IF 18
+#define TK_NOT 19
+#define TK_EXISTS 20
+#define TK_TEMP 21
+#define TK_LP 22
+#define TK_RP 23
+#define TK_AS 24
+#define TK_COMMA 25
+#define TK_ID 26
+#define TK_INDEXED 27
+#define TK_ABORT 28
+#define TK_ACTION 29
+#define TK_AFTER 30
+#define TK_ANALYZE 31
+#define TK_ASC 32
+#define TK_ATTACH 33
+#define TK_BEFORE 34
+#define TK_BY 35
+#define TK_CASCADE 36
+#define TK_CAST 37
+#define TK_COLUMNKW 38
+#define TK_CONFLICT 39
+#define TK_DATABASE 40
+#define TK_DESC 41
+#define TK_DETACH 42
+#define TK_EACH 43
+#define TK_FAIL 44
+#define TK_FOR 45
+#define TK_IGNORE 46
+#define TK_INITIALLY 47
+#define TK_INSTEAD 48
+#define TK_LIKE_KW 49
+#define TK_MATCH 50
+#define TK_NO 51
+#define TK_KEY 52
+#define TK_OF 53
+#define TK_OFFSET 54
+#define TK_PRAGMA 55
+#define TK_RAISE 56
+#define TK_REPLACE 57
+#define TK_RESTRICT 58
+#define TK_ROW 59
+#define TK_TRIGGER 60
+#define TK_VACUUM 61
+#define TK_VIEW 62
+#define TK_VIRTUAL 63
+#define TK_REINDEX 64
+#define TK_RENAME 65
+#define TK_CTIME_KW 66
+#define TK_ANY 67
+#define TK_OR 68
+#define TK_AND 69
+#define TK_IS 70
+#define TK_BETWEEN 71
+#define TK_IN 72
+#define TK_ISNULL 73
+#define TK_NOTNULL 74
+#define TK_NE 75
+#define TK_EQ 76
+#define TK_GT 77
+#define TK_LE 78
+#define TK_LT 79
+#define TK_GE 80
+#define TK_ESCAPE 81
+#define TK_BITAND 82
+#define TK_BITOR 83
+#define TK_LSHIFT 84
+#define TK_RSHIFT 85
+#define TK_PLUS 86
+#define TK_MINUS 87
+#define TK_STAR 88
+#define TK_SLASH 89
+#define TK_REM 90
+#define TK_CONCAT 91
+#define TK_COLLATE 92
+#define TK_BITNOT 93
+#define TK_STRING 94
+#define TK_JOIN_KW 95
+#define TK_CONSTRAINT 96
+#define TK_DEFAULT 97
+#define TK_NULL 98
+#define TK_PRIMARY 99
+#define TK_UNIQUE 100
+#define TK_CHECK 101
+#define TK_REFERENCES 102
+#define TK_AUTOINCR 103
+#define TK_ON 104
+#define TK_INSERT 105
+#define TK_DELETE 106
+#define TK_UPDATE 107
+#define TK_SET 108
+#define TK_DEFERRABLE 109
+#define TK_FOREIGN 110
+#define TK_DROP 111
+#define TK_UNION 112
+#define TK_ALL 113
+#define TK_EXCEPT 114
+#define TK_INTERSECT 115
+#define TK_SELECT 116
+#define TK_DISTINCT 117
+#define TK_DOT 118
+#define TK_FROM 119
+#define TK_JOIN 120
+#define TK_USING 121
+#define TK_ORDER 122
+#define TK_GROUP 123
+#define TK_HAVING 124
+#define TK_LIMIT 125
+#define TK_WHERE 126
+#define TK_INTO 127
+#define TK_VALUES 128
+#define TK_INTEGER 129
+#define TK_FLOAT 130
+#define TK_BLOB 131
+#define TK_REGISTER 132
+#define TK_VARIABLE 133
+#define TK_CASE 134
+#define TK_WHEN 135
+#define TK_THEN 136
+#define TK_ELSE 137
+#define TK_INDEX 138
+#define TK_ALTER 139
+#define TK_ADD 140
+#define TK_TO_TEXT 141
+#define TK_TO_BLOB 142
+#define TK_TO_NUMERIC 143
+#define TK_TO_INT 144
+#define TK_TO_REAL 145
+#define TK_ISNOT 146
+#define TK_END_OF_FILE 147
+#define TK_ILLEGAL 148
+#define TK_SPACE 149
+#define TK_UNCLOSED_STRING 150
+#define TK_FUNCTION 151
+#define TK_COLUMN 152
+#define TK_AGG_FUNCTION 153
+#define TK_AGG_COLUMN 154
+#define TK_CONST_FUNC 155
+#define TK_UMINUS 156
+#define TK_UPLUS 157
+
+/************** End of parse.h ***********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stddef.h>
+
+/*
+** If compiling for a processor that lacks floating point support,
+** substitute integer for floating-point
+*/
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# define double sqlite_int64
+# define float sqlite_int64
+# define LONGDOUBLE_TYPE sqlite_int64
+# ifndef SQLITE_BIG_DBL
+# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
+# endif
+# define SQLITE_OMIT_DATETIME_FUNCS 1
+# define SQLITE_OMIT_TRACE 1
+# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+# undef SQLITE_HAVE_ISNAN
+#endif
+#ifndef SQLITE_BIG_DBL
+# define SQLITE_BIG_DBL (1e99)
+#endif
+
+/*
+** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
+** afterward. Having this macro allows us to cause the C compiler
+** to omit code used by TEMP tables without messy #ifndef statements.
+*/
+#ifdef SQLITE_OMIT_TEMPDB
+#define OMIT_TEMPDB 1
+#else
+#define OMIT_TEMPDB 0
+#endif
+
+/*
+** The "file format" number is an integer that is incremented whenever
+** the VDBE-level file format changes. The following macros define the
+** the default file format for new databases and the maximum file format
+** that the library can read.
+*/
+#define SQLITE_MAX_FILE_FORMAT 4
+#ifndef SQLITE_DEFAULT_FILE_FORMAT
+# define SQLITE_DEFAULT_FILE_FORMAT 4
+#endif
+
+/*
+** Determine whether triggers are recursive by default. This can be
+** changed at run-time using a pragma.
+*/
+#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
+# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
+#endif
+
+/*
+** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
+** on the command-line
+*/
+#ifndef SQLITE_TEMP_STORE
+# define SQLITE_TEMP_STORE 1
+#endif
+
+/*
+** GCC does not define the offsetof() macro so we'll have to do it
+** ourselves.
+*/
+#ifndef offsetof
+#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+
+/*
+** Check to see if this machine uses EBCDIC. (Yes, believe it or
+** not, there are still machines out there that use EBCDIC.)
+*/
+#if 'A' == '\301'
+# define SQLITE_EBCDIC 1
+#else
+# define SQLITE_ASCII 1
+#endif
+
+/*
+** Integers of known sizes. These typedefs might change for architectures
+** where the sizes very. Preprocessor macros are available so that the
+** types can be conveniently redefined at compile-type. Like this:
+**
+** cc '-DUINTPTR_TYPE=long long int' ...
+*/
+#ifndef UINT32_TYPE
+# ifdef HAVE_UINT32_T
+# define UINT32_TYPE uint32_t
+# else
+# define UINT32_TYPE unsigned int
+# endif
+#endif
+#ifndef UINT16_TYPE
+# ifdef HAVE_UINT16_T
+# define UINT16_TYPE uint16_t
+# else
+# define UINT16_TYPE unsigned short int
+# endif
+#endif
+#ifndef INT16_TYPE
+# ifdef HAVE_INT16_T
+# define INT16_TYPE int16_t
+# else
+# define INT16_TYPE short int
+# endif
+#endif
+#ifndef UINT8_TYPE
+# ifdef HAVE_UINT8_T
+# define UINT8_TYPE uint8_t
+# else
+# define UINT8_TYPE unsigned char
+# endif
+#endif
+#ifndef INT8_TYPE
+# ifdef HAVE_INT8_T
+# define INT8_TYPE int8_t
+# else
+# define INT8_TYPE signed char
+# endif
+#endif
+#ifndef LONGDOUBLE_TYPE
+# define LONGDOUBLE_TYPE long double
+#endif
+typedef sqlite_int64 i64; /* 8-byte signed integer */
+typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
+typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
+typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
+typedef INT16_TYPE i16; /* 2-byte signed integer */
+typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
+typedef INT8_TYPE i8; /* 1-byte signed integer */
+
+/*
+** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
+** that can be stored in a u32 without loss of data. The value
+** is 0x00000000ffffffff. But because of quirks of some compilers, we
+** have to specify the value in the less intuitive manner shown:
+*/
+#define SQLITE_MAX_U32 ((((u64)1)<<32)-1)
+
+/*
+** The datatype used to store estimates of the number of rows in a
+** table or index. This is an unsigned integer type. For 99.9% of
+** the world, a 32-bit integer is sufficient. But a 64-bit integer
+** can be used at compile-time if desired.
+*/
+#ifdef SQLITE_64BIT_STATS
+ typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
+#else
+ typedef u32 tRowcnt; /* 32-bit is the default */
+#endif
+
+/*
+** Macros to determine whether the machine is big or little endian,
+** evaluated at runtime.
+*/
+#ifdef SQLITE_AMALGAMATION
+SQLITE_PRIVATE const int sqlite3one = 1;
+#else
+SQLITE_PRIVATE const int sqlite3one;
+#endif
+#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
+ || defined(__x86_64) || defined(__x86_64__)
+# define SQLITE_BIGENDIAN 0
+# define SQLITE_LITTLEENDIAN 1
+# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
+#else
+# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
+# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
+# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
+#endif
+
+/*
+** Constants for the largest and smallest possible 64-bit signed integers.
+** These macros are designed to work correctly on both 32-bit and 64-bit
+** compilers.
+*/
+#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
+#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
+
+/*
+** Round up a number to the next larger multiple of 8. This is used
+** to force 8-byte alignment on 64-bit architectures.
+*/
+#define ROUND8(x) (((x)+7)&~7)
+
+/*
+** Round down to the nearest multiple of 8
+*/
+#define ROUNDDOWN8(x) ((x)&~7)
+
+/*
+** Assert that the pointer X is aligned to an 8-byte boundary. This
+** macro is used only within assert() to verify that the code gets
+** all alignment restrictions correct.
+**
+** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
+** underlying malloc() implemention might return us 4-byte aligned
+** pointers. In that case, only verify 4-byte alignment.
+*/
+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0)
+#else
+# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0)
+#endif
+
+
+/*
+** An instance of the following structure is used to store the busy-handler
+** callback for a given sqlite handle.
+**
+** The sqlite.busyHandler member of the sqlite struct contains the busy
+** callback for the database handle. Each pager opened via the sqlite
+** handle is passed a pointer to sqlite.busyHandler. The busy-handler
+** callback is currently invoked only from within pager.c.
+*/
+typedef struct BusyHandler BusyHandler;
+struct BusyHandler {
+ int (*xFunc)(void *,int); /* The busy callback */
+ void *pArg; /* First arg to busy callback */
+ int nBusy; /* Incremented with each busy call */
+};
+
+/*
+** Name of the master database table. The master database table
+** is a special table that holds the names and attributes of all
+** user tables and indices.
+*/
+#define MASTER_NAME "sqlite_master"
+#define TEMP_MASTER_NAME "sqlite_temp_master"
+
+/*
+** The root-page of the master database table.
+*/
+#define MASTER_ROOT 1
+
+/*
+** The name of the schema table.
+*/
+#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
+
+/*
+** A convenience macro that returns the number of elements in
+** an array.
+*/
+#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
+
+/*
+** Determine if the argument is a power of two
+*/
+#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
+
+/*
+** The following value as a destructor means to use sqlite3DbFree().
+** The sqlite3DbFree() routine requires two parameters instead of the
+** one parameter that destructors normally want. So we have to introduce
+** this magic value that the code knows to handle differently. Any
+** pointer will work here as long as it is distinct from SQLITE_STATIC
+** and SQLITE_TRANSIENT.
+*/
+#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize)
+
+/*
+** When SQLITE_OMIT_WSD is defined, it means that the target platform does
+** not support Writable Static Data (WSD) such as global and static variables.
+** All variables must either be on the stack or dynamically allocated from
+** the heap. When WSD is unsupported, the variable declarations scattered
+** throughout the SQLite code must become constants instead. The SQLITE_WSD
+** macro is used for this purpose. And instead of referencing the variable
+** directly, we use its constant as a key to lookup the run-time allocated
+** buffer that holds real variable. The constant is also the initializer
+** for the run-time allocated buffer.
+**
+** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
+** macros become no-ops and have zero performance impact.
+*/
+#ifdef SQLITE_OMIT_WSD
+ #define SQLITE_WSD const
+ #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
+ #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
+SQLITE_API int sqlite3_wsd_init(int N, int J);
+SQLITE_API void *sqlite3_wsd_find(void *K, int L);
+#else
+ #define SQLITE_WSD
+ #define GLOBAL(t,v) v
+ #define sqlite3GlobalConfig sqlite3Config
+#endif
+
+/*
+** The following macros are used to suppress compiler warnings and to
+** make it clear to human readers when a function parameter is deliberately
+** left unused within the body of a function. This usually happens when
+** a function is called via a function pointer. For example the
+** implementation of an SQL aggregate step callback may not use the
+** parameter indicating the number of arguments passed to the aggregate,
+** if it knows that this is enforced elsewhere.
+**
+** When a function parameter is not used at all within the body of a function,
+** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
+** However, these macros may also be used to suppress warnings related to
+** parameters that may or may not be used depending on compilation options.
+** For example those parameters only used in assert() statements. In these
+** cases the parameters are named as per the usual conventions.
+*/
+#define UNUSED_PARAMETER(x) (void)(x)
+#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
+
+/*
+** Forward references to structures
+*/
+typedef struct AggInfo AggInfo;
+typedef struct AuthContext AuthContext;
+typedef struct AutoincInfo AutoincInfo;
+typedef struct Bitvec Bitvec;
+typedef struct CollSeq CollSeq;
+typedef struct Column Column;
+typedef struct Db Db;
+typedef struct Schema Schema;
+typedef struct Expr Expr;
+typedef struct ExprList ExprList;
+typedef struct ExprSpan ExprSpan;
+typedef struct FKey FKey;
+typedef struct FuncDestructor FuncDestructor;
+typedef struct FuncDef FuncDef;
+typedef struct FuncDefHash FuncDefHash;
+typedef struct IdList IdList;
+typedef struct Index Index;
+typedef struct IndexSample IndexSample;
+typedef struct KeyClass KeyClass;
+typedef struct KeyInfo KeyInfo;
+typedef struct Lookaside Lookaside;
+typedef struct LookasideSlot LookasideSlot;
+typedef struct Module Module;
+typedef struct NameContext NameContext;
+typedef struct Parse Parse;
+typedef struct RowSet RowSet;
+typedef struct Savepoint Savepoint;
+typedef struct Select Select;
+typedef struct SelectDest SelectDest;
+typedef struct SrcList SrcList;
+typedef struct StrAccum StrAccum;
+typedef struct Table Table;
+typedef struct TableLock TableLock;
+typedef struct Token Token;
+typedef struct Trigger Trigger;
+typedef struct TriggerPrg TriggerPrg;
+typedef struct TriggerStep TriggerStep;
+typedef struct UnpackedRecord UnpackedRecord;
+typedef struct VTable VTable;
+typedef struct VtabCtx VtabCtx;
+typedef struct Walker Walker;
+typedef struct WherePlan WherePlan;
+typedef struct WhereInfo WhereInfo;
+typedef struct WhereLevel WhereLevel;
+
+/*
+** Defer sourcing vdbe.h and btree.h until after the "u8" and
+** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
+** pointer types (i.e. FuncDef) defined above.
+*/
+/************** Include btree.h in the middle of sqliteInt.h *****************/
+/************** Begin file btree.h *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite B-Tree file
+** subsystem. See comments in the source code for a detailed description
+** of what each interface routine does.
+*/
+#ifndef _BTREE_H_
+#define _BTREE_H_
+
+/* TODO: This definition is just included so other modules compile. It
+** needs to be revisited.
+*/
+#define SQLITE_N_BTREE_META 10
+
+/*
+** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
+** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
+*/
+#ifndef SQLITE_DEFAULT_AUTOVACUUM
+ #define SQLITE_DEFAULT_AUTOVACUUM 0
+#endif
+
+#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */
+#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */
+#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */
+
+/*
+** Forward declarations of structure
+*/
+typedef struct Btree Btree;
+typedef struct BtCursor BtCursor;
+typedef struct BtShared BtShared;
+
+
+SQLITE_PRIVATE int sqlite3BtreeOpen(
+ sqlite3_vfs *pVfs, /* VFS to use with this b-tree */
+ const char *zFilename, /* Name of database file to open */
+ sqlite3 *db, /* Associated database connection */
+ Btree **ppBtree, /* Return open Btree* here */
+ int flags, /* Flags */
+ int vfsFlags /* Flags passed through to VFS open */
+);
+
+/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
+** following values.
+**
+** NOTE: These values must match the corresponding PAGER_ values in
+** pager.h.
+*/
+#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
+#define BTREE_MEMORY 2 /* This is an in-memory DB */
+#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */
+#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */
+
+SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
+SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
+SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
+SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
+#endif
+SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
+SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
+SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
+SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
+SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
+SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
+SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree);
+SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
+SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int);
+
+SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
+SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
+SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
+
+SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
+
+/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
+** of the flags shown below.
+**
+** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set.
+** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data
+** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With
+** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored
+** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL
+** indices.)
+*/
+#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
+#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
+
+SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
+SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
+
+SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
+SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
+
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
+
+/*
+** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
+** should be one of the following values. The integer values are assigned
+** to constants so that the offset of the corresponding field in an
+** SQLite database header may be found using the following formula:
+**
+** offset = 36 + (idx * 4)
+**
+** For example, the free-page-count field is located at byte offset 36 of
+** the database file header. The incr-vacuum-flag field is located at
+** byte offset 64 (== 36+4*7).
+*/
+#define BTREE_FREE_PAGE_COUNT 0
+#define BTREE_SCHEMA_VERSION 1
+#define BTREE_FILE_FORMAT 2
+#define BTREE_DEFAULT_CACHE_SIZE 3
+#define BTREE_LARGEST_ROOT_PAGE 4
+#define BTREE_TEXT_ENCODING 5
+#define BTREE_USER_VERSION 6
+#define BTREE_INCR_VACUUM 7
+
+/*
+** Values that may be OR'd together to form the second argument of an
+** sqlite3BtreeCursorHints() call.
+*/
+#define BTREE_BULKLOAD 0x00000001
+
+SQLITE_PRIVATE int sqlite3BtreeCursor(
+ Btree*, /* BTree containing table to open */
+ int iTable, /* Index of root page */
+ int wrFlag, /* 1 for writing. 0 for read-only */
+ struct KeyInfo*, /* First argument to compare function */
+ BtCursor *pCursor /* Space to write cursor structure */
+);
+SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
+SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
+
+SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
+SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+ BtCursor*,
+ UnpackedRecord *pUnKey,
+ i64 intKey,
+ int bias,
+ int *pRes
+);
+SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
+SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*);
+SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
+ const void *pData, int nData,
+ int nZero, int bias, int seekResult);
+SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
+SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
+SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
+SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
+SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
+SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
+SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
+SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64);
+SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*);
+
+SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
+SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
+
+SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
+SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *);
+SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
+SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
+SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
+
+#ifndef NDEBUG
+SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
+#endif
+
+#ifndef SQLITE_OMIT_BTREECOUNT
+SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *);
+#endif
+
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
+SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
+#endif
+
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
+#endif
+
+/*
+** If we are not using shared cache, then there is no need to
+** use mutexes to access the BtShared structures. So make the
+** Enter and Leave procedures no-ops.
+*/
+#ifndef SQLITE_OMIT_SHARED_CACHE
+SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*);
+SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*);
+#else
+# define sqlite3BtreeEnter(X)
+# define sqlite3BtreeEnterAll(X)
+#endif
+
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
+SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*);
+SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*);
+SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*);
+#ifndef NDEBUG
+ /* These routines are used inside assert() statements only. */
+SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*);
+SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
+#endif
+#else
+
+# define sqlite3BtreeSharable(X) 0
+# define sqlite3BtreeLeave(X)
+# define sqlite3BtreeEnterCursor(X)
+# define sqlite3BtreeLeaveCursor(X)
+# define sqlite3BtreeLeaveAll(X)
+
+# define sqlite3BtreeHoldsMutex(X) 1
+# define sqlite3BtreeHoldsAllMutexes(X) 1
+# define sqlite3SchemaMutexHeld(X,Y,Z) 1
+#endif
+
+
+#endif /* _BTREE_H_ */
+
+/************** End of btree.h ***********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include vdbe.h in the middle of sqliteInt.h ******************/
+/************** Begin file vdbe.h ********************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Header file for the Virtual DataBase Engine (VDBE)
+**
+** This header defines the interface to the virtual database engine
+** or VDBE. The VDBE implements an abstract machine that runs a
+** simple program to access and modify the underlying database.
+*/
+#ifndef _SQLITE_VDBE_H_
+#define _SQLITE_VDBE_H_
+/* #include <stdio.h> */
+
+/*
+** A single VDBE is an opaque structure named "Vdbe". Only routines
+** in the source file sqliteVdbe.c are allowed to see the insides
+** of this structure.
+*/
+typedef struct Vdbe Vdbe;
+
+/*
+** The names of the following types declared in vdbeInt.h are required
+** for the VdbeOp definition.
+*/
+typedef struct VdbeFunc VdbeFunc;
+typedef struct Mem Mem;
+typedef struct SubProgram SubProgram;
+
+/*
+** A single instruction of the virtual machine has an opcode
+** and as many as three operands. The instruction is recorded
+** as an instance of the following structure:
+*/
+struct VdbeOp {
+ u8 opcode; /* What operation to perform */
+ signed char p4type; /* One of the P4_xxx constants for p4 */
+ u8 opflags; /* Mask of the OPFLG_* flags in opcodes.h */
+ u8 p5; /* Fifth parameter is an unsigned character */
+ int p1; /* First operand */
+ int p2; /* Second parameter (often the jump destination) */
+ int p3; /* The third parameter */
+ union { /* fourth parameter */
+ int i; /* Integer value if p4type==P4_INT32 */
+ void *p; /* Generic pointer */
+ char *z; /* Pointer to data for string (char array) types */
+ i64 *pI64; /* Used when p4type is P4_INT64 */
+ double *pReal; /* Used when p4type is P4_REAL */
+ FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
+ VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */
+ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
+ Mem *pMem; /* Used when p4type is P4_MEM */
+ VTable *pVtab; /* Used when p4type is P4_VTAB */
+ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
+ int *ai; /* Used when p4type is P4_INTARRAY */
+ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
+ int (*xAdvance)(BtCursor *, int *);
+ } p4;
+#ifdef SQLITE_DEBUG
+ char *zComment; /* Comment to improve readability */
+#endif
+#ifdef VDBE_PROFILE
+ int cnt; /* Number of times this instruction was executed */
+ u64 cycles; /* Total time spent executing this instruction */
+#endif
+};
+typedef struct VdbeOp VdbeOp;
+
+
+/*
+** A sub-routine used to implement a trigger program.
+*/
+struct SubProgram {
+ VdbeOp *aOp; /* Array of opcodes for sub-program */
+ int nOp; /* Elements in aOp[] */
+ int nMem; /* Number of memory cells required */
+ int nCsr; /* Number of cursors required */
+ int nOnce; /* Number of OP_Once instructions */
+ void *token; /* id that may be used to recursive triggers */
+ SubProgram *pNext; /* Next sub-program already visited */
+};
+
+/*
+** A smaller version of VdbeOp used for the VdbeAddOpList() function because
+** it takes up less space.
+*/
+struct VdbeOpList {
+ u8 opcode; /* What operation to perform */
+ signed char p1; /* First operand */
+ signed char p2; /* Second parameter (often the jump destination) */
+ signed char p3; /* Third parameter */
+};
+typedef struct VdbeOpList VdbeOpList;
+
+/*
+** Allowed values of VdbeOp.p4type
+*/
+#define P4_NOTUSED 0 /* The P4 parameter is not used */
+#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */
+#define P4_STATIC (-2) /* Pointer to a static string */
+#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
+#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
+#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
+#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */
+#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
+#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
+#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
+#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */
+#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
+#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
+#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
+#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
+#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
+#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
+
+/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
+** is made. That copy is freed when the Vdbe is finalized. But if the
+** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still
+** gets freed when the Vdbe is finalized so it still should be obtained
+** from a single sqliteMalloc(). But no copy is made and the calling
+** function should *not* try to free the KeyInfo.
+*/
+#define P4_KEYINFO_HANDOFF (-16)
+#define P4_KEYINFO_STATIC (-17)
+
+/*
+** The Vdbe.aColName array contains 5n Mem structures, where n is the
+** number of columns of data returned by the statement.
+*/
+#define COLNAME_NAME 0
+#define COLNAME_DECLTYPE 1
+#define COLNAME_DATABASE 2
+#define COLNAME_TABLE 3
+#define COLNAME_COLUMN 4
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
+#else
+# ifdef SQLITE_OMIT_DECLTYPE
+# define COLNAME_N 1 /* Store only the name */
+# else
+# define COLNAME_N 2 /* Store the name and decltype */
+# endif
+#endif
+
+/*
+** The following macro converts a relative address in the p2 field
+** of a VdbeOp structure into a negative number so that
+** sqlite3VdbeAddOpList() knows that the address is relative. Calling
+** the macro again restores the address.
+*/
+#define ADDR(X) (-1-(X))
+
+/*
+** The makefile scans the vdbe.c source file and creates the "opcodes.h"
+** header file that defines a number for each opcode used by the VDBE.
+*/
+/************** Include opcodes.h in the middle of vdbe.h ********************/
+/************** Begin file opcodes.h *****************************************/
+/* Automatically generated. Do not edit */
+/* See the mkopcodeh.awk script for details */
+#define OP_Goto 1
+#define OP_Gosub 2
+#define OP_Return 3
+#define OP_Yield 4
+#define OP_HaltIfNull 5
+#define OP_Halt 6
+#define OP_Integer 7
+#define OP_Int64 8
+#define OP_Real 130 /* same as TK_FLOAT */
+#define OP_String8 94 /* same as TK_STRING */
+#define OP_String 9
+#define OP_Null 10
+#define OP_Blob 11
+#define OP_Variable 12
+#define OP_Move 13
+#define OP_Copy 14
+#define OP_SCopy 15
+#define OP_ResultRow 16
+#define OP_Concat 91 /* same as TK_CONCAT */
+#define OP_Add 86 /* same as TK_PLUS */
+#define OP_Subtract 87 /* same as TK_MINUS */
+#define OP_Multiply 88 /* same as TK_STAR */
+#define OP_Divide 89 /* same as TK_SLASH */
+#define OP_Remainder 90 /* same as TK_REM */
+#define OP_CollSeq 17
+#define OP_Function 18
+#define OP_BitAnd 82 /* same as TK_BITAND */
+#define OP_BitOr 83 /* same as TK_BITOR */
+#define OP_ShiftLeft 84 /* same as TK_LSHIFT */
+#define OP_ShiftRight 85 /* same as TK_RSHIFT */
+#define OP_AddImm 20
+#define OP_MustBeInt 21
+#define OP_RealAffinity 22
+#define OP_ToText 141 /* same as TK_TO_TEXT */
+#define OP_ToBlob 142 /* same as TK_TO_BLOB */
+#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/
+#define OP_ToInt 144 /* same as TK_TO_INT */
+#define OP_ToReal 145 /* same as TK_TO_REAL */
+#define OP_Eq 76 /* same as TK_EQ */
+#define OP_Ne 75 /* same as TK_NE */
+#define OP_Lt 79 /* same as TK_LT */
+#define OP_Le 78 /* same as TK_LE */
+#define OP_Gt 77 /* same as TK_GT */
+#define OP_Ge 80 /* same as TK_GE */
+#define OP_Permutation 23
+#define OP_Compare 24
+#define OP_Jump 25
+#define OP_And 69 /* same as TK_AND */
+#define OP_Or 68 /* same as TK_OR */
+#define OP_Not 19 /* same as TK_NOT */
+#define OP_BitNot 93 /* same as TK_BITNOT */
+#define OP_Once 26
+#define OP_If 27
+#define OP_IfNot 28
+#define OP_IsNull 73 /* same as TK_ISNULL */
+#define OP_NotNull 74 /* same as TK_NOTNULL */
+#define OP_Column 29
+#define OP_Affinity 30
+#define OP_MakeRecord 31
+#define OP_Count 32
+#define OP_Savepoint 33
+#define OP_AutoCommit 34
+#define OP_Transaction 35
+#define OP_ReadCookie 36
+#define OP_SetCookie 37
+#define OP_VerifyCookie 38
+#define OP_OpenRead 39
+#define OP_OpenWrite 40
+#define OP_OpenAutoindex 41
+#define OP_OpenEphemeral 42
+#define OP_SorterOpen 43
+#define OP_OpenPseudo 44
+#define OP_Close 45
+#define OP_SeekLt 46
+#define OP_SeekLe 47
+#define OP_SeekGe 48
+#define OP_SeekGt 49
+#define OP_Seek 50
+#define OP_NotFound 51
+#define OP_Found 52
+#define OP_IsUnique 53
+#define OP_NotExists 54
+#define OP_Sequence 55
+#define OP_NewRowid 56
+#define OP_Insert 57
+#define OP_InsertInt 58
+#define OP_Delete 59
+#define OP_ResetCount 60
+#define OP_SorterCompare 61
+#define OP_SorterData 62
+#define OP_RowKey 63
+#define OP_RowData 64
+#define OP_Rowid 65
+#define OP_NullRow 66
+#define OP_Last 67
+#define OP_SorterSort 70
+#define OP_Sort 71
+#define OP_Rewind 72
+#define OP_SorterNext 81
+#define OP_Prev 92
+#define OP_Next 95
+#define OP_SorterInsert 96
+#define OP_IdxInsert 97
+#define OP_IdxDelete 98
+#define OP_IdxRowid 99
+#define OP_IdxLT 100
+#define OP_IdxGE 101
+#define OP_Destroy 102
+#define OP_Clear 103
+#define OP_CreateIndex 104
+#define OP_CreateTable 105
+#define OP_ParseSchema 106
+#define OP_LoadAnalysis 107
+#define OP_DropTable 108
+#define OP_DropIndex 109
+#define OP_DropTrigger 110
+#define OP_IntegrityCk 111
+#define OP_RowSetAdd 112
+#define OP_RowSetRead 113
+#define OP_RowSetTest 114
+#define OP_Program 115
+#define OP_Param 116
+#define OP_FkCounter 117
+#define OP_FkIfZero 118
+#define OP_MemMax 119
+#define OP_IfPos 120
+#define OP_IfNeg 121
+#define OP_IfZero 122
+#define OP_AggStep 123
+#define OP_AggFinal 124
+#define OP_Checkpoint 125
+#define OP_JournalMode 126
+#define OP_Vacuum 127
+#define OP_IncrVacuum 128
+#define OP_Expire 129
+#define OP_TableLock 131
+#define OP_VBegin 132
+#define OP_VCreate 133
+#define OP_VDestroy 134
+#define OP_VOpen 135
+#define OP_VFilter 136
+#define OP_VColumn 137
+#define OP_VNext 138
+#define OP_VRename 139
+#define OP_VUpdate 140
+#define OP_Pagecount 146
+#define OP_MaxPgcnt 147
+#define OP_Trace 148
+#define OP_Noop 149
+#define OP_Explain 150
+
+
+/* Properties such as "out2" or "jump" that are specified in
+** comments following the "case" for each opcode in the vdbe.c
+** are encoded into bitvectors as follows:
+*/
+#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */
+#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */
+#define OPFLG_IN1 0x0004 /* in1: P1 is an input */
+#define OPFLG_IN2 0x0008 /* in2: P2 is an input */
+#define OPFLG_IN3 0x0010 /* in3: P3 is an input */
+#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */
+#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
+#define OPFLG_INITIALIZER {\
+/* 0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
+/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\
+/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
+/* 24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\
+/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
+/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
+/* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
+/* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
+/* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
+/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
+/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
+/* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
+/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
+/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\
+/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
+/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}
+
+/************** End of opcodes.h *********************************************/
+/************** Continuing where we left off in vdbe.h ***********************/
+
+/*
+** Prototypes for the VDBE interface. See comments on the implementation
+** for a description of what each of these routines does.
+*/
+SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*);
+SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
+SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
+SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
+SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
+SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
+SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
+SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
+SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
+SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
+SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
+SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
+SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
+SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
+SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
+SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int);
+SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*);
+#endif
+SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int);
+SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
+SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
+SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
+SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
+SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8);
+SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
+#ifndef SQLITE_OMIT_TRACE
+SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
+#endif
+
+SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
+
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
+#endif
+
+
+#ifndef NDEBUG
+SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...);
+# define VdbeComment(X) sqlite3VdbeComment X
+SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
+# define VdbeNoopComment(X) sqlite3VdbeNoopComment X
+#else
+# define VdbeComment(X)
+# define VdbeNoopComment(X)
+#endif
+
+#endif
+
+/************** End of vdbe.h ************************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include pager.h in the middle of sqliteInt.h *****************/
+/************** Begin file pager.h *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite page cache
+** subsystem. The page cache subsystem reads and writes a file a page
+** at a time and provides a journal for rollback.
+*/
+
+#ifndef _PAGER_H_
+#define _PAGER_H_
+
+/*
+** Default maximum size for persistent journal files. A negative
+** value means no limit. This value may be overridden using the
+** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit".
+*/
+#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
+ #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1
+#endif
+
+/*
+** The type used to represent a page number. The first page in a file
+** is called page 1. 0 is used to represent "not a page".
+*/
+typedef u32 Pgno;
+
+/*
+** Each open file is managed by a separate instance of the "Pager" structure.
+*/
+typedef struct Pager Pager;
+
+/*
+** Handle type for pages.
+*/
+typedef struct PgHdr DbPage;
+
+/*
+** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
+** reserved for working around a windows/posix incompatibility). It is
+** used in the journal to signify that the remainder of the journal file
+** is devoted to storing a master journal name - there are no more pages to
+** roll back. See comments for function writeMasterJournal() in pager.c
+** for details.
+*/
+#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
+
+/*
+** Allowed values for the flags parameter to sqlite3PagerOpen().
+**
+** NOTE: These values must match the corresponding BTREE_ values in btree.h.
+*/
+#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
+#define PAGER_MEMORY 0x0002 /* In-memory database */
+
+/*
+** Valid values for the second argument to sqlite3PagerLockingMode().
+*/
+#define PAGER_LOCKINGMODE_QUERY -1
+#define PAGER_LOCKINGMODE_NORMAL 0
+#define PAGER_LOCKINGMODE_EXCLUSIVE 1
+
+/*
+** Numeric constants that encode the journalmode.
+*/
+#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
+#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
+#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
+#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
+#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
+#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
+#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
+
+/*
+** The remainder of this file contains the declarations of the functions
+** that make up the Pager sub-system API. See source code comments for
+** a detailed description of each routine.
+*/
+
+/* Open and close a Pager connection. */
+SQLITE_PRIVATE int sqlite3PagerOpen(
+ sqlite3_vfs*,
+ Pager **ppPager,
+ const char*,
+ int,
+ int,
+ int,
+ void(*)(DbPage*)
+);
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
+
+/* Functions used to configure a Pager object. */
+SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
+SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
+SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
+SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
+SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
+SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
+SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
+SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
+SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
+SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*);
+SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
+SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
+
+/* Functions used to obtain and release page references. */
+SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
+#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
+SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
+SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
+
+/* Operations on page references. */
+SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
+SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
+SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*);
+SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
+SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
+
+/* Functions used to manage pager transactions and savepoints. */
+SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*);
+SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int);
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
+SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*);
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
+SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
+SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
+SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
+SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
+
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
+SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
+#endif
+
+#ifdef SQLITE_ENABLE_ZIPVFS
+SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
+#endif
+
+/* Functions used to query pager state and configuration. */
+SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
+SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
+SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
+SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
+SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
+SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
+SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
+SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
+SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
+SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
+SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
+SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *);
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
+
+/* Functions used to truncate the database file. */
+SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
+
+#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
+SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *);
+#endif
+
+/* Functions to support testing and debugging. */
+#if !defined(NDEBUG) || defined(SQLITE_TEST)
+SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*);
+SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*);
+#endif
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE int *sqlite3PagerStats(Pager*);
+SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
+ void disable_simulated_io_errors(void);
+ void enable_simulated_io_errors(void);
+#else
+# define disable_simulated_io_errors()
+# define enable_simulated_io_errors()
+#endif
+
+#endif /* _PAGER_H_ */
+
+/************** End of pager.h ***********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include pcache.h in the middle of sqliteInt.h ****************/
+/************** Begin file pcache.h ******************************************/
+/*
+** 2008 August 05
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite page cache
+** subsystem.
+*/
+
+#ifndef _PCACHE_H_
+
+typedef struct PgHdr PgHdr;
+typedef struct PCache PCache;
+
+/*
+** Every page in the cache is controlled by an instance of the following
+** structure.
+*/
+struct PgHdr {
+ sqlite3_pcache_page *pPage; /* Pcache object page handle */
+ void *pData; /* Page data */
+ void *pExtra; /* Extra content */
+ PgHdr *pDirty; /* Transient list of dirty pages */
+ Pager *pPager; /* The pager this page is part of */
+ Pgno pgno; /* Page number for this page */
+#ifdef SQLITE_CHECK_PAGES
+ u32 pageHash; /* Hash of page content */
+#endif
+ u16 flags; /* PGHDR flags defined below */
+
+ /**********************************************************************
+ ** Elements above are public. All that follows is private to pcache.c
+ ** and should not be accessed by other modules.
+ */
+ i16 nRef; /* Number of users of this page */
+ PCache *pCache; /* Cache that owns this page */
+
+ PgHdr *pDirtyNext; /* Next element in list of dirty pages */
+ PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
+};
+
+/* Bit values for PgHdr.flags */
+#define PGHDR_DIRTY 0x002 /* Page has changed */
+#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before
+ ** writing this page to the database */
+#define PGHDR_NEED_READ 0x008 /* Content is unread */
+#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */
+#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
+
+/* Initialize and shutdown the page cache subsystem */
+SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
+SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
+
+/* Page cache buffer management:
+** These routines implement SQLITE_CONFIG_PAGECACHE.
+*/
+SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n);
+
+/* Create a new pager cache.
+** Under memory stress, invoke xStress to try to make pages clean.
+** Only clean and unpinned pages can be reclaimed.
+*/
+SQLITE_PRIVATE void sqlite3PcacheOpen(
+ int szPage, /* Size of every page */
+ int szExtra, /* Extra space associated with each page */
+ int bPurgeable, /* True if pages are on backing store */
+ int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */
+ void *pStress, /* Argument to xStress */
+ PCache *pToInit /* Preallocated space for the PCache */
+);
+
+/* Modify the page-size after the cache has been created. */
+SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int);
+
+/* Return the size in bytes of a PCache object. Used to preallocate
+** storage space.
+*/
+SQLITE_PRIVATE int sqlite3PcacheSize(void);
+
+/* One release per successful fetch. Page is pinned until released.
+** Reference counted.
+*/
+SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
+SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*);
+
+SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
+SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
+SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
+SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
+
+/* Change a page number. Used by incr-vacuum. */
+SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno);
+
+/* Remove all pages with pgno>x. Reset the cache if x==0 */
+SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x);
+
+/* Get a list of all dirty pages in the cache, sorted by page number */
+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
+
+/* Reset and close the cache object */
+SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
+
+/* Clear flags from pages of the page cache */
+SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *);
+
+/* Discard the contents of the cache */
+SQLITE_PRIVATE void sqlite3PcacheClear(PCache*);
+
+/* Return the total number of outstanding page references */
+SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*);
+
+/* Increment the reference count of an existing page */
+SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*);
+
+SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*);
+
+/* Return the total number of pages stored in the cache */
+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
+
+#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
+/* Iterate through all dirty pages currently stored in the cache. This
+** interface is only available if SQLITE_CHECK_PAGES is defined when the
+** library is built.
+*/
+SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
+#endif
+
+/* Set and get the suggested cache-size for the specified pager-cache.
+**
+** If no global maximum is configured, then the system attempts to limit
+** the total number of pages cached by purgeable pager-caches to the sum
+** of the suggested cache-sizes.
+*/
+SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int);
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *);
+#endif
+
+/* Free up as much memory as possible from the page cache */
+SQLITE_PRIVATE void sqlite3PcacheShrink(PCache*);
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/* Try to return memory used by the pcache module to the main memory heap */
+SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int);
+#endif
+
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*);
+#endif
+
+SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
+
+#endif /* _PCACHE_H_ */
+
+/************** End of pcache.h **********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+
+/************** Include os.h in the middle of sqliteInt.h ********************/
+/************** Begin file os.h **********************************************/
+/*
+** 2001 September 16
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This header file (together with is companion C source-code file
+** "os.c") attempt to abstract the underlying operating system so that
+** the SQLite library will work on both POSIX and windows systems.
+**
+** This header file is #include-ed by sqliteInt.h and thus ends up
+** being included by every source file.
+*/
+#ifndef _SQLITE_OS_H_
+#define _SQLITE_OS_H_
+
+/*
+** Figure out if we are dealing with Unix, Windows, or some other
+** operating system. After the following block of preprocess macros,
+** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
+** will defined to either 1 or 0. One of the four will be 1. The other
+** three will be 0.
+*/
+#if defined(SQLITE_OS_OTHER)
+# if SQLITE_OS_OTHER==1
+# undef SQLITE_OS_UNIX
+# define SQLITE_OS_UNIX 0
+# undef SQLITE_OS_WIN
+# define SQLITE_OS_WIN 0
+# else
+# undef SQLITE_OS_OTHER
+# endif
+#endif
+#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
+# define SQLITE_OS_OTHER 0
+# ifndef SQLITE_OS_WIN
+# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
+# define SQLITE_OS_WIN 1
+# define SQLITE_OS_UNIX 0
+# else
+# define SQLITE_OS_WIN 0
+# define SQLITE_OS_UNIX 1
+# endif
+# else
+# define SQLITE_OS_UNIX 0
+# endif
+#else
+# ifndef SQLITE_OS_WIN
+# define SQLITE_OS_WIN 0
+# endif
+#endif
+
+#if SQLITE_OS_WIN
+# include <windows.h>
+#endif
+
+/*
+** Determine if we are dealing with Windows NT.
+**
+** We ought to be able to determine if we are compiling for win98 or winNT
+** using the _WIN32_WINNT macro as follows:
+**
+** #if defined(_WIN32_WINNT)
+** # define SQLITE_OS_WINNT 1
+** #else
+** # define SQLITE_OS_WINNT 0
+** #endif
+**
+** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
+** so the above test does not work. We'll just assume that everything is
+** winNT unless the programmer explicitly says otherwise by setting
+** SQLITE_OS_WINNT to 0.
+*/
+#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
+# define SQLITE_OS_WINNT 1
+#endif
+
+/*
+** Determine if we are dealing with WindowsCE - which has a much
+** reduced API.
+*/
+#if defined(_WIN32_WCE)
+# define SQLITE_OS_WINCE 1
+#else
+# define SQLITE_OS_WINCE 0
+#endif
+
+/*
+** Determine if we are dealing with WinRT, which provides only a subset of
+** the full Win32 API.
+*/
+#if !defined(SQLITE_OS_WINRT)
+# define SQLITE_OS_WINRT 0
+#endif
+
+/*
+** When compiled for WinCE or WinRT, there is no concept of the current
+** directory.
+ */
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+# define SQLITE_CURDIR 1
+#endif
+
+/* If the SET_FULLSYNC macro is not defined above, then make it
+** a no-op
+*/
+#ifndef SET_FULLSYNC
+# define SET_FULLSYNC(x,y)
+#endif
+
+/*
+** The default size of a disk sector
+*/
+#ifndef SQLITE_DEFAULT_SECTOR_SIZE
+# define SQLITE_DEFAULT_SECTOR_SIZE 4096
+#endif
+
+/*
+** Temporary files are named starting with this prefix followed by 16 random
+** alphanumeric characters, and no file extension. They are stored in the
+** OS's standard temporary file directory, and are deleted prior to exit.
+** If sqlite is being embedded in another program, you may wish to change the
+** prefix to reflect your program's name, so that if your program exits
+** prematurely, old temporary files can be easily identified. This can be done
+** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line.
+**
+** 2006-10-31: The default prefix used to be "sqlite_". But then
+** Mcafee started using SQLite in their anti-virus product and it
+** started putting files with the "sqlite" name in the c:/temp folder.
+** This annoyed many windows users. Those users would then do a
+** Google search for "sqlite", find the telephone numbers of the
+** developers and call to wake them up at night and complain.
+** For this reason, the default name prefix is changed to be "sqlite"
+** spelled backwards. So the temp files are still identified, but
+** anybody smart enough to figure out the code is also likely smart
+** enough to know that calling the developer will not help get rid
+** of the file.
+*/
+#ifndef SQLITE_TEMP_FILE_PREFIX
+# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
+#endif
+
+/*
+** The following values may be passed as the second argument to
+** sqlite3OsLock(). The various locks exhibit the following semantics:
+**
+** SHARED: Any number of processes may hold a SHARED lock simultaneously.
+** RESERVED: A single process may hold a RESERVED lock on a file at
+** any time. Other processes may hold and obtain new SHARED locks.
+** PENDING: A single process may hold a PENDING lock on a file at
+** any one time. Existing SHARED locks may persist, but no new
+** SHARED locks may be obtained by other processes.
+** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
+**
+** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
+** process that requests an EXCLUSIVE lock may actually obtain a PENDING
+** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
+** sqlite3OsLock().
+*/
+#define NO_LOCK 0
+#define SHARED_LOCK 1
+#define RESERVED_LOCK 2
+#define PENDING_LOCK 3
+#define EXCLUSIVE_LOCK 4
+
+/*
+** File Locking Notes: (Mostly about windows but also some info for Unix)
+**
+** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
+** those functions are not available. So we use only LockFile() and
+** UnlockFile().
+**
+** LockFile() prevents not just writing but also reading by other processes.
+** A SHARED_LOCK is obtained by locking a single randomly-chosen
+** byte out of a specific range of bytes. The lock byte is obtained at
+** random so two separate readers can probably access the file at the
+** same time, unless they are unlucky and choose the same lock byte.
+** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
+** There can only be one writer. A RESERVED_LOCK is obtained by locking
+** a single byte of the file that is designated as the reserved lock byte.
+** A PENDING_LOCK is obtained by locking a designated byte different from
+** the RESERVED_LOCK byte.
+**
+** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
+** which means we can use reader/writer locks. When reader/writer locks
+** are used, the lock is placed on the same range of bytes that is used
+** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
+** will support two or more Win95 readers or two or more WinNT readers.
+** But a single Win95 reader will lock out all WinNT readers and a single
+** WinNT reader will lock out all other Win95 readers.
+**
+** The following #defines specify the range of bytes used for locking.
+** SHARED_SIZE is the number of bytes available in the pool from which
+** a random byte is selected for a shared lock. The pool of bytes for
+** shared locks begins at SHARED_FIRST.
+**
+** The same locking strategy and
+** byte ranges are used for Unix. This leaves open the possiblity of having
+** clients on win95, winNT, and unix all talking to the same shared file
+** and all locking correctly. To do so would require that samba (or whatever
+** tool is being used for file sharing) implements locks correctly between
+** windows and unix. I'm guessing that isn't likely to happen, but by
+** using the same locking range we are at least open to the possibility.
+**
+** Locking in windows is manditory. For this reason, we cannot store
+** actual data in the bytes used for locking. The pager never allocates
+** the pages involved in locking therefore. SHARED_SIZE is selected so
+** that all locks will fit on a single page even at the minimum page size.
+** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE
+** is set high so that we don't have to allocate an unused page except
+** for very large databases. But one should test the page skipping logic
+** by setting PENDING_BYTE low and running the entire regression suite.
+**
+** Changing the value of PENDING_BYTE results in a subtly incompatible
+** file format. Depending on how it is changed, you might not notice
+** the incompatibility right away, even running a full regression test.
+** The default location of PENDING_BYTE is the first byte past the
+** 1GB boundary.
+**
+*/
+#ifdef SQLITE_OMIT_WSD
+# define PENDING_BYTE (0x40000000)
+#else
+# define PENDING_BYTE sqlite3PendingByte
+#endif
+#define RESERVED_BYTE (PENDING_BYTE+1)
+#define SHARED_FIRST (PENDING_BYTE+2)
+#define SHARED_SIZE 510
+
+/*
+** Wrapper around OS specific sqlite3_os_init() function.
+*/
+SQLITE_PRIVATE int sqlite3OsInit(void);
+
+/*
+** Functions for accessing sqlite3_file methods
+*/
+SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*);
+SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
+SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
+SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size);
+SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int);
+SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
+SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int);
+SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int);
+SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
+SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*);
+SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
+#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
+SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
+SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
+SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
+SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
+SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
+SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
+
+
+/*
+** Functions for accessing sqlite3_vfs methods
+*/
+SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
+SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
+SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
+SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
+SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *);
+SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
+SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
+SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
+SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
+
+/*
+** Convenience functions for opening and closing files using
+** sqlite3_malloc() to obtain space for the file-handle structure.
+*/
+SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
+SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
+
+#endif /* _SQLITE_OS_H_ */
+
+/************** End of os.h **************************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include mutex.h in the middle of sqliteInt.h *****************/
+/************** Begin file mutex.h *******************************************/
+/*
+** 2007 August 28
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains the common header for all mutex implementations.
+** The sqliteInt.h header #includes this file so that it is available
+** to all source files. We break it out in an effort to keep the code
+** better organized.
+**
+** NOTE: source files should *not* #include this header file directly.
+** Source files should #include the sqliteInt.h file and let that file
+** include this one indirectly.
+*/
+
+
+/*
+** Figure out what version of the code to use. The choices are
+**
+** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The
+** mutexes implemention cannot be overridden
+** at start-time.
+**
+** SQLITE_MUTEX_NOOP For single-threaded applications. No
+** mutual exclusion is provided. But this
+** implementation can be overridden at
+** start-time.
+**
+** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix.
+**
+** SQLITE_MUTEX_W32 For multi-threaded applications on Win32.
+*/
+#if !SQLITE_THREADSAFE
+# define SQLITE_MUTEX_OMIT
+#endif
+#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP)
+# if SQLITE_OS_UNIX
+# define SQLITE_MUTEX_PTHREADS
+# elif SQLITE_OS_WIN
+# define SQLITE_MUTEX_W32
+# else
+# define SQLITE_MUTEX_NOOP
+# endif
+#endif
+
+#ifdef SQLITE_MUTEX_OMIT
+/*
+** If this is a no-op implementation, implement everything as macros.
+*/
+#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
+#define sqlite3_mutex_free(X)
+#define sqlite3_mutex_enter(X)
+#define sqlite3_mutex_try(X) SQLITE_OK
+#define sqlite3_mutex_leave(X)
+#define sqlite3_mutex_held(X) ((void)(X),1)
+#define sqlite3_mutex_notheld(X) ((void)(X),1)
+#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8)
+#define sqlite3MutexInit() SQLITE_OK
+#define sqlite3MutexEnd()
+#define MUTEX_LOGIC(X)
+#else
+#define MUTEX_LOGIC(X) X
+#endif /* defined(SQLITE_MUTEX_OMIT) */
+
+/************** End of mutex.h ***********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+
+
+/*
+** Each database file to be accessed by the system is an instance
+** of the following structure. There are normally two of these structures
+** in the sqlite.aDb[] array. aDb[0] is the main database file and
+** aDb[1] is the database file used to hold temporary tables. Additional
+** databases may be attached.
+*/
+struct Db {
+ char *zName; /* Name of this database */
+ Btree *pBt; /* The B*Tree structure for this database file */
+ u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */
+ u8 safety_level; /* How aggressive at syncing data to disk */
+ Schema *pSchema; /* Pointer to database schema (possibly shared) */
+};
+
+/*
+** An instance of the following structure stores a database schema.
+**
+** Most Schema objects are associated with a Btree. The exception is
+** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing.
+** In shared cache mode, a single Schema object can be shared by multiple
+** Btrees that refer to the same underlying BtShared object.
+**
+** Schema objects are automatically deallocated when the last Btree that
+** references them is destroyed. The TEMP Schema is manually freed by
+** sqlite3_close().
+*
+** A thread must be holding a mutex on the corresponding Btree in order
+** to access Schema content. This implies that the thread must also be
+** holding a mutex on the sqlite3 connection pointer that owns the Btree.
+** For a TEMP Schema, only the connection mutex is required.
+*/
+struct Schema {
+ int schema_cookie; /* Database schema version number for this file */
+ int iGeneration; /* Generation counter. Incremented with each change */
+ Hash tblHash; /* All tables indexed by name */
+ Hash idxHash; /* All (named) indices indexed by name */
+ Hash trigHash; /* All triggers indexed by name */
+ Hash fkeyHash; /* All foreign keys by referenced table name */
+ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
+ u8 file_format; /* Schema format version for this file */
+ u8 enc; /* Text encoding used by this database */
+ u16 flags; /* Flags associated with this schema */
+ int cache_size; /* Number of pages to use in the cache */
+};
+
+/*
+** These macros can be used to test, set, or clear bits in the
+** Db.pSchema->flags field.
+*/
+#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P))
+#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0)
+#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P)
+#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P)
+
+/*
+** Allowed values for the DB.pSchema->flags field.
+**
+** The DB_SchemaLoaded flag is set after the database schema has been
+** read into internal hash tables.
+**
+** DB_UnresetViews means that one or more views have column names that
+** have been filled out. If the schema changes, these column names might
+** changes and so the view will need to be reset.
+*/
+#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */
+#define DB_UnresetViews 0x0002 /* Some views have defined column names */
+#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
+
+/*
+** The number of different kinds of things that can be limited
+** using the sqlite3_limit() interface.
+*/
+#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_DEPTH+1)
+
+/*
+** Lookaside malloc is a set of fixed-size buffers that can be used
+** to satisfy small transient memory allocation requests for objects
+** associated with a particular database connection. The use of
+** lookaside malloc provides a significant performance enhancement
+** (approx 10%) by avoiding numerous malloc/free requests while parsing
+** SQL statements.
+**
+** The Lookaside structure holds configuration information about the
+** lookaside malloc subsystem. Each available memory allocation in
+** the lookaside subsystem is stored on a linked list of LookasideSlot
+** objects.
+**
+** Lookaside allocations are only allowed for objects that are associated
+** with a particular database connection. Hence, schema information cannot
+** be stored in lookaside because in shared cache mode the schema information
+** is shared by multiple database connections. Therefore, while parsing
+** schema information, the Lookaside.bEnabled flag is cleared so that
+** lookaside allocations are not used to construct the schema objects.
+*/
+struct Lookaside {
+ u16 sz; /* Size of each buffer in bytes */
+ u8 bEnabled; /* False to disable new lookaside allocations */
+ u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
+ int nOut; /* Number of buffers currently checked out */
+ int mxOut; /* Highwater mark for nOut */
+ int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
+ LookasideSlot *pFree; /* List of available buffers */
+ void *pStart; /* First byte of available memory space */
+ void *pEnd; /* First byte past end of available space */
+};
+struct LookasideSlot {
+ LookasideSlot *pNext; /* Next buffer in the list of free buffers */
+};
+
+/*
+** A hash table for function definitions.
+**
+** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
+** Collisions are on the FuncDef.pHash chain.
+*/
+struct FuncDefHash {
+ FuncDef *a[23]; /* Hash table for functions */
+};
+
+/*
+** Each database connection is an instance of the following structure.
+*/
+struct sqlite3 {
+ sqlite3_vfs *pVfs; /* OS Interface */
+ struct Vdbe *pVdbe; /* List of active virtual machines */
+ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
+ sqlite3_mutex *mutex; /* Connection mutex */
+ Db *aDb; /* All backends */
+ int nDb; /* Number of backends currently in use */
+ int flags; /* Miscellaneous flags. See below */
+ i64 lastRowid; /* ROWID of most recent insert (see above) */
+ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
+ int errCode; /* Most recent error code (SQLITE_*) */
+ int errMask; /* & result codes with this before returning */
+ u16 dbOptFlags; /* Flags to enable/disable optimizations */
+ u8 autoCommit; /* The auto-commit flag. */
+ u8 temp_store; /* 1: file 2: memory 0: default */
+ u8 mallocFailed; /* True if we have seen a malloc failure */
+ u8 dfltLockMode; /* Default locking-mode for attached dbs */
+ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
+ u8 suppressErr; /* Do not issue error messages if true */
+ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
+ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
+ int nextPagesize; /* Pagesize after VACUUM if >0 */
+ u32 magic; /* Magic number for detect library misuse */
+ int nChange; /* Value returned by sqlite3_changes() */
+ int nTotalChange; /* Value returned by sqlite3_total_changes() */
+ int aLimit[SQLITE_N_LIMIT]; /* Limits */
+ struct sqlite3InitInfo { /* Information used during initialization */
+ int newTnum; /* Rootpage of table being initialized */
+ u8 iDb; /* Which db file is being initialized */
+ u8 busy; /* TRUE if currently initializing */
+ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */
+ } init;
+ int activeVdbeCnt; /* Number of VDBEs currently executing */
+ int writeVdbeCnt; /* Number of active VDBEs that are writing */
+ int vdbeExecCnt; /* Number of nested calls to VdbeExec() */
+ int nExtension; /* Number of loaded extensions */
+ void **aExtension; /* Array of shared library handles */
+ void (*xTrace)(void*,const char*); /* Trace function */
+ void *pTraceArg; /* Argument to the trace function */
+ void (*xProfile)(void*,const char*,u64); /* Profiling function */
+ void *pProfileArg; /* Argument to profile function */
+ void *pCommitArg; /* Argument to xCommitCallback() */
+ int (*xCommitCallback)(void*); /* Invoked at every commit. */
+ void *pRollbackArg; /* Argument to xRollbackCallback() */
+ void (*xRollbackCallback)(void*); /* Invoked at every commit. */
+ void *pUpdateArg;
+ void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
+#ifndef SQLITE_OMIT_WAL
+ int (*xWalCallback)(void *, sqlite3 *, const char *, int);
+ void *pWalArg;
+#endif
+ void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
+ void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
+ void *pCollNeededArg;
+ sqlite3_value *pErr; /* Most recent error message */
+ char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
+ char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
+ union {
+ volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
+ double notUsed1; /* Spacer */
+ } u1;
+ Lookaside lookaside; /* Lookaside malloc configuration */
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
+ /* Access authorization function */
+ void *pAuthArg; /* 1st argument to the access auth function */
+#endif
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ int (*xProgress)(void *); /* The progress callback */
+ void *pProgressArg; /* Argument to the progress callback */
+ int nProgressOps; /* Number of opcodes for progress callback */
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ int nVTrans; /* Allocated size of aVTrans */
+ Hash aModule; /* populated by sqlite3_create_module() */
+ VtabCtx *pVtabCtx; /* Context for active vtab connect/create */
+ VTable **aVTrans; /* Virtual tables with open transactions */
+ VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
+#endif
+ FuncDefHash aFunc; /* Hash table of connection functions */
+ Hash aCollSeq; /* All collating sequences */
+ BusyHandler busyHandler; /* Busy callback */
+ Db aDbStatic[2]; /* Static space for the 2 default backends */
+ Savepoint *pSavepoint; /* List of active savepoints */
+ int busyTimeout; /* Busy handler timeout, in msec */
+ int nSavepoint; /* Number of non-transaction savepoints */
+ int nStatement; /* Number of nested statement-transactions */
+ i64 nDeferredCons; /* Net deferred constraints this transaction. */
+ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
+
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+ /* The following variables are all protected by the STATIC_MASTER
+ ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
+ **
+ ** When X.pUnlockConnection==Y, that means that X is waiting for Y to
+ ** unlock so that it can proceed.
+ **
+ ** When X.pBlockingConnection==Y, that means that something that X tried
+ ** tried to do recently failed with an SQLITE_LOCKED error due to locks
+ ** held by Y.
+ */
+ sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
+ sqlite3 *pUnlockConnection; /* Connection to watch for unlock */
+ void *pUnlockArg; /* Argument to xUnlockNotify */
+ void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
+ sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
+#endif
+};
+
+/*
+** A macro to discover the encoding of a database.
+*/
+#define ENC(db) ((db)->aDb[0].pSchema->enc)
+
+/*
+** Possible values for the sqlite3.flags.
+*/
+#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
+#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
+#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
+#define SQLITE_ShortColNames 0x00000008 /* Show short columns names */
+#define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */
+ /* DELETE, or UPDATE and return */
+ /* the count using a callback. */
+#define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */
+ /* result set is empty */
+#define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */
+#define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */
+#define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */
+#define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */
+#define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */
+#define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */
+#define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */
+#define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */
+#define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */
+
+/*
+** Bits of the sqlite3.dbOptFlags field that are used by the
+** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
+** selectively disable various optimizations.
+*/
+#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
+#define SQLITE_ColumnCache 0x0002 /* Column cache */
+#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
+#define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */
+#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
+#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
+#define SQLITE_Transitive 0x0200 /* Transitive constraints */
+#define SQLITE_AllOpts 0xffff /* All optimizations */
+
+/*
+** Macros for testing whether or not optimizations are enabled or disabled.
+*/
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0)
+#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0)
+#else
+#define OptimizationDisabled(db, mask) 0
+#define OptimizationEnabled(db, mask) 1
+#endif
+
+/*
+** Possible values for the sqlite.magic field.
+** The numbers are obtained at random and have no special meaning, other
+** than being distinct from one another.
+*/
+#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */
+#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */
+#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */
+#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */
+#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */
+#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */
+
+/*
+** Each SQL function is defined by an instance of the following
+** structure. A pointer to this structure is stored in the sqlite.aFunc
+** hash table. When multiple functions have the same name, the hash table
+** points to a linked list of these structures.
+*/
+struct FuncDef {
+ i16 nArg; /* Number of arguments. -1 means unlimited */
+ u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
+ u8 flags; /* Some combination of SQLITE_FUNC_* */
+ void *pUserData; /* User data parameter */
+ FuncDef *pNext; /* Next function with same name */
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
+ void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */
+ char *zName; /* SQL name of the function. */
+ FuncDef *pHash; /* Next with a different name but the same hash */
+ FuncDestructor *pDestructor; /* Reference counted destructor function */
+};
+
+/*
+** This structure encapsulates a user-function destructor callback (as
+** configured using create_function_v2()) and a reference counter. When
+** create_function_v2() is called to create a function with a destructor,
+** a single object of this type is allocated. FuncDestructor.nRef is set to
+** the number of FuncDef objects created (either 1 or 3, depending on whether
+** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor
+** member of each of the new FuncDef objects is set to point to the allocated
+** FuncDestructor.
+**
+** Thereafter, when one of the FuncDef objects is deleted, the reference
+** count on this object is decremented. When it reaches 0, the destructor
+** is invoked and the FuncDestructor structure freed.
+*/
+struct FuncDestructor {
+ int nRef;
+ void (*xDestroy)(void *);
+ void *pUserData;
+};
+
+/*
+** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF
+** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
+** are assert() statements in the code to verify this.
+*/
+#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */
+#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
+#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */
+#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */
+#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */
+#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */
+
+/*
+** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
+** used to create the initializers for the FuncDef structures.
+**
+** FUNCTION(zName, nArg, iArg, bNC, xFunc)
+** Used to create a scalar function definition of a function zName
+** implemented by C function xFunc that accepts nArg arguments. The
+** value passed as iArg is cast to a (void*) and made available
+** as the user-data (sqlite3_user_data()) for the function. If
+** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
+**
+** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
+** Used to create an aggregate function definition implemented by
+** the C functions xStep and xFinal. The first four parameters
+** are interpreted in the same way as the first 4 parameters to
+** FUNCTION().
+**
+** LIKEFUNC(zName, nArg, pArg, flags)
+** Used to create a scalar function definition of a function zName
+** that accepts nArg arguments and is implemented by a call to C
+** function likeFunc. Argument pArg is cast to a (void *) and made
+** available as the function user-data (sqlite3_user_data()). The
+** FuncDef.flags variable is set to the value passed as the flags
+** parameter.
+*/
+#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
+ {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
+#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
+ {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
+#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
+ {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
+ pArg, 0, xFunc, 0, 0, #zName, 0, 0}
+#define LIKEFUNC(zName, nArg, arg, flags) \
+ {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
+#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
+ {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \
+ SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
+
+/*
+** All current savepoints are stored in a linked list starting at
+** sqlite3.pSavepoint. The first element in the list is the most recently
+** opened savepoint. Savepoints are added to the list by the vdbe
+** OP_Savepoint instruction.
+*/
+struct Savepoint {
+ char *zName; /* Savepoint name (nul-terminated) */
+ i64 nDeferredCons; /* Number of deferred fk violations */
+ Savepoint *pNext; /* Parent savepoint (if any) */
+};
+
+/*
+** The following are used as the second parameter to sqlite3Savepoint(),
+** and as the P1 argument to the OP_Savepoint instruction.
+*/
+#define SAVEPOINT_BEGIN 0
+#define SAVEPOINT_RELEASE 1
+#define SAVEPOINT_ROLLBACK 2
+
+
+/*
+** Each SQLite module (virtual table definition) is defined by an
+** instance of the following structure, stored in the sqlite3.aModule
+** hash table.
+*/
+struct Module {
+ const sqlite3_module *pModule; /* Callback pointers */
+ const char *zName; /* Name passed to create_module() */
+ void *pAux; /* pAux passed to create_module() */
+ void (*xDestroy)(void *); /* Module destructor function */
+};
+
+/*
+** information about each column of an SQL table is held in an instance
+** of this structure.
+*/
+struct Column {
+ char *zName; /* Name of this column */
+ Expr *pDflt; /* Default value of this column */
+ char *zDflt; /* Original text of the default value */
+ char *zType; /* Data type for this column */
+ char *zColl; /* Collating sequence. If NULL, use the default */
+ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
+ char affinity; /* One of the SQLITE_AFF_... values */
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
+};
+
+/* Allowed values for Column.colFlags:
+*/
+#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
+#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
+
+/*
+** A "Collating Sequence" is defined by an instance of the following
+** structure. Conceptually, a collating sequence consists of a name and
+** a comparison routine that defines the order of that sequence.
+**
+** If CollSeq.xCmp is NULL, it means that the
+** collating sequence is undefined. Indices built on an undefined
+** collating sequence may not be read or written.
+*/
+struct CollSeq {
+ char *zName; /* Name of the collating sequence, UTF-8 encoded */
+ u8 enc; /* Text encoding handled by xCmp() */
+ void *pUser; /* First argument to xCmp() */
+ int (*xCmp)(void*,int, const void*, int, const void*);
+ void (*xDel)(void*); /* Destructor for pUser */
+};
+
+/*
+** A sort order can be either ASC or DESC.
+*/
+#define SQLITE_SO_ASC 0 /* Sort in ascending order */
+#define SQLITE_SO_DESC 1 /* Sort in ascending order */
+
+/*
+** Column affinity types.
+**
+** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
+** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
+** the speed a little by numbering the values consecutively.
+**
+** But rather than start with 0 or 1, we begin with 'a'. That way,
+** when multiple affinity types are concatenated into a string and
+** used as the P4 operand, they will be more readable.
+**
+** Note also that the numeric types are grouped together so that testing
+** for a numeric type is a single comparison.
+*/
+#define SQLITE_AFF_TEXT 'a'
+#define SQLITE_AFF_NONE 'b'
+#define SQLITE_AFF_NUMERIC 'c'
+#define SQLITE_AFF_INTEGER 'd'
+#define SQLITE_AFF_REAL 'e'
+
+#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
+
+/*
+** The SQLITE_AFF_MASK values masks off the significant bits of an
+** affinity value.
+*/
+#define SQLITE_AFF_MASK 0x67
+
+/*
+** Additional bit values that can be ORed with an affinity without
+** changing the affinity.
+*/
+#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */
+#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */
+#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
+
+/*
+** An object of this type is created for each virtual table present in
+** the database schema.
+**
+** If the database schema is shared, then there is one instance of this
+** structure for each database connection (sqlite3*) that uses the shared
+** schema. This is because each database connection requires its own unique
+** instance of the sqlite3_vtab* handle used to access the virtual table
+** implementation. sqlite3_vtab* handles can not be shared between
+** database connections, even when the rest of the in-memory database
+** schema is shared, as the implementation often stores the database
+** connection handle passed to it via the xConnect() or xCreate() method
+** during initialization internally. This database connection handle may
+** then be used by the virtual table implementation to access real tables
+** within the database. So that they appear as part of the callers
+** transaction, these accesses need to be made via the same database
+** connection as that used to execute SQL operations on the virtual table.
+**
+** All VTable objects that correspond to a single table in a shared
+** database schema are initially stored in a linked-list pointed to by
+** the Table.pVTable member variable of the corresponding Table object.
+** When an sqlite3_prepare() operation is required to access the virtual
+** table, it searches the list for the VTable that corresponds to the
+** database connection doing the preparing so as to use the correct
+** sqlite3_vtab* handle in the compiled query.
+**
+** When an in-memory Table object is deleted (for example when the
+** schema is being reloaded for some reason), the VTable objects are not
+** deleted and the sqlite3_vtab* handles are not xDisconnect()ed
+** immediately. Instead, they are moved from the Table.pVTable list to
+** another linked list headed by the sqlite3.pDisconnect member of the
+** corresponding sqlite3 structure. They are then deleted/xDisconnected
+** next time a statement is prepared using said sqlite3*. This is done
+** to avoid deadlock issues involving multiple sqlite3.mutex mutexes.
+** Refer to comments above function sqlite3VtabUnlockList() for an
+** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect
+** list without holding the corresponding sqlite3.mutex mutex.
+**
+** The memory for objects of this type is always allocated by
+** sqlite3DbMalloc(), using the connection handle stored in VTable.db as
+** the first argument.
+*/
+struct VTable {
+ sqlite3 *db; /* Database connection associated with this table */
+ Module *pMod; /* Pointer to module implementation */
+ sqlite3_vtab *pVtab; /* Pointer to vtab instance */
+ int nRef; /* Number of pointers to this structure */
+ u8 bConstraint; /* True if constraints are supported */
+ int iSavepoint; /* Depth of the SAVEPOINT stack */
+ VTable *pNext; /* Next in linked list (see above) */
+};
+
+/*
+** Each SQL table is represented in memory by an instance of the
+** following structure.
+**
+** Table.zName is the name of the table. The case of the original
+** CREATE TABLE statement is stored, but case is not significant for
+** comparisons.
+**
+** Table.nCol is the number of columns in this table. Table.aCol is a
+** pointer to an array of Column structures, one for each column.
+**
+** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of
+** the column that is that key. Otherwise Table.iPKey is negative. Note
+** that the datatype of the PRIMARY KEY must be INTEGER for this field to
+** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
+** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
+** is generated for each row of the table. TF_HasPrimaryKey is set if
+** the table has any PRIMARY KEY, INTEGER or otherwise.
+**
+** Table.tnum is the page number for the root BTree page of the table in the
+** database file. If Table.iDb is the index of the database table backend
+** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
+** holds temporary tables and indices. If TF_Ephemeral is set
+** then the table is stored in a file that is automatically deleted
+** when the VDBE cursor to the table is closed. In this case Table.tnum
+** refers VDBE cursor number that holds the table open, not to the root
+** page number. Transient tables are used to hold the results of a
+** sub-query that appears instead of a real table name in the FROM clause
+** of a SELECT statement.
+*/
+struct Table {
+ char *zName; /* Name of the table or view */
+ Column *aCol; /* Information about each column */
+ Index *pIndex; /* List of SQL indexes on this table. */
+ Select *pSelect; /* NULL for tables. Points to definition if a view. */
+ FKey *pFKey; /* Linked list of all foreign keys in this table */
+ char *zColAff; /* String defining the affinity of each column */
+#ifndef SQLITE_OMIT_CHECK
+ ExprList *pCheck; /* All CHECK constraints */
+#endif
+ tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
+ int tnum; /* Root BTree node for this table (see note above) */
+ i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
+ i16 nCol; /* Number of columns in this table */
+ u16 nRef; /* Number of pointers to this Table */
+ u8 tabFlags; /* Mask of TF_* values */
+ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
+#ifndef SQLITE_OMIT_ALTERTABLE
+ int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ int nModuleArg; /* Number of arguments to the module */
+ char **azModuleArg; /* Text of all module args. [0] is module name */
+ VTable *pVTable; /* List of VTable objects. */
+#endif
+ Trigger *pTrigger; /* List of triggers stored in pSchema */
+ Schema *pSchema; /* Schema that contains this table */
+ Table *pNextZombie; /* Next on the Parse.pZombieTab list */
+};
+
+/*
+** Allowed values for Tabe.tabFlags.
+*/
+#define TF_Readonly 0x01 /* Read-only system table */
+#define TF_Ephemeral 0x02 /* An ephemeral table */
+#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
+#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
+#define TF_Virtual 0x10 /* Is a virtual table */
+
+
+/*
+** Test to see whether or not a table is a virtual table. This is
+** done as a macro so that it will be optimized out when virtual
+** table support is omitted from the build.
+*/
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
+# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
+#else
+# define IsVirtual(X) 0
+# define IsHiddenColumn(X) 0
+#endif
+
+/*
+** Each foreign key constraint is an instance of the following structure.
+**
+** A foreign key is associated with two tables. The "from" table is
+** the table that contains the REFERENCES clause that creates the foreign
+** key. The "to" table is the table that is named in the REFERENCES clause.
+** Consider this example:
+**
+** CREATE TABLE ex1(
+** a INTEGER PRIMARY KEY,
+** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x)
+** );
+**
+** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
+**
+** Each REFERENCES clause generates an instance of the following structure
+** which is attached to the from-table. The to-table need not exist when
+** the from-table is created. The existence of the to-table is not checked.
+*/
+struct FKey {
+ Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */
+ FKey *pNextFrom; /* Next foreign key in pFrom */
+ char *zTo; /* Name of table that the key points to (aka: Parent) */
+ FKey *pNextTo; /* Next foreign key on table named zTo */
+ FKey *pPrevTo; /* Previous foreign key on table named zTo */
+ int nCol; /* Number of columns in this key */
+ /* EV: R-30323-21917 */
+ u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
+ u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
+ Trigger *apTrigger[2]; /* Triggers for aAction[] actions */
+ struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
+ int iFrom; /* Index of column in pFrom */
+ char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */
+ } aCol[1]; /* One entry for each of nCol column s */
+};
+
+/*
+** SQLite supports many different ways to resolve a constraint
+** error. ROLLBACK processing means that a constraint violation
+** causes the operation in process to fail and for the current transaction
+** to be rolled back. ABORT processing means the operation in process
+** fails and any prior changes from that one operation are backed out,
+** but the transaction is not rolled back. FAIL processing means that
+** the operation in progress stops and returns an error code. But prior
+** changes due to the same operation are not backed out and no rollback
+** occurs. IGNORE means that the particular row that caused the constraint
+** error is not inserted or updated. Processing continues and no error
+** is returned. REPLACE means that preexisting database rows that caused
+** a UNIQUE constraint violation are removed so that the new insert or
+** update can proceed. Processing continues and no error is reported.
+**
+** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
+** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
+** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
+** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
+** referenced table row is propagated into the row that holds the
+** foreign key.
+**
+** The following symbolic values are used to record which type
+** of action to take.
+*/
+#define OE_None 0 /* There is no constraint to check */
+#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
+#define OE_Abort 2 /* Back out changes but do no rollback transaction */
+#define OE_Fail 3 /* Stop the operation but leave all prior changes */
+#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */
+#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */
+
+#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
+#define OE_SetNull 7 /* Set the foreign key value to NULL */
+#define OE_SetDflt 8 /* Set the foreign key value to its default */
+#define OE_Cascade 9 /* Cascade the changes */
+
+#define OE_Default 99 /* Do whatever the default action is */
+
+
+/*
+** An instance of the following structure is passed as the first
+** argument to sqlite3VdbeKeyCompare and is used to control the
+** comparison of the two index keys.
+*/
+struct KeyInfo {
+ sqlite3 *db; /* The database connection */
+ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
+ u16 nField; /* Number of entries in aColl[] */
+ u8 *aSortOrder; /* Sort order for each column. May be NULL */
+ CollSeq *aColl[1]; /* Collating sequence for each term of the key */
+};
+
+/*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index. A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassembled by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constituent fields.
+*/
+struct UnpackedRecord {
+ KeyInfo *pKeyInfo; /* Collation and sort-order information */
+ u16 nField; /* Number of entries in apMem[] */
+ u8 flags; /* Boolean settings. UNPACKED_... below */
+ i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */
+ Mem *aMem; /* Values */
+};
+
+/*
+** Allowed values of UnpackedRecord.flags
+*/
+#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */
+#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */
+#define UNPACKED_PREFIX_SEARCH 0x04 /* Ignore final (rowid) field */
+
+/*
+** Each SQL index is represented in memory by an
+** instance of the following structure.
+**
+** The columns of the table that are to be indexed are described
+** by the aiColumn[] field of this structure. For example, suppose
+** we have the following table and index:
+**
+** CREATE TABLE Ex1(c1 int, c2 int, c3 text);
+** CREATE INDEX Ex2 ON Ex1(c3,c1);
+**
+** In the Table structure describing Ex1, nCol==3 because there are
+** three columns in the table. In the Index structure describing
+** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
+** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
+** first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
+** The second column to be indexed (c1) has an index of 0 in
+** Ex1.aCol[], hence Ex2.aiColumn[1]==0.
+**
+** The Index.onError field determines whether or not the indexed columns
+** must be unique and what to do if they are not. When Index.onError=OE_None,
+** it means this is not a unique index. Otherwise it is a unique index
+** and the value of Index.onError indicate the which conflict resolution
+** algorithm to employ whenever an attempt is made to insert a non-unique
+** element.
+*/
+struct Index {
+ char *zName; /* Name of this index */
+ int *aiColumn; /* Which columns are used by this index. 1st is 0 */
+ tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
+ Table *pTable; /* The SQL table being indexed */
+ char *zColAff; /* String defining the affinity of each column */
+ Index *pNext; /* The next index associated with the same table */
+ Schema *pSchema; /* Schema containing this index */
+ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
+ char **azColl; /* Array of collation sequence names for index */
+ int tnum; /* DB Page containing root of this index */
+ u16 nColumn; /* Number of columns in table used by this index */
+ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
+ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+ unsigned bUnordered:1; /* Use this index for == or IN queries only */
+#ifdef SQLITE_ENABLE_STAT3
+ int nSample; /* Number of elements in aSample[] */
+ tRowcnt avgEq; /* Average nEq value for key values not in aSample */
+ IndexSample *aSample; /* Samples of the left-most key */
+#endif
+};
+
+/*
+** Each sample stored in the sqlite_stat3 table is represented in memory
+** using a structure of this type. See documentation at the top of the
+** analyze.c source file for additional information.
+*/
+struct IndexSample {
+ union {
+ char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
+ double r; /* Value if eType is SQLITE_FLOAT */
+ i64 i; /* Value if eType is SQLITE_INTEGER */
+ } u;
+ u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */
+ int nByte; /* Size in byte of text or blob. */
+ tRowcnt nEq; /* Est. number of rows where the key equals this sample */
+ tRowcnt nLt; /* Est. number of rows where key is less than this sample */
+ tRowcnt nDLt; /* Est. number of distinct keys less than this sample */
+};
+
+/*
+** Each token coming out of the lexer is an instance of
+** this structure. Tokens are also used as part of an expression.
+**
+** Note if Token.z==0 then Token.dyn and Token.n are undefined and
+** may contain random values. Do not make any assumptions about Token.dyn
+** and Token.n when Token.z==0.
+*/
+struct Token {
+ const char *z; /* Text of the token. Not NULL-terminated! */
+ unsigned int n; /* Number of characters in this token */
+};
+
+/*
+** An instance of this structure contains information needed to generate
+** code for a SELECT that contains aggregate functions.
+**
+** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
+** pointer to this structure. The Expr.iColumn field is the index in
+** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
+** code for that node.
+**
+** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
+** original Select structure that describes the SELECT statement. These
+** fields do not need to be freed when deallocating the AggInfo structure.
+*/
+struct AggInfo {
+ u8 directMode; /* Direct rendering mode means take data directly
+ ** from source tables rather than from accumulators */
+ u8 useSortingIdx; /* In direct mode, reference the sorting index rather
+ ** than the source table */
+ int sortingIdx; /* Cursor number of the sorting index */
+ int sortingIdxPTab; /* Cursor number of pseudo-table */
+ int nSortingColumn; /* Number of columns in the sorting index */
+ ExprList *pGroupBy; /* The group by clause */
+ struct AggInfo_col { /* For each column used in source tables */
+ Table *pTab; /* Source table */
+ int iTable; /* Cursor number of the source table */
+ int iColumn; /* Column number within the source table */
+ int iSorterColumn; /* Column number in the sorting index */
+ int iMem; /* Memory location that acts as accumulator */
+ Expr *pExpr; /* The original expression */
+ } *aCol;
+ int nColumn; /* Number of used entries in aCol[] */
+ int nAccumulator; /* Number of columns that show through to the output.
+ ** Additional columns are used only as parameters to
+ ** aggregate functions */
+ struct AggInfo_func { /* For each aggregate function */
+ Expr *pExpr; /* Expression encoding the function */
+ FuncDef *pFunc; /* The aggregate function implementation */
+ int iMem; /* Memory location that acts as accumulator */
+ int iDistinct; /* Ephemeral table used to enforce DISTINCT */
+ } *aFunc;
+ int nFunc; /* Number of entries in aFunc[] */
+};
+
+/*
+** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
+** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater
+** than 32767 we have to make it 32-bit. 16-bit is preferred because
+** it uses less memory in the Expr object, which is a big memory user
+** in systems with lots of prepared statements. And few applications
+** need more than about 10 or 20 variables. But some extreme users want
+** to have prepared statements with over 32767 variables, and for them
+** the option is available (at compile-time).
+*/
+#if SQLITE_MAX_VARIABLE_NUMBER<=32767
+typedef i16 ynVar;
+#else
+typedef int ynVar;
+#endif
+
+/*
+** Each node of an expression in the parse tree is an instance
+** of this structure.
+**
+** Expr.op is the opcode. The integer parser token codes are reused
+** as opcodes here. For example, the parser defines TK_GE to be an integer
+** code representing the ">=" operator. This same integer code is reused
+** to represent the greater-than-or-equal-to operator in the expression
+** tree.
+**
+** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
+** or TK_STRING), then Expr.token contains the text of the SQL literal. If
+** the expression is a variable (TK_VARIABLE), then Expr.token contains the
+** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
+** then Expr.token contains the name of the function.
+**
+** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
+** binary operator. Either or both may be NULL.
+**
+** Expr.x.pList is a list of arguments if the expression is an SQL function,
+** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
+** Expr.x.pSelect is used if the expression is a sub-select or an expression of
+** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
+** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
+** valid.
+**
+** An expression of the form ID or ID.ID refers to a column in a table.
+** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is
+** the integer cursor number of a VDBE cursor pointing to that table and
+** Expr.iColumn is the column number for the specific column. If the
+** expression is used as a result in an aggregate SELECT, then the
+** value is also stored in the Expr.iAgg column in the aggregate so that
+** it can be accessed after all aggregates are computed.
+**
+** If the expression is an unbound variable marker (a question mark
+** character '?' in the original SQL) then the Expr.iTable holds the index
+** number for that variable.
+**
+** If the expression is a subquery then Expr.iColumn holds an integer
+** register number containing the result of the subquery. If the
+** subquery gives a constant result, then iTable is -1. If the subquery
+** gives a different answer at different times during statement processing
+** then iTable is the address of a subroutine that computes the subquery.
+**
+** If the Expr is of type OP_Column, and the table it is selecting from
+** is a disk table or the "old.*" pseudo-table, then pTab points to the
+** corresponding table definition.
+**
+** ALLOCATION NOTES:
+**
+** Expr objects can use a lot of memory space in database schema. To
+** help reduce memory requirements, sometimes an Expr object will be
+** truncated. And to reduce the number of memory allocations, sometimes
+** two or more Expr objects will be stored in a single memory allocation,
+** together with Expr.zToken strings.
+**
+** If the EP_Reduced and EP_TokenOnly flags are set when
+** an Expr object is truncated. When EP_Reduced is set, then all
+** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
+** are contained within the same memory allocation. Note, however, that
+** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately
+** allocated, regardless of whether or not EP_Reduced is set.
+*/
+struct Expr {
+ u8 op; /* Operation performed by this node */
+ char affinity; /* The affinity of the column or 0 if not a column */
+ u16 flags; /* Various flags. EP_* See below */
+ union {
+ char *zToken; /* Token value. Zero terminated and dequoted */
+ int iValue; /* Non-negative integer value if EP_IntValue */
+ } u;
+
+ /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
+ ** space is allocated for the fields below this point. An attempt to
+ ** access them will result in a segfault or malfunction.
+ *********************************************************************/
+
+ Expr *pLeft; /* Left subnode */
+ Expr *pRight; /* Right subnode */
+ union {
+ ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
+ Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
+ } x;
+
+ /* If the EP_Reduced flag is set in the Expr.flags mask, then no
+ ** space is allocated for the fields below this point. An attempt to
+ ** access them will result in a segfault or malfunction.
+ *********************************************************************/
+
+#if SQLITE_MAX_EXPR_DEPTH>0
+ int nHeight; /* Height of the tree headed by this node */
+#endif
+ int iTable; /* TK_COLUMN: cursor number of table holding column
+ ** TK_REGISTER: register number
+ ** TK_TRIGGER: 1 -> new, 0 -> old */
+ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
+ ** TK_VARIABLE: variable number (always >= 1). */
+ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
+ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
+ u8 flags2; /* Second set of flags. EP2_... */
+ u8 op2; /* TK_REGISTER: original value of Expr.op
+ ** TK_COLUMN: the value of p5 for OP_Column
+ ** TK_AGG_FUNCTION: nesting depth */
+ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
+ Table *pTab; /* Table for TK_COLUMN expressions. */
+};
+
+/*
+** The following are the meanings of bits in the Expr.flags field.
+*/
+#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
+#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
+#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
+#define EP_Error 0x0008 /* Expression contains one or more errors */
+#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
+#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
+#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
+#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
+#define EP_FixedDest 0x0200 /* Result needed in a specific register */
+#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
+#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
+#define EP_Hint 0x1000 /* Not used */
+#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
+#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
+#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
+
+/*
+** The following are the meanings of bits in the Expr.flags2 field.
+*/
+#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */
+#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */
+
+/*
+** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible
+** flag on an expression structure. This flag is used for VV&A only. The
+** routine is implemented as a macro that only works when in debugging mode,
+** so as not to burden production code.
+*/
+#ifdef SQLITE_DEBUG
+# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible
+#else
+# define ExprSetIrreducible(X)
+#endif
+
+/*
+** These macros can be used to test, set, or clear bits in the
+** Expr.flags field.
+*/
+#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
+#define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0)
+#define ExprSetProperty(E,P) (E)->flags|=(P)
+#define ExprClearProperty(E,P) (E)->flags&=~(P)
+
+/*
+** Macros to determine the number of bytes required by a normal Expr
+** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
+** and an Expr struct with the EP_TokenOnly flag set.
+*/
+#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
+#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */
+#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */
+
+/*
+** Flags passed to the sqlite3ExprDup() function. See the header comment
+** above sqlite3ExprDup() for details.
+*/
+#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
+
+/*
+** A list of expressions. Each expression may optionally have a
+** name. An expr/name combination can be used in several ways, such
+** as the list of "expr AS ID" fields following a "SELECT" or in the
+** list of "ID = expr" items in an UPDATE. A list of expressions can
+** also be used as the argument to a function, in which case the a.zName
+** field is not used.
+**
+** By default the Expr.zSpan field holds a human-readable description of
+** the expression that is used in the generation of error messages and
+** column labels. In this case, Expr.zSpan is typically the text of a
+** column expression as it exists in a SELECT statement. However, if
+** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
+** of the result column in the form: DATABASE.TABLE.COLUMN. This later
+** form is used for name resolution with nested FROM clauses.
+*/
+struct ExprList {
+ int nExpr; /* Number of expressions on the list */
+ int iECursor; /* VDBE Cursor associated with this ExprList */
+ struct ExprList_item { /* For each expression in the list */
+ Expr *pExpr; /* The list of expressions */
+ char *zName; /* Token associated with this expression */
+ char *zSpan; /* Original text of the expression */
+ u8 sortOrder; /* 1 for DESC or 0 for ASC */
+ unsigned done :1; /* A flag to indicate when processing is finished */
+ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
+ u16 iOrderByCol; /* For ORDER BY, column number in result set */
+ u16 iAlias; /* Index into Parse.aAlias[] for zName */
+ } *a; /* Alloc a power of two greater or equal to nExpr */
+};
+
+/*
+** An instance of this structure is used by the parser to record both
+** the parse tree for an expression and the span of input text for an
+** expression.
+*/
+struct ExprSpan {
+ Expr *pExpr; /* The expression parse tree */
+ const char *zStart; /* First character of input text */
+ const char *zEnd; /* One character past the end of input text */
+};
+
+/*
+** An instance of this structure can hold a simple list of identifiers,
+** such as the list "a,b,c" in the following statements:
+**
+** INSERT INTO t(a,b,c) VALUES ...;
+** CREATE INDEX idx ON t(a,b,c);
+** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...;
+**
+** The IdList.a.idx field is used when the IdList represents the list of
+** column names after a table name in an INSERT statement. In the statement
+**
+** INSERT INTO t(a,b,c) ...
+**
+** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
+*/
+struct IdList {
+ struct IdList_item {
+ char *zName; /* Name of the identifier */
+ int idx; /* Index in some Table.aCol[] of a column named zName */
+ } *a;
+ int nId; /* Number of identifiers on the list */
+};
+
+/*
+** The bitmask datatype defined below is used for various optimizations.
+**
+** Changing this from a 64-bit to a 32-bit type limits the number of
+** tables in a join to 32 instead of 64. But it also reduces the size
+** of the library by 738 bytes on ix86.
+*/
+typedef u64 Bitmask;
+
+/*
+** The number of bits in a Bitmask. "BMS" means "BitMask Size".
+*/
+#define BMS ((int)(sizeof(Bitmask)*8))
+
+/*
+** The following structure describes the FROM clause of a SELECT statement.
+** Each table or subquery in the FROM clause is a separate element of
+** the SrcList.a[] array.
+**
+** With the addition of multiple database support, the following structure
+** can also be used to describe a particular table such as the table that
+** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL,
+** such a table must be a simple name: ID. But in SQLite, the table can
+** now be identified by a database name, a dot, then the table name: ID.ID.
+**
+** The jointype starts out showing the join type between the current table
+** and the next table on the list. The parser builds the list this way.
+** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
+** jointype expresses the join between the table and the previous table.
+**
+** In the colUsed field, the high-order bit (bit 63) is set if the table
+** contains more than 63 columns and the 64-th or later column is used.
+*/
+struct SrcList {
+ i16 nSrc; /* Number of tables or subqueries in the FROM clause */
+ i16 nAlloc; /* Number of entries allocated in a[] below */
+ struct SrcList_item {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ char *zName; /* Name of the table */
+ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
+ Table *pTab; /* An SQL table corresponding to zName */
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to manifest a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ u8 jointype; /* Type of join between this able and the previous */
+ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
+ unsigned isCorrelated :1; /* True if sub-query is correlated */
+ unsigned viaCoroutine :1; /* Implemented as a co-routine */
+#ifndef SQLITE_OMIT_EXPLAIN
+ u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
+#endif
+ int iCursor; /* The VDBE cursor number used to access this table */
+ Expr *pOn; /* The ON clause of a join */
+ IdList *pUsing; /* The USING clause of a join */
+ Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
+ char *zIndex; /* Identifier from "INDEXED BY <zIndex>" clause */
+ Index *pIndex; /* Index structure corresponding to zIndex, if any */
+ } a[1]; /* One entry for each identifier on the list */
+};
+
+/*
+** Permitted values of the SrcList.a.jointype field
+*/
+#define JT_INNER 0x0001 /* Any kind of inner or cross join */
+#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */
+#define JT_NATURAL 0x0004 /* True for a "natural" join */
+#define JT_LEFT 0x0008 /* Left outer join */
+#define JT_RIGHT 0x0010 /* Right outer join */
+#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */
+#define JT_ERROR 0x0040 /* unknown or unsupported join type */
+
+
+/*
+** A WherePlan object holds information that describes a lookup
+** strategy.
+**
+** This object is intended to be opaque outside of the where.c module.
+** It is included here only so that that compiler will know how big it
+** is. None of the fields in this object should be used outside of
+** the where.c module.
+**
+** Within the union, pIdx is only used when wsFlags&WHERE_INDEXED is true.
+** pTerm is only used when wsFlags&WHERE_MULTI_OR is true. And pVtabIdx
+** is only used when wsFlags&WHERE_VIRTUALTABLE is true. It is never the
+** case that more than one of these conditions is true.
+*/
+struct WherePlan {
+ u32 wsFlags; /* WHERE_* flags that describe the strategy */
+ u16 nEq; /* Number of == constraints */
+ u16 nOBSat; /* Number of ORDER BY terms satisfied */
+ double nRow; /* Estimated number of rows (for EQP) */
+ union {
+ Index *pIdx; /* Index when WHERE_INDEXED is true */
+ struct WhereTerm *pTerm; /* WHERE clause term for OR-search */
+ sqlite3_index_info *pVtabIdx; /* Virtual table index to use */
+ } u;
+};
+
+/*
+** For each nested loop in a WHERE clause implementation, the WhereInfo
+** structure contains a single instance of this structure. This structure
+** is intended to be private to the where.c module and should not be
+** access or modified by other modules.
+**
+** The pIdxInfo field is used to help pick the best index on a
+** virtual table. The pIdxInfo pointer contains indexing
+** information for the i-th table in the FROM clause before reordering.
+** All the pIdxInfo pointers are freed by whereInfoFree() in where.c.
+** All other information in the i-th WhereLevel object for the i-th table
+** after FROM clause ordering.
+*/
+struct WhereLevel {
+ WherePlan plan; /* query plan for this element of the FROM clause */
+ int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
+ int iTabCur; /* The VDBE cursor used to access the table */
+ int iIdxCur; /* The VDBE cursor used to access pIdx */
+ int addrBrk; /* Jump here to break out of the loop */
+ int addrNxt; /* Jump here to start the next IN combination */
+ int addrCont; /* Jump here to continue with the next loop cycle */
+ int addrFirst; /* First instruction of interior of the loop */
+ u8 iFrom; /* Which entry in the FROM clause */
+ u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
+ int p1, p2; /* Operands of the opcode used to ends the loop */
+ union { /* Information that depends on plan.wsFlags */
+ struct {
+ int nIn; /* Number of entries in aInLoop[] */
+ struct InLoop {
+ int iCur; /* The VDBE cursor used by this IN operator */
+ int addrInTop; /* Top of the IN loop */
+ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
+ } *aInLoop; /* Information about each nested IN operator */
+ } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
+ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
+ } u;
+ double rOptCost; /* "Optimal" cost for this level */
+
+ /* The following field is really not part of the current level. But
+ ** we need a place to cache virtual table index information for each
+ ** virtual table in the FROM clause and the WhereLevel structure is
+ ** a convenient place since there is one WhereLevel for each FROM clause
+ ** element.
+ */
+ sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */
+};
+
+/*
+** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
+** and the WhereInfo.wctrlFlags member.
+*/
+#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
+#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
+#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
+#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
+#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
+#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
+#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
+#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
+#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
+
+/*
+** The WHERE clause processing routine has two halves. The
+** first part does the start of the WHERE loop and the second
+** half does the tail of the WHERE loop. An instance of
+** this structure is returned by the first half and passed
+** into the second half to give some continuity.
+*/
+struct WhereInfo {
+ Parse *pParse; /* Parsing and code generating context */
+ SrcList *pTabList; /* List of tables in the join */
+ u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */
+ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
+ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
+ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
+ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
+ int iTop; /* The very beginning of the WHERE loop */
+ int iContinue; /* Jump here to continue with next record */
+ int iBreak; /* Jump here to break out of the loop */
+ int nLevel; /* Number of nested loop */
+ struct WhereClause *pWC; /* Decomposition of the WHERE clause */
+ double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
+ double nRowOut; /* Estimated number of output rows */
+ WhereLevel a[1]; /* Information about each nest loop in WHERE */
+};
+
+/* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */
+#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
+#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
+#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */
+#define WHERE_DISTINCT_UNORDERED 3 /* Duplicates are scattered */
+
+/*
+** A NameContext defines a context in which to resolve table and column
+** names. The context consists of a list of tables (the pSrcList) field and
+** a list of named expression (pEList). The named expression list may
+** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
+** to the table being operated on by INSERT, UPDATE, or DELETE. The
+** pEList corresponds to the result set of a SELECT and is NULL for
+** other statements.
+**
+** NameContexts can be nested. When resolving names, the inner-most
+** context is searched first. If no match is found, the next outer
+** context is checked. If there is still no match, the next context
+** is checked. This process continues until either a match is found
+** or all contexts are check. When a match is found, the nRef member of
+** the context containing the match is incremented.
+**
+** Each subquery gets a new NameContext. The pNext field points to the
+** NameContext in the parent query. Thus the process of scanning the
+** NameContext list corresponds to searching through successively outer
+** subqueries looking for a match.
+*/
+struct NameContext {
+ Parse *pParse; /* The parser */
+ SrcList *pSrcList; /* One or more tables used to resolve names */
+ ExprList *pEList; /* Optional list of named expressions */
+ AggInfo *pAggInfo; /* Information about aggregates at this level */
+ NameContext *pNext; /* Next outer name context. NULL for outermost */
+ int nRef; /* Number of names resolved by this context */
+ int nErr; /* Number of errors encountered while resolving names */
+ u8 ncFlags; /* Zero or more NC_* flags defined below */
+};
+
+/*
+** Allowed values for the NameContext, ncFlags field.
+*/
+#define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */
+#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
+#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
+#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
+
+/*
+** An instance of the following structure contains all information
+** needed to generate code for a single SELECT statement.
+**
+** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0.
+** If there is a LIMIT clause, the parser sets nLimit to the value of the
+** limit and nOffset to the value of the offset (or 0 if there is not
+** offset). But later on, nLimit and nOffset become the memory locations
+** in the VDBE that record the limit and offset counters.
+**
+** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
+** These addresses must be stored so that we can go back and fill in
+** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
+** the number of columns in P2 can be computed at the same time
+** as the OP_OpenEphm instruction is coded because not
+** enough information about the compound query is known at that point.
+** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
+** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
+** sequences for the ORDER BY clause.
+*/
+struct Select {
+ ExprList *pEList; /* The fields of the result */
+ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
+ u16 selFlags; /* Various SF_* values */
+ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
+ int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
+ double nSelectRow; /* Estimated number of result rows */
+ SrcList *pSrc; /* The FROM clause */
+ Expr *pWhere; /* The WHERE clause */
+ ExprList *pGroupBy; /* The GROUP BY clause */
+ Expr *pHaving; /* The HAVING clause */
+ ExprList *pOrderBy; /* The ORDER BY clause */
+ Select *pPrior; /* Prior select in a compound select statement */
+ Select *pNext; /* Next select to the left in a compound */
+ Select *pRightmost; /* Right-most select in a compound select statement */
+ Expr *pLimit; /* LIMIT expression. NULL means not used. */
+ Expr *pOffset; /* OFFSET expression. NULL means not used. */
+};
+
+/*
+** Allowed values for Select.selFlags. The "SF" prefix stands for
+** "Select Flag".
+*/
+#define SF_Distinct 0x0001 /* Output should be DISTINCT */
+#define SF_Resolved 0x0002 /* Identifiers have been resolved */
+#define SF_Aggregate 0x0004 /* Contains aggregate functions */
+#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
+#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
+#define SF_UseSorter 0x0040 /* Sort using a sorter */
+#define SF_Values 0x0080 /* Synthesized from VALUES clause */
+#define SF_Materialize 0x0100 /* Force materialization of views */
+#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
+
+
+/*
+** The results of a select can be distributed in several ways. The
+** "SRT" prefix means "SELECT Result Type".
+*/
+#define SRT_Union 1 /* Store result as keys in an index */
+#define SRT_Except 2 /* Remove result from a UNION index */
+#define SRT_Exists 3 /* Store 1 if the result is not empty */
+#define SRT_Discard 4 /* Do not save the results anywhere */
+
+/* The ORDER BY clause is ignored for all of the above */
+#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
+
+#define SRT_Output 5 /* Output each row of result */
+#define SRT_Mem 6 /* Store result in a memory cell */
+#define SRT_Set 7 /* Store results as keys in an index */
+#define SRT_Table 8 /* Store result as data with an automatic rowid */
+#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */
+#define SRT_Coroutine 10 /* Generate a single row of result */
+
+/*
+** An instance of this object describes where to put of the results of
+** a SELECT statement.
+*/
+struct SelectDest {
+ u8 eDest; /* How to dispose of the results. On of SRT_* above. */
+ char affSdst; /* Affinity used when eDest==SRT_Set */
+ int iSDParm; /* A parameter used by the eDest disposal method */
+ int iSdst; /* Base register where results are written */
+ int nSdst; /* Number of registers allocated */
+};
+
+/*
+** During code generation of statements that do inserts into AUTOINCREMENT
+** tables, the following information is attached to the Table.u.autoInc.p
+** pointer of each autoincrement table to record some side information that
+** the code generator needs. We have to keep per-table autoincrement
+** information in case inserts are down within triggers. Triggers do not
+** normally coordinate their activities, but we do need to coordinate the
+** loading and saving of autoincrement information.
+*/
+struct AutoincInfo {
+ AutoincInfo *pNext; /* Next info block in a list of them all */
+ Table *pTab; /* Table this info block refers to */
+ int iDb; /* Index in sqlite3.aDb[] of database holding pTab */
+ int regCtr; /* Memory register holding the rowid counter */
+};
+
+/*
+** Size of the column cache
+*/
+#ifndef SQLITE_N_COLCACHE
+# define SQLITE_N_COLCACHE 10
+#endif
+
+/*
+** At least one instance of the following structure is created for each
+** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
+** statement. All such objects are stored in the linked list headed at
+** Parse.pTriggerPrg and deleted once statement compilation has been
+** completed.
+**
+** A Vdbe sub-program that implements the body and WHEN clause of trigger
+** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of
+** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable.
+** The Parse.pTriggerPrg list never contains two entries with the same
+** values for both pTrigger and orconf.
+**
+** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
+** accessed (or set to 0 for triggers fired as a result of INSERT
+** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
+** a mask of new.* columns used by the program.
+*/
+struct TriggerPrg {
+ Trigger *pTrigger; /* Trigger this program was coded from */
+ TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */
+ SubProgram *pProgram; /* Program implementing pTrigger/orconf */
+ int orconf; /* Default ON CONFLICT policy */
+ u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */
+};
+
+/*
+** The yDbMask datatype for the bitmask of all attached databases.
+*/
+#if SQLITE_MAX_ATTACHED>30
+ typedef sqlite3_uint64 yDbMask;
+#else
+ typedef unsigned int yDbMask;
+#endif
+
+/*
+** An SQL parser context. A copy of this structure is passed through
+** the parser and down into all the parser action routine in order to
+** carry around information that is global to the entire parse.
+**
+** The structure is divided into two parts. When the parser and code
+** generate call themselves recursively, the first part of the structure
+** is constant but the second part is reset at the beginning and end of
+** each recursion.
+**
+** The nTableLock and aTableLock variables are only used if the shared-cache
+** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
+** used to store the set of table-locks required by the statement being
+** compiled. Function sqlite3TableLock() is used to add entries to the
+** list.
+*/
+struct Parse {
+ sqlite3 *db; /* The main database structure */
+ char *zErrMsg; /* An error message */
+ Vdbe *pVdbe; /* An engine for executing database bytecode */
+ int rc; /* Return code from execution */
+ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
+ u8 checkSchema; /* Causes schema cookie check after an error */
+ u8 nested; /* Number of nested calls to the parser/code generator */
+ u8 nTempReg; /* Number of temporary registers in aTempReg[] */
+ u8 nTempInUse; /* Number of aTempReg[] currently checked out */
+ u8 nColCache; /* Number of entries in aColCache[] */
+ u8 iColCache; /* Next entry in aColCache[] to replace */
+ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
+ u8 mayAbort; /* True if statement may throw an ABORT exception */
+ int aTempReg[8]; /* Holding area for temporary registers */
+ int nRangeReg; /* Size of the temporary register block */
+ int iRangeReg; /* First register in temporary register block */
+ int nErr; /* Number of errors seen */
+ int nTab; /* Number of previously allocated VDBE cursors */
+ int nMem; /* Number of memory cells used so far */
+ int nSet; /* Number of sets used so far */
+ int nOnce; /* Number of OP_Once instructions so far */
+ int ckBase; /* Base register of data during check constraints */
+ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
+ int iCacheCnt; /* Counter used to generate aColCache[].lru values */
+ struct yColCache {
+ int iTable; /* Table cursor number */
+ int iColumn; /* Table column number */
+ u8 tempReg; /* iReg is a temp register that needs to be freed */
+ int iLevel; /* Nesting level */
+ int iReg; /* Reg with value of this column. 0 means none. */
+ int lru; /* Least recently used entry has the smallest value */
+ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
+ yDbMask writeMask; /* Start a write transaction on these databases */
+ yDbMask cookieMask; /* Bitmask of schema verified databases */
+ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
+ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
+ int regRowid; /* Register holding rowid of CREATE TABLE entry */
+ int regRoot; /* Register holding root page number for new objects */
+ int nMaxArg; /* Max args passed to user function by sub-program */
+ Token constraintName;/* Name of the constraint currently being parsed */
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ int nTableLock; /* Number of locks in aTableLock */
+ TableLock *aTableLock; /* Required table locks for shared-cache mode */
+#endif
+ AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
+
+ /* Information used while coding trigger programs. */
+ Parse *pToplevel; /* Parse structure for main program (or NULL) */
+ Table *pTriggerTab; /* Table triggers are being coded for */
+ double nQueryLoop; /* Estimated number of iterations of a query */
+ u32 oldmask; /* Mask of old.* columns referenced */
+ u32 newmask; /* Mask of new.* columns referenced */
+ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
+ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
+ u8 disableTriggers; /* True to disable triggers */
+
+ /* Above is constant between recursions. Below is reset before and after
+ ** each recursion */
+
+ int nVar; /* Number of '?' variables seen in the SQL so far */
+ int nzVar; /* Number of available slots in azVar[] */
+ u8 explain; /* True if the EXPLAIN flag is found on the query */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
+ int nVtabLock; /* Number of virtual tables to lock */
+#endif
+ int nAlias; /* Number of aliased result set columns */
+ int nHeight; /* Expression tree height of current sub-select */
+#ifndef SQLITE_OMIT_EXPLAIN
+ int iSelectId; /* ID of current select for EXPLAIN output */
+ int iNextSelectId; /* Next available select ID for EXPLAIN output */
+#endif
+ char **azVar; /* Pointers to names of parameters */
+ Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
+ int *aAlias; /* Register used to hold aliased result */
+ const char *zTail; /* All SQL text past the last semicolon parsed */
+ Table *pNewTable; /* A table being constructed by CREATE TABLE */
+ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
+ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
+ Token sNameToken; /* Token with unqualified schema object name */
+ Token sLastToken; /* The last token parsed */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ Token sArg; /* Complete text of a module argument */
+ Table **apVtabLock; /* Pointer to virtual tables needing locking */
+#endif
+ Table *pZombieTab; /* List of Table objects to delete after code gen */
+ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
+};
+
+/*
+** Return true if currently inside an sqlite3_declare_vtab() call.
+*/
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+ #define IN_DECLARE_VTAB 0
+#else
+ #define IN_DECLARE_VTAB (pParse->declareVtab)
+#endif
+
+/*
+** An instance of the following structure can be declared on a stack and used
+** to save the Parse.zAuthContext value so that it can be restored later.
+*/
+struct AuthContext {
+ const char *zAuthContext; /* Put saved Parse.zAuthContext here */
+ Parse *pParse; /* The Parse structure */
+};
+
+/*
+** Bitfield flags for P5 value in various opcodes.
+*/
+#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */
+#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
+#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
+#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
+#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
+#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
+#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
+#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
+#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
+#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
+#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
+
+/*
+ * Each trigger present in the database schema is stored as an instance of
+ * struct Trigger.
+ *
+ * Pointers to instances of struct Trigger are stored in two ways.
+ * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
+ * database). This allows Trigger structures to be retrieved by name.
+ * 2. All triggers associated with a single table form a linked list, using the
+ * pNext member of struct Trigger. A pointer to the first element of the
+ * linked list is stored as the "pTrigger" member of the associated
+ * struct Table.
+ *
+ * The "step_list" member points to the first element of a linked list
+ * containing the SQL statements specified as the trigger program.
+ */
+struct Trigger {
+ char *zName; /* The name of the trigger */
+ char *table; /* The table or view to which the trigger applies */
+ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
+ u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
+ Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
+ IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
+ the <column-list> is stored here */
+ Schema *pSchema; /* Schema containing the trigger */
+ Schema *pTabSchema; /* Schema containing the table */
+ TriggerStep *step_list; /* Link list of trigger program steps */
+ Trigger *pNext; /* Next trigger associated with the table */
+};
+
+/*
+** A trigger is either a BEFORE or an AFTER trigger. The following constants
+** determine which.
+**
+** If there are multiple triggers, you might of some BEFORE and some AFTER.
+** In that cases, the constants below can be ORed together.
+*/
+#define TRIGGER_BEFORE 1
+#define TRIGGER_AFTER 2
+
+/*
+ * An instance of struct TriggerStep is used to store a single SQL statement
+ * that is a part of a trigger-program.
+ *
+ * Instances of struct TriggerStep are stored in a singly linked list (linked
+ * using the "pNext" member) referenced by the "step_list" member of the
+ * associated struct Trigger instance. The first element of the linked list is
+ * the first step of the trigger-program.
+ *
+ * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
+ * "SELECT" statement. The meanings of the other members is determined by the
+ * value of "op" as follows:
+ *
+ * (op == TK_INSERT)
+ * orconf -> stores the ON CONFLICT algorithm
+ * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
+ * this stores a pointer to the SELECT statement. Otherwise NULL.
+ * target -> A token holding the quoted name of the table to insert into.
+ * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
+ * this stores values to be inserted. Otherwise NULL.
+ * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
+ * statement, then this stores the column-names to be
+ * inserted into.
+ *
+ * (op == TK_DELETE)
+ * target -> A token holding the quoted name of the table to delete from.
+ * pWhere -> The WHERE clause of the DELETE statement if one is specified.
+ * Otherwise NULL.
+ *
+ * (op == TK_UPDATE)
+ * target -> A token holding the quoted name of the table to update rows of.
+ * pWhere -> The WHERE clause of the UPDATE statement if one is specified.
+ * Otherwise NULL.
+ * pExprList -> A list of the columns to update and the expressions to update
+ * them to. See sqlite3Update() documentation of "pChanges"
+ * argument.
+ *
+ */
+struct TriggerStep {
+ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
+ u8 orconf; /* OE_Rollback etc. */
+ Trigger *pTrig; /* The trigger that this step is a part of */
+ Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
+ Token target; /* Target table for DELETE, UPDATE, INSERT */
+ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
+ ExprList *pExprList; /* SET clause for UPDATE. VALUES clause for INSERT */
+ IdList *pIdList; /* Column names for INSERT */
+ TriggerStep *pNext; /* Next in the link-list */
+ TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
+};
+
+/*
+** The following structure contains information used by the sqliteFix...
+** routines as they walk the parse tree to make database references
+** explicit.
+*/
+typedef struct DbFixer DbFixer;
+struct DbFixer {
+ Parse *pParse; /* The parsing context. Error messages written here */
+ Schema *pSchema; /* Fix items to this schema */
+ const char *zDb; /* Make sure all objects are contained in this database */
+ const char *zType; /* Type of the container - used for error messages */
+ const Token *pName; /* Name of the container - used for error messages */
+};
+
+/*
+** An objected used to accumulate the text of a string where we
+** do not necessarily know how big the string will be in the end.
+*/
+struct StrAccum {
+ sqlite3 *db; /* Optional database for lookaside. Can be NULL */
+ char *zBase; /* A base allocation. Not from malloc. */
+ char *zText; /* The string collected so far */
+ int nChar; /* Length of the string so far */
+ int nAlloc; /* Amount of space allocated in zText */
+ int mxAlloc; /* Maximum allowed string length */
+ u8 mallocFailed; /* Becomes true if any memory allocation fails */
+ u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */
+ u8 tooBig; /* Becomes true if string size exceeds limits */
+};
+
+/*
+** A pointer to this structure is used to communicate information
+** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
+*/
+typedef struct {
+ sqlite3 *db; /* The database being initialized */
+ char **pzErrMsg; /* Error message stored here */
+ int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
+ int rc; /* Result code stored here */
+} InitData;
+
+/*
+** Structure containing global configuration data for the SQLite library.
+**
+** This structure also contains some state information.
+*/
+struct Sqlite3Config {
+ int bMemstat; /* True to enable memory status */
+ int bCoreMutex; /* True to enable core mutexing */
+ int bFullMutex; /* True to enable full mutexing */
+ int bOpenUri; /* True to interpret filenames as URIs */
+ int bUseCis; /* Use covering indices for full-scans */
+ int mxStrlen; /* Maximum string length */
+ int szLookaside; /* Default lookaside buffer size */
+ int nLookaside; /* Default lookaside buffer count */
+ sqlite3_mem_methods m; /* Low-level memory allocation interface */
+ sqlite3_mutex_methods mutex; /* Low-level mutex interface */
+ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */
+ void *pHeap; /* Heap storage space */
+ int nHeap; /* Size of pHeap[] */
+ int mnReq, mxReq; /* Min and max heap requests sizes */
+ void *pScratch; /* Scratch memory */
+ int szScratch; /* Size of each scratch buffer */
+ int nScratch; /* Number of scratch buffers */
+ void *pPage; /* Page cache memory */
+ int szPage; /* Size of each page in pPage[] */
+ int nPage; /* Number of pages in pPage[] */
+ int mxParserStack; /* maximum depth of the parser stack */
+ int sharedCacheEnabled; /* true if shared-cache mode enabled */
+ /* The above might be initialized to non-zero. The following need to always
+ ** initially be zero, however. */
+ int isInit; /* True after initialization has finished */
+ int inProgress; /* True while initialization in progress */
+ int isMutexInit; /* True after mutexes are initialized */
+ int isMallocInit; /* True after malloc is initialized */
+ int isPCacheInit; /* True after malloc is initialized */
+ sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
+ int nRefInitMutex; /* Number of users of pInitMutex */
+ void (*xLog)(void*,int,const char*); /* Function for logging */
+ void *pLogArg; /* First argument to xLog() */
+ int bLocaltimeFault; /* True to fail localtime() calls */
+#ifdef SQLITE_ENABLE_SQLLOG
+ void(*xSqllog)(void*,sqlite3*,const char*, int);
+ void *pSqllogArg;
+#endif
+};
+
+/*
+** Context pointer passed down through the tree-walk.
+*/
+struct Walker {
+ int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
+ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
+ Parse *pParse; /* Parser context. */
+ int walkerDepth; /* Number of subqueries */
+ union { /* Extra data for callback */
+ NameContext *pNC; /* Naming context */
+ int i; /* Integer value */
+ SrcList *pSrcList; /* FROM clause */
+ struct SrcCount *pSrcCount; /* Counting column references */
+ } u;
+};
+
+/* Forward declarations */
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
+SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
+SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
+
+/*
+** Return code from the parse-tree walking primitives and their
+** callbacks.
+*/
+#define WRC_Continue 0 /* Continue down into children */
+#define WRC_Prune 1 /* Omit children but continue walking siblings */
+#define WRC_Abort 2 /* Abandon the tree walk */
+
+/*
+** Assuming zIn points to the first byte of a UTF-8 character,
+** advance zIn to point to the first byte of the next UTF-8 character.
+*/
+#define SQLITE_SKIP_UTF8(zIn) { \
+ if( (*(zIn++))>=0xc0 ){ \
+ while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
+ } \
+}
+
+/*
+** The SQLITE_*_BKPT macros are substitutes for the error codes with
+** the same name but without the _BKPT suffix. These macros invoke
+** routines that report the line-number on which the error originated
+** using sqlite3_log(). The routines also provide a convenient place
+** to set a debugger breakpoint.
+*/
+SQLITE_PRIVATE int sqlite3CorruptError(int);
+SQLITE_PRIVATE int sqlite3MisuseError(int);
+SQLITE_PRIVATE int sqlite3CantopenError(int);
+#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
+#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
+#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
+
+
+/*
+** FTS4 is really an extension for FTS3. It is enabled using the
+** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
+** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
+*/
+#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
+# define SQLITE_ENABLE_FTS3
+#endif
+
+/*
+** The ctype.h header is needed for non-ASCII systems. It is also
+** needed by FTS3 when FTS3 is included in the amalgamation.
+*/
+#if !defined(SQLITE_ASCII) || \
+ (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
+# include <ctype.h>
+#endif
+
+/*
+** The following macros mimic the standard library functions toupper(),
+** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
+** sqlite versions only work for ASCII characters, regardless of locale.
+*/
+#ifdef SQLITE_ASCII
+# define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20))
+# define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01)
+# define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06)
+# define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02)
+# define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04)
+# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
+# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
+#else
+# define sqlite3Toupper(x) toupper((unsigned char)(x))
+# define sqlite3Isspace(x) isspace((unsigned char)(x))
+# define sqlite3Isalnum(x) isalnum((unsigned char)(x))
+# define sqlite3Isalpha(x) isalpha((unsigned char)(x))
+# define sqlite3Isdigit(x) isdigit((unsigned char)(x))
+# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
+# define sqlite3Tolower(x) tolower((unsigned char)(x))
+#endif
+
+/*
+** Internal function prototypes
+*/
+#define sqlite3StrICmp sqlite3_stricmp
+SQLITE_PRIVATE int sqlite3Strlen30(const char*);
+#define sqlite3StrNICmp sqlite3_strnicmp
+
+SQLITE_PRIVATE int sqlite3MallocInit(void);
+SQLITE_PRIVATE void sqlite3MallocEnd(void);
+SQLITE_PRIVATE void *sqlite3Malloc(int);
+SQLITE_PRIVATE void *sqlite3MallocZero(int);
+SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, int);
+SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, int);
+SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*);
+SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, int);
+SQLITE_PRIVATE void *sqlite3Realloc(void*, int);
+SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
+SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, int);
+SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
+SQLITE_PRIVATE int sqlite3MallocSize(void*);
+SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*);
+SQLITE_PRIVATE void *sqlite3ScratchMalloc(int);
+SQLITE_PRIVATE void sqlite3ScratchFree(void*);
+SQLITE_PRIVATE void *sqlite3PageMalloc(int);
+SQLITE_PRIVATE void sqlite3PageFree(void*);
+SQLITE_PRIVATE void sqlite3MemSetDefault(void);
+SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
+SQLITE_PRIVATE int sqlite3HeapNearlyFull(void);
+
+/*
+** On systems with ample stack space and that support alloca(), make
+** use of alloca() to obtain space for large automatic objects. By default,
+** obtain space from malloc().
+**
+** The alloca() routine never returns NULL. This will cause code paths
+** that deal with sqlite3StackAlloc() failures to be unreachable.
+*/
+#ifdef SQLITE_USE_ALLOCA
+# define sqlite3StackAllocRaw(D,N) alloca(N)
+# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N)
+# define sqlite3StackFree(D,P)
+#else
+# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N)
+# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N)
+# define sqlite3StackFree(D,P) sqlite3DbFree(D,P)
+#endif
+
+#ifdef SQLITE_ENABLE_MEMSYS3
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS5
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
+#endif
+
+
+#ifndef SQLITE_MUTEX_OMIT
+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void);
+SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int);
+SQLITE_PRIVATE int sqlite3MutexInit(void);
+SQLITE_PRIVATE int sqlite3MutexEnd(void);
+#endif
+
+SQLITE_PRIVATE int sqlite3StatusValue(int);
+SQLITE_PRIVATE void sqlite3StatusAdd(int, int);
+SQLITE_PRIVATE void sqlite3StatusSet(int, int);
+
+#ifndef SQLITE_OMIT_FLOATING_POINT
+SQLITE_PRIVATE int sqlite3IsNaN(double);
+#else
+# define sqlite3IsNaN(X) 0
+#endif
+
+SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
+#ifndef SQLITE_OMIT_TRACE
+SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...);
+#endif
+SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
+SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
+SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
+#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...);
+#endif
+#if defined(SQLITE_TEST)
+SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
+#endif
+
+/* Output formatting for SQLITE_TESTCTRL_EXPLAIN */
+#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
+SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe*);
+SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe*, const char*, ...);
+SQLITE_PRIVATE void sqlite3ExplainNL(Vdbe*);
+SQLITE_PRIVATE void sqlite3ExplainPush(Vdbe*);
+SQLITE_PRIVATE void sqlite3ExplainPop(Vdbe*);
+SQLITE_PRIVATE void sqlite3ExplainFinish(Vdbe*);
+SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe*, Select*);
+SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe*, Expr*);
+SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe*, ExprList*);
+SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe*);
+#else
+# define sqlite3ExplainBegin(X)
+# define sqlite3ExplainSelect(A,B)
+# define sqlite3ExplainExpr(A,B)
+# define sqlite3ExplainExprList(A,B)
+# define sqlite3ExplainFinish(X)
+# define sqlite3VdbeExplanation(X) 0
+#endif
+
+
+SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...);
+SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
+SQLITE_PRIVATE int sqlite3Dequote(char*);
+SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
+SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
+SQLITE_PRIVATE void sqlite3FinishCoding(Parse*);
+SQLITE_PRIVATE int sqlite3GetTempReg(Parse*);
+SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int);
+SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int);
+SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse*,int,int);
+SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse*);
+SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
+SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
+SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
+SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
+SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
+SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
+SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
+SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
+SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
+SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
+SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
+SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
+SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
+SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
+SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
+SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
+SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
+SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
+SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
+SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
+SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
+SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
+SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
+SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
+SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
+SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
+SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
+SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
+ sqlite3_vfs**,char**,char **);
+SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
+SQLITE_PRIVATE int sqlite3CodeOnce(Parse *);
+
+SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
+SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
+SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
+SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*);
+SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
+SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*);
+SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
+
+SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
+SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*);
+SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
+SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, u8 iBatch, i64);
+SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);
+
+SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
+
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
+SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*);
+#else
+# define sqlite3ViewGetColumnNames(A,B) 0
+#endif
+
+SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
+SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
+SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
+SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
+#else
+# define sqlite3AutoincrementBegin(X)
+# define sqlite3AutoincrementEnd(X)
+#endif
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
+SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
+SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
+SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
+SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
+SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
+ Token*, Select*, Expr*, IdList*);
+SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
+SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
+SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*);
+SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
+SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
+SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
+SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
+ Token*, int, int);
+SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
+SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
+SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
+ Expr*,ExprList*,u16,Expr*,Expr*);
+SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
+SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
+SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
+SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
+#endif
+SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
+SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
+SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
+SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
+SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
+SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
+SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int);
+SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
+SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
+SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
+SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*);
+SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int);
+SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
+SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
+SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
+SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
+SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
+SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
+SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
+SQLITE_PRIVATE void sqlite3Vacuum(Parse*);
+SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*);
+SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*);
+SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
+SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
+SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
+SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
+SQLITE_PRIVATE void sqlite3PrngSaveState(void);
+SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
+SQLITE_PRIVATE void sqlite3PrngResetState(void);
+SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
+SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
+SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
+SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
+SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
+SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
+SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
+SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
+SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
+SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
+SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*);
+SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
+SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
+SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
+SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
+SQLITE_PRIVATE int sqlite3IsRowid(const char*);
+SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
+SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
+SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
+SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
+ int*,int,int,int,int,int*);
+SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
+SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
+SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
+SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
+SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
+SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int);
+SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
+SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
+SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
+SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
+SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int);
+SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
+SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8);
+SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*);
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
+SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void);
+SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
+SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
+SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
+
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
+SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
+ Expr*,int, int);
+SQLITE_PRIVATE void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
+SQLITE_PRIVATE void sqlite3DropTrigger(Parse*, SrcList*, int);
+SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse*, Trigger*);
+SQLITE_PRIVATE Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
+SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *, Table *);
+SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
+ int, int, int);
+SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
+ void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
+SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
+ ExprList*,Select*,u8);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
+SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
+SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
+SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
+# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
+#else
+# define sqlite3TriggersExist(B,C,D,E,F) 0
+# define sqlite3DeleteTrigger(A,B)
+# define sqlite3DropTriggerPtr(A,B)
+# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
+# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I)
+# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
+# define sqlite3TriggerList(X, Y) 0
+# define sqlite3ParseToplevel(p) p
+# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
+#endif
+
+SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
+SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+SQLITE_PRIVATE void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*);
+SQLITE_PRIVATE int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
+SQLITE_PRIVATE void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
+SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext*);
+SQLITE_PRIVATE int sqlite3AuthReadCol(Parse*, const char *, const char *, int);
+#else
+# define sqlite3AuthRead(a,b,c,d)
+# define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK
+# define sqlite3AuthContextPush(a,b,c)
+# define sqlite3AuthContextPop(a) ((void)(a))
+#endif
+SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
+SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
+SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
+SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
+SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
+SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
+SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
+SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
+SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
+SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
+SQLITE_PRIVATE int sqlite3Atoi(const char*);
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
+SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
+SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
+
+/*
+** Routines to read and write variable-length integers. These used to
+** be defined locally, but now we use the varint routines in the util.c
+** file. Code should use the MACRO forms below, as the Varint32 versions
+** are coded to assume the single byte case is already handled (which
+** the MACRO form does).
+*/
+SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64);
+SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char*, u32);
+SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *, u64 *);
+SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *, u32 *);
+SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
+
+/*
+** The header of a record consists of a sequence variable-length integers.
+** These integers are almost always small and are encoded as a single byte.
+** The following macros take advantage this fact to provide a fast encode
+** and decode of the integers in a record header. It is faster for the common
+** case where the integer is a single byte. It is a little slower when the
+** integer is two or more bytes. But overall it is faster.
+**
+** The following expressions are equivalent:
+**
+** x = sqlite3GetVarint32( A, &B );
+** x = sqlite3PutVarint32( A, B );
+**
+** x = getVarint32( A, B );
+** x = putVarint32( A, B );
+**
+*/
+#define getVarint32(A,B) \
+ (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
+#define putVarint32(A,B) \
+ (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
+ sqlite3PutVarint32((A),(B)))
+#define getVarint sqlite3GetVarint
+#define putVarint sqlite3PutVarint
+
+
+SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *);
+SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *);
+SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
+SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
+SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
+SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
+SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
+SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
+SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
+SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
+SQLITE_PRIVATE const char *sqlite3ErrStr(int);
+SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
+SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
+SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
+SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
+SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
+SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
+SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
+SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
+SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
+SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
+SQLITE_PRIVATE int sqlite3AbsInt32(int);
+#ifdef SQLITE_ENABLE_8_3_NAMES
+SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
+#else
+# define sqlite3FileSuffix3(X,Y)
+#endif
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,int);
+
+SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
+SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
+SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
+ void(*)(void*));
+SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
+SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
+SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
+#ifdef SQLITE_ENABLE_STAT3
+SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
+#endif
+SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
+SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
+#ifndef SQLITE_AMALGAMATION
+SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
+SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
+SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
+SQLITE_PRIVATE const Token sqlite3IntTokens[];
+SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
+#ifndef SQLITE_OMIT_WSD
+SQLITE_PRIVATE int sqlite3PendingByte;
+#endif
+#endif
+SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int);
+SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3AlterFunctions(void);
+SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
+SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
+SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
+SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
+SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
+SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
+SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
+SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
+SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
+SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
+SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
+SQLITE_PRIVATE char sqlite3AffinityType(const char*);
+SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
+SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
+SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
+SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
+SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*);
+SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*);
+SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int);
+SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
+SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int);
+SQLITE_PRIVATE void sqlite3SchemaClear(void *);
+SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
+SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
+SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
+SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
+ void (*)(sqlite3_context*,int,sqlite3_value **),
+ void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
+ FuncDestructor *pDestructor
+);
+SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int);
+SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
+
+SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int);
+SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int);
+SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum*,int);
+SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
+SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*);
+SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int);
+SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
+
+SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *);
+SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
+
+/*
+** The interface to the LEMON-generated parser
+*/
+SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(size_t));
+SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
+SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*);
+#ifdef YYTRACKMAXSTACKDEPTH
+SQLITE_PRIVATE int sqlite3ParserStackPeak(void*);
+#endif
+
+SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3*);
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*);
+#else
+# define sqlite3CloseExtensions(X)
+#endif
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, int, u8, const char *);
+#else
+ #define sqlite3TableLock(v,w,x,y,z)
+#endif
+
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
+#endif
+
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+# define sqlite3VtabClear(Y)
+# define sqlite3VtabSync(X,Y) SQLITE_OK
+# define sqlite3VtabRollback(X)
+# define sqlite3VtabCommit(X)
+# define sqlite3VtabInSync(db) 0
+# define sqlite3VtabLock(X)
+# define sqlite3VtabUnlock(X)
+# define sqlite3VtabUnlockList(X)
+# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
+# define sqlite3GetVTable(X,Y) ((VTable*)0)
+#else
+SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*);
+SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
+SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
+SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
+SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
+SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
+SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
+SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
+SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*);
+# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
+#endif
+SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
+SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
+SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
+SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*);
+SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*);
+SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
+SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*);
+SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
+SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
+SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
+SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
+SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
+SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
+SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
+SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
+SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
+SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
+SQLITE_PRIVATE const char *sqlite3JournalModename(int);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
+SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+#endif
+
+/* Declarations for functions in fkey.c. All of these are replaced by
+** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
+** key functionality is available. If OMIT_TRIGGER is defined but
+** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
+** this case foreign keys are parsed, but no other functionality is
+** provided (enforcement of FK constraints requires the triggers sub-system).
+*/
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+SQLITE_PRIVATE void sqlite3FkCheck(Parse*, Table*, int, int);
+SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*);
+SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int);
+SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int);
+SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*);
+SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
+#else
+ #define sqlite3FkActions(a,b,c,d)
+ #define sqlite3FkCheck(a,b,c,d)
+ #define sqlite3FkDropTable(a,b,c)
+ #define sqlite3FkOldmask(a,b) 0
+ #define sqlite3FkRequired(a,b,c,d) 0
+#endif
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
+SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
+#else
+ #define sqlite3FkDelete(a,b)
+ #define sqlite3FkLocateIndex(a,b,c,d,e)
+#endif
+
+
+/*
+** Available fault injectors. Should be numbered beginning with 0.
+*/
+#define SQLITE_FAULTINJECTOR_MALLOC 0
+#define SQLITE_FAULTINJECTOR_COUNT 1
+
+/*
+** The interface to the code in fault.c used for identifying "benign"
+** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST
+** is not defined.
+*/
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void);
+SQLITE_PRIVATE void sqlite3EndBenignMalloc(void);
+#else
+ #define sqlite3BeginBenignMalloc()
+ #define sqlite3EndBenignMalloc()
+#endif
+
+#define IN_INDEX_ROWID 1
+#define IN_INDEX_EPH 2
+#define IN_INDEX_INDEX_ASC 3
+#define IN_INDEX_INDEX_DESC 4
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
+SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
+SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
+SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p);
+#else
+ #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
+ #define sqlite3JournalExists(p) 1
+#endif
+
+SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
+SQLITE_PRIVATE int sqlite3MemJournalSize(void);
+SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *);
+
+#if SQLITE_MAX_EXPR_DEPTH>0
+SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
+SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *);
+SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
+#else
+ #define sqlite3ExprSetHeight(x,y)
+ #define sqlite3SelectExprHeight(x) 0
+ #define sqlite3ExprCheckHeight(x,y)
+#endif
+
+SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
+SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32);
+
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *, sqlite3 *);
+SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db);
+SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db);
+#else
+ #define sqlite3ConnectionBlocked(x,y)
+ #define sqlite3ConnectionUnlocked(x)
+ #define sqlite3ConnectionClosed(x)
+#endif
+
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *);
+#endif
+
+/*
+** If the SQLITE_ENABLE IOTRACE exists then the global variable
+** sqlite3IoTrace is a pointer to a printf-like routine used to
+** print I/O tracing messages.
+*/
+#ifdef SQLITE_ENABLE_IOTRACE
+# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
+SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*);
+SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...);
+#else
+# define IOTRACE(A)
+# define sqlite3VdbeIOTraceSql(X)
+#endif
+
+/*
+** These routines are available for the mem2.c debugging memory allocator
+** only. They are used to verify that different "types" of memory
+** allocations are properly tracked by the system.
+**
+** sqlite3MemdebugSetType() sets the "type" of an allocation to one of
+** the MEMTYPE_* macros defined below. The type must be a bitmask with
+** a single bit set.
+**
+** sqlite3MemdebugHasType() returns true if any of the bits in its second
+** argument match the type set by the previous sqlite3MemdebugSetType().
+** sqlite3MemdebugHasType() is intended for use inside assert() statements.
+**
+** sqlite3MemdebugNoType() returns true if none of the bits in its second
+** argument match the type set by the previous sqlite3MemdebugSetType().
+**
+** Perhaps the most important point is the difference between MEMTYPE_HEAP
+** and MEMTYPE_LOOKASIDE. If an allocation is MEMTYPE_LOOKASIDE, that means
+** it might have been allocated by lookaside, except the allocation was
+** too large or lookaside was already full. It is important to verify
+** that allocations that might have been satisfied by lookaside are not
+** passed back to non-lookaside free() routines. Asserts such as the
+** example above are placed on the non-lookaside free() routines to verify
+** this constraint.
+**
+** All of this is no-op for a production build. It only comes into
+** play when the SQLITE_MEMDEBUG compile-time option is used.
+*/
+#ifdef SQLITE_MEMDEBUG
+SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8);
+SQLITE_PRIVATE int sqlite3MemdebugHasType(void*,u8);
+SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8);
+#else
+# define sqlite3MemdebugSetType(X,Y) /* no-op */
+# define sqlite3MemdebugHasType(X,Y) 1
+# define sqlite3MemdebugNoType(X,Y) 1
+#endif
+#define MEMTYPE_HEAP 0x01 /* General heap allocations */
+#define MEMTYPE_LOOKASIDE 0x02 /* Might have been lookaside memory */
+#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
+#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
+#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */
+
+#endif /* _SQLITEINT_H_ */
+
+/************** End of sqliteInt.h *******************************************/
+/************** Begin file global.c ******************************************/
+/*
+** 2008 June 13
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains definitions of global variables and contants.
+*/
+
+/* An array to map all upper-case characters into their corresponding
+** lower-case character.
+**
+** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
+** handle case conversions for the UTF character set since the tables
+** involved are nearly as big or bigger than SQLite itself.
+*/
+SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
+#ifdef SQLITE_ASCII
+ 0, 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, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
+ 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
+ 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
+ 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
+ 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
+ 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
+ 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
+ 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
+ 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
+ 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
+ 252,253,254,255
+#endif
+#ifdef SQLITE_EBCDIC
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
+ 96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */
+ 112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */
+ 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
+ 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
+ 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
+ 224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */
+ 239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */
+#endif
+};
+
+/*
+** The following 256 byte lookup table is used to support SQLites built-in
+** equivalents to the following standard library functions:
+**
+** isspace() 0x01
+** isalpha() 0x02
+** isdigit() 0x04
+** isalnum() 0x06
+** isxdigit() 0x08
+** toupper() 0x20
+** SQLite identifier character 0x40
+**
+** Bit 0x20 is set if the mapped character requires translation to upper
+** case. i.e. if the character is a lower-case ASCII character.
+** If x is a lower-case ASCII character, then its upper-case equivalent
+** is (x - 0x20). Therefore toupper() can be implemented as:
+**
+** (x & ~(map[x]&0x20))
+**
+** Standard function tolower() is implemented using the sqlite3UpperToLower[]
+** array. tolower() is used more often than toupper() by SQLite.
+**
+** Bit 0x40 is set if the character non-alphanumeric and can be used in an
+** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
+** non-ASCII UTF character. Hence the test for whether or not a character is
+** part of an identifier is 0x46.
+**
+** SQLite's versions are identical to the standard versions assuming a
+** locale of "C". They are implemented as macros in sqliteInt.h.
+*/
+#ifdef SQLITE_ASCII
+SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
+ 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, /* 20..27 !"#$%&' */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
+ 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
+
+ 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
+ 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
+ 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
+
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
+
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
+};
+#endif
+
+#ifndef SQLITE_USE_URI
+# define SQLITE_USE_URI 0
+#endif
+
+#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+#endif
+
+/*
+** The following singleton contains the global configuration for
+** the SQLite library.
+*/
+SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
+ SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
+ 1, /* bCoreMutex */
+ SQLITE_THREADSAFE==1, /* bFullMutex */
+ SQLITE_USE_URI, /* bOpenUri */
+ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
+ 0x7ffffffe, /* mxStrlen */
+ 128, /* szLookaside */
+ 500, /* nLookaside */
+ {0,0,0,0,0,0,0,0}, /* m */
+ {0,0,0,0,0,0,0,0,0}, /* mutex */
+ {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
+ (void*)0, /* pHeap */
+ 0, /* nHeap */
+ 0, 0, /* mnHeap, mxHeap */
+ (void*)0, /* pScratch */
+ 0, /* szScratch */
+ 0, /* nScratch */
+ (void*)0, /* pPage */
+ 0, /* szPage */
+ 0, /* nPage */
+ 0, /* mxParserStack */
+ 0, /* sharedCacheEnabled */
+ /* All the rest should always be initialized to zero */
+ 0, /* isInit */
+ 0, /* inProgress */
+ 0, /* isMutexInit */
+ 0, /* isMallocInit */
+ 0, /* isPCacheInit */
+ 0, /* pInitMutex */
+ 0, /* nRefInitMutex */
+ 0, /* xLog */
+ 0, /* pLogArg */
+ 0, /* bLocaltimeFault */
+#ifdef SQLITE_ENABLE_SQLLOG
+ 0, /* xSqllog */
+ 0 /* pSqllogArg */
+#endif
+};
+
+
+/*
+** Hash table for global functions - functions common to all
+** database connections. After initialization, this table is
+** read-only.
+*/
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
+
+/*
+** Constant tokens for values 0 and 1.
+*/
+SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
+ { "0", 1 },
+ { "1", 1 }
+};
+
+
+/*
+** The value of the "pending" byte must be 0x40000000 (1 byte past the
+** 1-gibabyte boundary) in a compatible database. SQLite never uses
+** the database page that contains the pending byte. It never attempts
+** to read or write that page. The pending byte page is set assign
+** for use by the VFS layers as space for managing file locks.
+**
+** During testing, it is often desirable to move the pending byte to
+** a different position in the file. This allows code that has to
+** deal with the pending byte to run on files that are much smaller
+** than 1 GiB. The sqlite3_test_control() interface can be used to
+** move the pending byte.
+**
+** IMPORTANT: Changing the pending byte to any value other than
+** 0x40000000 results in an incompatible database file format!
+** Changing the pending byte during operating results in undefined
+** and dileterious behavior.
+*/
+#ifndef SQLITE_OMIT_WSD
+SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
+#endif
+
+/*
+** Properties of opcodes. The OPFLG_INITIALIZER macro is
+** created by mkopcodeh.awk during compilation. Data is obtained
+** from the comments following the "case OP_xxxx:" statements in
+** the vdbe.c file.
+*/
+SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
+
+/************** End of global.c **********************************************/
+/************** Begin file ctime.c *******************************************/
+/*
+** 2010 February 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements routines used to report what compile-time options
+** SQLite was built with.
+*/
+
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+
+
+/*
+** An array of names of all compile-time options. This array should
+** be sorted A-Z.
+**
+** This array looks large, but in a typical installation actually uses
+** only a handful of compile-time options, so most times this array is usually
+** rather short and uses little memory space.
+*/
+static const char * const azCompileOpt[] = {
+
+/* These macros are provided to "stringify" the value of the define
+** for those options in which the value is meaningful. */
+#define CTIMEOPT_VAL_(opt) #opt
+#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
+
+#ifdef SQLITE_32BIT_ROWID
+ "32BIT_ROWID",
+#endif
+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+ "4_BYTE_ALIGNED_MALLOC",
+#endif
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+ "CASE_SENSITIVE_LIKE",
+#endif
+#ifdef SQLITE_CHECK_PAGES
+ "CHECK_PAGES",
+#endif
+#ifdef SQLITE_COVERAGE_TEST
+ "COVERAGE_TEST",
+#endif
+#ifdef SQLITE_CURDIR
+ "CURDIR",
+#endif
+#ifdef SQLITE_DEBUG
+ "DEBUG",
+#endif
+#ifdef SQLITE_DEFAULT_LOCKING_MODE
+ "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
+#endif
+#ifdef SQLITE_DISABLE_DIRSYNC
+ "DISABLE_DIRSYNC",
+#endif
+#ifdef SQLITE_DISABLE_LFS
+ "DISABLE_LFS",
+#endif
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ "ENABLE_ATOMIC_WRITE",
+#endif
+#ifdef SQLITE_ENABLE_CEROD
+ "ENABLE_CEROD",
+#endif
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ "ENABLE_COLUMN_METADATA",
+#endif
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+ "ENABLE_EXPENSIVE_ASSERT",
+#endif
+#ifdef SQLITE_ENABLE_FTS1
+ "ENABLE_FTS1",
+#endif
+#ifdef SQLITE_ENABLE_FTS2
+ "ENABLE_FTS2",
+#endif
+#ifdef SQLITE_ENABLE_FTS3
+ "ENABLE_FTS3",
+#endif
+#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
+ "ENABLE_FTS3_PARENTHESIS",
+#endif
+#ifdef SQLITE_ENABLE_FTS4
+ "ENABLE_FTS4",
+#endif
+#ifdef SQLITE_ENABLE_ICU
+ "ENABLE_ICU",
+#endif
+#ifdef SQLITE_ENABLE_IOTRACE
+ "ENABLE_IOTRACE",
+#endif
+#ifdef SQLITE_ENABLE_LOAD_EXTENSION
+ "ENABLE_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+ "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
+#endif
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ "ENABLE_MEMORY_MANAGEMENT",
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS3
+ "ENABLE_MEMSYS3",
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS5
+ "ENABLE_MEMSYS5",
+#endif
+#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
+ "ENABLE_OVERSIZE_CELL_CHECK",
+#endif
+#ifdef SQLITE_ENABLE_RTREE
+ "ENABLE_RTREE",
+#endif
+#ifdef SQLITE_ENABLE_STAT3
+ "ENABLE_STAT3",
+#endif
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+ "ENABLE_UNLOCK_NOTIFY",
+#endif
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ "ENABLE_UPDATE_DELETE_LIMIT",
+#endif
+#ifdef SQLITE_HAS_CODEC
+ "HAS_CODEC",
+#endif
+#ifdef SQLITE_HAVE_ISNAN
+ "HAVE_ISNAN",
+#endif
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+ "HOMEGROWN_RECURSIVE_MUTEX",
+#endif
+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
+ "IGNORE_AFP_LOCK_ERRORS",
+#endif
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ "IGNORE_FLOCK_LOCK_ERRORS",
+#endif
+#ifdef SQLITE_INT64_TYPE
+ "INT64_TYPE",
+#endif
+#ifdef SQLITE_LOCK_TRACE
+ "LOCK_TRACE",
+#endif
+#ifdef SQLITE_MAX_SCHEMA_RETRY
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
+#endif
+#ifdef SQLITE_MEMDEBUG
+ "MEMDEBUG",
+#endif
+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+ "MIXED_ENDIAN_64BIT_FLOAT",
+#endif
+#ifdef SQLITE_NO_SYNC
+ "NO_SYNC",
+#endif
+#ifdef SQLITE_OMIT_ALTERTABLE
+ "OMIT_ALTERTABLE",
+#endif
+#ifdef SQLITE_OMIT_ANALYZE
+ "OMIT_ANALYZE",
+#endif
+#ifdef SQLITE_OMIT_ATTACH
+ "OMIT_ATTACH",
+#endif
+#ifdef SQLITE_OMIT_AUTHORIZATION
+ "OMIT_AUTHORIZATION",
+#endif
+#ifdef SQLITE_OMIT_AUTOINCREMENT
+ "OMIT_AUTOINCREMENT",
+#endif
+#ifdef SQLITE_OMIT_AUTOINIT
+ "OMIT_AUTOINIT",
+#endif
+#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
+ "OMIT_AUTOMATIC_INDEX",
+#endif
+#ifdef SQLITE_OMIT_AUTORESET
+ "OMIT_AUTORESET",
+#endif
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ "OMIT_AUTOVACUUM",
+#endif
+#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
+ "OMIT_BETWEEN_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_BLOB_LITERAL
+ "OMIT_BLOB_LITERAL",
+#endif
+#ifdef SQLITE_OMIT_BTREECOUNT
+ "OMIT_BTREECOUNT",
+#endif
+#ifdef SQLITE_OMIT_BUILTIN_TEST
+ "OMIT_BUILTIN_TEST",
+#endif
+#ifdef SQLITE_OMIT_CAST
+ "OMIT_CAST",
+#endif
+#ifdef SQLITE_OMIT_CHECK
+ "OMIT_CHECK",
+#endif
+/* // redundant
+** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
+** "OMIT_COMPILEOPTION_DIAGS",
+** #endif
+*/
+#ifdef SQLITE_OMIT_COMPLETE
+ "OMIT_COMPLETE",
+#endif
+#ifdef SQLITE_OMIT_COMPOUND_SELECT
+ "OMIT_COMPOUND_SELECT",
+#endif
+#ifdef SQLITE_OMIT_DATETIME_FUNCS
+ "OMIT_DATETIME_FUNCS",
+#endif
+#ifdef SQLITE_OMIT_DECLTYPE
+ "OMIT_DECLTYPE",
+#endif
+#ifdef SQLITE_OMIT_DEPRECATED
+ "OMIT_DEPRECATED",
+#endif
+#ifdef SQLITE_OMIT_DISKIO
+ "OMIT_DISKIO",
+#endif
+#ifdef SQLITE_OMIT_EXPLAIN
+ "OMIT_EXPLAIN",
+#endif
+#ifdef SQLITE_OMIT_FLAG_PRAGMAS
+ "OMIT_FLAG_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ "OMIT_FLOATING_POINT",
+#endif
+#ifdef SQLITE_OMIT_FOREIGN_KEY
+ "OMIT_FOREIGN_KEY",
+#endif
+#ifdef SQLITE_OMIT_GET_TABLE
+ "OMIT_GET_TABLE",
+#endif
+#ifdef SQLITE_OMIT_INCRBLOB
+ "OMIT_INCRBLOB",
+#endif
+#ifdef SQLITE_OMIT_INTEGRITY_CHECK
+ "OMIT_INTEGRITY_CHECK",
+#endif
+#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
+ "OMIT_LIKE_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+ "OMIT_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_OMIT_LOCALTIME
+ "OMIT_LOCALTIME",
+#endif
+#ifdef SQLITE_OMIT_LOOKASIDE
+ "OMIT_LOOKASIDE",
+#endif
+#ifdef SQLITE_OMIT_MEMORYDB
+ "OMIT_MEMORYDB",
+#endif
+#ifdef SQLITE_OMIT_OR_OPTIMIZATION
+ "OMIT_OR_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_PAGER_PRAGMAS
+ "OMIT_PAGER_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_PRAGMA
+ "OMIT_PRAGMA",
+#endif
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+ "OMIT_PROGRESS_CALLBACK",
+#endif
+#ifdef SQLITE_OMIT_QUICKBALANCE
+ "OMIT_QUICKBALANCE",
+#endif
+#ifdef SQLITE_OMIT_REINDEX
+ "OMIT_REINDEX",
+#endif
+#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
+ "OMIT_SCHEMA_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ "OMIT_SCHEMA_VERSION_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_SHARED_CACHE
+ "OMIT_SHARED_CACHE",
+#endif
+#ifdef SQLITE_OMIT_SUBQUERY
+ "OMIT_SUBQUERY",
+#endif
+#ifdef SQLITE_OMIT_TCL_VARIABLE
+ "OMIT_TCL_VARIABLE",
+#endif
+#ifdef SQLITE_OMIT_TEMPDB
+ "OMIT_TEMPDB",
+#endif
+#ifdef SQLITE_OMIT_TRACE
+ "OMIT_TRACE",
+#endif
+#ifdef SQLITE_OMIT_TRIGGER
+ "OMIT_TRIGGER",
+#endif
+#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
+ "OMIT_TRUNCATE_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_UTF16
+ "OMIT_UTF16",
+#endif
+#ifdef SQLITE_OMIT_VACUUM
+ "OMIT_VACUUM",
+#endif
+#ifdef SQLITE_OMIT_VIEW
+ "OMIT_VIEW",
+#endif
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+ "OMIT_VIRTUALTABLE",
+#endif
+#ifdef SQLITE_OMIT_WAL
+ "OMIT_WAL",
+#endif
+#ifdef SQLITE_OMIT_WSD
+ "OMIT_WSD",
+#endif
+#ifdef SQLITE_OMIT_XFER_OPT
+ "OMIT_XFER_OPT",
+#endif
+#ifdef SQLITE_PERFORMANCE_TRACE
+ "PERFORMANCE_TRACE",
+#endif
+#ifdef SQLITE_PROXY_DEBUG
+ "PROXY_DEBUG",
+#endif
+#ifdef SQLITE_RTREE_INT_ONLY
+ "RTREE_INT_ONLY",
+#endif
+#ifdef SQLITE_SECURE_DELETE
+ "SECURE_DELETE",
+#endif
+#ifdef SQLITE_SMALL_STACK
+ "SMALL_STACK",
+#endif
+#ifdef SQLITE_SOUNDEX
+ "SOUNDEX",
+#endif
+#ifdef SQLITE_TCL
+ "TCL",
+#endif
+#ifdef SQLITE_TEMP_STORE
+ "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
+#endif
+#ifdef SQLITE_TEST
+ "TEST",
+#endif
+#ifdef SQLITE_THREADSAFE
+ "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
+#endif
+#ifdef SQLITE_USE_ALLOCA
+ "USE_ALLOCA",
+#endif
+#ifdef SQLITE_ZERO_MALLOC
+ "ZERO_MALLOC"
+#endif
+};
+
+/*
+** Given the name of a compile-time option, return true if that option
+** was used and false if not.
+**
+** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
+** is not required for a match.
+*/
+SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
+ int i, n;
+ if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
+ n = sqlite3Strlen30(zOptName);
+
+ /* Since ArraySize(azCompileOpt) is normally in single digits, a
+ ** linear search is adequate. No need for a binary search. */
+ for(i=0; i<ArraySize(azCompileOpt); i++){
+ if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0)
+ && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Return the N-th compile-time option string. If N is out of range,
+** return a NULL pointer.
+*/
+SQLITE_API const char *sqlite3_compileoption_get(int N){
+ if( N>=0 && N<ArraySize(azCompileOpt) ){
+ return azCompileOpt[N];
+ }
+ return 0;
+}
+
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+
+/************** End of ctime.c ***********************************************/
+/************** Begin file status.c ******************************************/
+/*
+** 2008 June 18
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This module implements the sqlite3_status() interface and related
+** functionality.
+*/
+/************** Include vdbeInt.h in the middle of status.c ******************/
+/************** Begin file vdbeInt.h *****************************************/
+/*
+** 2003 September 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This is the header file for information that is private to the
+** VDBE. This information used to all be at the top of the single
+** source code file "vdbe.c". When that file became too big (over
+** 6000 lines long) it was split up into several smaller files and
+** this header information was factored out.
+*/
+#ifndef _VDBEINT_H_
+#define _VDBEINT_H_
+
+/*
+** SQL is translated into a sequence of instructions to be
+** executed by a virtual machine. Each instruction is an instance
+** of the following structure.
+*/
+typedef struct VdbeOp Op;
+
+/*
+** Boolean values
+*/
+typedef unsigned char Bool;
+
+/* Opaque type used by code in vdbesort.c */
+typedef struct VdbeSorter VdbeSorter;
+
+/* Opaque type used by the explainer */
+typedef struct Explain Explain;
+
+/*
+** A cursor is a pointer into a single BTree within a database file.
+** The cursor can seek to a BTree entry with a particular key, or
+** loop over all entries of the Btree. You can also insert new BTree
+** entries or retrieve the key or data from the entry that the cursor
+** is currently pointing to.
+**
+** Every cursor that the virtual machine has open is represented by an
+** instance of the following structure.
+*/
+struct VdbeCursor {
+ BtCursor *pCursor; /* The cursor structure of the backend */
+ Btree *pBt; /* Separate file holding temporary table */
+ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
+ int iDb; /* Index of cursor database in db->aDb[] (or -1) */
+ int pseudoTableReg; /* Register holding pseudotable content. */
+ int nField; /* Number of fields in the header */
+ Bool zeroed; /* True if zeroed out and ready for reuse */
+ Bool rowidIsValid; /* True if lastRowid is valid */
+ Bool atFirst; /* True if pointing to first entry */
+ Bool useRandomRowid; /* Generate new record numbers semi-randomly */
+ Bool nullRow; /* True if pointing to a row with no data */
+ Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
+ Bool isTable; /* True if a table requiring integer keys */
+ Bool isIndex; /* True if an index containing keys only - no data */
+ Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
+ Bool isSorter; /* True if a new-style sorter */
+ Bool multiPseudo; /* Multi-register pseudo-cursor */
+ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
+ const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
+ i64 seqCount; /* Sequence counter */
+ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
+ i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
+ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
+
+ /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
+ ** OP_IsUnique opcode on this cursor. */
+ int seekResult;
+
+ /* Cached information about the header for the data record that the
+ ** cursor is currently pointing to. Only valid if cacheStatus matches
+ ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
+ ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
+ ** the cache is out of date.
+ **
+ ** aRow might point to (ephemeral) data for the current row, or it might
+ ** be NULL.
+ */
+ u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
+ int payloadSize; /* Total number of bytes in the record */
+ u32 *aType; /* Type values for all entries in the record */
+ u32 *aOffset; /* Cached offsets to the start of each columns data */
+ u8 *aRow; /* Data for the current row, if all on one page */
+};
+typedef struct VdbeCursor VdbeCursor;
+
+/*
+** When a sub-program is executed (OP_Program), a structure of this type
+** is allocated to store the current value of the program counter, as
+** well as the current memory cell array and various other frame specific
+** values stored in the Vdbe struct. When the sub-program is finished,
+** these values are copied back to the Vdbe from the VdbeFrame structure,
+** restoring the state of the VM to as it was before the sub-program
+** began executing.
+**
+** The memory for a VdbeFrame object is allocated and managed by a memory
+** cell in the parent (calling) frame. When the memory cell is deleted or
+** overwritten, the VdbeFrame object is not freed immediately. Instead, it
+** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
+** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
+** this instead of deleting the VdbeFrame immediately is to avoid recursive
+** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
+** child frame are released.
+**
+** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
+** set to NULL if the currently executing frame is the main program.
+*/
+typedef struct VdbeFrame VdbeFrame;
+struct VdbeFrame {
+ Vdbe *v; /* VM this frame belongs to */
+ VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
+ Op *aOp; /* Program instructions for parent frame */
+ Mem *aMem; /* Array of memory cells for parent frame */
+ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */
+ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
+ void *token; /* Copy of SubProgram.token */
+ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
+ int nCursor; /* Number of entries in apCsr */
+ int pc; /* Program Counter in parent (calling) frame */
+ int nOp; /* Size of aOp array */
+ int nMem; /* Number of entries in aMem */
+ int nOnceFlag; /* Number of entries in aOnceFlag */
+ int nChildMem; /* Number of memory cells for child frame */
+ int nChildCsr; /* Number of cursors for child frame */
+ int nChange; /* Statement changes (Vdbe.nChanges) */
+};
+
+#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
+
+/*
+** A value for VdbeCursor.cacheValid that means the cache is always invalid.
+*/
+#define CACHE_STALE 0
+
+/*
+** Internally, the vdbe manipulates nearly all SQL values as Mem
+** structures. Each Mem struct may cache multiple representations (string,
+** integer etc.) of the same value.
+*/
+struct Mem {
+ sqlite3 *db; /* The associated database connection */
+ char *z; /* String or BLOB value */
+ double r; /* Real value */
+ union {
+ i64 i; /* Integer value used when MEM_Int is set in flags */
+ int nZero; /* Used when bit MEM_Zero is set in flags */
+ FuncDef *pDef; /* Used only when flags==MEM_Agg */
+ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
+ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
+ } u;
+ int n; /* Number of characters in string value, excluding '\0' */
+ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
+ u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
+ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
+#ifdef SQLITE_DEBUG
+ Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
+ void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
+#endif
+ void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
+ char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */
+};
+
+/* One or more of the following flags are set to indicate the validOK
+** representations of the value stored in the Mem struct.
+**
+** If the MEM_Null flag is set, then the value is an SQL NULL value.
+** No other flags may be set in this case.
+**
+** If the MEM_Str flag is set then Mem.z points at a string representation.
+** Usually this is encoded in the same unicode encoding as the main
+** database (see below for exceptions). If the MEM_Term flag is also
+** set, then the string is nul terminated. The MEM_Int and MEM_Real
+** flags may coexist with the MEM_Str flag.
+*/
+#define MEM_Null 0x0001 /* Value is NULL */
+#define MEM_Str 0x0002 /* Value is a string */
+#define MEM_Int 0x0004 /* Value is an integer */
+#define MEM_Real 0x0008 /* Value is a real number */
+#define MEM_Blob 0x0010 /* Value is a BLOB */
+#define MEM_RowSet 0x0020 /* Value is a RowSet object */
+#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
+#define MEM_Invalid 0x0080 /* Value is undefined */
+#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
+#define MEM_TypeMask 0x01ff /* Mask of type bits */
+
+
+/* Whenever Mem contains a valid string or blob representation, one of
+** the following flags must be set to determine the memory management
+** policy for Mem.z. The MEM_Term flag tells us whether or not the
+** string is \000 or \u0000 terminated
+*/
+#define MEM_Term 0x0200 /* String rep is nul terminated */
+#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
+#define MEM_Static 0x0800 /* Mem.z points to a static string */
+#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
+#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
+#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
+#ifdef SQLITE_OMIT_INCRBLOB
+ #undef MEM_Zero
+ #define MEM_Zero 0x0000
+#endif
+
+/*
+** Clear any existing type flags from a Mem and replace them with f
+*/
+#define MemSetTypeFlag(p, f) \
+ ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
+
+/*
+** Return true if a memory cell is not marked as invalid. This macro
+** is for use inside assert() statements only.
+*/
+#ifdef SQLITE_DEBUG
+#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
+#endif
+
+
+/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
+** additional information about auxiliary information bound to arguments
+** of the function. This is used to implement the sqlite3_get_auxdata()
+** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
+** that can be associated with a constant argument to a function. This
+** allows functions such as "regexp" to compile their constant regular
+** expression argument once and reused the compiled code for multiple
+** invocations.
+*/
+struct VdbeFunc {
+ FuncDef *pFunc; /* The definition of the function */
+ int nAux; /* Number of entries allocated for apAux[] */
+ struct AuxData {
+ void *pAux; /* Aux data for the i-th argument */
+ void (*xDelete)(void *); /* Destructor for the aux data */
+ } apAux[1]; /* One slot for each function argument */
+};
+
+/*
+** The "context" argument for a installable function. A pointer to an
+** instance of this structure is the first argument to the routines used
+** implement the SQL functions.
+**
+** There is a typedef for this structure in sqlite.h. So all routines,
+** even the public interface to SQLite, can use a pointer to this structure.
+** But this file is the only place where the internal details of this
+** structure are known.
+**
+** This structure is defined inside of vdbeInt.h because it uses substructures
+** (Mem) which are only defined there.
+*/
+struct sqlite3_context {
+ FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
+ VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
+ Mem s; /* The return value is stored here */
+ Mem *pMem; /* Memory cell used to store aggregate context */
+ CollSeq *pColl; /* Collating sequence */
+ int isError; /* Error code returned by the function. */
+ int skipFlag; /* Skip skip accumulator loading if true */
+};
+
+/*
+** An Explain object accumulates indented output which is helpful
+** in describing recursive data structures.
+*/
+struct Explain {
+ Vdbe *pVdbe; /* Attach the explanation to this Vdbe */
+ StrAccum str; /* The string being accumulated */
+ int nIndent; /* Number of elements in aIndent */
+ u16 aIndent[100]; /* Levels of indentation */
+ char zBase[100]; /* Initial space */
+};
+
+/* A bitfield type for use inside of structures. Always follow with :N where
+** N is the number of bits.
+*/
+typedef unsigned bft; /* Bit Field Type */
+
+/*
+** An instance of the virtual machine. This structure contains the complete
+** state of the virtual machine.
+**
+** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
+** is really a pointer to an instance of this structure.
+**
+** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
+** any virtual table method invocations made by the vdbe program. It is
+** set to 2 for xDestroy method calls and 1 for all other methods. This
+** variable is used for two purposes: to allow xDestroy methods to execute
+** "DROP TABLE" statements and to prevent some nasty side effects of
+** malloc failure when SQLite is invoked recursively by a virtual table
+** method function.
+*/
+struct Vdbe {
+ sqlite3 *db; /* The database connection that owns this statement */
+ Op *aOp; /* Space to hold the virtual machine's program */
+ Mem *aMem; /* The memory locations */
+ Mem **apArg; /* Arguments to currently executing user function */
+ Mem *aColName; /* Column names to return */
+ Mem *pResultSet; /* Pointer to an array of results */
+ int nMem; /* Number of memory locations currently allocated */
+ int nOp; /* Number of instructions in the program */
+ int nOpAlloc; /* Number of slots allocated for aOp[] */
+ int nLabel; /* Number of labels used */
+ int *aLabel; /* Space to hold the labels */
+ u16 nResColumn; /* Number of columns in one row of the result set */
+ int nCursor; /* Number of slots in apCsr[] */
+ u32 magic; /* Magic number for sanity checking */
+ char *zErrMsg; /* Error message written here */
+ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
+ VdbeCursor **apCsr; /* One element of this array for each open cursor */
+ Mem *aVar; /* Values for the OP_Variable opcode. */
+ char **azVar; /* Name of variables */
+ ynVar nVar; /* Number of entries in aVar[] */
+ ynVar nzVar; /* Number of entries in azVar[] */
+ u32 cacheCtr; /* VdbeCursor row cache generation counter */
+ int pc; /* The program counter */
+ int rc; /* Value to return */
+ u8 errorAction; /* Recovery action to do in case of an error */
+ u8 minWriteFileFormat; /* Minimum file format for writable database files */
+ bft explain:2; /* True if EXPLAIN present on SQL command */
+ bft inVtabMethod:2; /* See comments above */
+ bft changeCntOn:1; /* True to update the change-counter */
+ bft expired:1; /* True if the VM needs to be recompiled */
+ bft runOnlyOnce:1; /* Automatically expire on reset */
+ bft usesStmtJournal:1; /* True if uses a statement journal */
+ bft readOnly:1; /* True for read-only statements */
+ bft isPrepareV2:1; /* True if prepared with prepare_v2() */
+ bft doingRerun:1; /* True if rerunning after an auto-reprepare */
+ int nChange; /* Number of db changes made since last reset */
+ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
+ yDbMask lockMask; /* Subset of btreeMask that requires a lock */
+ int iStatement; /* Statement number (or 0 if has not opened stmt) */
+ int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
+#ifndef SQLITE_OMIT_TRACE
+ i64 startTime; /* Time when query started - used for profiling */
+#endif
+ i64 nFkConstraint; /* Number of imm. FK constraints this VM */
+ i64 nStmtDefCons; /* Number of def. constraints when stmt started */
+ char *zSql; /* Text of the SQL statement that generated this */
+ void *pFree; /* Free this when deleting the vdbe */
+#ifdef SQLITE_DEBUG
+ FILE *trace; /* Write an execution trace here, if not NULL */
+#endif
+#ifdef SQLITE_ENABLE_TREE_EXPLAIN
+ Explain *pExplain; /* The explainer */
+ char *zExplain; /* Explanation of data structures */
+#endif
+ VdbeFrame *pFrame; /* Parent frame */
+ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
+ int nFrame; /* Number of frames in pFrame list */
+ u32 expmask; /* Binding to these vars invalidates VM */
+ SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
+ int nOnceFlag; /* Size of array aOnceFlag[] */
+ u8 *aOnceFlag; /* Flags for OP_Once */
+};
+
+/*
+** The following are allowed values for Vdbe.magic
+*/
+#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
+#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
+#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
+#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
+
+/*
+** Function prototypes
+*/
+SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
+void sqliteVdbePopStack(Vdbe*,int);
+SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*);
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
+#endif
+SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
+SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
+SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
+SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
+
+int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
+SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
+SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
+SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
+SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
+SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
+SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
+SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
+#else
+SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
+#endif
+SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
+SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
+SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int);
+SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
+SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
+SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
+SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
+SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
+#define VdbeMemRelease(X) \
+ if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
+ sqlite3VdbeMemReleaseExternal(X);
+SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
+SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
+SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
+SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
+SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
+SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
+SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
+SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
+
+SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
+SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
+SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
+SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
+SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
+SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
+
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
+SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
+#else
+# define sqlite3VdbeEnter(X)
+# define sqlite3VdbeLeave(X)
+#endif
+
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
+#endif
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
+#else
+# define sqlite3VdbeCheckFk(p,i) 0
+#endif
+
+SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
+#endif
+SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
+
+#ifndef SQLITE_OMIT_INCRBLOB
+SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
+ #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
+#else
+ #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
+ #define ExpandBlob(P) SQLITE_OK
+#endif
+
+#endif /* !defined(_VDBEINT_H_) */
+
+/************** End of vdbeInt.h *********************************************/
+/************** Continuing where we left off in status.c *********************/
+
+/*
+** Variables in which to record status information.
+*/
+typedef struct sqlite3StatType sqlite3StatType;
+static SQLITE_WSD struct sqlite3StatType {
+ int nowValue[10]; /* Current value */
+ int mxValue[10]; /* Maximum value */
+} sqlite3Stat = { {0,}, {0,} };
+
+
+/* The "wsdStat" macro will resolve to the status information
+** state vector. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdStat can refer directly
+** to the "sqlite3Stat" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
+# define wsdStat x[0]
+#else
+# define wsdStatInit
+# define wsdStat sqlite3Stat
+#endif
+
+/*
+** Return the current value of a status parameter.
+*/
+SQLITE_PRIVATE int sqlite3StatusValue(int op){
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ return wsdStat.nowValue[op];
+}
+
+/*
+** Add N to the value of a status record. It is assumed that the
+** caller holds appropriate locks.
+*/
+SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ wsdStat.nowValue[op] += N;
+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
+ }
+}
+
+/*
+** Set the value of a status to X.
+*/
+SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ wsdStat.nowValue[op] = X;
+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
+ }
+}
+
+/*
+** Query status information.
+**
+** This implementation assumes that reading or writing an aligned
+** 32-bit integer is an atomic operation. If that assumption is not true,
+** then this routine is not threadsafe.
+*/
+SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
+ wsdStatInit;
+ if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ *pCurrent = wsdStat.nowValue[op];
+ *pHighwater = wsdStat.mxValue[op];
+ if( resetFlag ){
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Query status information for a single database connection
+*/
+SQLITE_API int sqlite3_db_status(
+ sqlite3 *db, /* The database connection whose status is desired */
+ int op, /* Status verb */
+ int *pCurrent, /* Write current value here */
+ int *pHighwater, /* Write high-water mark here */
+ int resetFlag /* Reset high-water mark if true */
+){
+ int rc = SQLITE_OK; /* Return code */
+ sqlite3_mutex_enter(db->mutex);
+ switch( op ){
+ case SQLITE_DBSTATUS_LOOKASIDE_USED: {
+ *pCurrent = db->lookaside.nOut;
+ *pHighwater = db->lookaside.mxOut;
+ if( resetFlag ){
+ db->lookaside.mxOut = db->lookaside.nOut;
+ }
+ break;
+ }
+
+ case SQLITE_DBSTATUS_LOOKASIDE_HIT:
+ case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
+ case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
+ testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
+ testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
+ testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
+ assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
+ assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
+ *pCurrent = 0;
+ *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
+ if( resetFlag ){
+ db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
+ }
+ break;
+ }
+
+ /*
+ ** Return an approximation for the amount of memory currently used
+ ** by all pagers associated with the given database connection. The
+ ** highwater mark is meaningless and is returned as zero.
+ */
+ case SQLITE_DBSTATUS_CACHE_USED: {
+ int totalUsed = 0;
+ int i;
+ sqlite3BtreeEnterAll(db);
+ for(i=0; i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ Pager *pPager = sqlite3BtreePager(pBt);
+ totalUsed += sqlite3PagerMemUsed(pPager);
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+ *pCurrent = totalUsed;
+ *pHighwater = 0;
+ break;
+ }
+
+ /*
+ ** *pCurrent gets an accurate estimate of the amount of memory used
+ ** to store the schema for all databases (main, temp, and any ATTACHed
+ ** databases. *pHighwater is set to zero.
+ */
+ case SQLITE_DBSTATUS_SCHEMA_USED: {
+ int i; /* Used to iterate through schemas */
+ int nByte = 0; /* Used to accumulate return value */
+
+ sqlite3BtreeEnterAll(db);
+ db->pnBytesFreed = &nByte;
+ for(i=0; i<db->nDb; i++){
+ Schema *pSchema = db->aDb[i].pSchema;
+ if( ALWAYS(pSchema!=0) ){
+ HashElem *p;
+
+ nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
+ pSchema->tblHash.count
+ + pSchema->trigHash.count
+ + pSchema->idxHash.count
+ + pSchema->fkeyHash.count
+ );
+ nByte += sqlite3MallocSize(pSchema->tblHash.ht);
+ nByte += sqlite3MallocSize(pSchema->trigHash.ht);
+ nByte += sqlite3MallocSize(pSchema->idxHash.ht);
+ nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
+
+ for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
+ sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
+ }
+ for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
+ sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
+ }
+ }
+ }
+ db->pnBytesFreed = 0;
+ sqlite3BtreeLeaveAll(db);
+
+ *pHighwater = 0;
+ *pCurrent = nByte;
+ break;
+ }
+
+ /*
+ ** *pCurrent gets an accurate estimate of the amount of memory used
+ ** to store all prepared statements.
+ ** *pHighwater is set to zero.
+ */
+ case SQLITE_DBSTATUS_STMT_USED: {
+ struct Vdbe *pVdbe; /* Used to iterate through VMs */
+ int nByte = 0; /* Used to accumulate return value */
+
+ db->pnBytesFreed = &nByte;
+ for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
+ sqlite3VdbeClearObject(db, pVdbe);
+ sqlite3DbFree(db, pVdbe);
+ }
+ db->pnBytesFreed = 0;
+
+ *pHighwater = 0;
+ *pCurrent = nByte;
+
+ break;
+ }
+
+ /*
+ ** Set *pCurrent to the total cache hits or misses encountered by all
+ ** pagers the database handle is connected to. *pHighwater is always set
+ ** to zero.
+ */
+ case SQLITE_DBSTATUS_CACHE_HIT:
+ case SQLITE_DBSTATUS_CACHE_MISS:
+ case SQLITE_DBSTATUS_CACHE_WRITE:{
+ int i;
+ int nRet = 0;
+ assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
+ assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
+
+ for(i=0; i<db->nDb; i++){
+ if( db->aDb[i].pBt ){
+ Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
+ sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
+ }
+ }
+ *pHighwater = 0;
+ *pCurrent = nRet;
+ break;
+ }
+
+ default: {
+ rc = SQLITE_ERROR;
+ }
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/************** End of status.c **********************************************/
+/************** Begin file date.c ********************************************/
+/*
+** 2003 October 31
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement date and time
+** functions for SQLite.
+**
+** There is only one exported symbol in this file - the function
+** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
+** All other code has file scope.
+**
+** SQLite processes all times and dates as Julian Day numbers. The
+** dates and times are stored as the number of days since noon
+** in Greenwich on November 24, 4714 B.C. according to the Gregorian
+** calendar system.
+**
+** 1970-01-01 00:00:00 is JD 2440587.5
+** 2000-01-01 00:00:00 is JD 2451544.5
+**
+** This implemention requires years to be expressed as a 4-digit number
+** which means that only dates between 0000-01-01 and 9999-12-31 can
+** be represented, even though julian day numbers allow a much wider
+** range of dates.
+**
+** The Gregorian calendar system is used for all dates and times,
+** even those that predate the Gregorian calendar. Historians usually
+** use the Julian calendar for dates prior to 1582-10-15 and for some
+** dates afterwards, depending on locale. Beware of this difference.
+**
+** The conversion algorithms are implemented based on descriptions
+** in the following text:
+**
+** Jean Meeus
+** Astronomical Algorithms, 2nd Edition, 1998
+** ISBM 0-943396-61-1
+** Willmann-Bell, Inc
+** Richmond, Virginia (USA)
+*/
+/* #include <stdlib.h> */
+/* #include <assert.h> */
+#include <time.h>
+
+#ifndef SQLITE_OMIT_DATETIME_FUNCS
+
+
+/*
+** A structure for holding a single date and time.
+*/
+typedef struct DateTime DateTime;
+struct DateTime {
+ sqlite3_int64 iJD; /* The julian day number times 86400000 */
+ int Y, M, D; /* Year, month, and day */
+ int h, m; /* Hour and minutes */
+ int tz; /* Timezone offset in minutes */
+ double s; /* Seconds */
+ char validYMD; /* True (1) if Y,M,D are valid */
+ char validHMS; /* True (1) if h,m,s are valid */
+ char validJD; /* True (1) if iJD is valid */
+ char validTZ; /* True (1) if tz is valid */
+};
+
+
+/*
+** Convert zDate into one or more integers. Additional arguments
+** come in groups of 5 as follows:
+**
+** N number of digits in the integer
+** min minimum allowed value of the integer
+** max maximum allowed value of the integer
+** nextC first character after the integer
+** pVal where to write the integers value.
+**
+** Conversions continue until one with nextC==0 is encountered.
+** The function returns the number of successful conversions.
+*/
+static int getDigits(const char *zDate, ...){
+ va_list ap;
+ int val;
+ int N;
+ int min;
+ int max;
+ int nextC;
+ int *pVal;
+ int cnt = 0;
+ va_start(ap, zDate);
+ do{
+ N = va_arg(ap, int);
+ min = va_arg(ap, int);
+ max = va_arg(ap, int);
+ nextC = va_arg(ap, int);
+ pVal = va_arg(ap, int*);
+ val = 0;
+ while( N-- ){
+ if( !sqlite3Isdigit(*zDate) ){
+ goto end_getDigits;
+ }
+ val = val*10 + *zDate - '0';
+ zDate++;
+ }
+ if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
+ goto end_getDigits;
+ }
+ *pVal = val;
+ zDate++;
+ cnt++;
+ }while( nextC );
+end_getDigits:
+ va_end(ap);
+ return cnt;
+}
+
+/*
+** Parse a timezone extension on the end of a date-time.
+** The extension is of the form:
+**
+** (+/-)HH:MM
+**
+** Or the "zulu" notation:
+**
+** Z
+**
+** If the parse is successful, write the number of minutes
+** of change in p->tz and return 0. If a parser error occurs,
+** return non-zero.
+**
+** A missing specifier is not considered an error.
+*/
+static int parseTimezone(const char *zDate, DateTime *p){
+ int sgn = 0;
+ int nHr, nMn;
+ int c;
+ while( sqlite3Isspace(*zDate) ){ zDate++; }
+ p->tz = 0;
+ c = *zDate;
+ if( c=='-' ){
+ sgn = -1;
+ }else if( c=='+' ){
+ sgn = +1;
+ }else if( c=='Z' || c=='z' ){
+ zDate++;
+ goto zulu_time;
+ }else{
+ return c!=0;
+ }
+ zDate++;
+ if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
+ return 1;
+ }
+ zDate += 5;
+ p->tz = sgn*(nMn + nHr*60);
+zulu_time:
+ while( sqlite3Isspace(*zDate) ){ zDate++; }
+ return *zDate!=0;
+}
+
+/*
+** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
+** The HH, MM, and SS must each be exactly 2 digits. The
+** fractional seconds FFFF can be one or more digits.
+**
+** Return 1 if there is a parsing error and 0 on success.
+*/
+static int parseHhMmSs(const char *zDate, DateTime *p){
+ int h, m, s;
+ double ms = 0.0;
+ if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
+ return 1;
+ }
+ zDate += 5;
+ if( *zDate==':' ){
+ zDate++;
+ if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
+ return 1;
+ }
+ zDate += 2;
+ if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
+ double rScale = 1.0;
+ zDate++;
+ while( sqlite3Isdigit(*zDate) ){
+ ms = ms*10.0 + *zDate - '0';
+ rScale *= 10.0;
+ zDate++;
+ }
+ ms /= rScale;
+ }
+ }else{
+ s = 0;
+ }
+ p->validJD = 0;
+ p->validHMS = 1;
+ p->h = h;
+ p->m = m;
+ p->s = s + ms;
+ if( parseTimezone(zDate, p) ) return 1;
+ p->validTZ = (p->tz!=0)?1:0;
+ return 0;
+}
+
+/*
+** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
+** that the YYYY-MM-DD is according to the Gregorian calendar.
+**
+** Reference: Meeus page 61
+*/
+static void computeJD(DateTime *p){
+ int Y, M, D, A, B, X1, X2;
+
+ if( p->validJD ) return;
+ if( p->validYMD ){
+ Y = p->Y;
+ M = p->M;
+ D = p->D;
+ }else{
+ Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */
+ M = 1;
+ D = 1;
+ }
+ if( M<=2 ){
+ Y--;
+ M += 12;
+ }
+ A = Y/100;
+ B = 2 - A + (A/4);
+ X1 = 36525*(Y+4716)/100;
+ X2 = 306001*(M+1)/10000;
+ p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
+ p->validJD = 1;
+ if( p->validHMS ){
+ p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
+ if( p->validTZ ){
+ p->iJD -= p->tz*60000;
+ p->validYMD = 0;
+ p->validHMS = 0;
+ p->validTZ = 0;
+ }
+ }
+}
+
+/*
+** Parse dates of the form
+**
+** YYYY-MM-DD HH:MM:SS.FFF
+** YYYY-MM-DD HH:MM:SS
+** YYYY-MM-DD HH:MM
+** YYYY-MM-DD
+**
+** Write the result into the DateTime structure and return 0
+** on success and 1 if the input string is not a well-formed
+** date.
+*/
+static int parseYyyyMmDd(const char *zDate, DateTime *p){
+ int Y, M, D, neg;
+
+ if( zDate[0]=='-' ){
+ zDate++;
+ neg = 1;
+ }else{
+ neg = 0;
+ }
+ if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
+ return 1;
+ }
+ zDate += 10;
+ while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
+ if( parseHhMmSs(zDate, p)==0 ){
+ /* We got the time */
+ }else if( *zDate==0 ){
+ p->validHMS = 0;
+ }else{
+ return 1;
+ }
+ p->validJD = 0;
+ p->validYMD = 1;
+ p->Y = neg ? -Y : Y;
+ p->M = M;
+ p->D = D;
+ if( p->validTZ ){
+ computeJD(p);
+ }
+ return 0;
+}
+
+/*
+** Set the time to the current time reported by the VFS.
+**
+** Return the number of errors.
+*/
+static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
+ p->validJD = 1;
+ return 0;
+ }else{
+ return 1;
+ }
+}
+
+/*
+** Attempt to parse the given string into a Julian Day Number. Return
+** the number of errors.
+**
+** The following are acceptable forms for the input string:
+**
+** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
+** DDDD.DD
+** now
+**
+** In the first form, the +/-HH:MM is always optional. The fractional
+** seconds extension (the ".FFF") is optional. The seconds portion
+** (":SS.FFF") is option. The year and date can be omitted as long
+** as there is a time string. The time string can be omitted as long
+** as there is a year and date.
+*/
+static int parseDateOrTime(
+ sqlite3_context *context,
+ const char *zDate,
+ DateTime *p
+){
+ double r;
+ if( parseYyyyMmDd(zDate,p)==0 ){
+ return 0;
+ }else if( parseHhMmSs(zDate, p)==0 ){
+ return 0;
+ }else if( sqlite3StrICmp(zDate,"now")==0){
+ return setDateTimeToCurrent(context, p);
+ }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
+ p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
+ p->validJD = 1;
+ return 0;
+ }
+ return 1;
+}
+
+/*
+** Compute the Year, Month, and Day from the julian day number.
+*/
+static void computeYMD(DateTime *p){
+ int Z, A, B, C, D, E, X1;
+ if( p->validYMD ) return;
+ if( !p->validJD ){
+ p->Y = 2000;
+ p->M = 1;
+ p->D = 1;
+ }else{
+ Z = (int)((p->iJD + 43200000)/86400000);
+ A = (int)((Z - 1867216.25)/36524.25);
+ A = Z + 1 + A - (A/4);
+ B = A + 1524;
+ C = (int)((B - 122.1)/365.25);
+ D = (36525*C)/100;
+ E = (int)((B-D)/30.6001);
+ X1 = (int)(30.6001*E);
+ p->D = B - D - X1;
+ p->M = E<14 ? E-1 : E-13;
+ p->Y = p->M>2 ? C - 4716 : C - 4715;
+ }
+ p->validYMD = 1;
+}
+
+/*
+** Compute the Hour, Minute, and Seconds from the julian day number.
+*/
+static void computeHMS(DateTime *p){
+ int s;
+ if( p->validHMS ) return;
+ computeJD(p);
+ s = (int)((p->iJD + 43200000) % 86400000);
+ p->s = s/1000.0;
+ s = (int)p->s;
+ p->s -= s;
+ p->h = s/3600;
+ s -= p->h*3600;
+ p->m = s/60;
+ p->s += s - p->m*60;
+ p->validHMS = 1;
+}
+
+/*
+** Compute both YMD and HMS
+*/
+static void computeYMD_HMS(DateTime *p){
+ computeYMD(p);
+ computeHMS(p);
+}
+
+/*
+** Clear the YMD and HMS and the TZ
+*/
+static void clearYMD_HMS_TZ(DateTime *p){
+ p->validYMD = 0;
+ p->validHMS = 0;
+ p->validTZ = 0;
+}
+
+/*
+** On recent Windows platforms, the localtime_s() function is available
+** as part of the "Secure CRT". It is essentially equivalent to
+** localtime_r() available under most POSIX platforms, except that the
+** order of the parameters is reversed.
+**
+** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
+**
+** If the user has not indicated to use localtime_r() or localtime_s()
+** already, check for an MSVC build environment that provides
+** localtime_s().
+*/
+#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
+ defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
+#define HAVE_LOCALTIME_S 1
+#endif
+
+#ifndef SQLITE_OMIT_LOCALTIME
+/*
+** The following routine implements the rough equivalent of localtime_r()
+** using whatever operating-system specific localtime facility that
+** is available. This routine returns 0 on success and
+** non-zero on any kind of error.
+**
+** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
+** routine will always fail.
+*/
+static int osLocaltime(time_t *t, struct tm *pTm){
+ int rc;
+#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
+ && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
+ struct tm *pX;
+#if SQLITE_THREADSAFE>0
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ sqlite3_mutex_enter(mutex);
+ pX = localtime(t);
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+ if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
+#endif
+ if( pX ) *pTm = *pX;
+ sqlite3_mutex_leave(mutex);
+ rc = pX==0;
+#else
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+ if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
+#endif
+#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
+ rc = localtime_r(t, pTm)==0;
+#else
+ rc = localtime_s(pTm, t);
+#endif /* HAVE_LOCALTIME_R */
+#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
+ return rc;
+}
+#endif /* SQLITE_OMIT_LOCALTIME */
+
+
+#ifndef SQLITE_OMIT_LOCALTIME
+/*
+** Compute the difference (in milliseconds) between localtime and UTC
+** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
+** return this value and set *pRc to SQLITE_OK.
+**
+** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
+** is undefined in this case.
+*/
+static sqlite3_int64 localtimeOffset(
+ DateTime *p, /* Date at which to calculate offset */
+ sqlite3_context *pCtx, /* Write error here if one occurs */
+ int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
+){
+ DateTime x, y;
+ time_t t;
+ struct tm sLocal;
+
+ /* Initialize the contents of sLocal to avoid a compiler warning. */
+ memset(&sLocal, 0, sizeof(sLocal));
+
+ x = *p;
+ computeYMD_HMS(&x);
+ if( x.Y<1971 || x.Y>=2038 ){
+ x.Y = 2000;
+ x.M = 1;
+ x.D = 1;
+ x.h = 0;
+ x.m = 0;
+ x.s = 0.0;
+ } else {
+ int s = (int)(x.s + 0.5);
+ x.s = s;
+ }
+ x.tz = 0;
+ x.validJD = 0;
+ computeJD(&x);
+ t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
+ if( osLocaltime(&t, &sLocal) ){
+ sqlite3_result_error(pCtx, "local time unavailable", -1);
+ *pRc = SQLITE_ERROR;
+ return 0;
+ }
+ y.Y = sLocal.tm_year + 1900;
+ y.M = sLocal.tm_mon + 1;
+ y.D = sLocal.tm_mday;
+ y.h = sLocal.tm_hour;
+ y.m = sLocal.tm_min;
+ y.s = sLocal.tm_sec;
+ y.validYMD = 1;
+ y.validHMS = 1;
+ y.validJD = 0;
+ y.validTZ = 0;
+ computeJD(&y);
+ *pRc = SQLITE_OK;
+ return y.iJD - x.iJD;
+}
+#endif /* SQLITE_OMIT_LOCALTIME */
+
+/*
+** Process a modifier to a date-time stamp. The modifiers are
+** as follows:
+**
+** NNN days
+** NNN hours
+** NNN minutes
+** NNN.NNNN seconds
+** NNN months
+** NNN years
+** start of month
+** start of year
+** start of week
+** start of day
+** weekday N
+** unixepoch
+** localtime
+** utc
+**
+** Return 0 on success and 1 if there is any kind of error. If the error
+** is in a system call (i.e. localtime()), then an error message is written
+** to context pCtx. If the error is an unrecognized modifier, no error is
+** written to pCtx.
+*/
+static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
+ int rc = 1;
+ int n;
+ double r;
+ char *z, zBuf[30];
+ z = zBuf;
+ for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
+ z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
+ }
+ z[n] = 0;
+ switch( z[0] ){
+#ifndef SQLITE_OMIT_LOCALTIME
+ case 'l': {
+ /* localtime
+ **
+ ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
+ ** show local time.
+ */
+ if( strcmp(z, "localtime")==0 ){
+ computeJD(p);
+ p->iJD += localtimeOffset(p, pCtx, &rc);
+ clearYMD_HMS_TZ(p);
+ }
+ break;
+ }
+#endif
+ case 'u': {
+ /*
+ ** unixepoch
+ **
+ ** Treat the current value of p->iJD as the number of
+ ** seconds since 1970. Convert to a real julian day number.
+ */
+ if( strcmp(z, "unixepoch")==0 && p->validJD ){
+ p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
+ clearYMD_HMS_TZ(p);
+ rc = 0;
+ }
+#ifndef SQLITE_OMIT_LOCALTIME
+ else if( strcmp(z, "utc")==0 ){
+ sqlite3_int64 c1;
+ computeJD(p);
+ c1 = localtimeOffset(p, pCtx, &rc);
+ if( rc==SQLITE_OK ){
+ p->iJD -= c1;
+ clearYMD_HMS_TZ(p);
+ p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
+ }
+ }
+#endif
+ break;
+ }
+ case 'w': {
+ /*
+ ** weekday N
+ **
+ ** Move the date to the same time on the next occurrence of
+ ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
+ ** date is already on the appropriate weekday, this is a no-op.
+ */
+ if( strncmp(z, "weekday ", 8)==0
+ && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
+ && (n=(int)r)==r && n>=0 && r<7 ){
+ sqlite3_int64 Z;
+ computeYMD_HMS(p);
+ p->validTZ = 0;
+ p->validJD = 0;
+ computeJD(p);
+ Z = ((p->iJD + 129600000)/86400000) % 7;
+ if( Z>n ) Z -= 7;
+ p->iJD += (n - Z)*86400000;
+ clearYMD_HMS_TZ(p);
+ rc = 0;
+ }
+ break;
+ }
+ case 's': {
+ /*
+ ** start of TTTTT
+ **
+ ** Move the date backwards to the beginning of the current day,
+ ** or month or year.
+ */
+ if( strncmp(z, "start of ", 9)!=0 ) break;
+ z += 9;
+ computeYMD(p);
+ p->validHMS = 1;
+ p->h = p->m = 0;
+ p->s = 0.0;
+ p->validTZ = 0;
+ p->validJD = 0;
+ if( strcmp(z,"month")==0 ){
+ p->D = 1;
+ rc = 0;
+ }else if( strcmp(z,"year")==0 ){
+ computeYMD(p);
+ p->M = 1;
+ p->D = 1;
+ rc = 0;
+ }else if( strcmp(z,"day")==0 ){
+ rc = 0;
+ }
+ break;
+ }
+ case '+':
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ double rRounder;
+ for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
+ if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
+ rc = 1;
+ break;
+ }
+ if( z[n]==':' ){
+ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
+ ** specified number of hours, minutes, seconds, and fractional seconds
+ ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
+ ** omitted.
+ */
+ const char *z2 = z;
+ DateTime tx;
+ sqlite3_int64 day;
+ if( !sqlite3Isdigit(*z2) ) z2++;
+ memset(&tx, 0, sizeof(tx));
+ if( parseHhMmSs(z2, &tx) ) break;
+ computeJD(&tx);
+ tx.iJD -= 43200000;
+ day = tx.iJD/86400000;
+ tx.iJD -= day*86400000;
+ if( z[0]=='-' ) tx.iJD = -tx.iJD;
+ computeJD(p);
+ clearYMD_HMS_TZ(p);
+ p->iJD += tx.iJD;
+ rc = 0;
+ break;
+ }
+ z += n;
+ while( sqlite3Isspace(*z) ) z++;
+ n = sqlite3Strlen30(z);
+ if( n>10 || n<3 ) break;
+ if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
+ computeJD(p);
+ rc = 0;
+ rRounder = r<0 ? -0.5 : +0.5;
+ if( n==3 && strcmp(z,"day")==0 ){
+ p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
+ }else if( n==4 && strcmp(z,"hour")==0 ){
+ p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
+ }else if( n==6 && strcmp(z,"minute")==0 ){
+ p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
+ }else if( n==6 && strcmp(z,"second")==0 ){
+ p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
+ }else if( n==5 && strcmp(z,"month")==0 ){
+ int x, y;
+ computeYMD_HMS(p);
+ p->M += (int)r;
+ x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
+ p->Y += x;
+ p->M -= x*12;
+ p->validJD = 0;
+ computeJD(p);
+ y = (int)r;
+ if( y!=r ){
+ p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
+ }
+ }else if( n==4 && strcmp(z,"year")==0 ){
+ int y = (int)r;
+ computeYMD_HMS(p);
+ p->Y += y;
+ p->validJD = 0;
+ computeJD(p);
+ if( y!=r ){
+ p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
+ }
+ }else{
+ rc = 1;
+ }
+ clearYMD_HMS_TZ(p);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return rc;
+}
+
+/*
+** Process time function arguments. argv[0] is a date-time stamp.
+** argv[1] and following are modifiers. Parse them all and write
+** the resulting time into the DateTime structure p. Return 0
+** on success and 1 if there are any errors.
+**
+** If there are zero parameters (if even argv[0] is undefined)
+** then assume a default value of "now" for argv[0].
+*/
+static int isDate(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv,
+ DateTime *p
+){
+ int i;
+ const unsigned char *z;
+ int eType;
+ memset(p, 0, sizeof(*p));
+ if( argc==0 ){
+ return setDateTimeToCurrent(context, p);
+ }
+ if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
+ || eType==SQLITE_INTEGER ){
+ p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
+ p->validJD = 1;
+ }else{
+ z = sqlite3_value_text(argv[0]);
+ if( !z || parseDateOrTime(context, (char*)z, p) ){
+ return 1;
+ }
+ }
+ for(i=1; i<argc; i++){
+ z = sqlite3_value_text(argv[i]);
+ if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
+ }
+ return 0;
+}
+
+
+/*
+** The following routines implement the various date and time functions
+** of SQLite.
+*/
+
+/*
+** julianday( TIMESTRING, MOD, MOD, ...)
+**
+** Return the julian day number of the date specified in the arguments
+*/
+static void juliandayFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ computeJD(&x);
+ sqlite3_result_double(context, x.iJD/86400000.0);
+ }
+}
+
+/*
+** datetime( TIMESTRING, MOD, MOD, ...)
+**
+** Return YYYY-MM-DD HH:MM:SS
+*/
+static void datetimeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ char zBuf[100];
+ computeYMD_HMS(&x);
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
+ x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ }
+}
+
+/*
+** time( TIMESTRING, MOD, MOD, ...)
+**
+** Return HH:MM:SS
+*/
+static void timeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ char zBuf[100];
+ computeHMS(&x);
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ }
+}
+
+/*
+** date( TIMESTRING, MOD, MOD, ...)
+**
+** Return YYYY-MM-DD
+*/
+static void dateFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ char zBuf[100];
+ computeYMD(&x);
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ }
+}
+
+/*
+** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
+**
+** Return a string described by FORMAT. Conversions as follows:
+**
+** %d day of month
+** %f ** fractional seconds SS.SSS
+** %H hour 00-24
+** %j day of year 000-366
+** %J ** Julian day number
+** %m month 01-12
+** %M minute 00-59
+** %s seconds since 1970-01-01
+** %S seconds 00-59
+** %w day of week 0-6 sunday==0
+** %W week of year 00-53
+** %Y year 0000-9999
+** %% %
+*/
+static void strftimeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ u64 n;
+ size_t i,j;
+ char *z;
+ sqlite3 *db;
+ const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
+ char zBuf[100];
+ if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
+ db = sqlite3_context_db_handle(context);
+ for(i=0, n=1; zFmt[i]; i++, n++){
+ if( zFmt[i]=='%' ){
+ switch( zFmt[i+1] ){
+ case 'd':
+ case 'H':
+ case 'm':
+ case 'M':
+ case 'S':
+ case 'W':
+ n++;
+ /* fall thru */
+ case 'w':
+ case '%':
+ break;
+ case 'f':
+ n += 8;
+ break;
+ case 'j':
+ n += 3;
+ break;
+ case 'Y':
+ n += 8;
+ break;
+ case 's':
+ case 'J':
+ n += 50;
+ break;
+ default:
+ return; /* ERROR. return a NULL */
+ }
+ i++;
+ }
+ }
+ testcase( n==sizeof(zBuf)-1 );
+ testcase( n==sizeof(zBuf) );
+ testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
+ testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
+ if( n<sizeof(zBuf) ){
+ z = zBuf;
+ }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ sqlite3_result_error_toobig(context);
+ return;
+ }else{
+ z = sqlite3DbMallocRaw(db, (int)n);
+ if( z==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ }
+ computeJD(&x);
+ computeYMD_HMS(&x);
+ for(i=j=0; zFmt[i]; i++){
+ if( zFmt[i]!='%' ){
+ z[j++] = zFmt[i];
+ }else{
+ i++;
+ switch( zFmt[i] ){
+ case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
+ case 'f': {
+ double s = x.s;
+ if( s>59.999 ) s = 59.999;
+ sqlite3_snprintf(7, &z[j],"%06.3f", s);
+ j += sqlite3Strlen30(&z[j]);
+ break;
+ }
+ case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
+ case 'W': /* Fall thru */
+ case 'j': {
+ int nDay; /* Number of days since 1st day of year */
+ DateTime y = x;
+ y.validJD = 0;
+ y.M = 1;
+ y.D = 1;
+ computeJD(&y);
+ nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
+ if( zFmt[i]=='W' ){
+ int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
+ wd = (int)(((x.iJD+43200000)/86400000)%7);
+ sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
+ j += 2;
+ }else{
+ sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
+ j += 3;
+ }
+ break;
+ }
+ case 'J': {
+ sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
+ j+=sqlite3Strlen30(&z[j]);
+ break;
+ }
+ case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
+ case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
+ case 's': {
+ sqlite3_snprintf(30,&z[j],"%lld",
+ (i64)(x.iJD/1000 - 21086676*(i64)10000));
+ j += sqlite3Strlen30(&z[j]);
+ break;
+ }
+ case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
+ case 'w': {
+ z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
+ break;
+ }
+ case 'Y': {
+ sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
+ break;
+ }
+ default: z[j++] = '%'; break;
+ }
+ }
+ }
+ z[j] = 0;
+ sqlite3_result_text(context, z, -1,
+ z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
+}
+
+/*
+** current_time()
+**
+** This function returns the same value as time('now').
+*/
+static void ctimeFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ timeFunc(context, 0, 0);
+}
+
+/*
+** current_date()
+**
+** This function returns the same value as date('now').
+*/
+static void cdateFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ dateFunc(context, 0, 0);
+}
+
+/*
+** current_timestamp()
+**
+** This function returns the same value as datetime('now').
+*/
+static void ctimestampFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ datetimeFunc(context, 0, 0);
+}
+#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
+
+#ifdef SQLITE_OMIT_DATETIME_FUNCS
+/*
+** If the library is compiled to omit the full-scale date and time
+** handling (to get a smaller binary), the following minimal version
+** of the functions current_time(), current_date() and current_timestamp()
+** are included instead. This is to support column declarations that
+** include "DEFAULT CURRENT_TIME" etc.
+**
+** This function uses the C-library functions time(), gmtime()
+** and strftime(). The format string to pass to strftime() is supplied
+** as the user-data for the function.
+*/
+static void currentTimeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ time_t t;
+ char *zFormat = (char *)sqlite3_user_data(context);
+ sqlite3 *db;
+ sqlite3_int64 iT;
+ struct tm *pTm;
+ struct tm sNow;
+ char zBuf[20];
+
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
+
+ db = sqlite3_context_db_handle(context);
+ if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
+ t = iT/1000 - 10000*(sqlite3_int64)21086676;
+#ifdef HAVE_GMTIME_R
+ pTm = gmtime_r(&t, &sNow);
+#else
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+ pTm = gmtime(&t);
+ if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+#endif
+ if( pTm ){
+ strftime(zBuf, 20, zFormat, &sNow);
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ }
+}
+#endif
+
+/*
+** This function registered all of the above C functions as SQL
+** functions. This should be the only routine in this file with
+** external linkage.
+*/
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
+ static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
+#ifndef SQLITE_OMIT_DATETIME_FUNCS
+ FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
+ FUNCTION(date, -1, 0, 0, dateFunc ),
+ FUNCTION(time, -1, 0, 0, timeFunc ),
+ FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
+ FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
+ FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
+ FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
+ FUNCTION(current_date, 0, 0, 0, cdateFunc ),
+#else
+ STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
+ STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
+ STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
+#endif
+ };
+ int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
+
+ for(i=0; i<ArraySize(aDateTimeFuncs); i++){
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
+ }
+}
+
+/************** End of date.c ************************************************/
+/************** Begin file os.c **********************************************/
+/*
+** 2005 November 29
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains OS interface code that is common to all
+** architectures.
+*/
+#define _SQLITE_OS_C_ 1
+#undef _SQLITE_OS_C_
+
+/*
+** The default SQLite sqlite3_vfs implementations do not allocate
+** memory (actually, os_unix.c allocates a small amount of memory
+** from within OsOpen()), but some third-party implementations may.
+** So we test the effects of a malloc() failing and the sqlite3OsXXX()
+** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
+**
+** The following functions are instrumented for malloc() failure
+** testing:
+**
+** sqlite3OsRead()
+** sqlite3OsWrite()
+** sqlite3OsSync()
+** sqlite3OsFileSize()
+** sqlite3OsLock()
+** sqlite3OsCheckReservedLock()
+** sqlite3OsFileControl()
+** sqlite3OsShmMap()
+** sqlite3OsOpen()
+** sqlite3OsDelete()
+** sqlite3OsAccess()
+** sqlite3OsFullPathname()
+**
+*/
+#if defined(SQLITE_TEST)
+SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
+ #define DO_OS_MALLOC_TEST(x) \
+ if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \
+ void *pTstAlloc = sqlite3Malloc(10); \
+ if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
+ sqlite3_free(pTstAlloc); \
+ }
+#else
+ #define DO_OS_MALLOC_TEST(x)
+#endif
+
+/*
+** The following routines are convenience wrappers around methods
+** of the sqlite3_file object. This is mostly just syntactic sugar. All
+** of this would be completely automatic if SQLite were coded using
+** C++ instead of plain old C.
+*/
+SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file *pId){
+ int rc = SQLITE_OK;
+ if( pId->pMethods ){
+ rc = pId->pMethods->xClose(pId);
+ pId->pMethods = 0;
+ }
+ return rc;
+}
+SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xRead(id, pBuf, amt, offset);
+}
+SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xWrite(id, pBuf, amt, offset);
+}
+SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
+ return id->pMethods->xTruncate(id, size);
+}
+SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xSync(id, flags);
+}
+SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xFileSize(id, pSize);
+}
+SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xLock(id, lockType);
+}
+SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
+ return id->pMethods->xUnlock(id, lockType);
+}
+SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xCheckReservedLock(id, pResOut);
+}
+
+/*
+** Use sqlite3OsFileControl() when we are doing something that might fail
+** and we need to know about the failures. Use sqlite3OsFileControlHint()
+** when simply tossing information over the wall to the VFS and we do not
+** really care if the VFS receives and understands the information since it
+** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
+** routine has no return value since the return value would be meaningless.
+*/
+SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xFileControl(id, op, pArg);
+}
+SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
+ (void)id->pMethods->xFileControl(id, op, pArg);
+}
+
+SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
+ int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
+ return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
+}
+SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
+ return id->pMethods->xDeviceCharacteristics(id);
+}
+SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
+ return id->pMethods->xShmLock(id, offset, n, flags);
+}
+SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){
+ id->pMethods->xShmBarrier(id);
+}
+SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
+ return id->pMethods->xShmUnmap(id, deleteFlag);
+}
+SQLITE_PRIVATE int sqlite3OsShmMap(
+ sqlite3_file *id, /* Database file handle */
+ int iPage,
+ int pgsz,
+ int bExtend, /* True to extend file if necessary */
+ void volatile **pp /* OUT: Pointer to mapping */
+){
+ DO_OS_MALLOC_TEST(id);
+ return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
+}
+
+/*
+** The next group of routines are convenience wrappers around the
+** VFS methods.
+*/
+SQLITE_PRIVATE int sqlite3OsOpen(
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ sqlite3_file *pFile,
+ int flags,
+ int *pFlagsOut
+){
+ int rc;
+ DO_OS_MALLOC_TEST(0);
+ /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
+ ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
+ ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
+ ** reaching the VFS. */
+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
+ assert( rc==SQLITE_OK || pFile->pMethods==0 );
+ return rc;
+}
+SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+ DO_OS_MALLOC_TEST(0);
+ assert( dirSync==0 || dirSync==1 );
+ return pVfs->xDelete(pVfs, zPath, dirSync);
+}
+SQLITE_PRIVATE int sqlite3OsAccess(
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int flags,
+ int *pResOut
+){
+ DO_OS_MALLOC_TEST(0);
+ return pVfs->xAccess(pVfs, zPath, flags, pResOut);
+}
+SQLITE_PRIVATE int sqlite3OsFullPathname(
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int nPathOut,
+ char *zPathOut
+){
+ DO_OS_MALLOC_TEST(0);
+ zPathOut[0] = 0;
+ return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
+}
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+ return pVfs->xDlOpen(pVfs, zPath);
+}
+SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+ pVfs->xDlError(pVfs, nByte, zBufOut);
+}
+SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
+ return pVfs->xDlSym(pVfs, pHdle, zSym);
+}
+SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
+ pVfs->xDlClose(pVfs, pHandle);
+}
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+ return pVfs->xRandomness(pVfs, nByte, zBufOut);
+}
+SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
+ return pVfs->xSleep(pVfs, nMicro);
+}
+SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
+ int rc;
+ /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
+ ** method to get the current date and time if that method is available
+ ** (if iVersion is 2 or greater and the function pointer is not NULL) and
+ ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
+ ** unavailable.
+ */
+ if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
+ rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
+ }else{
+ double r;
+ rc = pVfs->xCurrentTime(pVfs, &r);
+ *pTimeOut = (sqlite3_int64)(r*86400000.0);
+ }
+ return rc;
+}
+
+SQLITE_PRIVATE int sqlite3OsOpenMalloc(
+ sqlite3_vfs *pVfs,
+ const char *zFile,
+ sqlite3_file **ppFile,
+ int flags,
+ int *pOutFlags
+){
+ int rc = SQLITE_NOMEM;
+ sqlite3_file *pFile;
+ pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
+ if( pFile ){
+ rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pFile);
+ }else{
+ *ppFile = pFile;
+ }
+ }
+ return rc;
+}
+SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){
+ int rc = SQLITE_OK;
+ assert( pFile );
+ rc = sqlite3OsClose(pFile);
+ sqlite3_free(pFile);
+ return rc;
+}
+
+/*
+** This function is a wrapper around the OS specific implementation of
+** sqlite3_os_init(). The purpose of the wrapper is to provide the
+** ability to simulate a malloc failure, so that the handling of an
+** error in sqlite3_os_init() by the upper layers can be tested.
+*/
+SQLITE_PRIVATE int sqlite3OsInit(void){
+ void *p = sqlite3_malloc(10);
+ if( p==0 ) return SQLITE_NOMEM;
+ sqlite3_free(p);
+ return sqlite3_os_init();
+}
+
+/*
+** The list of all registered VFS implementations.
+*/
+static sqlite3_vfs * SQLITE_WSD vfsList = 0;
+#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
+
+/*
+** Locate a VFS by name. If no name is given, simply return the
+** first VFS on the list.
+*/
+SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
+ sqlite3_vfs *pVfs = 0;
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex;
+#endif
+#ifndef SQLITE_OMIT_AUTOINIT
+ int rc = sqlite3_initialize();
+ if( rc ) return 0;
+#endif
+#if SQLITE_THREADSAFE
+ mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ sqlite3_mutex_enter(mutex);
+ for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
+ if( zVfs==0 ) break;
+ if( strcmp(zVfs, pVfs->zName)==0 ) break;
+ }
+ sqlite3_mutex_leave(mutex);
+ return pVfs;
+}
+
+/*
+** Unlink a VFS from the linked list
+*/
+static void vfsUnlink(sqlite3_vfs *pVfs){
+ assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
+ if( pVfs==0 ){
+ /* No-op */
+ }else if( vfsList==pVfs ){
+ vfsList = pVfs->pNext;
+ }else if( vfsList ){
+ sqlite3_vfs *p = vfsList;
+ while( p->pNext && p->pNext!=pVfs ){
+ p = p->pNext;
+ }
+ if( p->pNext==pVfs ){
+ p->pNext = pVfs->pNext;
+ }
+ }
+}
+
+/*
+** Register a VFS with the system. It is harmless to register the same
+** VFS multiple times. The new VFS becomes the default if makeDflt is
+** true.
+*/
+SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
+ MUTEX_LOGIC(sqlite3_mutex *mutex;)
+#ifndef SQLITE_OMIT_AUTOINIT
+ int rc = sqlite3_initialize();
+ if( rc ) return rc;
+#endif
+ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+ sqlite3_mutex_enter(mutex);
+ vfsUnlink(pVfs);
+ if( makeDflt || vfsList==0 ){
+ pVfs->pNext = vfsList;
+ vfsList = pVfs;
+ }else{
+ pVfs->pNext = vfsList->pNext;
+ vfsList->pNext = pVfs;
+ }
+ assert(vfsList);
+ sqlite3_mutex_leave(mutex);
+ return SQLITE_OK;
+}
+
+/*
+** Unregister a VFS so that it is no longer accessible.
+*/
+SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ sqlite3_mutex_enter(mutex);
+ vfsUnlink(pVfs);
+ sqlite3_mutex_leave(mutex);
+ return SQLITE_OK;
+}
+
+/************** End of os.c **************************************************/
+/************** Begin file fault.c *******************************************/
+/*
+** 2008 Jan 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code to support the concept of "benign"
+** malloc failures (when the xMalloc() or xRealloc() method of the
+** sqlite3_mem_methods structure fails to allocate a block of memory
+** and returns 0).
+**
+** Most malloc failures are non-benign. After they occur, SQLite
+** abandons the current operation and returns an error code (usually
+** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
+** fatal. For example, if a malloc fails while resizing a hash table, this
+** is completely recoverable simply by not carrying out the resize. The
+** hash table will continue to function normally. So a malloc failure
+** during a hash table resize is a benign fault.
+*/
+
+
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+
+/*
+** Global variables.
+*/
+typedef struct BenignMallocHooks BenignMallocHooks;
+static SQLITE_WSD struct BenignMallocHooks {
+ void (*xBenignBegin)(void);
+ void (*xBenignEnd)(void);
+} sqlite3Hooks = { 0, 0 };
+
+/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
+** structure. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdHooks can refer directly
+** to the "sqlite3Hooks" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdHooksInit \
+ BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
+# define wsdHooks x[0]
+#else
+# define wsdHooksInit
+# define wsdHooks sqlite3Hooks
+#endif
+
+
+/*
+** Register hooks to call when sqlite3BeginBenignMalloc() and
+** sqlite3EndBenignMalloc() are called, respectively.
+*/
+SQLITE_PRIVATE void sqlite3BenignMallocHooks(
+ void (*xBenignBegin)(void),
+ void (*xBenignEnd)(void)
+){
+ wsdHooksInit;
+ wsdHooks.xBenignBegin = xBenignBegin;
+ wsdHooks.xBenignEnd = xBenignEnd;
+}
+
+/*
+** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
+** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
+** indicates that subsequent malloc failures are non-benign.
+*/
+SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
+ wsdHooksInit;
+ if( wsdHooks.xBenignBegin ){
+ wsdHooks.xBenignBegin();
+ }
+}
+SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
+ wsdHooksInit;
+ if( wsdHooks.xBenignEnd ){
+ wsdHooks.xBenignEnd();
+ }
+}
+
+#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
+
+/************** End of fault.c ***********************************************/
+/************** Begin file mem0.c ********************************************/
+/*
+** 2008 October 28
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains a no-op memory allocation drivers for use when
+** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented
+** here always fail. SQLite will not operate with these drivers. These
+** are merely placeholders. Real drivers must be substituted using
+** sqlite3_config() before SQLite will operate.
+*/
+
+/*
+** This version of the memory allocator is the default. It is
+** used when no other memory allocator is specified using compile-time
+** macros.
+*/
+#ifdef SQLITE_ZERO_MALLOC
+
+/*
+** No-op versions of all memory allocation routines
+*/
+static void *sqlite3MemMalloc(int nByte){ return 0; }
+static void sqlite3MemFree(void *pPrior){ return; }
+static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
+static int sqlite3MemSize(void *pPrior){ return 0; }
+static int sqlite3MemRoundup(int n){ return n; }
+static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
+static void sqlite3MemShutdown(void *NotUsed){ return; }
+
+/*
+** This routine is the only routine in this file with external linkage.
+**
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
+*/
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ static const sqlite3_mem_methods defaultMethods = {
+ sqlite3MemMalloc,
+ sqlite3MemFree,
+ sqlite3MemRealloc,
+ sqlite3MemSize,
+ sqlite3MemRoundup,
+ sqlite3MemInit,
+ sqlite3MemShutdown,
+ 0
+ };
+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+}
+
+#endif /* SQLITE_ZERO_MALLOC */
+
+/************** End of mem0.c ************************************************/
+/************** Begin file mem1.c ********************************************/
+/*
+** 2007 August 14
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains low-level memory allocation drivers for when
+** SQLite will use the standard C-library malloc/realloc/free interface
+** to obtain the memory it needs.
+**
+** This file contains implementations of the low-level memory allocation
+** routines specified in the sqlite3_mem_methods object. The content of
+** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The
+** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
+** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The
+** default configuration is to use memory allocation routines in this
+** file.
+**
+** C-preprocessor macro summary:
+**
+** HAVE_MALLOC_USABLE_SIZE The configure script sets this symbol if
+** the malloc_usable_size() interface exists
+** on the target platform. Or, this symbol
+** can be set manually, if desired.
+** If an equivalent interface exists by
+** a different name, using a separate -D
+** option to rename it.
+**
+** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone
+** memory allocator. Set this symbol to enable
+** building on older macs.
+**
+** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of
+** _msize() on windows systems. This might
+** be necessary when compiling for Delphi,
+** for example.
+*/
+
+/*
+** This version of the memory allocator is the default. It is
+** used when no other memory allocator is specified using compile-time
+** macros.
+*/
+#ifdef SQLITE_SYSTEM_MALLOC
+
+/*
+** The MSVCRT has malloc_usable_size() but it is called _msize().
+** The use of _msize() is automatic, but can be disabled by compiling
+** with -DSQLITE_WITHOUT_MSIZE
+*/
+#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
+# define SQLITE_MALLOCSIZE _msize
+#endif
+
+#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
+
+/*
+** Use the zone allocator available on apple products unless the
+** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
+*/
+#include <sys/sysctl.h>
+#include <malloc/malloc.h>
+#include <libkern/OSAtomic.h>
+static malloc_zone_t* _sqliteZone_;
+#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
+#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
+#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
+#define SQLITE_MALLOCSIZE(x) \
+ (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
+
+#else /* if not __APPLE__ */
+
+/*
+** Use standard C library malloc and free on non-Apple systems.
+** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
+*/
+#define SQLITE_MALLOC(x) malloc(x)
+#define SQLITE_FREE(x) free(x)
+#define SQLITE_REALLOC(x,y) realloc((x),(y))
+
+#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
+ || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
+# include <malloc.h> /* Needed for malloc_usable_size on linux */
+#endif
+#ifdef HAVE_MALLOC_USABLE_SIZE
+# ifndef SQLITE_MALLOCSIZE
+# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
+# endif
+#else
+# undef SQLITE_MALLOCSIZE
+#endif
+
+#endif /* __APPLE__ or not __APPLE__ */
+
+/*
+** Like malloc(), but remember the size of the allocation
+** so that we can find it later using sqlite3MemSize().
+**
+** For this low-level routine, we are guaranteed that nByte>0 because
+** cases of nByte<=0 will be intercepted and dealt with by higher level
+** routines.
+*/
+static void *sqlite3MemMalloc(int nByte){
+#ifdef SQLITE_MALLOCSIZE
+ void *p = SQLITE_MALLOC( nByte );
+ if( p==0 ){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
+ }
+ return p;
+#else
+ sqlite3_int64 *p;
+ assert( nByte>0 );
+ nByte = ROUND8(nByte);
+ p = SQLITE_MALLOC( nByte+8 );
+ if( p ){
+ p[0] = nByte;
+ p++;
+ }else{
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
+ }
+ return (void *)p;
+#endif
+}
+
+/*
+** Like free() but works for allocations obtained from sqlite3MemMalloc()
+** or sqlite3MemRealloc().
+**
+** For this low-level routine, we already know that pPrior!=0 since
+** cases where pPrior==0 will have been intecepted and dealt with
+** by higher-level routines.
+*/
+static void sqlite3MemFree(void *pPrior){
+#ifdef SQLITE_MALLOCSIZE
+ SQLITE_FREE(pPrior);
+#else
+ sqlite3_int64 *p = (sqlite3_int64*)pPrior;
+ assert( pPrior!=0 );
+ p--;
+ SQLITE_FREE(p);
+#endif
+}
+
+/*
+** Report the allocated size of a prior return from xMalloc()
+** or xRealloc().
+*/
+static int sqlite3MemSize(void *pPrior){
+#ifdef SQLITE_MALLOCSIZE
+ return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
+#else
+ sqlite3_int64 *p;
+ if( pPrior==0 ) return 0;
+ p = (sqlite3_int64*)pPrior;
+ p--;
+ return (int)p[0];
+#endif
+}
+
+/*
+** Like realloc(). Resize an allocation previously obtained from
+** sqlite3MemMalloc().
+**
+** For this low-level interface, we know that pPrior!=0. Cases where
+** pPrior==0 while have been intercepted by higher-level routine and
+** redirected to xMalloc. Similarly, we know that nByte>0 becauses
+** cases where nByte<=0 will have been intercepted by higher-level
+** routines and redirected to xFree.
+*/
+static void *sqlite3MemRealloc(void *pPrior, int nByte){
+#ifdef SQLITE_MALLOCSIZE
+ void *p = SQLITE_REALLOC(pPrior, nByte);
+ if( p==0 ){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_NOMEM,
+ "failed memory resize %u to %u bytes",
+ SQLITE_MALLOCSIZE(pPrior), nByte);
+ }
+ return p;
+#else
+ sqlite3_int64 *p = (sqlite3_int64*)pPrior;
+ assert( pPrior!=0 && nByte>0 );
+ assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
+ p--;
+ p = SQLITE_REALLOC(p, nByte+8 );
+ if( p ){
+ p[0] = nByte;
+ p++;
+ }else{
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_NOMEM,
+ "failed memory resize %u to %u bytes",
+ sqlite3MemSize(pPrior), nByte);
+ }
+ return (void*)p;
+#endif
+}
+
+/*
+** Round up a request size to the next valid allocation size.
+*/
+static int sqlite3MemRoundup(int n){
+ return ROUND8(n);
+}
+
+/*
+** Initialize this module.
+*/
+static int sqlite3MemInit(void *NotUsed){
+#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
+ int cpuCount;
+ size_t len;
+ if( _sqliteZone_ ){
+ return SQLITE_OK;
+ }
+ len = sizeof(cpuCount);
+ /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
+ sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
+ if( cpuCount>1 ){
+ /* defer MT decisions to system malloc */
+ _sqliteZone_ = malloc_default_zone();
+ }else{
+ /* only 1 core, use our own zone to contention over global locks,
+ ** e.g. we have our own dedicated locks */
+ bool success;
+ malloc_zone_t* newzone = malloc_create_zone(4096, 0);
+ malloc_set_zone_name(newzone, "Sqlite_Heap");
+ do{
+ success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
+ (void * volatile *)&_sqliteZone_);
+ }while(!_sqliteZone_);
+ if( !success ){
+ /* somebody registered a zone first */
+ malloc_destroy_zone(newzone);
+ }
+ }
+#endif
+ UNUSED_PARAMETER(NotUsed);
+ return SQLITE_OK;
+}
+
+/*
+** Deinitialize this module.
+*/
+static void sqlite3MemShutdown(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ return;
+}
+
+/*
+** This routine is the only routine in this file with external linkage.
+**
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
+*/
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ static const sqlite3_mem_methods defaultMethods = {
+ sqlite3MemMalloc,
+ sqlite3MemFree,
+ sqlite3MemRealloc,
+ sqlite3MemSize,
+ sqlite3MemRoundup,
+ sqlite3MemInit,
+ sqlite3MemShutdown,
+ 0
+ };
+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+}
+
+#endif /* SQLITE_SYSTEM_MALLOC */
+
+/************** End of mem1.c ************************************************/
+/************** Begin file mem2.c ********************************************/
+/*
+** 2007 August 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains low-level memory allocation drivers for when
+** SQLite will use the standard C-library malloc/realloc/free interface
+** to obtain the memory it needs while adding lots of additional debugging
+** information to each allocation in order to help detect and fix memory
+** leaks and memory usage errors.
+**
+** This file contains implementations of the low-level memory allocation
+** routines specified in the sqlite3_mem_methods object.
+*/
+
+/*
+** This version of the memory allocator is used only if the
+** SQLITE_MEMDEBUG macro is defined
+*/
+#ifdef SQLITE_MEMDEBUG
+
+/*
+** The backtrace functionality is only available with GLIBC
+*/
+#ifdef __GLIBC__
+ extern int backtrace(void**,int);
+ extern void backtrace_symbols_fd(void*const*,int,int);
+#else
+# define backtrace(A,B) 1
+# define backtrace_symbols_fd(A,B,C)
+#endif
+/* #include <stdio.h> */
+
+/*
+** Each memory allocation looks like this:
+**
+** ------------------------------------------------------------------------
+** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard |
+** ------------------------------------------------------------------------
+**
+** The application code sees only a pointer to the allocation. We have
+** to back up from the allocation pointer to find the MemBlockHdr. The
+** MemBlockHdr tells us the size of the allocation and the number of
+** backtrace pointers. There is also a guard word at the end of the
+** MemBlockHdr.
+*/
+struct MemBlockHdr {
+ i64 iSize; /* Size of this allocation */
+ struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
+ char nBacktrace; /* Number of backtraces on this alloc */
+ char nBacktraceSlots; /* Available backtrace slots */
+ u8 nTitle; /* Bytes of title; includes '\0' */
+ u8 eType; /* Allocation type code */
+ int iForeGuard; /* Guard word for sanity */
+};
+
+/*
+** Guard words
+*/
+#define FOREGUARD 0x80F5E153
+#define REARGUARD 0xE4676B53
+
+/*
+** Number of malloc size increments to track.
+*/
+#define NCSIZE 1000
+
+/*
+** All of the static variables used by this module are collected
+** into a single structure named "mem". This is to keep the
+** static variables organized and to reduce namespace pollution
+** when this module is combined with other in the amalgamation.
+*/
+static struct {
+
+ /*
+ ** Mutex to control access to the memory allocation subsystem.
+ */
+ sqlite3_mutex *mutex;
+
+ /*
+ ** Head and tail of a linked list of all outstanding allocations
+ */
+ struct MemBlockHdr *pFirst;
+ struct MemBlockHdr *pLast;
+
+ /*
+ ** The number of levels of backtrace to save in new allocations.
+ */
+ int nBacktrace;
+ void (*xBacktrace)(int, int, void **);
+
+ /*
+ ** Title text to insert in front of each block
+ */
+ int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */
+ char zTitle[100]; /* The title text */
+
+ /*
+ ** sqlite3MallocDisallow() increments the following counter.
+ ** sqlite3MallocAllow() decrements it.
+ */
+ int disallow; /* Do not allow memory allocation */
+
+ /*
+ ** Gather statistics on the sizes of memory allocations.
+ ** nAlloc[i] is the number of allocation attempts of i*8
+ ** bytes. i==NCSIZE is the number of allocation attempts for
+ ** sizes more than NCSIZE*8 bytes.
+ */
+ int nAlloc[NCSIZE]; /* Total number of allocations */
+ int nCurrent[NCSIZE]; /* Current number of allocations */
+ int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */
+
+} mem;
+
+
+/*
+** Adjust memory usage statistics
+*/
+static void adjustStats(int iSize, int increment){
+ int i = ROUND8(iSize)/8;
+ if( i>NCSIZE-1 ){
+ i = NCSIZE - 1;
+ }
+ if( increment>0 ){
+ mem.nAlloc[i]++;
+ mem.nCurrent[i]++;
+ if( mem.nCurrent[i]>mem.mxCurrent[i] ){
+ mem.mxCurrent[i] = mem.nCurrent[i];
+ }
+ }else{
+ mem.nCurrent[i]--;
+ assert( mem.nCurrent[i]>=0 );
+ }
+}
+
+/*
+** Given an allocation, find the MemBlockHdr for that allocation.
+**
+** This routine checks the guards at either end of the allocation and
+** if they are incorrect it asserts.
+*/
+static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
+ struct MemBlockHdr *p;
+ int *pInt;
+ u8 *pU8;
+ int nReserve;
+
+ p = (struct MemBlockHdr*)pAllocation;
+ p--;
+ assert( p->iForeGuard==(int)FOREGUARD );
+ nReserve = ROUND8(p->iSize);
+ pInt = (int*)pAllocation;
+ pU8 = (u8*)pAllocation;
+ assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
+ /* This checks any of the "extra" bytes allocated due
+ ** to rounding up to an 8 byte boundary to ensure
+ ** they haven't been overwritten.
+ */
+ while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
+ return p;
+}
+
+/*
+** Return the number of bytes currently allocated at address p.
+*/
+static int sqlite3MemSize(void *p){
+ struct MemBlockHdr *pHdr;
+ if( !p ){
+ return 0;
+ }
+ pHdr = sqlite3MemsysGetHeader(p);
+ return pHdr->iSize;
+}
+
+/*
+** Initialize the memory allocation subsystem.
+*/
+static int sqlite3MemInit(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ assert( (sizeof(struct MemBlockHdr)&7) == 0 );
+ if( !sqlite3GlobalConfig.bMemstat ){
+ /* If memory status is enabled, then the malloc.c wrapper will already
+ ** hold the STATIC_MEM mutex when the routines here are invoked. */
+ mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Deinitialize the memory allocation subsystem.
+*/
+static void sqlite3MemShutdown(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ mem.mutex = 0;
+}
+
+/*
+** Round up a request size to the next valid allocation size.
+*/
+static int sqlite3MemRoundup(int n){
+ return ROUND8(n);
+}
+
+/*
+** Fill a buffer with pseudo-random bytes. This is used to preset
+** the content of a new memory allocation to unpredictable values and
+** to clear the content of a freed allocation to unpredictable values.
+*/
+static void randomFill(char *pBuf, int nByte){
+ unsigned int x, y, r;
+ x = SQLITE_PTR_TO_INT(pBuf);
+ y = nByte | 1;
+ while( nByte >= 4 ){
+ x = (x>>1) ^ (-(x&1) & 0xd0000001);
+ y = y*1103515245 + 12345;
+ r = x ^ y;
+ *(int*)pBuf = r;
+ pBuf += 4;
+ nByte -= 4;
+ }
+ while( nByte-- > 0 ){
+ x = (x>>1) ^ (-(x&1) & 0xd0000001);
+ y = y*1103515245 + 12345;
+ r = x ^ y;
+ *(pBuf++) = r & 0xff;
+ }
+}
+
+/*
+** Allocate nByte bytes of memory.
+*/
+static void *sqlite3MemMalloc(int nByte){
+ struct MemBlockHdr *pHdr;
+ void **pBt;
+ char *z;
+ int *pInt;
+ void *p = 0;
+ int totalSize;
+ int nReserve;
+ sqlite3_mutex_enter(mem.mutex);
+ assert( mem.disallow==0 );
+ nReserve = ROUND8(nByte);
+ totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
+ mem.nBacktrace*sizeof(void*) + mem.nTitle;
+ p = malloc(totalSize);
+ if( p ){
+ z = p;
+ pBt = (void**)&z[mem.nTitle];
+ pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
+ pHdr->pNext = 0;
+ pHdr->pPrev = mem.pLast;
+ if( mem.pLast ){
+ mem.pLast->pNext = pHdr;
+ }else{
+ mem.pFirst = pHdr;
+ }
+ mem.pLast = pHdr;
+ pHdr->iForeGuard = FOREGUARD;
+ pHdr->eType = MEMTYPE_HEAP;
+ pHdr->nBacktraceSlots = mem.nBacktrace;
+ pHdr->nTitle = mem.nTitle;
+ if( mem.nBacktrace ){
+ void *aAddr[40];
+ pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
+ memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
+ assert(pBt[0]);
+ if( mem.xBacktrace ){
+ mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
+ }
+ }else{
+ pHdr->nBacktrace = 0;
+ }
+ if( mem.nTitle ){
+ memcpy(z, mem.zTitle, mem.nTitle);
+ }
+ pHdr->iSize = nByte;
+ adjustStats(nByte, +1);
+ pInt = (int*)&pHdr[1];
+ pInt[nReserve/sizeof(int)] = REARGUARD;
+ randomFill((char*)pInt, nByte);
+ memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
+ p = (void*)pInt;
+ }
+ sqlite3_mutex_leave(mem.mutex);
+ return p;
+}
+
+/*
+** Free memory.
+*/
+static void sqlite3MemFree(void *pPrior){
+ struct MemBlockHdr *pHdr;
+ void **pBt;
+ char *z;
+ assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
+ || mem.mutex!=0 );
+ pHdr = sqlite3MemsysGetHeader(pPrior);
+ pBt = (void**)pHdr;
+ pBt -= pHdr->nBacktraceSlots;
+ sqlite3_mutex_enter(mem.mutex);
+ if( pHdr->pPrev ){
+ assert( pHdr->pPrev->pNext==pHdr );
+ pHdr->pPrev->pNext = pHdr->pNext;
+ }else{
+ assert( mem.pFirst==pHdr );
+ mem.pFirst = pHdr->pNext;
+ }
+ if( pHdr->pNext ){
+ assert( pHdr->pNext->pPrev==pHdr );
+ pHdr->pNext->pPrev = pHdr->pPrev;
+ }else{
+ assert( mem.pLast==pHdr );
+ mem.pLast = pHdr->pPrev;
+ }
+ z = (char*)pBt;
+ z -= pHdr->nTitle;
+ adjustStats(pHdr->iSize, -1);
+ randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
+ pHdr->iSize + sizeof(int) + pHdr->nTitle);
+ free(z);
+ sqlite3_mutex_leave(mem.mutex);
+}
+
+/*
+** Change the size of an existing memory allocation.
+**
+** For this debugging implementation, we *always* make a copy of the
+** allocation into a new place in memory. In this way, if the
+** higher level code is using pointer to the old allocation, it is
+** much more likely to break and we are much more liking to find
+** the error.
+*/
+static void *sqlite3MemRealloc(void *pPrior, int nByte){
+ struct MemBlockHdr *pOldHdr;
+ void *pNew;
+ assert( mem.disallow==0 );
+ assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */
+ pOldHdr = sqlite3MemsysGetHeader(pPrior);
+ pNew = sqlite3MemMalloc(nByte);
+ if( pNew ){
+ memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
+ if( nByte>pOldHdr->iSize ){
+ randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
+ }
+ sqlite3MemFree(pPrior);
+ }
+ return pNew;
+}
+
+/*
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
+*/
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ static const sqlite3_mem_methods defaultMethods = {
+ sqlite3MemMalloc,
+ sqlite3MemFree,
+ sqlite3MemRealloc,
+ sqlite3MemSize,
+ sqlite3MemRoundup,
+ sqlite3MemInit,
+ sqlite3MemShutdown,
+ 0
+ };
+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+}
+
+/*
+** Set the "type" of an allocation.
+*/
+SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
+ if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+ struct MemBlockHdr *pHdr;
+ pHdr = sqlite3MemsysGetHeader(p);
+ assert( pHdr->iForeGuard==FOREGUARD );
+ pHdr->eType = eType;
+ }
+}
+
+/*
+** Return TRUE if the mask of type in eType matches the type of the
+** allocation p. Also return true if p==NULL.
+**
+** This routine is designed for use within an assert() statement, to
+** verify the type of an allocation. For example:
+**
+** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+*/
+SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
+ int rc = 1;
+ if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+ struct MemBlockHdr *pHdr;
+ pHdr = sqlite3MemsysGetHeader(p);
+ assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
+ if( (pHdr->eType&eType)==0 ){
+ rc = 0;
+ }
+ }
+ return rc;
+}
+
+/*
+** Return TRUE if the mask of type in eType matches no bits of the type of the
+** allocation p. Also return true if p==NULL.
+**
+** This routine is designed for use within an assert() statement, to
+** verify the type of an allocation. For example:
+**
+** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
+*/
+SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
+ int rc = 1;
+ if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+ struct MemBlockHdr *pHdr;
+ pHdr = sqlite3MemsysGetHeader(p);
+ assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
+ if( (pHdr->eType&eType)!=0 ){
+ rc = 0;
+ }
+ }
+ return rc;
+}
+
+/*
+** Set the number of backtrace levels kept for each allocation.
+** A value of zero turns off backtracing. The number is always rounded
+** up to a multiple of 2.
+*/
+SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){
+ if( depth<0 ){ depth = 0; }
+ if( depth>20 ){ depth = 20; }
+ depth = (depth+1)&0xfe;
+ mem.nBacktrace = depth;
+}
+
+SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
+ mem.xBacktrace = xBacktrace;
+}
+
+/*
+** Set the title string for subsequent allocations.
+*/
+SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
+ unsigned int n = sqlite3Strlen30(zTitle) + 1;
+ sqlite3_mutex_enter(mem.mutex);
+ if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
+ memcpy(mem.zTitle, zTitle, n);
+ mem.zTitle[n] = 0;
+ mem.nTitle = ROUND8(n);
+ sqlite3_mutex_leave(mem.mutex);
+}
+
+SQLITE_PRIVATE void sqlite3MemdebugSync(){
+ struct MemBlockHdr *pHdr;
+ for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
+ void **pBt = (void**)pHdr;
+ pBt -= pHdr->nBacktraceSlots;
+ mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
+ }
+}
+
+/*
+** Open the file indicated and write a log of all unfreed memory
+** allocations into that log.
+*/
+SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
+ FILE *out;
+ struct MemBlockHdr *pHdr;
+ void **pBt;
+ int i;
+ out = fopen(zFilename, "w");
+ if( out==0 ){
+ fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
+ zFilename);
+ return;
+ }
+ for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
+ char *z = (char*)pHdr;
+ z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
+ fprintf(out, "**** %lld bytes at %p from %s ****\n",
+ pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
+ if( pHdr->nBacktrace ){
+ fflush(out);
+ pBt = (void**)pHdr;
+ pBt -= pHdr->nBacktraceSlots;
+ backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
+ fprintf(out, "\n");
+ }
+ }
+ fprintf(out, "COUNTS:\n");
+ for(i=0; i<NCSIZE-1; i++){
+ if( mem.nAlloc[i] ){
+ fprintf(out, " %5d: %10d %10d %10d\n",
+ i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
+ }
+ }
+ if( mem.nAlloc[NCSIZE-1] ){
+ fprintf(out, " %5d: %10d %10d %10d\n",
+ NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
+ mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
+ }
+ fclose(out);
+}
+
+/*
+** Return the number of times sqlite3MemMalloc() has been called.
+*/
+SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
+ int i;
+ int nTotal = 0;
+ for(i=0; i<NCSIZE; i++){
+ nTotal += mem.nAlloc[i];
+ }
+ return nTotal;
+}
+
+
+#endif /* SQLITE_MEMDEBUG */
+
+/************** End of mem2.c ************************************************/
+/************** Begin file mem3.c ********************************************/
+/*
+** 2007 October 14
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement a memory
+** allocation subsystem for use by SQLite.
+**
+** This version of the memory allocation subsystem omits all
+** use of malloc(). The SQLite user supplies a block of memory
+** before calling sqlite3_initialize() from which allocations
+** are made and returned by the xMalloc() and xRealloc()
+** implementations. Once sqlite3_initialize() has been called,
+** the amount of memory available to SQLite is fixed and cannot
+** be changed.
+**
+** This version of the memory allocation subsystem is included
+** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
+*/
+
+/*
+** This version of the memory allocator is only built into the library
+** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
+** mean that the library will use a memory-pool by default, just that
+** it is available. The mempool allocator is activated by calling
+** sqlite3_config().
+*/
+#ifdef SQLITE_ENABLE_MEMSYS3
+
+/*
+** Maximum size (in Mem3Blocks) of a "small" chunk.
+*/
+#define MX_SMALL 10
+
+
+/*
+** Number of freelist hash slots
+*/
+#define N_HASH 61
+
+/*
+** A memory allocation (also called a "chunk") consists of two or
+** more blocks where each block is 8 bytes. The first 8 bytes are
+** a header that is not returned to the user.
+**
+** A chunk is two or more blocks that is either checked out or
+** free. The first block has format u.hdr. u.hdr.size4x is 4 times the
+** size of the allocation in blocks if the allocation is free.
+** The u.hdr.size4x&1 bit is true if the chunk is checked out and
+** false if the chunk is on the freelist. The u.hdr.size4x&2 bit
+** is true if the previous chunk is checked out and false if the
+** previous chunk is free. The u.hdr.prevSize field is the size of
+** the previous chunk in blocks if the previous chunk is on the
+** freelist. If the previous chunk is checked out, then
+** u.hdr.prevSize can be part of the data for that chunk and should
+** not be read or written.
+**
+** We often identify a chunk by its index in mem3.aPool[]. When
+** this is done, the chunk index refers to the second block of
+** the chunk. In this way, the first chunk has an index of 1.
+** A chunk index of 0 means "no such chunk" and is the equivalent
+** of a NULL pointer.
+**
+** The second block of free chunks is of the form u.list. The
+** two fields form a double-linked list of chunks of related sizes.
+** Pointers to the head of the list are stored in mem3.aiSmall[]
+** for smaller chunks and mem3.aiHash[] for larger chunks.
+**
+** The second block of a chunk is user data if the chunk is checked
+** out. If a chunk is checked out, the user data may extend into
+** the u.hdr.prevSize value of the following chunk.
+*/
+typedef struct Mem3Block Mem3Block;
+struct Mem3Block {
+ union {
+ struct {
+ u32 prevSize; /* Size of previous chunk in Mem3Block elements */
+ u32 size4x; /* 4x the size of current chunk in Mem3Block elements */
+ } hdr;
+ struct {
+ u32 next; /* Index in mem3.aPool[] of next free chunk */
+ u32 prev; /* Index in mem3.aPool[] of previous free chunk */
+ } list;
+ } u;
+};
+
+/*
+** All of the static variables used by this module are collected
+** into a single structure named "mem3". This is to keep the
+** static variables organized and to reduce namespace pollution
+** when this module is combined with other in the amalgamation.
+*/
+static SQLITE_WSD struct Mem3Global {
+ /*
+ ** Memory available for allocation. nPool is the size of the array
+ ** (in Mem3Blocks) pointed to by aPool less 2.
+ */
+ u32 nPool;
+ Mem3Block *aPool;
+
+ /*
+ ** True if we are evaluating an out-of-memory callback.
+ */
+ int alarmBusy;
+
+ /*
+ ** Mutex to control access to the memory allocation subsystem.
+ */
+ sqlite3_mutex *mutex;
+
+ /*
+ ** The minimum amount of free space that we have seen.
+ */
+ u32 mnMaster;
+
+ /*
+ ** iMaster is the index of the master chunk. Most new allocations
+ ** occur off of this chunk. szMaster is the size (in Mem3Blocks)
+ ** of the current master. iMaster is 0 if there is not master chunk.
+ ** The master chunk is not in either the aiHash[] or aiSmall[].
+ */
+ u32 iMaster;
+ u32 szMaster;
+
+ /*
+ ** Array of lists of free blocks according to the block size
+ ** for smaller chunks, or a hash on the block size for larger
+ ** chunks.
+ */
+ u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
+ u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
+} mem3 = { 97535575 };
+
+#define mem3 GLOBAL(struct Mem3Global, mem3)
+
+/*
+** Unlink the chunk at mem3.aPool[i] from list it is currently
+** on. *pRoot is the list that i is a member of.
+*/
+static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
+ u32 next = mem3.aPool[i].u.list.next;
+ u32 prev = mem3.aPool[i].u.list.prev;
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ if( prev==0 ){
+ *pRoot = next;
+ }else{
+ mem3.aPool[prev].u.list.next = next;
+ }
+ if( next ){
+ mem3.aPool[next].u.list.prev = prev;
+ }
+ mem3.aPool[i].u.list.next = 0;
+ mem3.aPool[i].u.list.prev = 0;
+}
+
+/*
+** Unlink the chunk at index i from
+** whatever list is currently a member of.
+*/
+static void memsys3Unlink(u32 i){
+ u32 size, hash;
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
+ assert( i>=1 );
+ size = mem3.aPool[i-1].u.hdr.size4x/4;
+ assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
+ assert( size>=2 );
+ if( size <= MX_SMALL ){
+ memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
+ }else{
+ hash = size % N_HASH;
+ memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
+ }
+}
+
+/*
+** Link the chunk at mem3.aPool[i] so that is on the list rooted
+** at *pRoot.
+*/
+static void memsys3LinkIntoList(u32 i, u32 *pRoot){
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ mem3.aPool[i].u.list.next = *pRoot;
+ mem3.aPool[i].u.list.prev = 0;
+ if( *pRoot ){
+ mem3.aPool[*pRoot].u.list.prev = i;
+ }
+ *pRoot = i;
+}
+
+/*
+** Link the chunk at index i into either the appropriate
+** small chunk list, or into the large chunk hash table.
+*/
+static void memsys3Link(u32 i){
+ u32 size, hash;
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ assert( i>=1 );
+ assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
+ size = mem3.aPool[i-1].u.hdr.size4x/4;
+ assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
+ assert( size>=2 );
+ if( size <= MX_SMALL ){
+ memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
+ }else{
+ hash = size % N_HASH;
+ memsys3LinkIntoList(i, &mem3.aiHash[hash]);
+ }
+}
+
+/*
+** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
+** will already be held (obtained by code in malloc.c) if
+** sqlite3GlobalConfig.bMemStat is true.
+*/
+static void memsys3Enter(void){
+ if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
+ mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+ }
+ sqlite3_mutex_enter(mem3.mutex);
+}
+static void memsys3Leave(void){
+ sqlite3_mutex_leave(mem3.mutex);
+}
+
+/*
+** Called when we are unable to satisfy an allocation of nBytes.
+*/
+static void memsys3OutOfMemory(int nByte){
+ if( !mem3.alarmBusy ){
+ mem3.alarmBusy = 1;
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ sqlite3_mutex_leave(mem3.mutex);
+ sqlite3_release_memory(nByte);
+ sqlite3_mutex_enter(mem3.mutex);
+ mem3.alarmBusy = 0;
+ }
+}
+
+
+/*
+** Chunk i is a free chunk that has been unlinked. Adjust its
+** size parameters for check-out and return a pointer to the
+** user portion of the chunk.
+*/
+static void *memsys3Checkout(u32 i, u32 nBlock){
+ u32 x;
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ assert( i>=1 );
+ assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
+ assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
+ x = mem3.aPool[i-1].u.hdr.size4x;
+ mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
+ mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
+ mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
+ return &mem3.aPool[i];
+}
+
+/*
+** Carve a piece off of the end of the mem3.iMaster free chunk.
+** Return a pointer to the new allocation. Or, if the master chunk
+** is not large enough, return 0.
+*/
+static void *memsys3FromMaster(u32 nBlock){
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ assert( mem3.szMaster>=nBlock );
+ if( nBlock>=mem3.szMaster-1 ){
+ /* Use the entire master */
+ void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
+ mem3.iMaster = 0;
+ mem3.szMaster = 0;
+ mem3.mnMaster = 0;
+ return p;
+ }else{
+ /* Split the master block. Return the tail. */
+ u32 newi, x;
+ newi = mem3.iMaster + mem3.szMaster - nBlock;
+ assert( newi > mem3.iMaster+1 );
+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
+ mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
+ mem3.szMaster -= nBlock;
+ mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
+ x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
+ mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
+ if( mem3.szMaster < mem3.mnMaster ){
+ mem3.mnMaster = mem3.szMaster;
+ }
+ return (void*)&mem3.aPool[newi];
+ }
+}
+
+/*
+** *pRoot is the head of a list of free chunks of the same size
+** or same size hash. In other words, *pRoot is an entry in either
+** mem3.aiSmall[] or mem3.aiHash[].
+**
+** This routine examines all entries on the given list and tries
+** to coalesce each entries with adjacent free chunks.
+**
+** If it sees a chunk that is larger than mem3.iMaster, it replaces
+** the current mem3.iMaster with the new larger chunk. In order for
+** this mem3.iMaster replacement to work, the master chunk must be
+** linked into the hash tables. That is not the normal state of
+** affairs, of course. The calling routine must link the master
+** chunk before invoking this routine, then must unlink the (possibly
+** changed) master chunk once this routine has finished.
+*/
+static void memsys3Merge(u32 *pRoot){
+ u32 iNext, prev, size, i, x;
+
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ for(i=*pRoot; i>0; i=iNext){
+ iNext = mem3.aPool[i].u.list.next;
+ size = mem3.aPool[i-1].u.hdr.size4x;
+ assert( (size&1)==0 );
+ if( (size&2)==0 ){
+ memsys3UnlinkFromList(i, pRoot);
+ assert( i > mem3.aPool[i-1].u.hdr.prevSize );
+ prev = i - mem3.aPool[i-1].u.hdr.prevSize;
+ if( prev==iNext ){
+ iNext = mem3.aPool[prev].u.list.next;
+ }
+ memsys3Unlink(prev);
+ size = i + size/4 - prev;
+ x = mem3.aPool[prev-1].u.hdr.size4x & 2;
+ mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
+ mem3.aPool[prev+size-1].u.hdr.prevSize = size;
+ memsys3Link(prev);
+ i = prev;
+ }else{
+ size /= 4;
+ }
+ if( size>mem3.szMaster ){
+ mem3.iMaster = i;
+ mem3.szMaster = size;
+ }
+ }
+}
+
+/*
+** Return a block of memory of at least nBytes in size.
+** Return NULL if unable.
+**
+** This function assumes that the necessary mutexes, if any, are
+** already held by the caller. Hence "Unsafe".
+*/
+static void *memsys3MallocUnsafe(int nByte){
+ u32 i;
+ u32 nBlock;
+ u32 toFree;
+
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ assert( sizeof(Mem3Block)==8 );
+ if( nByte<=12 ){
+ nBlock = 2;
+ }else{
+ nBlock = (nByte + 11)/8;
+ }
+ assert( nBlock>=2 );
+
+ /* STEP 1:
+ ** Look for an entry of the correct size in either the small
+ ** chunk table or in the large chunk hash table. This is
+ ** successful most of the time (about 9 times out of 10).
+ */
+ if( nBlock <= MX_SMALL ){
+ i = mem3.aiSmall[nBlock-2];
+ if( i>0 ){
+ memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
+ return memsys3Checkout(i, nBlock);
+ }
+ }else{
+ int hash = nBlock % N_HASH;
+ for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
+ if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
+ memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
+ return memsys3Checkout(i, nBlock);
+ }
+ }
+ }
+
+ /* STEP 2:
+ ** Try to satisfy the allocation by carving a piece off of the end
+ ** of the master chunk. This step usually works if step 1 fails.
+ */
+ if( mem3.szMaster>=nBlock ){
+ return memsys3FromMaster(nBlock);
+ }
+
+
+ /* STEP 3:
+ ** Loop through the entire memory pool. Coalesce adjacent free
+ ** chunks. Recompute the master chunk as the largest free chunk.
+ ** Then try again to satisfy the allocation by carving a piece off
+ ** of the end of the master chunk. This step happens very
+ ** rarely (we hope!)
+ */
+ for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
+ memsys3OutOfMemory(toFree);
+ if( mem3.iMaster ){
+ memsys3Link(mem3.iMaster);
+ mem3.iMaster = 0;
+ mem3.szMaster = 0;
+ }
+ for(i=0; i<N_HASH; i++){
+ memsys3Merge(&mem3.aiHash[i]);
+ }
+ for(i=0; i<MX_SMALL-1; i++){
+ memsys3Merge(&mem3.aiSmall[i]);
+ }
+ if( mem3.szMaster ){
+ memsys3Unlink(mem3.iMaster);
+ if( mem3.szMaster>=nBlock ){
+ return memsys3FromMaster(nBlock);
+ }
+ }
+ }
+
+ /* If none of the above worked, then we fail. */
+ return 0;
+}
+
+/*
+** Free an outstanding memory allocation.
+**
+** This function assumes that the necessary mutexes, if any, are
+** already held by the caller. Hence "Unsafe".
+*/
+static void memsys3FreeUnsafe(void *pOld){
+ Mem3Block *p = (Mem3Block*)pOld;
+ int i;
+ u32 size, x;
+ assert( sqlite3_mutex_held(mem3.mutex) );
+ assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
+ i = p - mem3.aPool;
+ assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
+ size = mem3.aPool[i-1].u.hdr.size4x/4;
+ assert( i+size<=mem3.nPool+1 );
+ mem3.aPool[i-1].u.hdr.size4x &= ~1;
+ mem3.aPool[i+size-1].u.hdr.prevSize = size;
+ mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
+ memsys3Link(i);
+
+ /* Try to expand the master using the newly freed chunk */
+ if( mem3.iMaster ){
+ while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
+ size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
+ mem3.iMaster -= size;
+ mem3.szMaster += size;
+ memsys3Unlink(mem3.iMaster);
+ x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
+ mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
+ }
+ x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
+ while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
+ memsys3Unlink(mem3.iMaster+mem3.szMaster);
+ mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
+ mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
+ }
+ }
+}
+
+/*
+** Return the size of an outstanding allocation, in bytes. The
+** size returned omits the 8-byte header overhead. This only
+** works for chunks that are currently checked out.
+*/
+static int memsys3Size(void *p){
+ Mem3Block *pBlock;
+ if( p==0 ) return 0;
+ pBlock = (Mem3Block*)p;
+ assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
+ return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
+}
+
+/*
+** Round up a request size to the next valid allocation size.
+*/
+static int memsys3Roundup(int n){
+ if( n<=12 ){
+ return 12;
+ }else{
+ return ((n+11)&~7) - 4;
+ }
+}
+
+/*
+** Allocate nBytes of memory.
+*/
+static void *memsys3Malloc(int nBytes){
+ sqlite3_int64 *p;
+ assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */
+ memsys3Enter();
+ p = memsys3MallocUnsafe(nBytes);
+ memsys3Leave();
+ return (void*)p;
+}
+
+/*
+** Free memory.
+*/
+static void memsys3Free(void *pPrior){
+ assert( pPrior );
+ memsys3Enter();
+ memsys3FreeUnsafe(pPrior);
+ memsys3Leave();
+}
+
+/*
+** Change the size of an existing memory allocation
+*/
+static void *memsys3Realloc(void *pPrior, int nBytes){
+ int nOld;
+ void *p;
+ if( pPrior==0 ){
+ return sqlite3_malloc(nBytes);
+ }
+ if( nBytes<=0 ){
+ sqlite3_free(pPrior);
+ return 0;
+ }
+ nOld = memsys3Size(pPrior);
+ if( nBytes<=nOld && nBytes>=nOld-128 ){
+ return pPrior;
+ }
+ memsys3Enter();
+ p = memsys3MallocUnsafe(nBytes);
+ if( p ){
+ if( nOld<nBytes ){
+ memcpy(p, pPrior, nOld);
+ }else{
+ memcpy(p, pPrior, nBytes);
+ }
+ memsys3FreeUnsafe(pPrior);
+ }
+ memsys3Leave();
+ return p;
+}
+
+/*
+** Initialize this module.
+*/
+static int memsys3Init(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ if( !sqlite3GlobalConfig.pHeap ){
+ return SQLITE_ERROR;
+ }
+
+ /* Store a pointer to the memory block in global structure mem3. */
+ assert( sizeof(Mem3Block)==8 );
+ mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
+ mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
+
+ /* Initialize the master block. */
+ mem3.szMaster = mem3.nPool;
+ mem3.mnMaster = mem3.szMaster;
+ mem3.iMaster = 1;
+ mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
+ mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
+ mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
+
+ return SQLITE_OK;
+}
+
+/*
+** Deinitialize this module.
+*/
+static void memsys3Shutdown(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ mem3.mutex = 0;
+ return;
+}
+
+
+
+/*
+** Open the file indicated and write a log of all unfreed memory
+** allocations into that log.
+*/
+SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
+#ifdef SQLITE_DEBUG
+ FILE *out;
+ u32 i, j;
+ u32 size;
+ if( zFilename==0 || zFilename[0]==0 ){
+ out = stdout;
+ }else{
+ out = fopen(zFilename, "w");
+ if( out==0 ){
+ fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
+ zFilename);
+ return;
+ }
+ }
+ memsys3Enter();
+ fprintf(out, "CHUNKS:\n");
+ for(i=1; i<=mem3.nPool; i+=size/4){
+ size = mem3.aPool[i-1].u.hdr.size4x;
+ if( size/4<=1 ){
+ fprintf(out, "%p size error\n", &mem3.aPool[i]);
+ assert( 0 );
+ break;
+ }
+ if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
+ fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
+ assert( 0 );
+ break;
+ }
+ if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
+ fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
+ assert( 0 );
+ break;
+ }
+ if( size&1 ){
+ fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
+ }else{
+ fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
+ i==mem3.iMaster ? " **master**" : "");
+ }
+ }
+ for(i=0; i<MX_SMALL-1; i++){
+ if( mem3.aiSmall[i]==0 ) continue;
+ fprintf(out, "small(%2d):", i);
+ for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
+ fprintf(out, " %p(%d)", &mem3.aPool[j],
+ (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
+ }
+ fprintf(out, "\n");
+ }
+ for(i=0; i<N_HASH; i++){
+ if( mem3.aiHash[i]==0 ) continue;
+ fprintf(out, "hash(%2d):", i);
+ for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
+ fprintf(out, " %p(%d)", &mem3.aPool[j],
+ (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
+ }
+ fprintf(out, "\n");
+ }
+ fprintf(out, "master=%d\n", mem3.iMaster);
+ fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
+ fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
+ sqlite3_mutex_leave(mem3.mutex);
+ if( out==stdout ){
+ fflush(stdout);
+ }else{
+ fclose(out);
+ }
+#else
+ UNUSED_PARAMETER(zFilename);
+#endif
+}
+
+/*
+** This routine is the only routine in this file with external
+** linkage.
+**
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
+** arguments specify the block of memory to manage.
+**
+** This routine is only called by sqlite3_config(), and therefore
+** is not required to be threadsafe (it is not).
+*/
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
+ static const sqlite3_mem_methods mempoolMethods = {
+ memsys3Malloc,
+ memsys3Free,
+ memsys3Realloc,
+ memsys3Size,
+ memsys3Roundup,
+ memsys3Init,
+ memsys3Shutdown,
+ 0
+ };
+ return &mempoolMethods;
+}
+
+#endif /* SQLITE_ENABLE_MEMSYS3 */
+
+/************** End of mem3.c ************************************************/
+/************** Begin file mem5.c ********************************************/
+/*
+** 2007 October 14
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement a memory
+** allocation subsystem for use by SQLite.
+**
+** This version of the memory allocation subsystem omits all
+** use of malloc(). The application gives SQLite a block of memory
+** before calling sqlite3_initialize() from which allocations
+** are made and returned by the xMalloc() and xRealloc()
+** implementations. Once sqlite3_initialize() has been called,
+** the amount of memory available to SQLite is fixed and cannot
+** be changed.
+**
+** This version of the memory allocation subsystem is included
+** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
+**
+** This memory allocator uses the following algorithm:
+**
+** 1. All memory allocations sizes are rounded up to a power of 2.
+**
+** 2. If two adjacent free blocks are the halves of a larger block,
+** then the two blocks are coalesed into the single larger block.
+**
+** 3. New memory is allocated from the first available free block.
+**
+** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
+** Concerning Dynamic Storage Allocation". Journal of the Association for
+** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
+**
+** Let n be the size of the largest allocation divided by the minimum
+** allocation size (after rounding all sizes up to a power of 2.) Let M
+** be the maximum amount of memory ever outstanding at one time. Let
+** N be the total amount of memory available for allocation. Robson
+** proved that this memory allocator will never breakdown due to
+** fragmentation as long as the following constraint holds:
+**
+** N >= M*(1 + log2(n)/2) - n + 1
+**
+** The sqlite3_status() logic tracks the maximum values of n and M so
+** that an application can, at any time, verify this constraint.
+*/
+
+/*
+** This version of the memory allocator is used only when
+** SQLITE_ENABLE_MEMSYS5 is defined.
+*/
+#ifdef SQLITE_ENABLE_MEMSYS5
+
+/*
+** A minimum allocation is an instance of the following structure.
+** Larger allocations are an array of these structures where the
+** size of the array is a power of 2.
+**
+** The size of this object must be a power of two. That fact is
+** verified in memsys5Init().
+*/
+typedef struct Mem5Link Mem5Link;
+struct Mem5Link {
+ int next; /* Index of next free chunk */
+ int prev; /* Index of previous free chunk */
+};
+
+/*
+** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
+** mem5.szAtom is always at least 8 and 32-bit integers are used,
+** it is not actually possible to reach this limit.
+*/
+#define LOGMAX 30
+
+/*
+** Masks used for mem5.aCtrl[] elements.
+*/
+#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block */
+#define CTRL_FREE 0x20 /* True if not checked out */
+
+/*
+** All of the static variables used by this module are collected
+** into a single structure named "mem5". This is to keep the
+** static variables organized and to reduce namespace pollution
+** when this module is combined with other in the amalgamation.
+*/
+static SQLITE_WSD struct Mem5Global {
+ /*
+ ** Memory available for allocation
+ */
+ int szAtom; /* Smallest possible allocation in bytes */
+ int nBlock; /* Number of szAtom sized blocks in zPool */
+ u8 *zPool; /* Memory available to be allocated */
+
+ /*
+ ** Mutex to control access to the memory allocation subsystem.
+ */
+ sqlite3_mutex *mutex;
+
+ /*
+ ** Performance statistics
+ */
+ u64 nAlloc; /* Total number of calls to malloc */
+ u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
+ u64 totalExcess; /* Total internal fragmentation */
+ u32 currentOut; /* Current checkout, including internal fragmentation */
+ u32 currentCount; /* Current number of distinct checkouts */
+ u32 maxOut; /* Maximum instantaneous currentOut */
+ u32 maxCount; /* Maximum instantaneous currentCount */
+ u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
+
+ /*
+ ** Lists of free blocks. aiFreelist[0] is a list of free blocks of
+ ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
+ ** and so forth.
+ */
+ int aiFreelist[LOGMAX+1];
+
+ /*
+ ** Space for tracking which blocks are checked out and the size
+ ** of each block. One byte per block.
+ */
+ u8 *aCtrl;
+
+} mem5;
+
+/*
+** Access the static variable through a macro for SQLITE_OMIT_WSD
+*/
+#define mem5 GLOBAL(struct Mem5Global, mem5)
+
+/*
+** Assuming mem5.zPool is divided up into an array of Mem5Link
+** structures, return a pointer to the idx-th such lik.
+*/
+#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
+
+/*
+** Unlink the chunk at mem5.aPool[i] from list it is currently
+** on. It should be found on mem5.aiFreelist[iLogsize].
+*/
+static void memsys5Unlink(int i, int iLogsize){
+ int next, prev;
+ assert( i>=0 && i<mem5.nBlock );
+ assert( iLogsize>=0 && iLogsize<=LOGMAX );
+ assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+
+ next = MEM5LINK(i)->next;
+ prev = MEM5LINK(i)->prev;
+ if( prev<0 ){
+ mem5.aiFreelist[iLogsize] = next;
+ }else{
+ MEM5LINK(prev)->next = next;
+ }
+ if( next>=0 ){
+ MEM5LINK(next)->prev = prev;
+ }
+}
+
+/*
+** Link the chunk at mem5.aPool[i] so that is on the iLogsize
+** free list.
+*/
+static void memsys5Link(int i, int iLogsize){
+ int x;
+ assert( sqlite3_mutex_held(mem5.mutex) );
+ assert( i>=0 && i<mem5.nBlock );
+ assert( iLogsize>=0 && iLogsize<=LOGMAX );
+ assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+
+ x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
+ MEM5LINK(i)->prev = -1;
+ if( x>=0 ){
+ assert( x<mem5.nBlock );
+ MEM5LINK(x)->prev = i;
+ }
+ mem5.aiFreelist[iLogsize] = i;
+}
+
+/*
+** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
+** will already be held (obtained by code in malloc.c) if
+** sqlite3GlobalConfig.bMemStat is true.
+*/
+static void memsys5Enter(void){
+ sqlite3_mutex_enter(mem5.mutex);
+}
+static void memsys5Leave(void){
+ sqlite3_mutex_leave(mem5.mutex);
+}
+
+/*
+** Return the size of an outstanding allocation, in bytes. The
+** size returned omits the 8-byte header overhead. This only
+** works for chunks that are currently checked out.
+*/
+static int memsys5Size(void *p){
+ int iSize = 0;
+ if( p ){
+ int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
+ assert( i>=0 && i<mem5.nBlock );
+ iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
+ }
+ return iSize;
+}
+
+/*
+** Find the first entry on the freelist iLogsize. Unlink that
+** entry and return its index.
+*/
+static int memsys5UnlinkFirst(int iLogsize){
+ int i;
+ int iFirst;
+
+ assert( iLogsize>=0 && iLogsize<=LOGMAX );
+ i = iFirst = mem5.aiFreelist[iLogsize];
+ assert( iFirst>=0 );
+ while( i>0 ){
+ if( i<iFirst ) iFirst = i;
+ i = MEM5LINK(i)->next;
+ }
+ memsys5Unlink(iFirst, iLogsize);
+ return iFirst;
+}
+
+/*
+** Return a block of memory of at least nBytes in size.
+** Return NULL if unable. Return NULL if nBytes==0.
+**
+** The caller guarantees that nByte positive.
+**
+** The caller has obtained a mutex prior to invoking this
+** routine so there is never any chance that two or more
+** threads can be in this routine at the same time.
+*/
+static void *memsys5MallocUnsafe(int nByte){
+ int i; /* Index of a mem5.aPool[] slot */
+ int iBin; /* Index into mem5.aiFreelist[] */
+ int iFullSz; /* Size of allocation rounded up to power of 2 */
+ int iLogsize; /* Log2 of iFullSz/POW2_MIN */
+
+ /* nByte must be a positive */
+ assert( nByte>0 );
+
+ /* Keep track of the maximum allocation request. Even unfulfilled
+ ** requests are counted */
+ if( (u32)nByte>mem5.maxRequest ){
+ mem5.maxRequest = nByte;
+ }
+
+ /* Abort if the requested allocation size is larger than the largest
+ ** power of two that we can represent using 32-bit signed integers.
+ */
+ if( nByte > 0x40000000 ){
+ return 0;
+ }
+
+ /* Round nByte up to the next valid power of two */
+ for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
+
+ /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
+ ** block. If not, then split a block of the next larger power of
+ ** two in order to create a new free block of size iLogsize.
+ */
+ for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
+ if( iBin>LOGMAX ){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
+ return 0;
+ }
+ i = memsys5UnlinkFirst(iBin);
+ while( iBin>iLogsize ){
+ int newSize;
+
+ iBin--;
+ newSize = 1 << iBin;
+ mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
+ memsys5Link(i+newSize, iBin);
+ }
+ mem5.aCtrl[i] = iLogsize;
+
+ /* Update allocator performance statistics. */
+ mem5.nAlloc++;
+ mem5.totalAlloc += iFullSz;
+ mem5.totalExcess += iFullSz - nByte;
+ mem5.currentCount++;
+ mem5.currentOut += iFullSz;
+ if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
+ if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
+
+ /* Return a pointer to the allocated memory. */
+ return (void*)&mem5.zPool[i*mem5.szAtom];
+}
+
+/*
+** Free an outstanding memory allocation.
+*/
+static void memsys5FreeUnsafe(void *pOld){
+ u32 size, iLogsize;
+ int iBlock;
+
+ /* Set iBlock to the index of the block pointed to by pOld in
+ ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
+ */
+ iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
+
+ /* Check that the pointer pOld points to a valid, non-free block. */
+ assert( iBlock>=0 && iBlock<mem5.nBlock );
+ assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
+ assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
+
+ iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
+ size = 1<<iLogsize;
+ assert( iBlock+size-1<(u32)mem5.nBlock );
+
+ mem5.aCtrl[iBlock] |= CTRL_FREE;
+ mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
+ assert( mem5.currentCount>0 );
+ assert( mem5.currentOut>=(size*mem5.szAtom) );
+ mem5.currentCount--;
+ mem5.currentOut -= size*mem5.szAtom;
+ assert( mem5.currentOut>0 || mem5.currentCount==0 );
+ assert( mem5.currentCount>0 || mem5.currentOut==0 );
+
+ mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
+ while( ALWAYS(iLogsize<LOGMAX) ){
+ int iBuddy;
+ if( (iBlock>>iLogsize) & 1 ){
+ iBuddy = iBlock - size;
+ }else{
+ iBuddy = iBlock + size;
+ }
+ assert( iBuddy>=0 );
+ if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
+ if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
+ memsys5Unlink(iBuddy, iLogsize);
+ iLogsize++;
+ if( iBuddy<iBlock ){
+ mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
+ mem5.aCtrl[iBlock] = 0;
+ iBlock = iBuddy;
+ }else{
+ mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
+ mem5.aCtrl[iBuddy] = 0;
+ }
+ size *= 2;
+ }
+ memsys5Link(iBlock, iLogsize);
+}
+
+/*
+** Allocate nBytes of memory
+*/
+static void *memsys5Malloc(int nBytes){
+ sqlite3_int64 *p = 0;
+ if( nBytes>0 ){
+ memsys5Enter();
+ p = memsys5MallocUnsafe(nBytes);
+ memsys5Leave();
+ }
+ return (void*)p;
+}
+
+/*
+** Free memory.
+**
+** The outer layer memory allocator prevents this routine from
+** being called with pPrior==0.
+*/
+static void memsys5Free(void *pPrior){
+ assert( pPrior!=0 );
+ memsys5Enter();
+ memsys5FreeUnsafe(pPrior);
+ memsys5Leave();
+}
+
+/*
+** Change the size of an existing memory allocation.
+**
+** The outer layer memory allocator prevents this routine from
+** being called with pPrior==0.
+**
+** nBytes is always a value obtained from a prior call to
+** memsys5Round(). Hence nBytes is always a non-negative power
+** of two. If nBytes==0 that means that an oversize allocation
+** (an allocation larger than 0x40000000) was requested and this
+** routine should return 0 without freeing pPrior.
+*/
+static void *memsys5Realloc(void *pPrior, int nBytes){
+ int nOld;
+ void *p;
+ assert( pPrior!=0 );
+ assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */
+ assert( nBytes>=0 );
+ if( nBytes==0 ){
+ return 0;
+ }
+ nOld = memsys5Size(pPrior);
+ if( nBytes<=nOld ){
+ return pPrior;
+ }
+ memsys5Enter();
+ p = memsys5MallocUnsafe(nBytes);
+ if( p ){
+ memcpy(p, pPrior, nOld);
+ memsys5FreeUnsafe(pPrior);
+ }
+ memsys5Leave();
+ return p;
+}
+
+/*
+** Round up a request size to the next valid allocation size. If
+** the allocation is too large to be handled by this allocation system,
+** return 0.
+**
+** All allocations must be a power of two and must be expressed by a
+** 32-bit signed integer. Hence the largest allocation is 0x40000000
+** or 1073741824 bytes.
+*/
+static int memsys5Roundup(int n){
+ int iFullSz;
+ if( n > 0x40000000 ) return 0;
+ for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
+ return iFullSz;
+}
+
+/*
+** Return the ceiling of the logarithm base 2 of iValue.
+**
+** Examples: memsys5Log(1) -> 0
+** memsys5Log(2) -> 1
+** memsys5Log(4) -> 2
+** memsys5Log(5) -> 3
+** memsys5Log(8) -> 3
+** memsys5Log(9) -> 4
+*/
+static int memsys5Log(int iValue){
+ int iLog;
+ for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
+ return iLog;
+}
+
+/*
+** Initialize the memory allocator.
+**
+** This routine is not threadsafe. The caller must be holding a mutex
+** to prevent multiple threads from entering at the same time.
+*/
+static int memsys5Init(void *NotUsed){
+ int ii; /* Loop counter */
+ int nByte; /* Number of bytes of memory available to this allocator */
+ u8 *zByte; /* Memory usable by this allocator */
+ int nMinLog; /* Log base 2 of minimum allocation size in bytes */
+ int iOffset; /* An offset into mem5.aCtrl[] */
+
+ UNUSED_PARAMETER(NotUsed);
+
+ /* For the purposes of this routine, disable the mutex */
+ mem5.mutex = 0;
+
+ /* The size of a Mem5Link object must be a power of two. Verify that
+ ** this is case.
+ */
+ assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );
+
+ nByte = sqlite3GlobalConfig.nHeap;
+ zByte = (u8*)sqlite3GlobalConfig.pHeap;
+ assert( zByte!=0 ); /* sqlite3_config() does not allow otherwise */
+
+ /* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
+ nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
+ mem5.szAtom = (1<<nMinLog);
+ while( (int)sizeof(Mem5Link)>mem5.szAtom ){
+ mem5.szAtom = mem5.szAtom << 1;
+ }
+
+ mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
+ mem5.zPool = zByte;
+ mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];
+
+ for(ii=0; ii<=LOGMAX; ii++){
+ mem5.aiFreelist[ii] = -1;
+ }
+
+ iOffset = 0;
+ for(ii=LOGMAX; ii>=0; ii--){
+ int nAlloc = (1<<ii);
+ if( (iOffset+nAlloc)<=mem5.nBlock ){
+ mem5.aCtrl[iOffset] = ii | CTRL_FREE;
+ memsys5Link(iOffset, ii);
+ iOffset += nAlloc;
+ }
+ assert((iOffset+nAlloc)>mem5.nBlock);
+ }
+
+ /* If a mutex is required for normal operation, allocate one */
+ if( sqlite3GlobalConfig.bMemstat==0 ){
+ mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Deinitialize this module.
+*/
+static void memsys5Shutdown(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ mem5.mutex = 0;
+ return;
+}
+
+#ifdef SQLITE_TEST
+/*
+** Open the file indicated and write a log of all unfreed memory
+** allocations into that log.
+*/
+SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
+ FILE *out;
+ int i, j, n;
+ int nMinLog;
+
+ if( zFilename==0 || zFilename[0]==0 ){
+ out = stdout;
+ }else{
+ out = fopen(zFilename, "w");
+ if( out==0 ){
+ fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
+ zFilename);
+ return;
+ }
+ }
+ memsys5Enter();
+ nMinLog = memsys5Log(mem5.szAtom);
+ for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
+ for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
+ fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
+ }
+ fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc);
+ fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc);
+ fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess);
+ fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut);
+ fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
+ fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut);
+ fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount);
+ fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest);
+ memsys5Leave();
+ if( out==stdout ){
+ fflush(stdout);
+ }else{
+ fclose(out);
+ }
+}
+#endif
+
+/*
+** This routine is the only routine in this file with external
+** linkage. It returns a pointer to a static sqlite3_mem_methods
+** struct populated with the memsys5 methods.
+*/
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
+ static const sqlite3_mem_methods memsys5Methods = {
+ memsys5Malloc,
+ memsys5Free,
+ memsys5Realloc,
+ memsys5Size,
+ memsys5Roundup,
+ memsys5Init,
+ memsys5Shutdown,
+ 0
+ };
+ return &memsys5Methods;
+}
+
+#endif /* SQLITE_ENABLE_MEMSYS5 */
+
+/************** End of mem5.c ************************************************/
+/************** Begin file mutex.c *******************************************/
+/*
+** 2007 August 14
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement mutexes.
+**
+** This file contains code that is common across all mutex implementations.
+*/
+
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
+/*
+** For debugging purposes, record when the mutex subsystem is initialized
+** and uninitialized so that we can assert() if there is an attempt to
+** allocate a mutex while the system is uninitialized.
+*/
+static SQLITE_WSD int mutexIsInit = 0;
+#endif /* SQLITE_DEBUG */
+
+
+#ifndef SQLITE_MUTEX_OMIT
+/*
+** Initialize the mutex system.
+*/
+SQLITE_PRIVATE int sqlite3MutexInit(void){
+ int rc = SQLITE_OK;
+ if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
+ /* If the xMutexAlloc method has not been set, then the user did not
+ ** install a mutex implementation via sqlite3_config() prior to
+ ** sqlite3_initialize() being called. This block copies pointers to
+ ** the default implementation into the sqlite3GlobalConfig structure.
+ */
+ sqlite3_mutex_methods const *pFrom;
+ sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
+
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ pFrom = sqlite3DefaultMutex();
+ }else{
+ pFrom = sqlite3NoopMutex();
+ }
+ memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
+ memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
+ sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
+ pTo->xMutexAlloc = pFrom->xMutexAlloc;
+ }
+ rc = sqlite3GlobalConfig.mutex.xMutexInit();
+
+#ifdef SQLITE_DEBUG
+ GLOBAL(int, mutexIsInit) = 1;
+#endif
+
+ return rc;
+}
+
+/*
+** Shutdown the mutex system. This call frees resources allocated by
+** sqlite3MutexInit().
+*/
+SQLITE_PRIVATE int sqlite3MutexEnd(void){
+ int rc = SQLITE_OK;
+ if( sqlite3GlobalConfig.mutex.xMutexEnd ){
+ rc = sqlite3GlobalConfig.mutex.xMutexEnd();
+ }
+
+#ifdef SQLITE_DEBUG
+ GLOBAL(int, mutexIsInit) = 0;
+#endif
+
+ return rc;
+}
+
+/*
+** Retrieve a pointer to a static mutex or allocate a new dynamic one.
+*/
+SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
+#ifndef SQLITE_OMIT_AUTOINIT
+ if( sqlite3_initialize() ) return 0;
+#endif
+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+}
+
+SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
+ if( !sqlite3GlobalConfig.bCoreMutex ){
+ return 0;
+ }
+ assert( GLOBAL(int, mutexIsInit) );
+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+}
+
+/*
+** Free a dynamic mutex.
+*/
+SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
+ if( p ){
+ sqlite3GlobalConfig.mutex.xMutexFree(p);
+ }
+}
+
+/*
+** Obtain the mutex p. If some other thread already has the mutex, block
+** until it can be obtained.
+*/
+SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
+ if( p ){
+ sqlite3GlobalConfig.mutex.xMutexEnter(p);
+ }
+}
+
+/*
+** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
+** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
+*/
+SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
+ int rc = SQLITE_OK;
+ if( p ){
+ return sqlite3GlobalConfig.mutex.xMutexTry(p);
+ }
+ return rc;
+}
+
+/*
+** The sqlite3_mutex_leave() routine exits a mutex that was previously
+** entered by the same thread. The behavior is undefined if the mutex
+** is not currently entered. If a NULL pointer is passed as an argument
+** this function is a no-op.
+*/
+SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
+ if( p ){
+ sqlite3GlobalConfig.mutex.xMutexLeave(p);
+ }
+}
+
+#ifndef NDEBUG
+/*
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+** intended for use inside assert() statements.
+*/
+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+ return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
+}
+SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+ return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
+}
+#endif
+
+#endif /* !defined(SQLITE_MUTEX_OMIT) */
+
+/************** End of mutex.c ***********************************************/
+/************** Begin file mutex_noop.c **************************************/
+/*
+** 2008 October 07
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement mutexes.
+**
+** This implementation in this file does not provide any mutual
+** exclusion and is thus suitable for use only in applications
+** that use SQLite in a single thread. The routines defined
+** here are place-holders. Applications can substitute working
+** mutex routines at start-time using the
+**
+** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
+**
+** interface.
+**
+** If compiled with SQLITE_DEBUG, then additional logic is inserted
+** that does error checking on mutexes to make sure they are being
+** called correctly.
+*/
+
+#ifndef SQLITE_MUTEX_OMIT
+
+#ifndef SQLITE_DEBUG
+/*
+** Stub routines for all mutex methods.
+**
+** This routines provide no mutual exclusion or error checking.
+*/
+static int noopMutexInit(void){ return SQLITE_OK; }
+static int noopMutexEnd(void){ return SQLITE_OK; }
+static sqlite3_mutex *noopMutexAlloc(int id){
+ UNUSED_PARAMETER(id);
+ return (sqlite3_mutex*)8;
+}
+static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
+static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
+static int noopMutexTry(sqlite3_mutex *p){
+ UNUSED_PARAMETER(p);
+ return SQLITE_OK;
+}
+static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
+
+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
+ static const sqlite3_mutex_methods sMutex = {
+ noopMutexInit,
+ noopMutexEnd,
+ noopMutexAlloc,
+ noopMutexFree,
+ noopMutexEnter,
+ noopMutexTry,
+ noopMutexLeave,
+
+ 0,
+ 0,
+ };
+
+ return &sMutex;
+}
+#endif /* !SQLITE_DEBUG */
+
+#ifdef SQLITE_DEBUG
+/*
+** In this implementation, error checking is provided for testing
+** and debugging purposes. The mutexes still do not provide any
+** mutual exclusion.
+*/
+
+/*
+** The mutex object
+*/
+typedef struct sqlite3_debug_mutex {
+ int id; /* The mutex type */
+ int cnt; /* Number of entries without a matching leave */
+} sqlite3_debug_mutex;
+
+/*
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+** intended for use inside assert() statements.
+*/
+static int debugMutexHeld(sqlite3_mutex *pX){
+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+ return p==0 || p->cnt>0;
+}
+static int debugMutexNotheld(sqlite3_mutex *pX){
+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+ return p==0 || p->cnt==0;
+}
+
+/*
+** Initialize and deinitialize the mutex subsystem.
+*/
+static int debugMutexInit(void){ return SQLITE_OK; }
+static int debugMutexEnd(void){ return SQLITE_OK; }
+
+/*
+** The sqlite3_mutex_alloc() routine allocates a new
+** mutex and returns a pointer to it. If it returns NULL
+** that means that a mutex could not be allocated.
+*/
+static sqlite3_mutex *debugMutexAlloc(int id){
+ static sqlite3_debug_mutex aStatic[6];
+ sqlite3_debug_mutex *pNew = 0;
+ switch( id ){
+ case SQLITE_MUTEX_FAST:
+ case SQLITE_MUTEX_RECURSIVE: {
+ pNew = sqlite3Malloc(sizeof(*pNew));
+ if( pNew ){
+ pNew->id = id;
+ pNew->cnt = 0;
+ }
+ break;
+ }
+ default: {
+ assert( id-2 >= 0 );
+ assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
+ pNew = &aStatic[id-2];
+ pNew->id = id;
+ break;
+ }
+ }
+ return (sqlite3_mutex*)pNew;
+}
+
+/*
+** This routine deallocates a previously allocated mutex.
+*/
+static void debugMutexFree(sqlite3_mutex *pX){
+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+ assert( p->cnt==0 );
+ assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+ sqlite3_free(p);
+}
+
+/*
+** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+** to enter a mutex. If another thread is already within the mutex,
+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
+** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
+** be entered multiple times by the same thread. In such cases the,
+** mutex must be exited an equal number of times before another thread
+** can enter. If the same thread tries to enter any other kind of mutex
+** more than once, the behavior is undefined.
+*/
+static void debugMutexEnter(sqlite3_mutex *pX){
+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+ p->cnt++;
+}
+static int debugMutexTry(sqlite3_mutex *pX){
+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+ p->cnt++;
+ return SQLITE_OK;
+}
+
+/*
+** The sqlite3_mutex_leave() routine exits a mutex that was
+** previously entered by the same thread. The behavior
+** is undefined if the mutex is not currently entered or
+** is not currently allocated. SQLite will never do either.
+*/
+static void debugMutexLeave(sqlite3_mutex *pX){
+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+ assert( debugMutexHeld(pX) );
+ p->cnt--;
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+}
+
+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
+ static const sqlite3_mutex_methods sMutex = {
+ debugMutexInit,
+ debugMutexEnd,
+ debugMutexAlloc,
+ debugMutexFree,
+ debugMutexEnter,
+ debugMutexTry,
+ debugMutexLeave,
+
+ debugMutexHeld,
+ debugMutexNotheld
+ };
+
+ return &sMutex;
+}
+#endif /* SQLITE_DEBUG */
+
+/*
+** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
+** is used regardless of the run-time threadsafety setting.
+*/
+#ifdef SQLITE_MUTEX_NOOP
+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
+ return sqlite3NoopMutex();
+}
+#endif /* defined(SQLITE_MUTEX_NOOP) */
+#endif /* !defined(SQLITE_MUTEX_OMIT) */
+
+/************** End of mutex_noop.c ******************************************/
+/************** Begin file mutex_unix.c **************************************/
+/*
+** 2007 August 28
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement mutexes for pthreads
+*/
+
+/*
+** The code in this file is only used if we are compiling threadsafe
+** under unix with pthreads.
+**
+** Note that this implementation requires a version of pthreads that
+** supports recursive mutexes.
+*/
+#ifdef SQLITE_MUTEX_PTHREADS
+
+#include <pthread.h>
+
+/*
+** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
+** are necessary under two condidtions: (1) Debug builds and (2) using
+** home-grown mutexes. Encapsulate these conditions into a single #define.
+*/
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
+# define SQLITE_MUTEX_NREF 1
+#else
+# define SQLITE_MUTEX_NREF 0
+#endif
+
+/*
+** Each recursive mutex is an instance of the following structure.
+*/
+struct sqlite3_mutex {
+ pthread_mutex_t mutex; /* Mutex controlling the lock */
+#if SQLITE_MUTEX_NREF
+ int id; /* Mutex type */
+ volatile int nRef; /* Number of entrances */
+ volatile pthread_t owner; /* Thread that is within this mutex */
+ int trace; /* True to trace changes */
+#endif
+};
+#if SQLITE_MUTEX_NREF
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
+#else
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
+#endif
+
+/*
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+** intended for use only inside assert() statements. On some platforms,
+** there might be race conditions that can cause these routines to
+** deliver incorrect results. In particular, if pthread_equal() is
+** not an atomic operation, then these routines might delivery
+** incorrect results. On most platforms, pthread_equal() is a
+** comparison of two integers and is therefore atomic. But we are
+** told that HPUX is not such a platform. If so, then these routines
+** will not always work correctly on HPUX.
+**
+** On those platforms where pthread_equal() is not atomic, SQLite
+** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
+** make sure no assert() statements are evaluated and hence these
+** routines are never called.
+*/
+#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
+static int pthreadMutexHeld(sqlite3_mutex *p){
+ return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
+}
+static int pthreadMutexNotheld(sqlite3_mutex *p){
+ return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
+}
+#endif
+
+/*
+** Initialize and deinitialize the mutex subsystem.
+*/
+static int pthreadMutexInit(void){ return SQLITE_OK; }
+static int pthreadMutexEnd(void){ return SQLITE_OK; }
+
+/*
+** The sqlite3_mutex_alloc() routine allocates a new
+** mutex and returns a pointer to it. If it returns NULL
+** that means that a mutex could not be allocated. SQLite
+** will unwind its stack and return an error. The argument
+** to sqlite3_mutex_alloc() is one of these integer constants:
+**
+** <ul>
+** <li> SQLITE_MUTEX_FAST
+** <li> SQLITE_MUTEX_RECURSIVE
+** <li> SQLITE_MUTEX_STATIC_MASTER
+** <li> SQLITE_MUTEX_STATIC_MEM
+** <li> SQLITE_MUTEX_STATIC_MEM2
+** <li> SQLITE_MUTEX_STATIC_PRNG
+** <li> SQLITE_MUTEX_STATIC_LRU
+** <li> SQLITE_MUTEX_STATIC_PMEM
+** </ul>
+**
+** The first two constants cause sqlite3_mutex_alloc() to create
+** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
+** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
+** The mutex implementation does not need to make a distinction
+** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
+** not want to. But SQLite will only request a recursive mutex in
+** cases where it really needs one. If a faster non-recursive mutex
+** implementation is available on the host platform, the mutex subsystem
+** might return such a mutex in response to SQLITE_MUTEX_FAST.
+**
+** The other allowed parameters to sqlite3_mutex_alloc() each return
+** a pointer to a static preexisting mutex. Six static mutexes are
+** used by the current version of SQLite. Future versions of SQLite
+** may add additional static mutexes. Static mutexes are for internal
+** use by SQLite only. Applications that use SQLite mutexes should
+** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
+** SQLITE_MUTEX_RECURSIVE.
+**
+** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
+** returns a different mutex on every call. But for the static
+** mutex types, the same mutex is returned on every call that has
+** the same type number.
+*/
+static sqlite3_mutex *pthreadMutexAlloc(int iType){
+ static sqlite3_mutex staticMutexes[] = {
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER
+ };
+ sqlite3_mutex *p;
+ switch( iType ){
+ case SQLITE_MUTEX_RECURSIVE: {
+ p = sqlite3MallocZero( sizeof(*p) );
+ if( p ){
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+ /* If recursive mutexes are not available, we will have to
+ ** build our own. See below. */
+ pthread_mutex_init(&p->mutex, 0);
+#else
+ /* Use a recursive mutex if it is available */
+ pthread_mutexattr_t recursiveAttr;
+ pthread_mutexattr_init(&recursiveAttr);
+ pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&p->mutex, &recursiveAttr);
+ pthread_mutexattr_destroy(&recursiveAttr);
+#endif
+#if SQLITE_MUTEX_NREF
+ p->id = iType;
+#endif
+ }
+ break;
+ }
+ case SQLITE_MUTEX_FAST: {
+ p = sqlite3MallocZero( sizeof(*p) );
+ if( p ){
+#if SQLITE_MUTEX_NREF
+ p->id = iType;
+#endif
+ pthread_mutex_init(&p->mutex, 0);
+ }
+ break;
+ }
+ default: {
+ assert( iType-2 >= 0 );
+ assert( iType-2 < ArraySize(staticMutexes) );
+ p = &staticMutexes[iType-2];
+#if SQLITE_MUTEX_NREF
+ p->id = iType;
+#endif
+ break;
+ }
+ }
+ return p;
+}
+
+
+/*
+** This routine deallocates a previously
+** allocated mutex. SQLite is careful to deallocate every
+** mutex that it allocates.
+*/
+static void pthreadMutexFree(sqlite3_mutex *p){
+ assert( p->nRef==0 );
+ assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+ pthread_mutex_destroy(&p->mutex);
+ sqlite3_free(p);
+}
+
+/*
+** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+** to enter a mutex. If another thread is already within the mutex,
+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
+** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
+** be entered multiple times by the same thread. In such cases the,
+** mutex must be exited an equal number of times before another thread
+** can enter. If the same thread tries to enter any other kind of mutex
+** more than once, the behavior is undefined.
+*/
+static void pthreadMutexEnter(sqlite3_mutex *p){
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
+
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+ /* If recursive mutexes are not available, then we have to grow
+ ** our own. This implementation assumes that pthread_equal()
+ ** is atomic - that it cannot be deceived into thinking self
+ ** and p->owner are equal if p->owner changes between two values
+ ** that are not equal to self while the comparison is taking place.
+ ** This implementation also assumes a coherent cache - that
+ ** separate processes cannot read different values from the same
+ ** address at the same time. If either of these two conditions
+ ** are not met, then the mutexes will fail and problems will result.
+ */
+ {
+ pthread_t self = pthread_self();
+ if( p->nRef>0 && pthread_equal(p->owner, self) ){
+ p->nRef++;
+ }else{
+ pthread_mutex_lock(&p->mutex);
+ assert( p->nRef==0 );
+ p->owner = self;
+ p->nRef = 1;
+ }
+ }
+#else
+ /* Use the built-in recursive mutexes if they are available.
+ */
+ pthread_mutex_lock(&p->mutex);
+#if SQLITE_MUTEX_NREF
+ assert( p->nRef>0 || p->owner==0 );
+ p->owner = pthread_self();
+ p->nRef++;
+#endif
+#endif
+
+#ifdef SQLITE_DEBUG
+ if( p->trace ){
+ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+ }
+#endif
+}
+static int pthreadMutexTry(sqlite3_mutex *p){
+ int rc;
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
+
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+ /* If recursive mutexes are not available, then we have to grow
+ ** our own. This implementation assumes that pthread_equal()
+ ** is atomic - that it cannot be deceived into thinking self
+ ** and p->owner are equal if p->owner changes between two values
+ ** that are not equal to self while the comparison is taking place.
+ ** This implementation also assumes a coherent cache - that
+ ** separate processes cannot read different values from the same
+ ** address at the same time. If either of these two conditions
+ ** are not met, then the mutexes will fail and problems will result.
+ */
+ {
+ pthread_t self = pthread_self();
+ if( p->nRef>0 && pthread_equal(p->owner, self) ){
+ p->nRef++;
+ rc = SQLITE_OK;
+ }else if( pthread_mutex_trylock(&p->mutex)==0 ){
+ assert( p->nRef==0 );
+ p->owner = self;
+ p->nRef = 1;
+ rc = SQLITE_OK;
+ }else{
+ rc = SQLITE_BUSY;
+ }
+ }
+#else
+ /* Use the built-in recursive mutexes if they are available.
+ */
+ if( pthread_mutex_trylock(&p->mutex)==0 ){
+#if SQLITE_MUTEX_NREF
+ p->owner = pthread_self();
+ p->nRef++;
+#endif
+ rc = SQLITE_OK;
+ }else{
+ rc = SQLITE_BUSY;
+ }
+#endif
+
+#ifdef SQLITE_DEBUG
+ if( rc==SQLITE_OK && p->trace ){
+ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+ }
+#endif
+ return rc;
+}
+
+/*
+** The sqlite3_mutex_leave() routine exits a mutex that was
+** previously entered by the same thread. The behavior
+** is undefined if the mutex is not currently entered or
+** is not currently allocated. SQLite will never do either.
+*/
+static void pthreadMutexLeave(sqlite3_mutex *p){
+ assert( pthreadMutexHeld(p) );
+#if SQLITE_MUTEX_NREF
+ p->nRef--;
+ if( p->nRef==0 ) p->owner = 0;
+#endif
+ assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
+
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+ if( p->nRef==0 ){
+ pthread_mutex_unlock(&p->mutex);
+ }
+#else
+ pthread_mutex_unlock(&p->mutex);
+#endif
+
+#ifdef SQLITE_DEBUG
+ if( p->trace ){
+ printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+ }
+#endif
+}
+
+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
+ static const sqlite3_mutex_methods sMutex = {
+ pthreadMutexInit,
+ pthreadMutexEnd,
+ pthreadMutexAlloc,
+ pthreadMutexFree,
+ pthreadMutexEnter,
+ pthreadMutexTry,
+ pthreadMutexLeave,
+#ifdef SQLITE_DEBUG
+ pthreadMutexHeld,
+ pthreadMutexNotheld
+#else
+ 0,
+ 0
+#endif
+ };
+
+ return &sMutex;
+}
+
+#endif /* SQLITE_MUTEX_PTHREADS */
+
+/************** End of mutex_unix.c ******************************************/
+/************** Begin file mutex_w32.c ***************************************/
+/*
+** 2007 August 14
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement mutexes for win32
+*/
+
+/*
+** The code in this file is only used if we are compiling multithreaded
+** on a win32 system.
+*/
+#ifdef SQLITE_MUTEX_W32
+
+/*
+** Each recursive mutex is an instance of the following structure.
+*/
+struct sqlite3_mutex {
+ CRITICAL_SECTION mutex; /* Mutex controlling the lock */
+ int id; /* Mutex type */
+#ifdef SQLITE_DEBUG
+ volatile int nRef; /* Number of enterances */
+ volatile DWORD owner; /* Thread holding this mutex */
+ int trace; /* True to trace changes */
+#endif
+};
+#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
+#ifdef SQLITE_DEBUG
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
+#else
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
+#endif
+
+/*
+** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
+** or WinCE. Return false (zero) for Win95, Win98, or WinME.
+**
+** Here is an interesting observation: Win95, Win98, and WinME lack
+** the LockFileEx() API. But we can still statically link against that
+** API as long as we don't call it win running Win95/98/ME. A call to
+** this routine is used to determine if the host is Win95/98/ME or
+** WinNT/2K/XP so that we will know whether or not we can safely call
+** the LockFileEx() API.
+**
+** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
+** which is only available if your application was compiled with
+** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
+** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
+** this out as well.
+*/
+#if 0
+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
+# define mutexIsNT() (1)
+#else
+ static int mutexIsNT(void){
+ static int osType = 0;
+ if( osType==0 ){
+ OSVERSIONINFO sInfo;
+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+ GetVersionEx(&sInfo);
+ osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
+ }
+ return osType==2;
+ }
+#endif /* SQLITE_OS_WINCE */
+#endif
+
+#ifdef SQLITE_DEBUG
+/*
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
+** intended for use only inside assert() statements.
+*/
+static int winMutexHeld(sqlite3_mutex *p){
+ return p->nRef!=0 && p->owner==GetCurrentThreadId();
+}
+static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
+ return p->nRef==0 || p->owner!=tid;
+}
+static int winMutexNotheld(sqlite3_mutex *p){
+ DWORD tid = GetCurrentThreadId();
+ return winMutexNotheld2(p, tid);
+}
+#endif
+
+
+/*
+** Initialize and deinitialize the mutex subsystem.
+*/
+static sqlite3_mutex winMutex_staticMutexes[6] = {
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER
+};
+static int winMutex_isInit = 0;
+/* As winMutexInit() and winMutexEnd() are called as part
+** of the sqlite3_initialize and sqlite3_shutdown()
+** processing, the "interlocked" magic is probably not
+** strictly necessary.
+*/
+static long winMutex_lock = 0;
+
+SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
+
+static int winMutexInit(void){
+ /* The first to increment to 1 does actual initialization */
+ if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
+ int i;
+ for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
+#if SQLITE_OS_WINRT
+ InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
+#else
+ InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
+#endif
+ }
+ winMutex_isInit = 1;
+ }else{
+ /* Someone else is in the process of initing the static mutexes */
+ while( !winMutex_isInit ){
+ sqlite3_win32_sleep(1);
+ }
+ }
+ return SQLITE_OK;
+}
+
+static int winMutexEnd(void){
+ /* The first to decrement to 0 does actual shutdown
+ ** (which should be the last to shutdown.) */
+ if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
+ if( winMutex_isInit==1 ){
+ int i;
+ for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
+ DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
+ }
+ winMutex_isInit = 0;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** The sqlite3_mutex_alloc() routine allocates a new
+** mutex and returns a pointer to it. If it returns NULL
+** that means that a mutex could not be allocated. SQLite
+** will unwind its stack and return an error. The argument
+** to sqlite3_mutex_alloc() is one of these integer constants:
+**
+** <ul>
+** <li> SQLITE_MUTEX_FAST
+** <li> SQLITE_MUTEX_RECURSIVE
+** <li> SQLITE_MUTEX_STATIC_MASTER
+** <li> SQLITE_MUTEX_STATIC_MEM
+** <li> SQLITE_MUTEX_STATIC_MEM2
+** <li> SQLITE_MUTEX_STATIC_PRNG
+** <li> SQLITE_MUTEX_STATIC_LRU
+** <li> SQLITE_MUTEX_STATIC_PMEM
+** </ul>
+**
+** The first two constants cause sqlite3_mutex_alloc() to create
+** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
+** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
+** The mutex implementation does not need to make a distinction
+** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
+** not want to. But SQLite will only request a recursive mutex in
+** cases where it really needs one. If a faster non-recursive mutex
+** implementation is available on the host platform, the mutex subsystem
+** might return such a mutex in response to SQLITE_MUTEX_FAST.
+**
+** The other allowed parameters to sqlite3_mutex_alloc() each return
+** a pointer to a static preexisting mutex. Six static mutexes are
+** used by the current version of SQLite. Future versions of SQLite
+** may add additional static mutexes. Static mutexes are for internal
+** use by SQLite only. Applications that use SQLite mutexes should
+** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
+** SQLITE_MUTEX_RECURSIVE.
+**
+** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
+** returns a different mutex on every call. But for the static
+** mutex types, the same mutex is returned on every call that has
+** the same type number.
+*/
+static sqlite3_mutex *winMutexAlloc(int iType){
+ sqlite3_mutex *p;
+
+ switch( iType ){
+ case SQLITE_MUTEX_FAST:
+ case SQLITE_MUTEX_RECURSIVE: {
+ p = sqlite3MallocZero( sizeof(*p) );
+ if( p ){
+#ifdef SQLITE_DEBUG
+ p->id = iType;
+#endif
+#if SQLITE_OS_WINRT
+ InitializeCriticalSectionEx(&p->mutex, 0, 0);
+#else
+ InitializeCriticalSection(&p->mutex);
+#endif
+ }
+ break;
+ }
+ default: {
+ assert( winMutex_isInit==1 );
+ assert( iType-2 >= 0 );
+ assert( iType-2 < ArraySize(winMutex_staticMutexes) );
+ p = &winMutex_staticMutexes[iType-2];
+#ifdef SQLITE_DEBUG
+ p->id = iType;
+#endif
+ break;
+ }
+ }
+ return p;
+}
+
+
+/*
+** This routine deallocates a previously
+** allocated mutex. SQLite is careful to deallocate every
+** mutex that it allocates.
+*/
+static void winMutexFree(sqlite3_mutex *p){
+ assert( p );
+ assert( p->nRef==0 && p->owner==0 );
+ assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+ DeleteCriticalSection(&p->mutex);
+ sqlite3_free(p);
+}
+
+/*
+** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+** to enter a mutex. If another thread is already within the mutex,
+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
+** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
+** be entered multiple times by the same thread. In such cases the,
+** mutex must be exited an equal number of times before another thread
+** can enter. If the same thread tries to enter any other kind of mutex
+** more than once, the behavior is undefined.
+*/
+static void winMutexEnter(sqlite3_mutex *p){
+#ifdef SQLITE_DEBUG
+ DWORD tid = GetCurrentThreadId();
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
+#endif
+ EnterCriticalSection(&p->mutex);
+#ifdef SQLITE_DEBUG
+ assert( p->nRef>0 || p->owner==0 );
+ p->owner = tid;
+ p->nRef++;
+ if( p->trace ){
+ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+ }
+#endif
+}
+static int winMutexTry(sqlite3_mutex *p){
+#ifndef NDEBUG
+ DWORD tid = GetCurrentThreadId();
+#endif
+ int rc = SQLITE_BUSY;
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
+ /*
+ ** The sqlite3_mutex_try() routine is very rarely used, and when it
+ ** is used it is merely an optimization. So it is OK for it to always
+ ** fail.
+ **
+ ** The TryEnterCriticalSection() interface is only available on WinNT.
+ ** And some windows compilers complain if you try to use it without
+ ** first doing some #defines that prevent SQLite from building on Win98.
+ ** For that reason, we will omit this optimization for now. See
+ ** ticket #2685.
+ */
+#if 0
+ if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
+ p->owner = tid;
+ p->nRef++;
+ rc = SQLITE_OK;
+ }
+#else
+ UNUSED_PARAMETER(p);
+#endif
+#ifdef SQLITE_DEBUG
+ if( rc==SQLITE_OK && p->trace ){
+ printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+ }
+#endif
+ return rc;
+}
+
+/*
+** The sqlite3_mutex_leave() routine exits a mutex that was
+** previously entered by the same thread. The behavior
+** is undefined if the mutex is not currently entered or
+** is not currently allocated. SQLite will never do either.
+*/
+static void winMutexLeave(sqlite3_mutex *p){
+#ifndef NDEBUG
+ DWORD tid = GetCurrentThreadId();
+ assert( p->nRef>0 );
+ assert( p->owner==tid );
+ p->nRef--;
+ if( p->nRef==0 ) p->owner = 0;
+ assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
+#endif
+ LeaveCriticalSection(&p->mutex);
+#ifdef SQLITE_DEBUG
+ if( p->trace ){
+ printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+ }
+#endif
+}
+
+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
+ static const sqlite3_mutex_methods sMutex = {
+ winMutexInit,
+ winMutexEnd,
+ winMutexAlloc,
+ winMutexFree,
+ winMutexEnter,
+ winMutexTry,
+ winMutexLeave,
+#ifdef SQLITE_DEBUG
+ winMutexHeld,
+ winMutexNotheld
+#else
+ 0,
+ 0
+#endif
+ };
+
+ return &sMutex;
+}
+#endif /* SQLITE_MUTEX_W32 */
+
+/************** End of mutex_w32.c *******************************************/
+/************** Begin file malloc.c ******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** Memory allocation functions used throughout sqlite.
+*/
+/* #include <stdarg.h> */
+
+/*
+** Attempt to release up to n bytes of non-essential memory currently
+** held by SQLite. An example of non-essential memory is memory used to
+** cache database pages that are not currently in use.
+*/
+SQLITE_API int sqlite3_release_memory(int n){
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ return sqlite3PcacheReleaseMemory(n);
+#else
+ /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine
+ ** is a no-op returning zero if SQLite is not compiled with
+ ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
+ UNUSED_PARAMETER(n);
+ return 0;
+#endif
+}
+
+/*
+** An instance of the following object records the location of
+** each unused scratch buffer.
+*/
+typedef struct ScratchFreeslot {
+ struct ScratchFreeslot *pNext; /* Next unused scratch buffer */
+} ScratchFreeslot;
+
+/*
+** State information local to the memory allocation subsystem.
+*/
+static SQLITE_WSD struct Mem0Global {
+ sqlite3_mutex *mutex; /* Mutex to serialize access */
+
+ /*
+ ** The alarm callback and its arguments. The mem0.mutex lock will
+ ** be held while the callback is running. Recursive calls into
+ ** the memory subsystem are allowed, but no new callbacks will be
+ ** issued.
+ */
+ sqlite3_int64 alarmThreshold;
+ void (*alarmCallback)(void*, sqlite3_int64,int);
+ void *alarmArg;
+
+ /*
+ ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
+ ** (so that a range test can be used to determine if an allocation
+ ** being freed came from pScratch) and a pointer to the list of
+ ** unused scratch allocations.
+ */
+ void *pScratchEnd;
+ ScratchFreeslot *pScratchFree;
+ u32 nScratchFree;
+
+ /*
+ ** True if heap is nearly "full" where "full" is defined by the
+ ** sqlite3_soft_heap_limit() setting.
+ */
+ int nearlyFull;
+} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+#define mem0 GLOBAL(struct Mem0Global, mem0)
+
+/*
+** This routine runs when the memory allocator sees that the
+** total memory allocation is about to exceed the soft heap
+** limit.
+*/
+static void softHeapLimitEnforcer(
+ void *NotUsed,
+ sqlite3_int64 NotUsed2,
+ int allocSize
+){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ sqlite3_release_memory(allocSize);
+}
+
+/*
+** Change the alarm callback
+*/
+static int sqlite3MemoryAlarm(
+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+ void *pArg,
+ sqlite3_int64 iThreshold
+){
+ int nUsed;
+ sqlite3_mutex_enter(mem0.mutex);
+ mem0.alarmCallback = xCallback;
+ mem0.alarmArg = pArg;
+ mem0.alarmThreshold = iThreshold;
+ nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+ mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed);
+ sqlite3_mutex_leave(mem0.mutex);
+ return SQLITE_OK;
+}
+
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** Deprecated external interface. Internal/core SQLite code
+** should call sqlite3MemoryAlarm.
+*/
+SQLITE_API int sqlite3_memory_alarm(
+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+ void *pArg,
+ sqlite3_int64 iThreshold
+){
+ return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
+}
+#endif
+
+/*
+** Set the soft heap-size limit for the library. Passing a zero or
+** negative value indicates no limit.
+*/
+SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
+ sqlite3_int64 priorLimit;
+ sqlite3_int64 excess;
+#ifndef SQLITE_OMIT_AUTOINIT
+ int rc = sqlite3_initialize();
+ if( rc ) return -1;
+#endif
+ sqlite3_mutex_enter(mem0.mutex);
+ priorLimit = mem0.alarmThreshold;
+ sqlite3_mutex_leave(mem0.mutex);
+ if( n<0 ) return priorLimit;
+ if( n>0 ){
+ sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
+ }else{
+ sqlite3MemoryAlarm(0, 0, 0);
+ }
+ excess = sqlite3_memory_used() - n;
+ if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
+ return priorLimit;
+}
+SQLITE_API void sqlite3_soft_heap_limit(int n){
+ if( n<0 ) n = 0;
+ sqlite3_soft_heap_limit64(n);
+}
+
+/*
+** Initialize the memory allocation subsystem.
+*/
+SQLITE_PRIVATE int sqlite3MallocInit(void){
+ if( sqlite3GlobalConfig.m.xMalloc==0 ){
+ sqlite3MemSetDefault();
+ }
+ memset(&mem0, 0, sizeof(mem0));
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+ }
+ if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
+ && sqlite3GlobalConfig.nScratch>0 ){
+ int i, n, sz;
+ ScratchFreeslot *pSlot;
+ sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
+ sqlite3GlobalConfig.szScratch = sz;
+ pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
+ n = sqlite3GlobalConfig.nScratch;
+ mem0.pScratchFree = pSlot;
+ mem0.nScratchFree = n;
+ for(i=0; i<n-1; i++){
+ pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
+ pSlot = pSlot->pNext;
+ }
+ pSlot->pNext = 0;
+ mem0.pScratchEnd = (void*)&pSlot[1];
+ }else{
+ mem0.pScratchEnd = 0;
+ sqlite3GlobalConfig.pScratch = 0;
+ sqlite3GlobalConfig.szScratch = 0;
+ sqlite3GlobalConfig.nScratch = 0;
+ }
+ if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
+ || sqlite3GlobalConfig.nPage<1 ){
+ sqlite3GlobalConfig.pPage = 0;
+ sqlite3GlobalConfig.szPage = 0;
+ sqlite3GlobalConfig.nPage = 0;
+ }
+ return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
+}
+
+/*
+** Return true if the heap is currently under memory pressure - in other
+** words if the amount of heap used is close to the limit set by
+** sqlite3_soft_heap_limit().
+*/
+SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
+ return mem0.nearlyFull;
+}
+
+/*
+** Deinitialize the memory allocation subsystem.
+*/
+SQLITE_PRIVATE void sqlite3MallocEnd(void){
+ if( sqlite3GlobalConfig.m.xShutdown ){
+ sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
+ }
+ memset(&mem0, 0, sizeof(mem0));
+}
+
+/*
+** Return the amount of memory currently checked out.
+*/
+SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
+ int n, mx;
+ sqlite3_int64 res;
+ sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
+ res = (sqlite3_int64)n; /* Work around bug in Borland C. Ticket #3216 */
+ return res;
+}
+
+/*
+** Return the maximum amount of memory that has ever been
+** checked out since either the beginning of this process
+** or since the most recent reset.
+*/
+SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
+ int n, mx;
+ sqlite3_int64 res;
+ sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);
+ res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */
+ return res;
+}
+
+/*
+** Trigger the alarm
+*/
+static void sqlite3MallocAlarm(int nByte){
+ void (*xCallback)(void*,sqlite3_int64,int);
+ sqlite3_int64 nowUsed;
+ void *pArg;
+ if( mem0.alarmCallback==0 ) return;
+ xCallback = mem0.alarmCallback;
+ nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+ pArg = mem0.alarmArg;
+ mem0.alarmCallback = 0;
+ sqlite3_mutex_leave(mem0.mutex);
+ xCallback(pArg, nowUsed, nByte);
+ sqlite3_mutex_enter(mem0.mutex);
+ mem0.alarmCallback = xCallback;
+ mem0.alarmArg = pArg;
+}
+
+/*
+** Do a memory allocation with statistics and alarms. Assume the
+** lock is already held.
+*/
+static int mallocWithAlarm(int n, void **pp){
+ int nFull;
+ void *p;
+ assert( sqlite3_mutex_held(mem0.mutex) );
+ nFull = sqlite3GlobalConfig.m.xRoundup(n);
+ sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
+ if( mem0.alarmCallback!=0 ){
+ int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+ if( nUsed >= mem0.alarmThreshold - nFull ){
+ mem0.nearlyFull = 1;
+ sqlite3MallocAlarm(nFull);
+ }else{
+ mem0.nearlyFull = 0;
+ }
+ }
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ if( p==0 && mem0.alarmCallback ){
+ sqlite3MallocAlarm(nFull);
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
+ }
+#endif
+ if( p ){
+ nFull = sqlite3MallocSize(p);
+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
+ }
+ *pp = p;
+ return nFull;
+}
+
+/*
+** Allocate memory. This routine is like sqlite3_malloc() except that it
+** assumes the memory subsystem has already been initialized.
+*/
+SQLITE_PRIVATE void *sqlite3Malloc(int n){
+ void *p;
+ if( n<=0 /* IMP: R-65312-04917 */
+ || n>=0x7fffff00
+ ){
+ /* A memory allocation of a number of bytes which is near the maximum
+ ** signed integer value might cause an integer overflow inside of the
+ ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
+ ** 255 bytes of overhead. SQLite itself will never use anything near
+ ** this amount. The only way to reach the limit is with sqlite3_malloc() */
+ p = 0;
+ }else if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3_mutex_enter(mem0.mutex);
+ mallocWithAlarm(n, &p);
+ sqlite3_mutex_leave(mem0.mutex);
+ }else{
+ p = sqlite3GlobalConfig.m.xMalloc(n);
+ }
+ assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */
+ return p;
+}
+
+/*
+** This version of the memory allocation is for use by the application.
+** First make sure the memory subsystem is initialized, then do the
+** allocation.
+*/
+SQLITE_API void *sqlite3_malloc(int n){
+#ifndef SQLITE_OMIT_AUTOINIT
+ if( sqlite3_initialize() ) return 0;
+#endif
+ return sqlite3Malloc(n);
+}
+
+/*
+** Each thread may only have a single outstanding allocation from
+** xScratchMalloc(). We verify this constraint in the single-threaded
+** case by setting scratchAllocOut to 1 when an allocation
+** is outstanding clearing it when the allocation is freed.
+*/
+#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+static int scratchAllocOut = 0;
+#endif
+
+
+/*
+** Allocate memory that is to be used and released right away.
+** This routine is similar to alloca() in that it is not intended
+** for situations where the memory might be held long-term. This
+** routine is intended to get memory to old large transient data
+** structures that would not normally fit on the stack of an
+** embedded processor.
+*/
+SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
+ void *p;
+ assert( n>0 );
+
+ sqlite3_mutex_enter(mem0.mutex);
+ if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
+ p = mem0.pScratchFree;
+ mem0.pScratchFree = mem0.pScratchFree->pNext;
+ mem0.nScratchFree--;
+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
+ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
+ sqlite3_mutex_leave(mem0.mutex);
+ }else{
+ if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
+ n = mallocWithAlarm(n, &p);
+ if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
+ sqlite3_mutex_leave(mem0.mutex);
+ }else{
+ sqlite3_mutex_leave(mem0.mutex);
+ p = sqlite3GlobalConfig.m.xMalloc(n);
+ }
+ sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
+ }
+ assert( sqlite3_mutex_notheld(mem0.mutex) );
+
+
+#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+ /* Verify that no more than two scratch allocations per thread
+ ** are outstanding at one time. (This is only checked in the
+ ** single-threaded case since checking in the multi-threaded case
+ ** would be much more complicated.) */
+ assert( scratchAllocOut<=1 );
+ if( p ) scratchAllocOut++;
+#endif
+
+ return p;
+}
+SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
+ if( p ){
+
+#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+ /* Verify that no more than two scratch allocation per thread
+ ** is outstanding at one time. (This is only checked in the
+ ** single-threaded case since checking in the multi-threaded case
+ ** would be much more complicated.) */
+ assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
+ scratchAllocOut--;
+#endif
+
+ if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){
+ /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
+ ScratchFreeslot *pSlot;
+ pSlot = (ScratchFreeslot*)p;
+ sqlite3_mutex_enter(mem0.mutex);
+ pSlot->pNext = mem0.pScratchFree;
+ mem0.pScratchFree = pSlot;
+ mem0.nScratchFree++;
+ assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
+ sqlite3_mutex_leave(mem0.mutex);
+ }else{
+ /* Release memory back to the heap */
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
+ assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+ if( sqlite3GlobalConfig.bMemstat ){
+ int iSize = sqlite3MallocSize(p);
+ sqlite3_mutex_enter(mem0.mutex);
+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
+ sqlite3GlobalConfig.m.xFree(p);
+ sqlite3_mutex_leave(mem0.mutex);
+ }else{
+ sqlite3GlobalConfig.m.xFree(p);
+ }
+ }
+ }
+}
+
+/*
+** TRUE if p is a lookaside memory allocation from db
+*/
+#ifndef SQLITE_OMIT_LOOKASIDE
+static int isLookaside(sqlite3 *db, void *p){
+ return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
+}
+#else
+#define isLookaside(A,B) 0
+#endif
+
+/*
+** Return the size of a memory allocation previously obtained from
+** sqlite3Malloc() or sqlite3_malloc().
+*/
+SQLITE_PRIVATE int sqlite3MallocSize(void *p){
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
+ assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
+ return sqlite3GlobalConfig.m.xSize(p);
+}
+SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
+ if( db && isLookaside(db, p) ){
+ return db->lookaside.sz;
+ }else{
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
+ assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
+ return sqlite3GlobalConfig.m.xSize(p);
+ }
+}
+
+/*
+** Free memory previously obtained from sqlite3Malloc().
+*/
+SQLITE_API void sqlite3_free(void *p){
+ if( p==0 ) return; /* IMP: R-49053-54554 */
+ assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
+ if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3_mutex_enter(mem0.mutex);
+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
+ sqlite3GlobalConfig.m.xFree(p);
+ sqlite3_mutex_leave(mem0.mutex);
+ }else{
+ sqlite3GlobalConfig.m.xFree(p);
+ }
+}
+
+/*
+** Free memory that might be associated with a particular database
+** connection.
+*/
+SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
+ if( db ){
+ if( db->pnBytesFreed ){
+ *db->pnBytesFreed += sqlite3DbMallocSize(db, p);
+ return;
+ }
+ if( isLookaside(db, p) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
+#if SQLITE_DEBUG
+ /* Trash all content in the buffer being freed */
+ memset(p, 0xaa, db->lookaside.sz);
+#endif
+ pBuf->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = pBuf;
+ db->lookaside.nOut--;
+ return;
+ }
+ }
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
+ assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+ sqlite3_free(p);
+}
+
+/*
+** Change the size of an existing memory allocation
+*/
+SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
+ int nOld, nNew, nDiff;
+ void *pNew;
+ if( pOld==0 ){
+ return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
+ }
+ if( nBytes<=0 ){
+ sqlite3_free(pOld); /* IMP: R-31593-10574 */
+ return 0;
+ }
+ if( nBytes>=0x7fffff00 ){
+ /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
+ return 0;
+ }
+ nOld = sqlite3MallocSize(pOld);
+ /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
+ ** argument to xRealloc is always a value returned by a prior call to
+ ** xRoundup. */
+ nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
+ if( nOld==nNew ){
+ pNew = pOld;
+ }else if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3_mutex_enter(mem0.mutex);
+ sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
+ nDiff = nNew - nOld;
+ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ mem0.alarmThreshold-nDiff ){
+ sqlite3MallocAlarm(nDiff);
+ }
+ assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
+ assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+ if( pNew==0 && mem0.alarmCallback ){
+ sqlite3MallocAlarm(nBytes);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+ }
+ if( pNew ){
+ nNew = sqlite3MallocSize(pNew);
+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
+ }
+ sqlite3_mutex_leave(mem0.mutex);
+ }else{
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+ }
+ assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
+ return pNew;
+}
+
+/*
+** The public interface to sqlite3Realloc. Make sure that the memory
+** subsystem is initialized prior to invoking sqliteRealloc.
+*/
+SQLITE_API void *sqlite3_realloc(void *pOld, int n){
+#ifndef SQLITE_OMIT_AUTOINIT
+ if( sqlite3_initialize() ) return 0;
+#endif
+ return sqlite3Realloc(pOld, n);
+}
+
+
+/*
+** Allocate and zero memory.
+*/
+SQLITE_PRIVATE void *sqlite3MallocZero(int n){
+ void *p = sqlite3Malloc(n);
+ if( p ){
+ memset(p, 0, n);
+ }
+ return p;
+}
+
+/*
+** Allocate and zero memory. If the allocation fails, make
+** the mallocFailed flag in the connection pointer.
+*/
+SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, int n){
+ void *p = sqlite3DbMallocRaw(db, n);
+ if( p ){
+ memset(p, 0, n);
+ }
+ return p;
+}
+
+/*
+** Allocate and zero memory. If the allocation fails, make
+** the mallocFailed flag in the connection pointer.
+**
+** If db!=0 and db->mallocFailed is true (indicating a prior malloc
+** failure on the same database connection) then always return 0.
+** Hence for a particular database connection, once malloc starts
+** failing, it fails consistently until mallocFailed is reset.
+** This is an important assumption. There are many places in the
+** code that do things like this:
+**
+** int *a = (int*)sqlite3DbMallocRaw(db, 100);
+** int *b = (int*)sqlite3DbMallocRaw(db, 200);
+** if( b ) a[10] = 9;
+**
+** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
+** that all prior mallocs (ex: "a") worked too.
+*/
+SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
+ void *p;
+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
+ assert( db==0 || db->pnBytesFreed==0 );
+#ifndef SQLITE_OMIT_LOOKASIDE
+ if( db ){
+ LookasideSlot *pBuf;
+ if( db->mallocFailed ){
+ return 0;
+ }
+ if( db->lookaside.bEnabled ){
+ if( n>db->lookaside.sz ){
+ db->lookaside.anStat[1]++;
+ }else if( (pBuf = db->lookaside.pFree)==0 ){
+ db->lookaside.anStat[2]++;
+ }else{
+ db->lookaside.pFree = pBuf->pNext;
+ db->lookaside.nOut++;
+ db->lookaside.anStat[0]++;
+ if( db->lookaside.nOut>db->lookaside.mxOut ){
+ db->lookaside.mxOut = db->lookaside.nOut;
+ }
+ return (void*)pBuf;
+ }
+ }
+ }
+#else
+ if( db && db->mallocFailed ){
+ return 0;
+ }
+#endif
+ p = sqlite3Malloc(n);
+ if( !p && db ){
+ db->mallocFailed = 1;
+ }
+ sqlite3MemdebugSetType(p, MEMTYPE_DB |
+ ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
+ return p;
+}
+
+/*
+** Resize the block of memory pointed to by p to n bytes. If the
+** resize fails, set the mallocFailed flag in the connection object.
+*/
+SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
+ void *pNew = 0;
+ assert( db!=0 );
+ assert( sqlite3_mutex_held(db->mutex) );
+ if( db->mallocFailed==0 ){
+ if( p==0 ){
+ return sqlite3DbMallocRaw(db, n);
+ }
+ if( isLookaside(db, p) ){
+ if( n<=db->lookaside.sz ){
+ return p;
+ }
+ pNew = sqlite3DbMallocRaw(db, n);
+ if( pNew ){
+ memcpy(pNew, p, db->lookaside.sz);
+ sqlite3DbFree(db, p);
+ }
+ }else{
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+ pNew = sqlite3_realloc(p, n);
+ if( !pNew ){
+ sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
+ db->mallocFailed = 1;
+ }
+ sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
+ (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
+ }
+ }
+ return pNew;
+}
+
+/*
+** Attempt to reallocate p. If the reallocation fails, then free p
+** and set the mallocFailed flag in the database connection.
+*/
+SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
+ void *pNew;
+ pNew = sqlite3DbRealloc(db, p, n);
+ if( !pNew ){
+ sqlite3DbFree(db, p);
+ }
+ return pNew;
+}
+
+/*
+** Make a copy of a string in memory obtained from sqliteMalloc(). These
+** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
+** is because when memory debugging is turned on, these two functions are
+** called via macros that record the current file and line number in the
+** ThreadData structure.
+*/
+SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
+ char *zNew;
+ size_t n;
+ if( z==0 ){
+ return 0;
+ }
+ n = sqlite3Strlen30(z) + 1;
+ assert( (n&0x7fffffff)==n );
+ zNew = sqlite3DbMallocRaw(db, (int)n);
+ if( zNew ){
+ memcpy(zNew, z, n);
+ }
+ return zNew;
+}
+SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
+ char *zNew;
+ if( z==0 ){
+ return 0;
+ }
+ assert( (n&0x7fffffff)==n );
+ zNew = sqlite3DbMallocRaw(db, n+1);
+ if( zNew ){
+ memcpy(zNew, z, n);
+ zNew[n] = 0;
+ }
+ return zNew;
+}
+
+/*
+** Create a string from the zFromat argument and the va_list that follows.
+** Store the string in memory obtained from sqliteMalloc() and make *pz
+** point to that string.
+*/
+SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){
+ va_list ap;
+ char *z;
+
+ va_start(ap, zFormat);
+ z = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ sqlite3DbFree(db, *pz);
+ *pz = z;
+}
+
+
+/*
+** This function must be called before exiting any API function (i.e.
+** returning control to the user) that has called sqlite3_malloc or
+** sqlite3_realloc.
+**
+** The returned value is normally a copy of the second argument to this
+** function. However, if a malloc() failure has occurred since the previous
+** invocation SQLITE_NOMEM is returned instead.
+**
+** If the first argument, db, is not NULL and a malloc() error has occurred,
+** then the connection error-code (the value returned by sqlite3_errcode())
+** is set to SQLITE_NOMEM.
+*/
+SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
+ /* If the db handle is not NULL, then we must hold the connection handle
+ ** mutex here. Otherwise the read (and possible write) of db->mallocFailed
+ ** is unsafe, as is the call to sqlite3Error().
+ */
+ assert( !db || sqlite3_mutex_held(db->mutex) );
+ if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){
+ sqlite3Error(db, SQLITE_NOMEM, 0);
+ db->mallocFailed = 0;
+ rc = SQLITE_NOMEM;
+ }
+ return rc & (db ? db->errMask : 0xff);
+}
+
+/************** End of malloc.c **********************************************/
+/************** Begin file printf.c ******************************************/
+/*
+** The "printf" code that follows dates from the 1980's. It is in
+** the public domain. The original comments are included here for
+** completeness. They are very out-of-date but might be useful as
+** an historical reference. Most of the "enhancements" have been backed
+** out so that the functionality is now the same as standard printf().
+**
+**************************************************************************
+**
+** This file contains code for a set of "printf"-like routines. These
+** routines format strings much like the printf() from the standard C
+** library, though the implementation here has enhancements to support
+** SQLlite.
+*/
+
+/*
+** Conversion types fall into various categories as defined by the
+** following enumeration.
+*/
+#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
+#define etFLOAT 2 /* Floating point. %f */
+#define etEXP 3 /* Exponentional notation. %e and %E */
+#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
+#define etSIZE 5 /* Return number of characters processed so far. %n */
+#define etSTRING 6 /* Strings. %s */
+#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
+#define etPERCENT 8 /* Percent symbol. %% */
+#define etCHARX 9 /* Characters. %c */
+/* The rest are extensions, not normally found in printf() */
+#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */
+#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
+ NULL pointers replaced by SQL NULL. %Q */
+#define etTOKEN 12 /* a pointer to a Token structure */
+#define etSRCLIST 13 /* a pointer to a SrcList */
+#define etPOINTER 14 /* The %p conversion */
+#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
+#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
+
+#define etINVALID 0 /* Any unrecognized conversion type */
+
+
+/*
+** An "etByte" is an 8-bit unsigned value.
+*/
+typedef unsigned char etByte;
+
+/*
+** Each builtin conversion character (ex: the 'd' in "%d") is described
+** by an instance of the following structure
+*/
+typedef struct et_info { /* Information about each format field */
+ char fmttype; /* The format field code letter */
+ etByte base; /* The base for radix conversion */
+ etByte flags; /* One or more of FLAG_ constants below */
+ etByte type; /* Conversion paradigm */
+ etByte charset; /* Offset into aDigits[] of the digits string */
+ etByte prefix; /* Offset into aPrefix[] of the prefix string */
+} et_info;
+
+/*
+** Allowed values for et_info.flags
+*/
+#define FLAG_SIGNED 1 /* True if the value to convert is signed */
+#define FLAG_INTERN 2 /* True if for internal use only */
+#define FLAG_STRING 4 /* Allow infinity precision */
+
+
+/*
+** The following table is searched linearly, so it is good to put the
+** most frequently used conversion types first.
+*/
+static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
+static const char aPrefix[] = "-x0\000X0";
+static const et_info fmtinfo[] = {
+ { 'd', 10, 1, etRADIX, 0, 0 },
+ { 's', 0, 4, etSTRING, 0, 0 },
+ { 'g', 0, 1, etGENERIC, 30, 0 },
+ { 'z', 0, 4, etDYNSTRING, 0, 0 },
+ { 'q', 0, 4, etSQLESCAPE, 0, 0 },
+ { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
+ { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
+ { 'c', 0, 0, etCHARX, 0, 0 },
+ { 'o', 8, 0, etRADIX, 0, 2 },
+ { 'u', 10, 0, etRADIX, 0, 0 },
+ { 'x', 16, 0, etRADIX, 16, 1 },
+ { 'X', 16, 0, etRADIX, 0, 4 },
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ { 'f', 0, 1, etFLOAT, 0, 0 },
+ { 'e', 0, 1, etEXP, 30, 0 },
+ { 'E', 0, 1, etEXP, 14, 0 },
+ { 'G', 0, 1, etGENERIC, 14, 0 },
+#endif
+ { 'i', 10, 1, etRADIX, 0, 0 },
+ { 'n', 0, 0, etSIZE, 0, 0 },
+ { '%', 0, 0, etPERCENT, 0, 0 },
+ { 'p', 16, 0, etPOINTER, 0, 1 },
+
+/* All the rest have the FLAG_INTERN bit set and are thus for internal
+** use only */
+ { 'T', 0, 2, etTOKEN, 0, 0 },
+ { 'S', 0, 2, etSRCLIST, 0, 0 },
+ { 'r', 10, 3, etORDINAL, 0, 0 },
+};
+
+/*
+** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
+** conversions will work.
+*/
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/*
+** "*val" is a double such that 0.1 <= *val < 10.0
+** Return the ascii code for the leading digit of *val, then
+** multiply "*val" by 10.0 to renormalize.
+**
+** Example:
+** input: *val = 3.14159
+** output: *val = 1.4159 function return = '3'
+**
+** The counter *cnt is incremented each time. After counter exceeds
+** 16 (the number of significant digits in a 64-bit float) '0' is
+** always returned.
+*/
+static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
+ int digit;
+ LONGDOUBLE_TYPE d;
+ if( (*cnt)<=0 ) return '0';
+ (*cnt)--;
+ digit = (int)*val;
+ d = digit;
+ digit += '0';
+ *val = (*val - d)*10.0;
+ return (char)digit;
+}
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+
+/*
+** Append N space characters to the given string buffer.
+*/
+SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
+ static const char zSpaces[] = " ";
+ while( N>=(int)sizeof(zSpaces)-1 ){
+ sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
+ N -= sizeof(zSpaces)-1;
+ }
+ if( N>0 ){
+ sqlite3StrAccumAppend(pAccum, zSpaces, N);
+ }
+}
+
+/*
+** On machines with a small stack size, you can redefine the
+** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
+*/
+#ifndef SQLITE_PRINT_BUF_SIZE
+# define SQLITE_PRINT_BUF_SIZE 70
+#endif
+#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
+
+/*
+** Render a string given by "fmt" into the StrAccum object.
+*/
+SQLITE_PRIVATE void sqlite3VXPrintf(
+ StrAccum *pAccum, /* Accumulate results here */
+ int useExtended, /* Allow extended %-conversions */
+ const char *fmt, /* Format string */
+ va_list ap /* arguments */
+){
+ int c; /* Next character in the format string */
+ char *bufpt; /* Pointer to the conversion buffer */
+ int precision; /* Precision of the current field */
+ int length; /* Length of the field */
+ int idx; /* A general purpose loop counter */
+ int width; /* Width of the current field */
+ etByte flag_leftjustify; /* True if "-" flag is present */
+ etByte flag_plussign; /* True if "+" flag is present */
+ etByte flag_blanksign; /* True if " " flag is present */
+ etByte flag_alternateform; /* True if "#" flag is present */
+ etByte flag_altform2; /* True if "!" flag is present */
+ etByte flag_zeropad; /* True if field width constant starts with zero */
+ etByte flag_long; /* True if "l" flag is present */
+ etByte flag_longlong; /* True if the "ll" flag is present */
+ etByte done; /* Loop termination flag */
+ etByte xtype = 0; /* Conversion paradigm */
+ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
+ sqlite_uint64 longvalue; /* Value for integer types */
+ LONGDOUBLE_TYPE realvalue; /* Value for real types */
+ const et_info *infop; /* Pointer to the appropriate info structure */
+ char *zOut; /* Rendering buffer */
+ int nOut; /* Size of the rendering buffer */
+ char *zExtra; /* Malloced memory used by some conversion */
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ int exp, e2; /* exponent of real numbers */
+ int nsd; /* Number of significant digits returned */
+ double rounder; /* Used for rounding floating point values */
+ etByte flag_dp; /* True if decimal point should be shown */
+ etByte flag_rtz; /* True if trailing zeros should be removed */
+#endif
+ char buf[etBUFSIZE]; /* Conversion buffer */
+
+ bufpt = 0;
+ for(; (c=(*fmt))!=0; ++fmt){
+ if( c!='%' ){
+ int amt;
+ bufpt = (char *)fmt;
+ amt = 1;
+ while( (c=(*++fmt))!='%' && c!=0 ) amt++;
+ sqlite3StrAccumAppend(pAccum, bufpt, amt);
+ if( c==0 ) break;
+ }
+ if( (c=(*++fmt))==0 ){
+ sqlite3StrAccumAppend(pAccum, "%", 1);
+ break;
+ }
+ /* Find out what flags are present */
+ flag_leftjustify = flag_plussign = flag_blanksign =
+ flag_alternateform = flag_altform2 = flag_zeropad = 0;
+ done = 0;
+ do{
+ switch( c ){
+ case '-': flag_leftjustify = 1; break;
+ case '+': flag_plussign = 1; break;
+ case ' ': flag_blanksign = 1; break;
+ case '#': flag_alternateform = 1; break;
+ case '!': flag_altform2 = 1; break;
+ case '0': flag_zeropad = 1; break;
+ default: done = 1; break;
+ }
+ }while( !done && (c=(*++fmt))!=0 );
+ /* Get the field width */
+ width = 0;
+ if( c=='*' ){
+ width = va_arg(ap,int);
+ if( width<0 ){
+ flag_leftjustify = 1;
+ width = -width;
+ }
+ c = *++fmt;
+ }else{
+ while( c>='0' && c<='9' ){
+ width = width*10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ /* Get the precision */
+ if( c=='.' ){
+ precision = 0;
+ c = *++fmt;
+ if( c=='*' ){
+ precision = va_arg(ap,int);
+ if( precision<0 ) precision = -precision;
+ c = *++fmt;
+ }else{
+ while( c>='0' && c<='9' ){
+ precision = precision*10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ }else{
+ precision = -1;
+ }
+ /* Get the conversion type modifier */
+ if( c=='l' ){
+ flag_long = 1;
+ c = *++fmt;
+ if( c=='l' ){
+ flag_longlong = 1;
+ c = *++fmt;
+ }else{
+ flag_longlong = 0;
+ }
+ }else{
+ flag_long = flag_longlong = 0;
+ }
+ /* Fetch the info entry for the field */
+ infop = &fmtinfo[0];
+ xtype = etINVALID;
+ for(idx=0; idx<ArraySize(fmtinfo); idx++){
+ if( c==fmtinfo[idx].fmttype ){
+ infop = &fmtinfo[idx];
+ if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
+ xtype = infop->type;
+ }else{
+ return;
+ }
+ break;
+ }
+ }
+ zExtra = 0;
+
+ /*
+ ** At this point, variables are initialized as follows:
+ **
+ ** flag_alternateform TRUE if a '#' is present.
+ ** flag_altform2 TRUE if a '!' is present.
+ ** flag_plussign TRUE if a '+' is present.
+ ** flag_leftjustify TRUE if a '-' is present or if the
+ ** field width was negative.
+ ** flag_zeropad TRUE if the width began with 0.
+ ** flag_long TRUE if the letter 'l' (ell) prefixed
+ ** the conversion character.
+ ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
+ ** the conversion character.
+ ** flag_blanksign TRUE if a ' ' is present.
+ ** width The specified field width. This is
+ ** always non-negative. Zero is the default.
+ ** precision The specified precision. The default
+ ** is -1.
+ ** xtype The class of the conversion.
+ ** infop Pointer to the appropriate info struct.
+ */
+ switch( xtype ){
+ case etPOINTER:
+ flag_longlong = sizeof(char*)==sizeof(i64);
+ flag_long = sizeof(char*)==sizeof(long int);
+ /* Fall through into the next case */
+ case etORDINAL:
+ case etRADIX:
+ if( infop->flags & FLAG_SIGNED ){
+ i64 v;
+ if( flag_longlong ){
+ v = va_arg(ap,i64);
+ }else if( flag_long ){
+ v = va_arg(ap,long int);
+ }else{
+ v = va_arg(ap,int);
+ }
+ if( v<0 ){
+ if( v==SMALLEST_INT64 ){
+ longvalue = ((u64)1)<<63;
+ }else{
+ longvalue = -v;
+ }
+ prefix = '-';
+ }else{
+ longvalue = v;
+ if( flag_plussign ) prefix = '+';
+ else if( flag_blanksign ) prefix = ' ';
+ else prefix = 0;
+ }
+ }else{
+ if( flag_longlong ){
+ longvalue = va_arg(ap,u64);
+ }else if( flag_long ){
+ longvalue = va_arg(ap,unsigned long int);
+ }else{
+ longvalue = va_arg(ap,unsigned int);
+ }
+ prefix = 0;
+ }
+ if( longvalue==0 ) flag_alternateform = 0;
+ if( flag_zeropad && precision<width-(prefix!=0) ){
+ precision = width-(prefix!=0);
+ }
+ if( precision<etBUFSIZE-10 ){
+ nOut = etBUFSIZE;
+ zOut = buf;
+ }else{
+ nOut = precision + 10;
+ zOut = zExtra = sqlite3Malloc( nOut );
+ if( zOut==0 ){
+ pAccum->mallocFailed = 1;
+ return;
+ }
+ }
+ bufpt = &zOut[nOut-1];
+ if( xtype==etORDINAL ){
+ static const char zOrd[] = "thstndrd";
+ int x = (int)(longvalue % 10);
+ if( x>=4 || (longvalue/10)%10==1 ){
+ x = 0;
+ }
+ *(--bufpt) = zOrd[x*2+1];
+ *(--bufpt) = zOrd[x*2];
+ }
+ {
+ register const char *cset; /* Use registers for speed */
+ register int base;
+ cset = &aDigits[infop->charset];
+ base = infop->base;
+ do{ /* Convert to ascii */
+ *(--bufpt) = cset[longvalue%base];
+ longvalue = longvalue/base;
+ }while( longvalue>0 );
+ }
+ length = (int)(&zOut[nOut-1]-bufpt);
+ for(idx=precision-length; idx>0; idx--){
+ *(--bufpt) = '0'; /* Zero pad */
+ }
+ if( prefix ) *(--bufpt) = prefix; /* Add sign */
+ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
+ const char *pre;
+ char x;
+ pre = &aPrefix[infop->prefix];
+ for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
+ }
+ length = (int)(&zOut[nOut-1]-bufpt);
+ break;
+ case etFLOAT:
+ case etEXP:
+ case etGENERIC:
+ realvalue = va_arg(ap,double);
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ length = 0;
+#else
+ if( precision<0 ) precision = 6; /* Set default precision */
+ if( realvalue<0.0 ){
+ realvalue = -realvalue;
+ prefix = '-';
+ }else{
+ if( flag_plussign ) prefix = '+';
+ else if( flag_blanksign ) prefix = ' ';
+ else prefix = 0;
+ }
+ if( xtype==etGENERIC && precision>0 ) precision--;
+#if 0
+ /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
+ for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
+#else
+ /* It makes more sense to use 0.5 */
+ for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
+#endif
+ if( xtype==etFLOAT ) realvalue += rounder;
+ /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
+ exp = 0;
+ if( sqlite3IsNaN((double)realvalue) ){
+ bufpt = "NaN";
+ length = 3;
+ break;
+ }
+ if( realvalue>0.0 ){
+ LONGDOUBLE_TYPE scale = 1.0;
+ while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
+ while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; }
+ while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; }
+ while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
+ realvalue /= scale;
+ while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
+ while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
+ if( exp>350 ){
+ if( prefix=='-' ){
+ bufpt = "-Inf";
+ }else if( prefix=='+' ){
+ bufpt = "+Inf";
+ }else{
+ bufpt = "Inf";
+ }
+ length = sqlite3Strlen30(bufpt);
+ break;
+ }
+ }
+ bufpt = buf;
+ /*
+ ** If the field type is etGENERIC, then convert to either etEXP
+ ** or etFLOAT, as appropriate.
+ */
+ if( xtype!=etFLOAT ){
+ realvalue += rounder;
+ if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
+ }
+ if( xtype==etGENERIC ){
+ flag_rtz = !flag_alternateform;
+ if( exp<-4 || exp>precision ){
+ xtype = etEXP;
+ }else{
+ precision = precision - exp;
+ xtype = etFLOAT;
+ }
+ }else{
+ flag_rtz = flag_altform2;
+ }
+ if( xtype==etEXP ){
+ e2 = 0;
+ }else{
+ e2 = exp;
+ }
+ if( e2+precision+width > etBUFSIZE - 15 ){
+ bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
+ if( bufpt==0 ){
+ pAccum->mallocFailed = 1;
+ return;
+ }
+ }
+ zOut = bufpt;
+ nsd = 16 + flag_altform2*10;
+ flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
+ /* The sign in front of the number */
+ if( prefix ){
+ *(bufpt++) = prefix;
+ }
+ /* Digits prior to the decimal point */
+ if( e2<0 ){
+ *(bufpt++) = '0';
+ }else{
+ for(; e2>=0; e2--){
+ *(bufpt++) = et_getdigit(&realvalue,&nsd);
+ }
+ }
+ /* The decimal point */
+ if( flag_dp ){
+ *(bufpt++) = '.';
+ }
+ /* "0" digits after the decimal point but before the first
+ ** significant digit of the number */
+ for(e2++; e2<0; precision--, e2++){
+ assert( precision>0 );
+ *(bufpt++) = '0';
+ }
+ /* Significant digits after the decimal point */
+ while( (precision--)>0 ){
+ *(bufpt++) = et_getdigit(&realvalue,&nsd);
+ }
+ /* Remove trailing zeros and the "." if no digits follow the "." */
+ if( flag_rtz && flag_dp ){
+ while( bufpt[-1]=='0' ) *(--bufpt) = 0;
+ assert( bufpt>zOut );
+ if( bufpt[-1]=='.' ){
+ if( flag_altform2 ){
+ *(bufpt++) = '0';
+ }else{
+ *(--bufpt) = 0;
+ }
+ }
+ }
+ /* Add the "eNNN" suffix */
+ if( xtype==etEXP ){
+ *(bufpt++) = aDigits[infop->charset];
+ if( exp<0 ){
+ *(bufpt++) = '-'; exp = -exp;
+ }else{
+ *(bufpt++) = '+';
+ }
+ if( exp>=100 ){
+ *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */
+ exp %= 100;
+ }
+ *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
+ *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
+ }
+ *bufpt = 0;
+
+ /* The converted number is in buf[] and zero terminated. Output it.
+ ** Note that the number is in the usual order, not reversed as with
+ ** integer conversions. */
+ length = (int)(bufpt-zOut);
+ bufpt = zOut;
+
+ /* Special case: Add leading zeros if the flag_zeropad flag is
+ ** set and we are not left justified */
+ if( flag_zeropad && !flag_leftjustify && length < width){
+ int i;
+ int nPad = width - length;
+ for(i=width; i>=nPad; i--){
+ bufpt[i] = bufpt[i-nPad];
+ }
+ i = prefix!=0;
+ while( nPad-- ) bufpt[i++] = '0';
+ length = width;
+ }
+#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
+ break;
+ case etSIZE:
+ *(va_arg(ap,int*)) = pAccum->nChar;
+ length = width = 0;
+ break;
+ case etPERCENT:
+ buf[0] = '%';
+ bufpt = buf;
+ length = 1;
+ break;
+ case etCHARX:
+ c = va_arg(ap,int);
+ buf[0] = (char)c;
+ if( precision>=0 ){
+ for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
+ length = precision;
+ }else{
+ length =1;
+ }
+ bufpt = buf;
+ break;
+ case etSTRING:
+ case etDYNSTRING:
+ bufpt = va_arg(ap,char*);
+ if( bufpt==0 ){
+ bufpt = "";
+ }else if( xtype==etDYNSTRING ){
+ zExtra = bufpt;
+ }
+ if( precision>=0 ){
+ for(length=0; length<precision && bufpt[length]; length++){}
+ }else{
+ length = sqlite3Strlen30(bufpt);
+ }
+ break;
+ case etSQLESCAPE:
+ case etSQLESCAPE2:
+ case etSQLESCAPE3: {
+ int i, j, k, n, isnull;
+ int needQuote;
+ char ch;
+ char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
+ char *escarg = va_arg(ap,char*);
+ isnull = escarg==0;
+ if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
+ k = precision;
+ for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
+ if( ch==q ) n++;
+ }
+ needQuote = !isnull && xtype==etSQLESCAPE2;
+ n += i + 1 + needQuote*2;
+ if( n>etBUFSIZE ){
+ bufpt = zExtra = sqlite3Malloc( n );
+ if( bufpt==0 ){
+ pAccum->mallocFailed = 1;
+ return;
+ }
+ }else{
+ bufpt = buf;
+ }
+ j = 0;
+ if( needQuote ) bufpt[j++] = q;
+ k = i;
+ for(i=0; i<k; i++){
+ bufpt[j++] = ch = escarg[i];
+ if( ch==q ) bufpt[j++] = ch;
+ }
+ if( needQuote ) bufpt[j++] = q;
+ bufpt[j] = 0;
+ length = j;
+ /* The precision in %q and %Q means how many input characters to
+ ** consume, not the length of the output...
+ ** if( precision>=0 && precision<length ) length = precision; */
+ break;
+ }
+ case etTOKEN: {
+ Token *pToken = va_arg(ap, Token*);
+ if( pToken ){
+ sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
+ }
+ length = width = 0;
+ break;
+ }
+ case etSRCLIST: {
+ SrcList *pSrc = va_arg(ap, SrcList*);
+ int k = va_arg(ap, int);
+ struct SrcList_item *pItem = &pSrc->a[k];
+ assert( k>=0 && k<pSrc->nSrc );
+ if( pItem->zDatabase ){
+ sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
+ sqlite3StrAccumAppend(pAccum, ".", 1);
+ }
+ sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
+ length = width = 0;
+ break;
+ }
+ default: {
+ assert( xtype==etINVALID );
+ return;
+ }
+ }/* End switch over the format type */
+ /*
+ ** The text of the conversion is pointed to by "bufpt" and is
+ ** "length" characters long. The field width is "width". Do
+ ** the output.
+ */
+ if( !flag_leftjustify ){
+ register int nspace;
+ nspace = width-length;
+ if( nspace>0 ){
+ sqlite3AppendSpace(pAccum, nspace);
+ }
+ }
+ if( length>0 ){
+ sqlite3StrAccumAppend(pAccum, bufpt, length);
+ }
+ if( flag_leftjustify ){
+ register int nspace;
+ nspace = width-length;
+ if( nspace>0 ){
+ sqlite3AppendSpace(pAccum, nspace);
+ }
+ }
+ sqlite3_free(zExtra);
+ }/* End for loop over the format string */
+} /* End of function */
+
+/*
+** Append N bytes of text from z to the StrAccum object.
+*/
+SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
+ assert( z!=0 || N==0 );
+ if( p->tooBig | p->mallocFailed ){
+ testcase(p->tooBig);
+ testcase(p->mallocFailed);
+ return;
+ }
+ assert( p->zText!=0 || p->nChar==0 );
+ if( N<0 ){
+ N = sqlite3Strlen30(z);
+ }
+ if( N==0 || NEVER(z==0) ){
+ return;
+ }
+ if( p->nChar+N >= p->nAlloc ){
+ char *zNew;
+ if( !p->useMalloc ){
+ p->tooBig = 1;
+ N = p->nAlloc - p->nChar - 1;
+ if( N<=0 ){
+ return;
+ }
+ }else{
+ char *zOld = (p->zText==p->zBase ? 0 : p->zText);
+ i64 szNew = p->nChar;
+ szNew += N + 1;
+ if( szNew > p->mxAlloc ){
+ sqlite3StrAccumReset(p);
+ p->tooBig = 1;
+ return;
+ }else{
+ p->nAlloc = (int)szNew;
+ }
+ if( p->useMalloc==1 ){
+ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
+ }else{
+ zNew = sqlite3_realloc(zOld, p->nAlloc);
+ }
+ if( zNew ){
+ if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
+ p->zText = zNew;
+ }else{
+ p->mallocFailed = 1;
+ sqlite3StrAccumReset(p);
+ return;
+ }
+ }
+ }
+ assert( p->zText );
+ memcpy(&p->zText[p->nChar], z, N);
+ p->nChar += N;
+}
+
+/*
+** Finish off a string by making sure it is zero-terminated.
+** Return a pointer to the resulting string. Return a NULL
+** pointer if any kind of error was encountered.
+*/
+SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
+ if( p->zText ){
+ p->zText[p->nChar] = 0;
+ if( p->useMalloc && p->zText==p->zBase ){
+ if( p->useMalloc==1 ){
+ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+ }else{
+ p->zText = sqlite3_malloc(p->nChar+1);
+ }
+ if( p->zText ){
+ memcpy(p->zText, p->zBase, p->nChar+1);
+ }else{
+ p->mallocFailed = 1;
+ }
+ }
+ }
+ return p->zText;
+}
+
+/*
+** Reset an StrAccum string. Reclaim all malloced memory.
+*/
+SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
+ if( p->zText!=p->zBase ){
+ if( p->useMalloc==1 ){
+ sqlite3DbFree(p->db, p->zText);
+ }else{
+ sqlite3_free(p->zText);
+ }
+ }
+ p->zText = 0;
+}
+
+/*
+** Initialize a string accumulator
+*/
+SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
+ p->zText = p->zBase = zBase;
+ p->db = 0;
+ p->nChar = 0;
+ p->nAlloc = n;
+ p->mxAlloc = mx;
+ p->useMalloc = 1;
+ p->tooBig = 0;
+ p->mallocFailed = 0;
+}
+
+/*
+** Print into memory obtained from sqliteMalloc(). Use the internal
+** %-conversion extensions.
+*/
+SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
+ char *z;
+ char zBase[SQLITE_PRINT_BUF_SIZE];
+ StrAccum acc;
+ assert( db!=0 );
+ sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
+ db->aLimit[SQLITE_LIMIT_LENGTH]);
+ acc.db = db;
+ sqlite3VXPrintf(&acc, 1, zFormat, ap);
+ z = sqlite3StrAccumFinish(&acc);
+ if( acc.mallocFailed ){
+ db->mallocFailed = 1;
+ }
+ return z;
+}
+
+/*
+** Print into memory obtained from sqliteMalloc(). Use the internal
+** %-conversion extensions.
+*/
+SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
+ va_list ap;
+ char *z;
+ va_start(ap, zFormat);
+ z = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ return z;
+}
+
+/*
+** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
+** the string and before returnning. This routine is intended to be used
+** to modify an existing string. For example:
+**
+** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
+**
+*/
+SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
+ va_list ap;
+ char *z;
+ va_start(ap, zFormat);
+ z = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ sqlite3DbFree(db, zStr);
+ return z;
+}
+
+/*
+** Print into memory obtained from sqlite3_malloc(). Omit the internal
+** %-conversion extensions.
+*/
+SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
+ char *z;
+ char zBase[SQLITE_PRINT_BUF_SIZE];
+ StrAccum acc;
+#ifndef SQLITE_OMIT_AUTOINIT
+ if( sqlite3_initialize() ) return 0;
+#endif
+ sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
+ acc.useMalloc = 2;
+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
+ z = sqlite3StrAccumFinish(&acc);
+ return z;
+}
+
+/*
+** Print into memory obtained from sqlite3_malloc()(). Omit the internal
+** %-conversion extensions.
+*/
+SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
+ va_list ap;
+ char *z;
+#ifndef SQLITE_OMIT_AUTOINIT
+ if( sqlite3_initialize() ) return 0;
+#endif
+ va_start(ap, zFormat);
+ z = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ return z;
+}
+
+/*
+** sqlite3_snprintf() works like snprintf() except that it ignores the
+** current locale settings. This is important for SQLite because we
+** are not able to use a "," as the decimal point in place of "." as
+** specified by some locales.
+**
+** Oops: The first two arguments of sqlite3_snprintf() are backwards
+** from the snprintf() standard. Unfortunately, it is too late to change
+** this without breaking compatibility, so we just have to live with the
+** mistake.
+**
+** sqlite3_vsnprintf() is the varargs version.
+*/
+SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
+ StrAccum acc;
+ if( n<=0 ) return zBuf;
+ sqlite3StrAccumInit(&acc, zBuf, n, 0);
+ acc.useMalloc = 0;
+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
+ return sqlite3StrAccumFinish(&acc);
+}
+SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
+ char *z;
+ va_list ap;
+ va_start(ap,zFormat);
+ z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
+ va_end(ap);
+ return z;
+}
+
+/*
+** This is the routine that actually formats the sqlite3_log() message.
+** We house it in a separate routine from sqlite3_log() to avoid using
+** stack space on small-stack systems when logging is disabled.
+**
+** sqlite3_log() must render into a static buffer. It cannot dynamically
+** allocate memory because it might be called while the memory allocator
+** mutex is held.
+*/
+static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
+ StrAccum acc; /* String accumulator */
+ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
+
+ sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
+ acc.useMalloc = 0;
+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
+ sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
+ sqlite3StrAccumFinish(&acc));
+}
+
+/*
+** Format and write a message to the log if logging is enabled.
+*/
+SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
+ va_list ap; /* Vararg list */
+ if( sqlite3GlobalConfig.xLog ){
+ va_start(ap, zFormat);
+ renderLogMsg(iErrCode, zFormat, ap);
+ va_end(ap);
+ }
+}
+
+#if defined(SQLITE_DEBUG)
+/*
+** A version of printf() that understands %lld. Used for debugging.
+** The printf() built into some versions of windows does not understand %lld
+** and segfaults if you give it a long long int.
+*/
+SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
+ va_list ap;
+ StrAccum acc;
+ char zBuf[500];
+ sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
+ acc.useMalloc = 0;
+ va_start(ap,zFormat);
+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
+ va_end(ap);
+ sqlite3StrAccumFinish(&acc);
+ fprintf(stdout,"%s", zBuf);
+ fflush(stdout);
+}
+#endif
+
+#ifndef SQLITE_OMIT_TRACE
+/*
+** variable-argument wrapper around sqlite3VXPrintf().
+*/
+SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
+ va_list ap;
+ va_start(ap,zFormat);
+ sqlite3VXPrintf(p, 1, zFormat, ap);
+ va_end(ap);
+}
+#endif
+
+/************** End of printf.c **********************************************/
+/************** Begin file random.c ******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code to implement a pseudo-random number
+** generator (PRNG) for SQLite.
+**
+** Random numbers are used by some of the database backends in order
+** to generate random integer keys for tables or random filenames.
+*/
+
+
+/* All threads share a single random number generator.
+** This structure is the current state of the generator.
+*/
+static SQLITE_WSD struct sqlite3PrngType {
+ unsigned char isInit; /* True if initialized */
+ unsigned char i, j; /* State variables */
+ unsigned char s[256]; /* State variables */
+} sqlite3Prng;
+
+/*
+** Get a single 8-bit random value from the RC4 PRNG. The Mutex
+** must be held while executing this routine.
+**
+** Why not just use a library random generator like lrand48() for this?
+** Because the OP_NewRowid opcode in the VDBE depends on having a very
+** good source of random numbers. The lrand48() library function may
+** well be good enough. But maybe not. Or maybe lrand48() has some
+** subtle problems on some systems that could cause problems. It is hard
+** to know. To minimize the risk of problems due to bad lrand48()
+** implementations, SQLite uses this random number generator based
+** on RC4, which we know works very well.
+**
+** (Later): Actually, OP_NewRowid does not depend on a good source of
+** randomness any more. But we will leave this code in all the same.
+*/
+static u8 randomByte(void){
+ unsigned char t;
+
+
+ /* The "wsdPrng" macro will resolve to the pseudo-random number generator
+ ** state vector. If writable static data is unsupported on the target,
+ ** we have to locate the state vector at run-time. In the more common
+ ** case where writable static data is supported, wsdPrng can refer directly
+ ** to the "sqlite3Prng" state vector declared above.
+ */
+#ifdef SQLITE_OMIT_WSD
+ struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
+# define wsdPrng p[0]
+#else
+# define wsdPrng sqlite3Prng
+#endif
+
+
+ /* Initialize the state of the random number generator once,
+ ** the first time this routine is called. The seed value does
+ ** not need to contain a lot of randomness since we are not
+ ** trying to do secure encryption or anything like that...
+ **
+ ** Nothing in this file or anywhere else in SQLite does any kind of
+ ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
+ ** number generator) not as an encryption device.
+ */
+ if( !wsdPrng.isInit ){
+ int i;
+ char k[256];
+ wsdPrng.j = 0;
+ wsdPrng.i = 0;
+ sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
+ for(i=0; i<256; i++){
+ wsdPrng.s[i] = (u8)i;
+ }
+ for(i=0; i<256; i++){
+ wsdPrng.j += wsdPrng.s[i] + k[i];
+ t = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
+ wsdPrng.s[i] = t;
+ }
+ wsdPrng.isInit = 1;
+ }
+
+ /* Generate and return single random byte
+ */
+ wsdPrng.i++;
+ t = wsdPrng.s[wsdPrng.i];
+ wsdPrng.j += t;
+ wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = t;
+ t += wsdPrng.s[wsdPrng.i];
+ return wsdPrng.s[t];
+}
+
+/*
+** Return N random bytes.
+*/
+SQLITE_API void sqlite3_randomness(int N, void *pBuf){
+ unsigned char *zBuf = pBuf;
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
+#endif
+ sqlite3_mutex_enter(mutex);
+ while( N-- ){
+ *(zBuf++) = randomByte();
+ }
+ sqlite3_mutex_leave(mutex);
+}
+
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+/*
+** For testing purposes, we sometimes want to preserve the state of
+** PRNG and restore the PRNG to its saved state at a later time, or
+** to reset the PRNG to its initial state. These routines accomplish
+** those tasks.
+**
+** The sqlite3_test_control() interface calls these routines to
+** control the PRNG.
+*/
+static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
+SQLITE_PRIVATE void sqlite3PrngSaveState(void){
+ memcpy(
+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+ sizeof(sqlite3Prng)
+ );
+}
+SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
+ memcpy(
+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+ sizeof(sqlite3Prng)
+ );
+}
+SQLITE_PRIVATE void sqlite3PrngResetState(void){
+ GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
+}
+#endif /* SQLITE_OMIT_BUILTIN_TEST */
+
+/************** End of random.c **********************************************/
+/************** Begin file utf.c *********************************************/
+/*
+** 2004 April 13
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains routines used to translate between UTF-8,
+** UTF-16, UTF-16BE, and UTF-16LE.
+**
+** Notes on UTF-8:
+**
+** Byte-0 Byte-1 Byte-2 Byte-3 Value
+** 0xxxxxxx 00000000 00000000 0xxxxxxx
+** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx
+** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx
+** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx
+**
+**
+** Notes on UTF-16: (with wwww+1==uuuuu)
+**
+** Word-0 Word-1 Value
+** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx
+** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx
+**
+**
+** BOM or Byte Order Mark:
+** 0xff 0xfe little-endian utf-16 follows
+** 0xfe 0xff big-endian utf-16 follows
+**
+*/
+/* #include <assert.h> */
+
+#ifndef SQLITE_AMALGAMATION
+/*
+** The following constant value is used by the SQLITE_BIGENDIAN and
+** SQLITE_LITTLEENDIAN macros.
+*/
+SQLITE_PRIVATE const int sqlite3one = 1;
+#endif /* SQLITE_AMALGAMATION */
+
+/*
+** This lookup table is used to help decode the first byte of
+** a multi-byte UTF8 character.
+*/
+static const unsigned char sqlite3Utf8Trans1[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
+};
+
+
+#define WRITE_UTF8(zOut, c) { \
+ if( c<0x00080 ){ \
+ *zOut++ = (u8)(c&0xFF); \
+ } \
+ else if( c<0x00800 ){ \
+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ } \
+ else if( c<0x10000 ){ \
+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ }else{ \
+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ } \
+}
+
+#define WRITE_UTF16LE(zOut, c) { \
+ if( c<=0xFFFF ){ \
+ *zOut++ = (u8)(c&0x00FF); \
+ *zOut++ = (u8)((c>>8)&0x00FF); \
+ }else{ \
+ *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
+ *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
+ *zOut++ = (u8)(c&0x00FF); \
+ *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
+ } \
+}
+
+#define WRITE_UTF16BE(zOut, c) { \
+ if( c<=0xFFFF ){ \
+ *zOut++ = (u8)((c>>8)&0x00FF); \
+ *zOut++ = (u8)(c&0x00FF); \
+ }else{ \
+ *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
+ *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
+ *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
+ *zOut++ = (u8)(c&0x00FF); \
+ } \
+}
+
+#define READ_UTF16LE(zIn, TERM, c){ \
+ c = (*zIn++); \
+ c += ((*zIn++)<<8); \
+ if( c>=0xD800 && c<0xE000 && TERM ){ \
+ int c2 = (*zIn++); \
+ c2 += ((*zIn++)<<8); \
+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
+ } \
+}
+
+#define READ_UTF16BE(zIn, TERM, c){ \
+ c = ((*zIn++)<<8); \
+ c += (*zIn++); \
+ if( c>=0xD800 && c<0xE000 && TERM ){ \
+ int c2 = ((*zIn++)<<8); \
+ c2 += (*zIn++); \
+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
+ } \
+}
+
+/*
+** Translate a single UTF-8 character. Return the unicode value.
+**
+** During translation, assume that the byte that zTerm points
+** is a 0x00.
+**
+** Write a pointer to the next unread byte back into *pzNext.
+**
+** Notes On Invalid UTF-8:
+**
+** * This routine never allows a 7-bit character (0x00 through 0x7f) to
+** be encoded as a multi-byte character. Any multi-byte character that
+** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
+**
+** * This routine never allows a UTF16 surrogate value to be encoded.
+** If a multi-byte character attempts to encode a value between
+** 0xd800 and 0xe000 then it is rendered as 0xfffd.
+**
+** * Bytes in the range of 0x80 through 0xbf which occur as the first
+** byte of a character are interpreted as single-byte characters
+** and rendered as themselves even though they are technically
+** invalid characters.
+**
+** * This routine accepts an infinite number of different UTF8 encodings
+** for unicode values 0x80 and greater. It do not change over-length
+** encodings to 0xfffd as some systems recommend.
+*/
+#define READ_UTF8(zIn, zTerm, c) \
+ c = *(zIn++); \
+ if( c>=0xc0 ){ \
+ c = sqlite3Utf8Trans1[c-0xc0]; \
+ while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ c = (c<<6) + (0x3f & *(zIn++)); \
+ } \
+ if( c<0x80 \
+ || (c&0xFFFFF800)==0xD800 \
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
+ }
+SQLITE_PRIVATE u32 sqlite3Utf8Read(
+ const unsigned char **pz /* Pointer to string from which to read char */
+){
+ unsigned int c;
+
+ /* Same as READ_UTF8() above but without the zTerm parameter.
+ ** For this routine, we assume the UTF8 string is always zero-terminated.
+ */
+ c = *((*pz)++);
+ if( c>=0xc0 ){
+ c = sqlite3Utf8Trans1[c-0xc0];
+ while( (*(*pz) & 0xc0)==0x80 ){
+ c = (c<<6) + (0x3f & *((*pz)++));
+ }
+ if( c<0x80
+ || (c&0xFFFFF800)==0xD800
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
+ }
+ return c;
+}
+
+
+
+
+/*
+** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
+** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
+*/
+/* #define TRANSLATE_TRACE 1 */
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** This routine transforms the internal text encoding used by pMem to
+** desiredEnc. It is an error if the string is already of the desired
+** encoding, or if *pMem does not contain a string value.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
+ int len; /* Maximum length of output string in bytes */
+ unsigned char *zOut; /* Output buffer */
+ unsigned char *zIn; /* Input iterator */
+ unsigned char *zTerm; /* End of input */
+ unsigned char *z; /* Output iterator */
+ unsigned int c;
+
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( pMem->flags&MEM_Str );
+ assert( pMem->enc!=desiredEnc );
+ assert( pMem->enc!=0 );
+ assert( pMem->n>=0 );
+
+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
+ {
+ char zBuf[100];
+ sqlite3VdbeMemPrettyPrint(pMem, zBuf);
+ fprintf(stderr, "INPUT: %s\n", zBuf);
+ }
+#endif
+
+ /* If the translation is between UTF-16 little and big endian, then
+ ** all that is required is to swap the byte order. This case is handled
+ ** differently from the others.
+ */
+ if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
+ u8 temp;
+ int rc;
+ rc = sqlite3VdbeMemMakeWriteable(pMem);
+ if( rc!=SQLITE_OK ){
+ assert( rc==SQLITE_NOMEM );
+ return SQLITE_NOMEM;
+ }
+ zIn = (u8*)pMem->z;
+ zTerm = &zIn[pMem->n&~1];
+ while( zIn<zTerm ){
+ temp = *zIn;
+ *zIn = *(zIn+1);
+ zIn++;
+ *zIn++ = temp;
+ }
+ pMem->enc = desiredEnc;
+ goto translate_out;
+ }
+
+ /* Set len to the maximum number of bytes required in the output buffer. */
+ if( desiredEnc==SQLITE_UTF8 ){
+ /* When converting from UTF-16, the maximum growth results from
+ ** translating a 2-byte character to a 4-byte UTF-8 character.
+ ** A single byte is required for the output string
+ ** nul-terminator.
+ */
+ pMem->n &= ~1;
+ len = pMem->n * 2 + 1;
+ }else{
+ /* When converting from UTF-8 to UTF-16 the maximum growth is caused
+ ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
+ ** character. Two bytes are required in the output buffer for the
+ ** nul-terminator.
+ */
+ len = pMem->n * 2 + 2;
+ }
+
+ /* Set zIn to point at the start of the input buffer and zTerm to point 1
+ ** byte past the end.
+ **
+ ** Variable zOut is set to point at the output buffer, space obtained
+ ** from sqlite3_malloc().
+ */
+ zIn = (u8*)pMem->z;
+ zTerm = &zIn[pMem->n];
+ zOut = sqlite3DbMallocRaw(pMem->db, len);
+ if( !zOut ){
+ return SQLITE_NOMEM;
+ }
+ z = zOut;
+
+ if( pMem->enc==SQLITE_UTF8 ){
+ if( desiredEnc==SQLITE_UTF16LE ){
+ /* UTF-8 -> UTF-16 Little-endian */
+ while( zIn<zTerm ){
+ READ_UTF8(zIn, zTerm, c);
+ WRITE_UTF16LE(z, c);
+ }
+ }else{
+ assert( desiredEnc==SQLITE_UTF16BE );
+ /* UTF-8 -> UTF-16 Big-endian */
+ while( zIn<zTerm ){
+ READ_UTF8(zIn, zTerm, c);
+ WRITE_UTF16BE(z, c);
+ }
+ }
+ pMem->n = (int)(z - zOut);
+ *z++ = 0;
+ }else{
+ assert( desiredEnc==SQLITE_UTF8 );
+ if( pMem->enc==SQLITE_UTF16LE ){
+ /* UTF-16 Little-endian -> UTF-8 */
+ while( zIn<zTerm ){
+ READ_UTF16LE(zIn, zIn<zTerm, c);
+ WRITE_UTF8(z, c);
+ }
+ }else{
+ /* UTF-16 Big-endian -> UTF-8 */
+ while( zIn<zTerm ){
+ READ_UTF16BE(zIn, zIn<zTerm, c);
+ WRITE_UTF8(z, c);
+ }
+ }
+ pMem->n = (int)(z - zOut);
+ }
+ *z = 0;
+ assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
+
+ sqlite3VdbeMemRelease(pMem);
+ pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
+ pMem->enc = desiredEnc;
+ pMem->flags |= (MEM_Term|MEM_Dyn);
+ pMem->z = (char*)zOut;
+ pMem->zMalloc = pMem->z;
+
+translate_out:
+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
+ {
+ char zBuf[100];
+ sqlite3VdbeMemPrettyPrint(pMem, zBuf);
+ fprintf(stderr, "OUTPUT: %s\n", zBuf);
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** This routine checks for a byte-order mark at the beginning of the
+** UTF-16 string stored in *pMem. If one is present, it is removed and
+** the encoding of the Mem adjusted. This routine does not do any
+** byte-swapping, it just sets Mem.enc appropriately.
+**
+** The allocation (static, dynamic etc.) and encoding of the Mem may be
+** changed by this function.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
+ int rc = SQLITE_OK;
+ u8 bom = 0;
+
+ assert( pMem->n>=0 );
+ if( pMem->n>1 ){
+ u8 b1 = *(u8 *)pMem->z;
+ u8 b2 = *(((u8 *)pMem->z) + 1);
+ if( b1==0xFE && b2==0xFF ){
+ bom = SQLITE_UTF16BE;
+ }
+ if( b1==0xFF && b2==0xFE ){
+ bom = SQLITE_UTF16LE;
+ }
+ }
+
+ if( bom ){
+ rc = sqlite3VdbeMemMakeWriteable(pMem);
+ if( rc==SQLITE_OK ){
+ pMem->n -= 2;
+ memmove(pMem->z, &pMem->z[2], pMem->n);
+ pMem->z[pMem->n] = '\0';
+ pMem->z[pMem->n+1] = '\0';
+ pMem->flags |= MEM_Term;
+ pMem->enc = bom;
+ }
+ }
+ return rc;
+}
+#endif /* SQLITE_OMIT_UTF16 */
+
+/*
+** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
+** return the number of unicode characters in pZ up to (but not including)
+** the first 0x00 byte. If nByte is not less than zero, return the
+** number of unicode characters in the first nByte of pZ (or up to
+** the first 0x00, whichever comes first).
+*/
+SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
+ int r = 0;
+ const u8 *z = (const u8*)zIn;
+ const u8 *zTerm;
+ if( nByte>=0 ){
+ zTerm = &z[nByte];
+ }else{
+ zTerm = (const u8*)(-1);
+ }
+ assert( z<=zTerm );
+ while( *z!=0 && z<zTerm ){
+ SQLITE_SKIP_UTF8(z);
+ r++;
+ }
+ return r;
+}
+
+/* This test function is not currently used by the automated test-suite.
+** Hence it is only available in debug builds.
+*/
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+/*
+** Translate UTF-8 to UTF-8.
+**
+** This has the effect of making sure that the string is well-formed
+** UTF-8. Miscoded characters are removed.
+**
+** The translation is done in-place and aborted if the output
+** overruns the input.
+*/
+SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
+ unsigned char *zOut = zIn;
+ unsigned char *zStart = zIn;
+ u32 c;
+
+ while( zIn[0] && zOut<=zIn ){
+ c = sqlite3Utf8Read((const u8**)&zIn);
+ if( c!=0xfffd ){
+ WRITE_UTF8(zOut, c);
+ }
+ }
+ *zOut = 0;
+ return (int)(zOut - zStart);
+}
+#endif
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Convert a UTF-16 string in the native encoding into a UTF-8 string.
+** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
+** be freed by the calling function.
+**
+** NULL is returned if there is an allocation error.
+*/
+SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
+ Mem m;
+ memset(&m, 0, sizeof(m));
+ m.db = db;
+ sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
+ sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
+ if( db->mallocFailed ){
+ sqlite3VdbeMemRelease(&m);
+ m.z = 0;
+ }
+ assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
+ assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
+ assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
+ assert( m.z || db->mallocFailed );
+ return m.z;
+}
+
+/*
+** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
+** enc. A pointer to the new string is returned, and the value of *pnOut
+** is set to the length of the returned string in bytes. The call should
+** arrange to call sqlite3DbFree() on the returned pointer when it is
+** no longer required.
+**
+** If a malloc failure occurs, NULL is returned and the db.mallocFailed
+** flag set.
+*/
+#ifdef SQLITE_ENABLE_STAT3
+SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
+ Mem m;
+ memset(&m, 0, sizeof(m));
+ m.db = db;
+ sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
+ if( sqlite3VdbeMemTranslate(&m, enc) ){
+ assert( db->mallocFailed );
+ return 0;
+ }
+ assert( m.z==m.zMalloc );
+ *pnOut = m.n;
+ return m.z;
+}
+#endif
+
+/*
+** zIn is a UTF-16 encoded unicode string at least nChar characters long.
+** Return the number of bytes in the first nChar unicode characters
+** in pZ. nChar must be non-negative.
+*/
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
+ int c;
+ unsigned char const *z = zIn;
+ int n = 0;
+
+ if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
+ while( n<nChar ){
+ READ_UTF16BE(z, 1, c);
+ n++;
+ }
+ }else{
+ while( n<nChar ){
+ READ_UTF16LE(z, 1, c);
+ n++;
+ }
+ }
+ return (int)(z-(unsigned char const *)zIn);
+}
+
+#if defined(SQLITE_TEST)
+/*
+** This routine is called from the TCL test function "translate_selftest".
+** It checks that the primitives for serializing and deserializing
+** characters in each encoding are inverses of each other.
+*/
+SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
+ unsigned int i, t;
+ unsigned char zBuf[20];
+ unsigned char *z;
+ int n;
+ unsigned int c;
+
+ for(i=0; i<0x00110000; i++){
+ z = zBuf;
+ WRITE_UTF8(z, i);
+ n = (int)(z-zBuf);
+ assert( n>0 && n<=4 );
+ z[0] = 0;
+ z = zBuf;
+ c = sqlite3Utf8Read((const u8**)&z);
+ t = i;
+ if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
+ if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
+ assert( c==t );
+ assert( (z-zBuf)==n );
+ }
+ for(i=0; i<0x00110000; i++){
+ if( i>=0xD800 && i<0xE000 ) continue;
+ z = zBuf;
+ WRITE_UTF16LE(z, i);
+ n = (int)(z-zBuf);
+ assert( n>0 && n<=4 );
+ z[0] = 0;
+ z = zBuf;
+ READ_UTF16LE(z, 1, c);
+ assert( c==i );
+ assert( (z-zBuf)==n );
+ }
+ for(i=0; i<0x00110000; i++){
+ if( i>=0xD800 && i<0xE000 ) continue;
+ z = zBuf;
+ WRITE_UTF16BE(z, i);
+ n = (int)(z-zBuf);
+ assert( n>0 && n<=4 );
+ z[0] = 0;
+ z = zBuf;
+ READ_UTF16BE(z, 1, c);
+ assert( c==i );
+ assert( (z-zBuf)==n );
+ }
+}
+#endif /* SQLITE_TEST */
+#endif /* SQLITE_OMIT_UTF16 */
+
+/************** End of utf.c *************************************************/
+/************** Begin file util.c ********************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Utility functions used throughout sqlite.
+**
+** This file contains functions for allocating memory, comparing
+** strings, and stuff like that.
+**
+*/
+/* #include <stdarg.h> */
+#ifdef SQLITE_HAVE_ISNAN
+# include <math.h>
+#endif
+
+/*
+** Routine needed to support the testcase() macro.
+*/
+#ifdef SQLITE_COVERAGE_TEST
+SQLITE_PRIVATE void sqlite3Coverage(int x){
+ static unsigned dummy = 0;
+ dummy += (unsigned)x;
+}
+#endif
+
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/*
+** Return true if the floating point value is Not a Number (NaN).
+**
+** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
+** Otherwise, we have our own implementation that works on most systems.
+*/
+SQLITE_PRIVATE int sqlite3IsNaN(double x){
+ int rc; /* The value return */
+#if !defined(SQLITE_HAVE_ISNAN)
+ /*
+ ** Systems that support the isnan() library function should probably
+ ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
+ ** found that many systems do not have a working isnan() function so
+ ** this implementation is provided as an alternative.
+ **
+ ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
+ ** On the other hand, the use of -ffast-math comes with the following
+ ** warning:
+ **
+ ** This option [-ffast-math] should never be turned on by any
+ ** -O option since it can result in incorrect output for programs
+ ** which depend on an exact implementation of IEEE or ISO
+ ** rules/specifications for math functions.
+ **
+ ** Under MSVC, this NaN test may fail if compiled with a floating-
+ ** point precision mode other than /fp:precise. From the MSDN
+ ** documentation:
+ **
+ ** The compiler [with /fp:precise] will properly handle comparisons
+ ** involving NaN. For example, x != x evaluates to true if x is NaN
+ ** ...
+ */
+#ifdef __FAST_MATH__
+# error SQLite will not work correctly with the -ffast-math option of GCC.
+#endif
+ volatile double y = x;
+ volatile double z = y;
+ rc = (y!=z);
+#else /* if defined(SQLITE_HAVE_ISNAN) */
+ rc = isnan(x);
+#endif /* SQLITE_HAVE_ISNAN */
+ testcase( rc );
+ return rc;
+}
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+
+/*
+** Compute a string length that is limited to what can be stored in
+** lower 30 bits of a 32-bit signed integer.
+**
+** The value returned will never be negative. Nor will it ever be greater
+** than the actual length of the string. For very long strings (greater
+** than 1GiB) the value returned might be less than the true string length.
+*/
+SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
+ const char *z2 = z;
+ if( z==0 ) return 0;
+ while( *z2 ){ z2++; }
+ return 0x3fffffff & (int)(z2 - z);
+}
+
+/*
+** Set the most recent error code and error string for the sqlite
+** handle "db". The error code is set to "err_code".
+**
+** If it is not NULL, string zFormat specifies the format of the
+** error string in the style of the printf functions: The following
+** format characters are allowed:
+**
+** %s Insert a string
+** %z A string that should be freed after use
+** %d Insert an integer
+** %T Insert a token
+** %S Insert the first element of a SrcList
+**
+** zFormat and any string tokens that follow it are assumed to be
+** encoded in UTF-8.
+**
+** To clear the most recent error for sqlite handle "db", sqlite3Error
+** should be called with err_code set to SQLITE_OK and zFormat set
+** to NULL.
+*/
+SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
+ if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
+ db->errCode = err_code;
+ if( zFormat ){
+ char *z;
+ va_list ap;
+ va_start(ap, zFormat);
+ z = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
+ }else{
+ sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
+ }
+ }
+}
+
+/*
+** Add an error message to pParse->zErrMsg and increment pParse->nErr.
+** The following formatting characters are allowed:
+**
+** %s Insert a string
+** %z A string that should be freed after use
+** %d Insert an integer
+** %T Insert a token
+** %S Insert the first element of a SrcList
+**
+** This function should be used to report any error that occurs whilst
+** compiling an SQL statement (i.e. within sqlite3_prepare()). The
+** last thing the sqlite3_prepare() function does is copy the error
+** stored by this function into the database handle using sqlite3Error().
+** Function sqlite3Error() should be used during statement execution
+** (sqlite3_step() etc.).
+*/
+SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
+ char *zMsg;
+ va_list ap;
+ sqlite3 *db = pParse->db;
+ va_start(ap, zFormat);
+ zMsg = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ if( db->suppressErr ){
+ sqlite3DbFree(db, zMsg);
+ }else{
+ pParse->nErr++;
+ sqlite3DbFree(db, pParse->zErrMsg);
+ pParse->zErrMsg = zMsg;
+ pParse->rc = SQLITE_ERROR;
+ }
+}
+
+/*
+** Convert an SQL-style quoted string into a normal string by removing
+** the quote characters. The conversion is done in-place. If the
+** input does not begin with a quote character, then this routine
+** is a no-op.
+**
+** The input string must be zero-terminated. A new zero-terminator
+** is added to the dequoted string.
+**
+** The return value is -1 if no dequoting occurs or the length of the
+** dequoted string, exclusive of the zero terminator, if dequoting does
+** occur.
+**
+** 2002-Feb-14: This routine is extended to remove MS-Access style
+** brackets from around identifers. For example: "[a-b-c]" becomes
+** "a-b-c".
+*/
+SQLITE_PRIVATE int sqlite3Dequote(char *z){
+ char quote;
+ int i, j;
+ if( z==0 ) return -1;
+ quote = z[0];
+ switch( quote ){
+ case '\'': break;
+ case '"': break;
+ case '`': break; /* For MySQL compatibility */
+ case '[': quote = ']'; break; /* For MS SqlServer compatibility */
+ default: return -1;
+ }
+ for(i=1, j=0; ALWAYS(z[i]); i++){
+ if( z[i]==quote ){
+ if( z[i+1]==quote ){
+ z[j++] = quote;
+ i++;
+ }else{
+ break;
+ }
+ }else{
+ z[j++] = z[i];
+ }
+ }
+ z[j] = 0;
+ return j;
+}
+
+/* Convenient short-hand */
+#define UpperToLower sqlite3UpperToLower
+
+/*
+** Some systems have stricmp(). Others have strcasecmp(). Because
+** there is no consistency, we will define our own.
+**
+** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
+** sqlite3_strnicmp() APIs allow applications and extensions to compare
+** the contents of two buffers containing UTF-8 strings in a
+** case-independent fashion, using the same definition of "case
+** independence" that SQLite uses internally when comparing identifiers.
+*/
+SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
+ register unsigned char *a, *b;
+ a = (unsigned char *)zLeft;
+ b = (unsigned char *)zRight;
+ while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
+ return UpperToLower[*a] - UpperToLower[*b];
+}
+SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
+ register unsigned char *a, *b;
+ a = (unsigned char *)zLeft;
+ b = (unsigned char *)zRight;
+ while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
+ return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
+}
+
+/*
+** The string z[] is an text representation of a real number.
+** Convert this string to a double and write it into *pResult.
+**
+** The string z[] is length bytes in length (bytes, not characters) and
+** uses the encoding enc. The string is not necessarily zero-terminated.
+**
+** Return TRUE if the result is a valid real number (or integer) and FALSE
+** if the string is empty or contains extraneous text. Valid numbers
+** are in one of these formats:
+**
+** [+-]digits[E[+-]digits]
+** [+-]digits.[digits][E[+-]digits]
+** [+-].digits[E[+-]digits]
+**
+** Leading and trailing whitespace is ignored for the purpose of determining
+** validity.
+**
+** If some prefix of the input string is a valid number, this routine
+** returns FALSE but it still converts the prefix and writes the result
+** into *pResult.
+*/
+SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ int incr;
+ const char *zEnd = z + length;
+ /* sign * significand * (10 ^ (esign * exponent)) */
+ int sign = 1; /* sign of significand */
+ i64 s = 0; /* significand */
+ int d = 0; /* adjust exponent for shifting decimal point */
+ int esign = 1; /* sign of exponent */
+ int e = 0; /* exponent */
+ int eValid = 1; /* True exponent is either not used or is well-formed */
+ double result;
+ int nDigits = 0;
+ int nonNum = 0;
+
+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+ *pResult = 0.0; /* Default return value, in case of an error */
+
+ if( enc==SQLITE_UTF8 ){
+ incr = 1;
+ }else{
+ int i;
+ incr = 2;
+ assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+ for(i=3-enc; i<length && z[i]==0; i+=2){}
+ nonNum = i<length;
+ zEnd = z+i+enc-3;
+ z += (enc&1);
+ }
+
+ /* skip leading spaces */
+ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
+ if( z>=zEnd ) return 0;
+
+ /* get sign of significand */
+ if( *z=='-' ){
+ sign = -1;
+ z+=incr;
+ }else if( *z=='+' ){
+ z+=incr;
+ }
+
+ /* skip leading zeroes */
+ while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
+
+ /* copy max significant digits to significand */
+ while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
+ s = s*10 + (*z - '0');
+ z+=incr, nDigits++;
+ }
+
+ /* skip non-significant significand digits
+ ** (increase exponent by d to shift decimal left) */
+ while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
+ if( z>=zEnd ) goto do_atof_calc;
+
+ /* if decimal point is present */
+ if( *z=='.' ){
+ z+=incr;
+ /* copy digits from after decimal to significand
+ ** (decrease exponent by d to shift decimal right) */
+ while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
+ s = s*10 + (*z - '0');
+ z+=incr, nDigits++, d--;
+ }
+ /* skip non-significant digits */
+ while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
+ }
+ if( z>=zEnd ) goto do_atof_calc;
+
+ /* if exponent is present */
+ if( *z=='e' || *z=='E' ){
+ z+=incr;
+ eValid = 0;
+ if( z>=zEnd ) goto do_atof_calc;
+ /* get sign of exponent */
+ if( *z=='-' ){
+ esign = -1;
+ z+=incr;
+ }else if( *z=='+' ){
+ z+=incr;
+ }
+ /* copy digits to exponent */
+ while( z<zEnd && sqlite3Isdigit(*z) ){
+ e = e<10000 ? (e*10 + (*z - '0')) : 10000;
+ z+=incr;
+ eValid = 1;
+ }
+ }
+
+ /* skip trailing spaces */
+ if( nDigits && eValid ){
+ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
+ }
+
+do_atof_calc:
+ /* adjust exponent by d, and update sign */
+ e = (e*esign) + d;
+ if( e<0 ) {
+ esign = -1;
+ e *= -1;
+ } else {
+ esign = 1;
+ }
+
+ /* if 0 significand */
+ if( !s ) {
+ /* In the IEEE 754 standard, zero is signed.
+ ** Add the sign if we've seen at least one digit */
+ result = (sign<0 && nDigits) ? -(double)0 : (double)0;
+ } else {
+ /* attempt to reduce exponent */
+ if( esign>0 ){
+ while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
+ }else{
+ while( !(s%10) && e>0 ) e--,s/=10;
+ }
+
+ /* adjust the sign of significand */
+ s = sign<0 ? -s : s;
+
+ /* if exponent, scale significand as appropriate
+ ** and store in result. */
+ if( e ){
+ LONGDOUBLE_TYPE scale = 1.0;
+ /* attempt to handle extremely small/large numbers better */
+ if( e>307 && e<342 ){
+ while( e%308 ) { scale *= 1.0e+1; e -= 1; }
+ if( esign<0 ){
+ result = s / scale;
+ result /= 1.0e+308;
+ }else{
+ result = s * scale;
+ result *= 1.0e+308;
+ }
+ }else if( e>=342 ){
+ if( esign<0 ){
+ result = 0.0*s;
+ }else{
+ result = 1e308*1e308*s; /* Infinity */
+ }
+ }else{
+ /* 1.0e+22 is the largest power of 10 than can be
+ ** represented exactly. */
+ while( e%22 ) { scale *= 1.0e+1; e -= 1; }
+ while( e>0 ) { scale *= 1.0e+22; e -= 22; }
+ if( esign<0 ){
+ result = s / scale;
+ }else{
+ result = s * scale;
+ }
+ }
+ } else {
+ result = (double)s;
+ }
+ }
+
+ /* store the result */
+ *pResult = result;
+
+ /* return true if number and no extra non-whitespace chracters after */
+ return z>=zEnd && nDigits>0 && eValid && nonNum==0;
+#else
+ return !sqlite3Atoi64(z, pResult, length, enc);
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+}
+
+/*
+** Compare the 19-character string zNum against the text representation
+** value 2^63: 9223372036854775808. Return negative, zero, or positive
+** if zNum is less than, equal to, or greater than the string.
+** Note that zNum must contain exactly 19 characters.
+**
+** Unlike memcmp() this routine is guaranteed to return the difference
+** in the values of the last digit if the only difference is in the
+** last digit. So, for example,
+**
+** compare2pow63("9223372036854775800", 1)
+**
+** will return -8.
+*/
+static int compare2pow63(const char *zNum, int incr){
+ int c = 0;
+ int i;
+ /* 012345678901234567 */
+ const char *pow63 = "922337203685477580";
+ for(i=0; c==0 && i<18; i++){
+ c = (zNum[i*incr]-pow63[i])*10;
+ }
+ if( c==0 ){
+ c = zNum[18*incr] - '8';
+ testcase( c==(-1) );
+ testcase( c==0 );
+ testcase( c==(+1) );
+ }
+ return c;
+}
+
+
+/*
+** Convert zNum to a 64-bit signed integer.
+**
+** If the zNum value is representable as a 64-bit twos-complement
+** integer, then write that value into *pNum and return 0.
+**
+** If zNum is exactly 9223372036854665808, return 2. This special
+** case is broken out because while 9223372036854665808 cannot be a
+** signed 64-bit integer, its negative -9223372036854665808 can be.
+**
+** If zNum is too big for a 64-bit integer and is not
+** 9223372036854665808 or if zNum contains any non-numeric text,
+** then return 1.
+**
+** length is the number of bytes in the string (bytes, not characters).
+** The string is not necessarily zero-terminated. The encoding is
+** given by enc.
+*/
+SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
+ int incr;
+ u64 u = 0;
+ int neg = 0; /* assume positive */
+ int i;
+ int c = 0;
+ int nonNum = 0;
+ const char *zStart;
+ const char *zEnd = zNum + length;
+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+ if( enc==SQLITE_UTF8 ){
+ incr = 1;
+ }else{
+ incr = 2;
+ assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+ for(i=3-enc; i<length && zNum[i]==0; i+=2){}
+ nonNum = i<length;
+ zEnd = zNum+i+enc-3;
+ zNum += (enc&1);
+ }
+ while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
+ if( zNum<zEnd ){
+ if( *zNum=='-' ){
+ neg = 1;
+ zNum+=incr;
+ }else if( *zNum=='+' ){
+ zNum+=incr;
+ }
+ }
+ zStart = zNum;
+ while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
+ for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
+ u = u*10 + c - '0';
+ }
+ if( u>LARGEST_INT64 ){
+ *pNum = SMALLEST_INT64;
+ }else if( neg ){
+ *pNum = -(i64)u;
+ }else{
+ *pNum = (i64)u;
+ }
+ testcase( i==18 );
+ testcase( i==19 );
+ testcase( i==20 );
+ if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr || nonNum ){
+ /* zNum is empty or contains non-numeric text or is longer
+ ** than 19 digits (thus guaranteeing that it is too large) */
+ return 1;
+ }else if( i<19*incr ){
+ /* Less than 19 digits, so we know that it fits in 64 bits */
+ assert( u<=LARGEST_INT64 );
+ return 0;
+ }else{
+ /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
+ c = compare2pow63(zNum, incr);
+ if( c<0 ){
+ /* zNum is less than 9223372036854775808 so it fits */
+ assert( u<=LARGEST_INT64 );
+ return 0;
+ }else if( c>0 ){
+ /* zNum is greater than 9223372036854775808 so it overflows */
+ return 1;
+ }else{
+ /* zNum is exactly 9223372036854775808. Fits if negative. The
+ ** special case 2 overflow if positive */
+ assert( u-1==LARGEST_INT64 );
+ assert( (*pNum)==SMALLEST_INT64 );
+ return neg ? 0 : 2;
+ }
+ }
+}
+
+/*
+** If zNum represents an integer that will fit in 32-bits, then set
+** *pValue to that integer and return true. Otherwise return false.
+**
+** Any non-numeric characters that following zNum are ignored.
+** This is different from sqlite3Atoi64() which requires the
+** input number to be zero-terminated.
+*/
+SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
+ sqlite_int64 v = 0;
+ int i, c;
+ int neg = 0;
+ if( zNum[0]=='-' ){
+ neg = 1;
+ zNum++;
+ }else if( zNum[0]=='+' ){
+ zNum++;
+ }
+ while( zNum[0]=='0' ) zNum++;
+ for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
+ v = v*10 + c;
+ }
+
+ /* The longest decimal representation of a 32 bit integer is 10 digits:
+ **
+ ** 1234567890
+ ** 2^31 -> 2147483648
+ */
+ testcase( i==10 );
+ if( i>10 ){
+ return 0;
+ }
+ testcase( v-neg==2147483647 );
+ if( v-neg>2147483647 ){
+ return 0;
+ }
+ if( neg ){
+ v = -v;
+ }
+ *pValue = (int)v;
+ return 1;
+}
+
+/*
+** Return a 32-bit integer value extracted from a string. If the
+** string is not an integer, just return 0.
+*/
+SQLITE_PRIVATE int sqlite3Atoi(const char *z){
+ int x = 0;
+ if( z ) sqlite3GetInt32(z, &x);
+ return x;
+}
+
+/*
+** The variable-length integer encoding is as follows:
+**
+** KEY:
+** A = 0xxxxxxx 7 bits of data and one flag bit
+** B = 1xxxxxxx 7 bits of data and one flag bit
+** C = xxxxxxxx 8 bits of data
+**
+** 7 bits - A
+** 14 bits - BA
+** 21 bits - BBA
+** 28 bits - BBBA
+** 35 bits - BBBBA
+** 42 bits - BBBBBA
+** 49 bits - BBBBBBA
+** 56 bits - BBBBBBBA
+** 64 bits - BBBBBBBBC
+*/
+
+/*
+** Write a 64-bit variable-length integer to memory starting at p[0].
+** The length of data write will be between 1 and 9 bytes. The number
+** of bytes written is returned.
+**
+** A variable-length integer consists of the lower 7 bits of each byte
+** for all bytes that have the 8th bit set and one byte with the 8th
+** bit clear. Except, if we get to the 9th byte, it stores the full
+** 8 bits and is the last byte.
+*/
+SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
+ int i, j, n;
+ u8 buf[10];
+ if( v & (((u64)0xff000000)<<32) ){
+ p[8] = (u8)v;
+ v >>= 8;
+ for(i=7; i>=0; i--){
+ p[i] = (u8)((v & 0x7f) | 0x80);
+ v >>= 7;
+ }
+ return 9;
+ }
+ n = 0;
+ do{
+ buf[n++] = (u8)((v & 0x7f) | 0x80);
+ v >>= 7;
+ }while( v!=0 );
+ buf[0] &= 0x7f;
+ assert( n<=9 );
+ for(i=0, j=n-1; j>=0; j--, i++){
+ p[i] = buf[j];
+ }
+ return n;
+}
+
+/*
+** This routine is a faster version of sqlite3PutVarint() that only
+** works for 32-bit positive integers and which is optimized for
+** the common case of small integers. A MACRO version, putVarint32,
+** is provided which inlines the single-byte case. All code should use
+** the MACRO version as this function assumes the single-byte case has
+** already been handled.
+*/
+SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){
+#ifndef putVarint32
+ if( (v & ~0x7f)==0 ){
+ p[0] = v;
+ return 1;
+ }
+#endif
+ if( (v & ~0x3fff)==0 ){
+ p[0] = (u8)((v>>7) | 0x80);
+ p[1] = (u8)(v & 0x7f);
+ return 2;
+ }
+ return sqlite3PutVarint(p, v);
+}
+
+/*
+** Bitmasks used by sqlite3GetVarint(). These precomputed constants
+** are defined here rather than simply putting the constant expressions
+** inline in order to work around bugs in the RVT compiler.
+**
+** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
+**
+** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
+*/
+#define SLOT_2_0 0x001fc07f
+#define SLOT_4_2_0 0xf01fc07f
+
+
+/*
+** Read a 64-bit variable-length integer from memory starting at p[0].
+** Return the number of bytes read. The value is stored in *v.
+*/
+SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
+ u32 a,b,s;
+
+ a = *p;
+ /* a: p0 (unmasked) */
+ if (!(a&0x80))
+ {
+ *v = a;
+ return 1;
+ }
+
+ p++;
+ b = *p;
+ /* b: p1 (unmasked) */
+ if (!(b&0x80))
+ {
+ a &= 0x7f;
+ a = a<<7;
+ a |= b;
+ *v = a;
+ return 2;
+ }
+
+ /* Verify that constants are precomputed correctly */
+ assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
+ assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ /* a: p0<<14 | p2 (unmasked) */
+ if (!(a&0x80))
+ {
+ a &= SLOT_2_0;
+ b &= 0x7f;
+ b = b<<7;
+ a |= b;
+ *v = a;
+ return 3;
+ }
+
+ /* CSE1 from below */
+ a &= SLOT_2_0;
+ p++;
+ b = b<<14;
+ b |= *p;
+ /* b: p1<<14 | p3 (unmasked) */
+ if (!(b&0x80))
+ {
+ b &= SLOT_2_0;
+ /* moved CSE1 up */
+ /* a &= (0x7f<<14)|(0x7f); */
+ a = a<<7;
+ a |= b;
+ *v = a;
+ return 4;
+ }
+
+ /* a: p0<<14 | p2 (masked) */
+ /* b: p1<<14 | p3 (unmasked) */
+ /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
+ /* moved CSE1 up */
+ /* a &= (0x7f<<14)|(0x7f); */
+ b &= SLOT_2_0;
+ s = a;
+ /* s: p0<<14 | p2 (masked) */
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ /* a: p0<<28 | p2<<14 | p4 (unmasked) */
+ if (!(a&0x80))
+ {
+ /* we can skip these cause they were (effectively) done above in calc'ing s */
+ /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
+ /* b &= (0x7f<<14)|(0x7f); */
+ b = b<<7;
+ a |= b;
+ s = s>>18;
+ *v = ((u64)s)<<32 | a;
+ return 5;
+ }
+
+ /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
+ s = s<<7;
+ s |= b;
+ /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
+
+ p++;
+ b = b<<14;
+ b |= *p;
+ /* b: p1<<28 | p3<<14 | p5 (unmasked) */
+ if (!(b&0x80))
+ {
+ /* we can skip this cause it was (effectively) done above in calc'ing s */
+ /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
+ a &= SLOT_2_0;
+ a = a<<7;
+ a |= b;
+ s = s>>18;
+ *v = ((u64)s)<<32 | a;
+ return 6;
+ }
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ /* a: p2<<28 | p4<<14 | p6 (unmasked) */
+ if (!(a&0x80))
+ {
+ a &= SLOT_4_2_0;
+ b &= SLOT_2_0;
+ b = b<<7;
+ a |= b;
+ s = s>>11;
+ *v = ((u64)s)<<32 | a;
+ return 7;
+ }
+
+ /* CSE2 from below */
+ a &= SLOT_2_0;
+ p++;
+ b = b<<14;
+ b |= *p;
+ /* b: p3<<28 | p5<<14 | p7 (unmasked) */
+ if (!(b&0x80))
+ {
+ b &= SLOT_4_2_0;
+ /* moved CSE2 up */
+ /* a &= (0x7f<<14)|(0x7f); */
+ a = a<<7;
+ a |= b;
+ s = s>>4;
+ *v = ((u64)s)<<32 | a;
+ return 8;
+ }
+
+ p++;
+ a = a<<15;
+ a |= *p;
+ /* a: p4<<29 | p6<<15 | p8 (unmasked) */
+
+ /* moved CSE2 up */
+ /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
+ b &= SLOT_2_0;
+ b = b<<8;
+ a |= b;
+
+ s = s<<4;
+ b = p[-4];
+ b &= 0x7f;
+ b = b>>3;
+ s |= b;
+
+ *v = ((u64)s)<<32 | a;
+
+ return 9;
+}
+
+/*
+** Read a 32-bit variable-length integer from memory starting at p[0].
+** Return the number of bytes read. The value is stored in *v.
+**
+** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
+** integer, then set *v to 0xffffffff.
+**
+** A MACRO version, getVarint32, is provided which inlines the
+** single-byte case. All code should use the MACRO version as
+** this function assumes the single-byte case has already been handled.
+*/
+SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
+ u32 a,b;
+
+ /* The 1-byte case. Overwhelmingly the most common. Handled inline
+ ** by the getVarin32() macro */
+ a = *p;
+ /* a: p0 (unmasked) */
+#ifndef getVarint32
+ if (!(a&0x80))
+ {
+ /* Values between 0 and 127 */
+ *v = a;
+ return 1;
+ }
+#endif
+
+ /* The 2-byte case */
+ p++;
+ b = *p;
+ /* b: p1 (unmasked) */
+ if (!(b&0x80))
+ {
+ /* Values between 128 and 16383 */
+ a &= 0x7f;
+ a = a<<7;
+ *v = a | b;
+ return 2;
+ }
+
+ /* The 3-byte case */
+ p++;
+ a = a<<14;
+ a |= *p;
+ /* a: p0<<14 | p2 (unmasked) */
+ if (!(a&0x80))
+ {
+ /* Values between 16384 and 2097151 */
+ a &= (0x7f<<14)|(0x7f);
+ b &= 0x7f;
+ b = b<<7;
+ *v = a | b;
+ return 3;
+ }
+
+ /* A 32-bit varint is used to store size information in btrees.
+ ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
+ ** A 3-byte varint is sufficient, for example, to record the size
+ ** of a 1048569-byte BLOB or string.
+ **
+ ** We only unroll the first 1-, 2-, and 3- byte cases. The very
+ ** rare larger cases can be handled by the slower 64-bit varint
+ ** routine.
+ */
+#if 1
+ {
+ u64 v64;
+ u8 n;
+
+ p -= 2;
+ n = sqlite3GetVarint(p, &v64);
+ assert( n>3 && n<=9 );
+ if( (v64 & SQLITE_MAX_U32)!=v64 ){
+ *v = 0xffffffff;
+ }else{
+ *v = (u32)v64;
+ }
+ return n;
+ }
+
+#else
+ /* For following code (kept for historical record only) shows an
+ ** unrolling for the 3- and 4-byte varint cases. This code is
+ ** slightly faster, but it is also larger and much harder to test.
+ */
+ p++;
+ b = b<<14;
+ b |= *p;
+ /* b: p1<<14 | p3 (unmasked) */
+ if (!(b&0x80))
+ {
+ /* Values between 2097152 and 268435455 */
+ b &= (0x7f<<14)|(0x7f);
+ a &= (0x7f<<14)|(0x7f);
+ a = a<<7;
+ *v = a | b;
+ return 4;
+ }
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ /* a: p0<<28 | p2<<14 | p4 (unmasked) */
+ if (!(a&0x80))
+ {
+ /* Values between 268435456 and 34359738367 */
+ a &= SLOT_4_2_0;
+ b &= SLOT_4_2_0;
+ b = b<<7;
+ *v = a | b;
+ return 5;
+ }
+
+ /* We can only reach this point when reading a corrupt database
+ ** file. In that case we are not in any hurry. Use the (relatively
+ ** slow) general-purpose sqlite3GetVarint() routine to extract the
+ ** value. */
+ {
+ u64 v64;
+ u8 n;
+
+ p -= 4;
+ n = sqlite3GetVarint(p, &v64);
+ assert( n>5 && n<=9 );
+ *v = (u32)v64;
+ return n;
+ }
+#endif
+}
+
+/*
+** Return the number of bytes that will be needed to store the given
+** 64-bit integer.
+*/
+SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
+ int i = 0;
+ do{
+ i++;
+ v >>= 7;
+ }while( v!=0 && ALWAYS(i<9) );
+ return i;
+}
+
+
+/*
+** Read or write a four-byte big-endian integer value.
+*/
+SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+}
+SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
+ p[0] = (u8)(v>>24);
+ p[1] = (u8)(v>>16);
+ p[2] = (u8)(v>>8);
+ p[3] = (u8)v;
+}
+
+
+
+/*
+** Translate a single byte of Hex into an integer.
+** This routine only works if h really is a valid hexadecimal
+** character: 0..9a..fA..F
+*/
+SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
+ assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
+#ifdef SQLITE_ASCII
+ h += 9*(1&(h>>6));
+#endif
+#ifdef SQLITE_EBCDIC
+ h += 9*(1&~(h>>4));
+#endif
+ return (u8)(h & 0xf);
+}
+
+#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
+/*
+** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
+** value. Return a pointer to its binary value. Space to hold the
+** binary value has been obtained from malloc and must be freed by
+** the calling routine.
+*/
+SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
+ char *zBlob;
+ int i;
+
+ zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
+ n--;
+ if( zBlob ){
+ for(i=0; i<n; i+=2){
+ zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
+ }
+ zBlob[i/2] = 0;
+ }
+ return zBlob;
+}
+#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
+
+/*
+** Log an error that is an API call on a connection pointer that should
+** not have been used. The "type" of connection pointer is given as the
+** argument. The zType is a word like "NULL" or "closed" or "invalid".
+*/
+static void logBadConnection(const char *zType){
+ sqlite3_log(SQLITE_MISUSE,
+ "API call with %s database connection pointer",
+ zType
+ );
+}
+
+/*
+** Check to make sure we have a valid db pointer. This test is not
+** foolproof but it does provide some measure of protection against
+** misuse of the interface such as passing in db pointers that are
+** NULL or which have been previously closed. If this routine returns
+** 1 it means that the db pointer is valid and 0 if it should not be
+** dereferenced for any reason. The calling function should invoke
+** SQLITE_MISUSE immediately.
+**
+** sqlite3SafetyCheckOk() requires that the db pointer be valid for
+** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
+** open properly and is not fit for general use but which can be
+** used as an argument to sqlite3_errmsg() or sqlite3_close().
+*/
+SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
+ u32 magic;
+ if( db==0 ){
+ logBadConnection("NULL");
+ return 0;
+ }
+ magic = db->magic;
+ if( magic!=SQLITE_MAGIC_OPEN ){
+ if( sqlite3SafetyCheckSickOrOk(db) ){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ logBadConnection("unopened");
+ }
+ return 0;
+ }else{
+ return 1;
+ }
+}
+SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
+ u32 magic;
+ magic = db->magic;
+ if( magic!=SQLITE_MAGIC_SICK &&
+ magic!=SQLITE_MAGIC_OPEN &&
+ magic!=SQLITE_MAGIC_BUSY ){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ logBadConnection("invalid");
+ return 0;
+ }else{
+ return 1;
+ }
+}
+
+/*
+** Attempt to add, substract, or multiply the 64-bit signed value iB against
+** the other 64-bit signed integer at *pA and store the result in *pA.
+** Return 0 on success. Or if the operation would have resulted in an
+** overflow, leave *pA unchanged and return 1.
+*/
+SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
+ i64 iA = *pA;
+ testcase( iA==0 ); testcase( iA==1 );
+ testcase( iB==-1 ); testcase( iB==0 );
+ if( iB>=0 ){
+ testcase( iA>0 && LARGEST_INT64 - iA == iB );
+ testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
+ if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
+ *pA += iB;
+ }else{
+ testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
+ testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
+ if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
+ *pA += iB;
+ }
+ return 0;
+}
+SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
+ testcase( iB==SMALLEST_INT64+1 );
+ if( iB==SMALLEST_INT64 ){
+ testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
+ if( (*pA)>=0 ) return 1;
+ *pA -= iB;
+ return 0;
+ }else{
+ return sqlite3AddInt64(pA, -iB);
+ }
+}
+#define TWOPOWER32 (((i64)1)<<32)
+#define TWOPOWER31 (((i64)1)<<31)
+SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
+ i64 iA = *pA;
+ i64 iA1, iA0, iB1, iB0, r;
+
+ iA1 = iA/TWOPOWER32;
+ iA0 = iA % TWOPOWER32;
+ iB1 = iB/TWOPOWER32;
+ iB0 = iB % TWOPOWER32;
+ if( iA1*iB1 != 0 ) return 1;
+ assert( iA1*iB0==0 || iA0*iB1==0 );
+ r = iA1*iB0 + iA0*iB1;
+ testcase( r==(-TWOPOWER31)-1 );
+ testcase( r==(-TWOPOWER31) );
+ testcase( r==TWOPOWER31 );
+ testcase( r==TWOPOWER31-1 );
+ if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
+ r *= TWOPOWER32;
+ if( sqlite3AddInt64(&r, iA0*iB0) ) return 1;
+ *pA = r;
+ return 0;
+}
+
+/*
+** Compute the absolute value of a 32-bit signed integer, of possible. Or
+** if the integer has a value of -2147483648, return +2147483647
+*/
+SQLITE_PRIVATE int sqlite3AbsInt32(int x){
+ if( x>=0 ) return x;
+ if( x==(int)0x80000000 ) return 0x7fffffff;
+ return -x;
+}
+
+#ifdef SQLITE_ENABLE_8_3_NAMES
+/*
+** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
+** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
+** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
+** three characters, then shorten the suffix on z[] to be the last three
+** characters of the original suffix.
+**
+** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
+** do the suffix shortening regardless of URI parameter.
+**
+** Examples:
+**
+** test.db-journal => test.nal
+** test.db-wal => test.wal
+** test.db-shm => test.shm
+** test.db-mj7f3319fa => test.9fa
+*/
+SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
+#if SQLITE_ENABLE_8_3_NAMES<2
+ if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
+#endif
+ {
+ int i, sz;
+ sz = sqlite3Strlen30(z);
+ for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
+ if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
+ }
+}
+#endif
+
+/************** End of util.c ************************************************/
+/************** Begin file hash.c ********************************************/
+/*
+** 2001 September 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This is the implementation of generic hash-tables
+** used in SQLite.
+*/
+/* #include <assert.h> */
+
+/* Turn bulk memory into a hash table object by initializing the
+** fields of the Hash structure.
+**
+** "pNew" is a pointer to the hash table that is to be initialized.
+*/
+SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
+ assert( pNew!=0 );
+ pNew->first = 0;
+ pNew->count = 0;
+ pNew->htsize = 0;
+ pNew->ht = 0;
+}
+
+/* Remove all entries from a hash table. Reclaim all memory.
+** Call this routine to delete a hash table or to reset a hash table
+** to the empty state.
+*/
+SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
+ HashElem *elem; /* For looping over all elements of the table */
+
+ assert( pH!=0 );
+ elem = pH->first;
+ pH->first = 0;
+ sqlite3_free(pH->ht);
+ pH->ht = 0;
+ pH->htsize = 0;
+ while( elem ){
+ HashElem *next_elem = elem->next;
+ sqlite3_free(elem);
+ elem = next_elem;
+ }
+ pH->count = 0;
+}
+
+/*
+** The hashing function.
+*/
+static unsigned int strHash(const char *z, int nKey){
+ int h = 0;
+ assert( nKey>=0 );
+ while( nKey > 0 ){
+ h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
+ nKey--;
+ }
+ return h;
+}
+
+
+/* Link pNew element into the hash table pH. If pEntry!=0 then also
+** insert pNew into the pEntry hash bucket.
+*/
+static void insertElement(
+ Hash *pH, /* The complete hash table */
+ struct _ht *pEntry, /* The entry into which pNew is inserted */
+ HashElem *pNew /* The element to be inserted */
+){
+ HashElem *pHead; /* First element already in pEntry */
+ if( pEntry ){
+ pHead = pEntry->count ? pEntry->chain : 0;
+ pEntry->count++;
+ pEntry->chain = pNew;
+ }else{
+ pHead = 0;
+ }
+ if( pHead ){
+ pNew->next = pHead;
+ pNew->prev = pHead->prev;
+ if( pHead->prev ){ pHead->prev->next = pNew; }
+ else { pH->first = pNew; }
+ pHead->prev = pNew;
+ }else{
+ pNew->next = pH->first;
+ if( pH->first ){ pH->first->prev = pNew; }
+ pNew->prev = 0;
+ pH->first = pNew;
+ }
+}
+
+
+/* Resize the hash table so that it cantains "new_size" buckets.
+**
+** The hash table might fail to resize if sqlite3_malloc() fails or
+** if the new size is the same as the prior size.
+** Return TRUE if the resize occurs and false if not.
+*/
+static int rehash(Hash *pH, unsigned int new_size){
+ struct _ht *new_ht; /* The new hash table */
+ HashElem *elem, *next_elem; /* For looping over existing elements */
+
+#if SQLITE_MALLOC_SOFT_LIMIT>0
+ if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
+ new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
+ }
+ if( new_size==pH->htsize ) return 0;
+#endif
+
+ /* The inability to allocates space for a larger hash table is
+ ** a performance hit but it is not a fatal error. So mark the
+ ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
+ ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
+ ** only zeroes the requested number of bytes whereas this module will
+ ** use the actual amount of space allocated for the hash table (which
+ ** may be larger than the requested amount).
+ */
+ sqlite3BeginBenignMalloc();
+ new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
+ sqlite3EndBenignMalloc();
+
+ if( new_ht==0 ) return 0;
+ sqlite3_free(pH->ht);
+ pH->ht = new_ht;
+ pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
+ memset(new_ht, 0, new_size*sizeof(struct _ht));
+ for(elem=pH->first, pH->first=0; elem; elem = next_elem){
+ unsigned int h = strHash(elem->pKey, elem->nKey) % new_size;
+ next_elem = elem->next;
+ insertElement(pH, &new_ht[h], elem);
+ }
+ return 1;
+}
+
+/* This function (for internal use only) locates an element in an
+** hash table that matches the given key. The hash for this key has
+** already been computed and is passed as the 4th parameter.
+*/
+static HashElem *findElementGivenHash(
+ const Hash *pH, /* The pH to be searched */
+ const char *pKey, /* The key we are searching for */
+ int nKey, /* Bytes in key (not counting zero terminator) */
+ unsigned int h /* The hash for this key. */
+){
+ HashElem *elem; /* Used to loop thru the element list */
+ int count; /* Number of elements left to test */
+
+ if( pH->ht ){
+ struct _ht *pEntry = &pH->ht[h];
+ elem = pEntry->chain;
+ count = pEntry->count;
+ }else{
+ elem = pH->first;
+ count = pH->count;
+ }
+ while( count-- && ALWAYS(elem) ){
+ if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
+ return elem;
+ }
+ elem = elem->next;
+ }
+ return 0;
+}
+
+/* Remove a single entry from the hash table given a pointer to that
+** element and a hash on the element's key.
+*/
+static void removeElementGivenHash(
+ Hash *pH, /* The pH containing "elem" */
+ HashElem* elem, /* The element to be removed from the pH */
+ unsigned int h /* Hash value for the element */
+){
+ struct _ht *pEntry;
+ if( elem->prev ){
+ elem->prev->next = elem->next;
+ }else{
+ pH->first = elem->next;
+ }
+ if( elem->next ){
+ elem->next->prev = elem->prev;
+ }
+ if( pH->ht ){
+ pEntry = &pH->ht[h];
+ if( pEntry->chain==elem ){
+ pEntry->chain = elem->next;
+ }
+ pEntry->count--;
+ assert( pEntry->count>=0 );
+ }
+ sqlite3_free( elem );
+ pH->count--;
+ if( pH->count==0 ){
+ assert( pH->first==0 );
+ assert( pH->count==0 );
+ sqlite3HashClear(pH);
+ }
+}
+
+/* Attempt to locate an element of the hash table pH with a key
+** that matches pKey,nKey. Return the data for this element if it is
+** found, or NULL if there is no match.
+*/
+SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
+ HashElem *elem; /* The element that matches key */
+ unsigned int h; /* A hash on key */
+
+ assert( pH!=0 );
+ assert( pKey!=0 );
+ assert( nKey>=0 );
+ if( pH->ht ){
+ h = strHash(pKey, nKey) % pH->htsize;
+ }else{
+ h = 0;
+ }
+ elem = findElementGivenHash(pH, pKey, nKey, h);
+ return elem ? elem->data : 0;
+}
+
+/* Insert an element into the hash table pH. The key is pKey,nKey
+** and the data is "data".
+**
+** If no element exists with a matching key, then a new
+** element is created and NULL is returned.
+**
+** If another element already exists with the same key, then the
+** new data replaces the old data and the old data is returned.
+** The key is not copied in this instance. If a malloc fails, then
+** the new data is returned and the hash table is unchanged.
+**
+** If the "data" parameter to this function is NULL, then the
+** element corresponding to "key" is removed from the hash table.
+*/
+SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
+ unsigned int h; /* the hash of the key modulo hash table size */
+ HashElem *elem; /* Used to loop thru the element list */
+ HashElem *new_elem; /* New element added to the pH */
+
+ assert( pH!=0 );
+ assert( pKey!=0 );
+ assert( nKey>=0 );
+ if( pH->htsize ){
+ h = strHash(pKey, nKey) % pH->htsize;
+ }else{
+ h = 0;
+ }
+ elem = findElementGivenHash(pH,pKey,nKey,h);
+ if( elem ){
+ void *old_data = elem->data;
+ if( data==0 ){
+ removeElementGivenHash(pH,elem,h);
+ }else{
+ elem->data = data;
+ elem->pKey = pKey;
+ assert(nKey==elem->nKey);
+ }
+ return old_data;
+ }
+ if( data==0 ) return 0;
+ new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
+ if( new_elem==0 ) return data;
+ new_elem->pKey = pKey;
+ new_elem->nKey = nKey;
+ new_elem->data = data;
+ pH->count++;
+ if( pH->count>=10 && pH->count > 2*pH->htsize ){
+ if( rehash(pH, pH->count*2) ){
+ assert( pH->htsize>0 );
+ h = strHash(pKey, nKey) % pH->htsize;
+ }
+ }
+ if( pH->ht ){
+ insertElement(pH, &pH->ht[h], new_elem);
+ }else{
+ insertElement(pH, 0, new_elem);
+ }
+ return 0;
+}
+
+/************** End of hash.c ************************************************/
+/************** Begin file opcodes.c *****************************************/
+/* Automatically generated. Do not edit */
+/* See the mkopcodec.awk script for details. */
+#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
+ static const char *const azName[] = { "?",
+ /* 1 */ "Goto",
+ /* 2 */ "Gosub",
+ /* 3 */ "Return",
+ /* 4 */ "Yield",
+ /* 5 */ "HaltIfNull",
+ /* 6 */ "Halt",
+ /* 7 */ "Integer",
+ /* 8 */ "Int64",
+ /* 9 */ "String",
+ /* 10 */ "Null",
+ /* 11 */ "Blob",
+ /* 12 */ "Variable",
+ /* 13 */ "Move",
+ /* 14 */ "Copy",
+ /* 15 */ "SCopy",
+ /* 16 */ "ResultRow",
+ /* 17 */ "CollSeq",
+ /* 18 */ "Function",
+ /* 19 */ "Not",
+ /* 20 */ "AddImm",
+ /* 21 */ "MustBeInt",
+ /* 22 */ "RealAffinity",
+ /* 23 */ "Permutation",
+ /* 24 */ "Compare",
+ /* 25 */ "Jump",
+ /* 26 */ "Once",
+ /* 27 */ "If",
+ /* 28 */ "IfNot",
+ /* 29 */ "Column",
+ /* 30 */ "Affinity",
+ /* 31 */ "MakeRecord",
+ /* 32 */ "Count",
+ /* 33 */ "Savepoint",
+ /* 34 */ "AutoCommit",
+ /* 35 */ "Transaction",
+ /* 36 */ "ReadCookie",
+ /* 37 */ "SetCookie",
+ /* 38 */ "VerifyCookie",
+ /* 39 */ "OpenRead",
+ /* 40 */ "OpenWrite",
+ /* 41 */ "OpenAutoindex",
+ /* 42 */ "OpenEphemeral",
+ /* 43 */ "SorterOpen",
+ /* 44 */ "OpenPseudo",
+ /* 45 */ "Close",
+ /* 46 */ "SeekLt",
+ /* 47 */ "SeekLe",
+ /* 48 */ "SeekGe",
+ /* 49 */ "SeekGt",
+ /* 50 */ "Seek",
+ /* 51 */ "NotFound",
+ /* 52 */ "Found",
+ /* 53 */ "IsUnique",
+ /* 54 */ "NotExists",
+ /* 55 */ "Sequence",
+ /* 56 */ "NewRowid",
+ /* 57 */ "Insert",
+ /* 58 */ "InsertInt",
+ /* 59 */ "Delete",
+ /* 60 */ "ResetCount",
+ /* 61 */ "SorterCompare",
+ /* 62 */ "SorterData",
+ /* 63 */ "RowKey",
+ /* 64 */ "RowData",
+ /* 65 */ "Rowid",
+ /* 66 */ "NullRow",
+ /* 67 */ "Last",
+ /* 68 */ "Or",
+ /* 69 */ "And",
+ /* 70 */ "SorterSort",
+ /* 71 */ "Sort",
+ /* 72 */ "Rewind",
+ /* 73 */ "IsNull",
+ /* 74 */ "NotNull",
+ /* 75 */ "Ne",
+ /* 76 */ "Eq",
+ /* 77 */ "Gt",
+ /* 78 */ "Le",
+ /* 79 */ "Lt",
+ /* 80 */ "Ge",
+ /* 81 */ "SorterNext",
+ /* 82 */ "BitAnd",
+ /* 83 */ "BitOr",
+ /* 84 */ "ShiftLeft",
+ /* 85 */ "ShiftRight",
+ /* 86 */ "Add",
+ /* 87 */ "Subtract",
+ /* 88 */ "Multiply",
+ /* 89 */ "Divide",
+ /* 90 */ "Remainder",
+ /* 91 */ "Concat",
+ /* 92 */ "Prev",
+ /* 93 */ "BitNot",
+ /* 94 */ "String8",
+ /* 95 */ "Next",
+ /* 96 */ "SorterInsert",
+ /* 97 */ "IdxInsert",
+ /* 98 */ "IdxDelete",
+ /* 99 */ "IdxRowid",
+ /* 100 */ "IdxLT",
+ /* 101 */ "IdxGE",
+ /* 102 */ "Destroy",
+ /* 103 */ "Clear",
+ /* 104 */ "CreateIndex",
+ /* 105 */ "CreateTable",
+ /* 106 */ "ParseSchema",
+ /* 107 */ "LoadAnalysis",
+ /* 108 */ "DropTable",
+ /* 109 */ "DropIndex",
+ /* 110 */ "DropTrigger",
+ /* 111 */ "IntegrityCk",
+ /* 112 */ "RowSetAdd",
+ /* 113 */ "RowSetRead",
+ /* 114 */ "RowSetTest",
+ /* 115 */ "Program",
+ /* 116 */ "Param",
+ /* 117 */ "FkCounter",
+ /* 118 */ "FkIfZero",
+ /* 119 */ "MemMax",
+ /* 120 */ "IfPos",
+ /* 121 */ "IfNeg",
+ /* 122 */ "IfZero",
+ /* 123 */ "AggStep",
+ /* 124 */ "AggFinal",
+ /* 125 */ "Checkpoint",
+ /* 126 */ "JournalMode",
+ /* 127 */ "Vacuum",
+ /* 128 */ "IncrVacuum",
+ /* 129 */ "Expire",
+ /* 130 */ "Real",
+ /* 131 */ "TableLock",
+ /* 132 */ "VBegin",
+ /* 133 */ "VCreate",
+ /* 134 */ "VDestroy",
+ /* 135 */ "VOpen",
+ /* 136 */ "VFilter",
+ /* 137 */ "VColumn",
+ /* 138 */ "VNext",
+ /* 139 */ "VRename",
+ /* 140 */ "VUpdate",
+ /* 141 */ "ToText",
+ /* 142 */ "ToBlob",
+ /* 143 */ "ToNumeric",
+ /* 144 */ "ToInt",
+ /* 145 */ "ToReal",
+ /* 146 */ "Pagecount",
+ /* 147 */ "MaxPgcnt",
+ /* 148 */ "Trace",
+ /* 149 */ "Noop",
+ /* 150 */ "Explain",
+ };
+ return azName[i];
+}
+#endif
+
+/************** End of opcodes.c *********************************************/
+/************** Begin file os_unix.c *****************************************/
+/*
+** 2004 May 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains the VFS implementation for unix-like operating systems
+** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
+**
+** There are actually several different VFS implementations in this file.
+** The differences are in the way that file locking is done. The default
+** implementation uses Posix Advisory Locks. Alternative implementations
+** use flock(), dot-files, various proprietary locking schemas, or simply
+** skip locking all together.
+**
+** This source file is organized into divisions where the logic for various
+** subfunctions is contained within the appropriate division. PLEASE
+** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
+** in the correct division and should be clearly labeled.
+**
+** The layout of divisions is as follows:
+**
+** * General-purpose declarations and utility functions.
+** * Unique file ID logic used by VxWorks.
+** * Various locking primitive implementations (all except proxy locking):
+** + for Posix Advisory Locks
+** + for no-op locks
+** + for dot-file locks
+** + for flock() locking
+** + for named semaphore locks (VxWorks only)
+** + for AFP filesystem locks (MacOSX only)
+** * sqlite3_file methods not associated with locking.
+** * Definitions of sqlite3_io_methods objects for all locking
+** methods plus "finder" functions for each locking method.
+** * sqlite3_vfs method implementations.
+** * Locking primitives for the proxy uber-locking-method. (MacOSX only)
+** * Definitions of sqlite3_vfs objects for all locking methods
+** plus implementations of sqlite3_os_init() and sqlite3_os_end().
+*/
+#if SQLITE_OS_UNIX /* This file is used on unix only */
+
+/* Use posix_fallocate() if it is available
+*/
+#if !defined(HAVE_POSIX_FALLOCATE) \
+ && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
+# define HAVE_POSIX_FALLOCATE 1
+#endif
+
+/*
+** There are various methods for file locking used for concurrency
+** control:
+**
+** 1. POSIX locking (the default),
+** 2. No locking,
+** 3. Dot-file locking,
+** 4. flock() locking,
+** 5. AFP locking (OSX only),
+** 6. Named POSIX semaphores (VXWorks only),
+** 7. proxy locking. (OSX only)
+**
+** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
+** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
+** selection of the appropriate locking style based on the filesystem
+** where the database is located.
+*/
+#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
+# if defined(__APPLE__)
+# define SQLITE_ENABLE_LOCKING_STYLE 1
+# else
+# define SQLITE_ENABLE_LOCKING_STYLE 0
+# endif
+#endif
+
+/*
+** Define the OS_VXWORKS pre-processor macro to 1 if building on
+** vxworks, or 0 otherwise.
+*/
+#ifndef OS_VXWORKS
+# if defined(__RTP__) || defined(_WRS_KERNEL)
+# define OS_VXWORKS 1
+# else
+# define OS_VXWORKS 0
+# endif
+#endif
+
+/*
+** These #defines should enable >2GB file support on Posix if the
+** underlying operating system supports it. If the OS lacks
+** large file support, these should be no-ops.
+**
+** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
+** on the compiler command line. This is necessary if you are compiling
+** on a recent machine (ex: RedHat 7.2) but you want your code to work
+** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
+** without this option, LFS is enable. But LFS does not exist in the kernel
+** in RedHat 6.0, so the code won't work. Hence, for maximum binary
+** portability you should omit LFS.
+**
+** The previous paragraph was written in 2005. (This paragraph is written
+** on 2008-11-28.) These days, all Linux kernels support large files, so
+** you should probably leave LFS enabled. But some embedded platforms might
+** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
+*/
+#ifndef SQLITE_DISABLE_LFS
+# define _LARGE_FILE 1
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
+# define _LARGEFILE_SOURCE 1
+#endif
+
+/*
+** standard include files.
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+/* #include <time.h> */
+#include <sys/time.h>
+#include <errno.h>
+#ifndef SQLITE_OMIT_WAL
+#include <sys/mman.h>
+#endif
+
+
+#if SQLITE_ENABLE_LOCKING_STYLE
+# include <sys/ioctl.h>
+# if OS_VXWORKS
+# include <semaphore.h>
+# include <limits.h>
+# else
+# include <sys/file.h>
+# include <sys/param.h>
+# endif
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
+#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
+# include <sys/mount.h>
+#endif
+
+#ifdef HAVE_UTIME
+# include <utime.h>
+#endif
+
+/*
+** Allowed values of unixFile.fsFlags
+*/
+#define SQLITE_FSFLAGS_IS_MSDOS 0x1
+
+/*
+** If we are to be thread-safe, include the pthreads header and define
+** the SQLITE_UNIX_THREADS macro.
+*/
+#if SQLITE_THREADSAFE
+/* # include <pthread.h> */
+# define SQLITE_UNIX_THREADS 1
+#endif
+
+/*
+** Default permissions when creating a new file
+*/
+#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
+# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
+#endif
+
+/*
+** Default permissions when creating auto proxy dir
+*/
+#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
+#endif
+
+/*
+** Maximum supported path-length.
+*/
+#define MAX_PATHNAME 512
+
+/*
+** Only set the lastErrno if the error code is a real error and not
+** a normal expected return code of SQLITE_BUSY or SQLITE_OK
+*/
+#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
+
+/* Forward references */
+typedef struct unixShm unixShm; /* Connection shared memory */
+typedef struct unixShmNode unixShmNode; /* Shared memory instance */
+typedef struct unixInodeInfo unixInodeInfo; /* An i-node */
+typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */
+
+/*
+** Sometimes, after a file handle is closed by SQLite, the file descriptor
+** cannot be closed immediately. In these cases, instances of the following
+** structure are used to store the file descriptor while waiting for an
+** opportunity to either close or reuse it.
+*/
+struct UnixUnusedFd {
+ int fd; /* File descriptor to close */
+ int flags; /* Flags this file descriptor was opened with */
+ UnixUnusedFd *pNext; /* Next unused file descriptor on same file */
+};
+
+/*
+** The unixFile structure is subclass of sqlite3_file specific to the unix
+** VFS implementations.
+*/
+typedef struct unixFile unixFile;
+struct unixFile {
+ sqlite3_io_methods const *pMethod; /* Always the first entry */
+ sqlite3_vfs *pVfs; /* The VFS that created this unixFile */
+ unixInodeInfo *pInode; /* Info about locks on this inode */
+ int h; /* The file descriptor */
+ unsigned char eFileLock; /* The type of lock held on this fd */
+ unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
+ int lastErrno; /* The unix errno from last I/O error */
+ void *lockingContext; /* Locking style specific state */
+ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
+ const char *zPath; /* Name of the file */
+ unixShm *pShm; /* Shared memory segment information */
+ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
+#ifdef __QNXNTO__
+ int sectorSize; /* Device sector size */
+ int deviceCharacteristics; /* Precomputed device characteristics */
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE
+ int openFlags; /* The flags specified at open() */
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
+ unsigned fsFlags; /* cached details from statfs() */
+#endif
+#if OS_VXWORKS
+ struct vxworksFileId *pId; /* Unique file ID */
+#endif
+#ifdef SQLITE_DEBUG
+ /* The next group of variables are used to track whether or not the
+ ** transaction counter in bytes 24-27 of database files are updated
+ ** whenever any part of the database changes. An assertion fault will
+ ** occur if a file is updated without also updating the transaction
+ ** counter. This test is made to avoid new problems similar to the
+ ** one described by ticket #3584.
+ */
+ unsigned char transCntrChng; /* True if the transaction counter changed */
+ unsigned char dbUpdate; /* True if any part of database file changed */
+ unsigned char inNormalWrite; /* True if in a normal write operation */
+#endif
+#ifdef SQLITE_TEST
+ /* In test mode, increase the size of this structure a bit so that
+ ** it is larger than the struct CrashFile defined in test6.c.
+ */
+ char aPadding[32];
+#endif
+};
+
+/*
+** Allowed values for the unixFile.ctrlFlags bitmask:
+*/
+#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
+#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
+#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
+#ifndef SQLITE_DISABLE_DIRSYNC
+# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
+#else
+# define UNIXFILE_DIRSYNC 0x00
+#endif
+#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
+#define UNIXFILE_DELETE 0x20 /* Delete on close */
+#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
+#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
+
+/*
+** Include code that is common to all os_*.c files
+*/
+/************** Include os_common.h in the middle of os_unix.c ***************/
+/************** Begin file os_common.h ***************************************/
+/*
+** 2004 May 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains macros and a little bit of code that is common to
+** all of the platform-specific files (os_*.c) and is #included into those
+** files.
+**
+** This file should be #included by the os_*.c files only. It is not a
+** general purpose header file.
+*/
+#ifndef _OS_COMMON_H_
+#define _OS_COMMON_H_
+
+/*
+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
+** switch. The following code should catch this problem at compile-time.
+*/
+#ifdef MEMORY_DEBUG
+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
+#endif
+
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+# ifndef SQLITE_DEBUG_OS_TRACE
+# define SQLITE_DEBUG_OS_TRACE 0
+# endif
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
+#else
+# define OSTRACE(X)
+#endif
+
+/*
+** Macros for performance tracing. Normally turned off. Only works
+** on i486 hardware.
+*/
+#ifdef SQLITE_PERFORMANCE_TRACE
+
+/*
+** hwtime.h contains inline assembler code for implementing
+** high-performance timing routines.
+*/
+/************** Include hwtime.h in the middle of os_common.h ****************/
+/************** Begin file hwtime.h ******************************************/
+/*
+** 2008 May 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains inline asm code for retrieving "high-performance"
+** counters for x86 class CPUs.
+*/
+#ifndef _HWTIME_H_
+#define _HWTIME_H_
+
+/*
+** The following routine only works on pentium-class (or newer) processors.
+** It uses the RDTSC opcode to read the cycle count value out of the
+** processor and returns that value. This can be used for high-res
+** profiling.
+*/
+#if (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
+
+ #if defined(__GNUC__)
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+ #elif defined(_MSC_VER)
+
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+ __asm {
+ rdtsc
+ ret ; return value at EDX:EAX
+ }
+ }
+
+ #endif
+
+#elif (defined(__GNUC__) && defined(__x86_64__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long val;
+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
+ return val;
+ }
+
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
+ }
+
+#else
+
+ #error Need implementation of sqlite3Hwtime() for your platform.
+
+ /*
+ ** To compile without implementing sqlite3Hwtime() for your platform,
+ ** you can remove the above #error and use the following
+ ** stub function. You will lose timing support for many
+ ** of the debugging and testing utilities, but it should at
+ ** least compile and run.
+ */
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+
+#endif
+
+#endif /* !defined(_HWTIME_H_) */
+
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in os_common.h ******************/
+
+static sqlite_uint64 g_start;
+static sqlite_uint64 g_elapsed;
+#define TIMER_START g_start=sqlite3Hwtime()
+#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
+#define TIMER_ELAPSED g_elapsed
+#else
+#define TIMER_START
+#define TIMER_END
+#define TIMER_ELAPSED ((sqlite_uint64)0)
+#endif
+
+/*
+** If we compile with the SQLITE_TEST macro set, then the following block
+** of code will give us the ability to simulate a disk I/O error. This
+** is used for testing the I/O recovery logic.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
+SQLITE_API int sqlite3_diskfull_pending = 0;
+SQLITE_API int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
+#define SimulateIOError(CODE) \
+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+ || sqlite3_io_error_pending-- == 1 ) \
+ { local_ioerr(); CODE; }
+static void local_ioerr(){
+ IOTRACE(("IOERR\n"));
+ sqlite3_io_error_hit++;
+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
+}
+#define SimulateDiskfullError(CODE) \
+ if( sqlite3_diskfull_pending ){ \
+ if( sqlite3_diskfull_pending == 1 ){ \
+ local_ioerr(); \
+ sqlite3_diskfull = 1; \
+ sqlite3_io_error_hit = 1; \
+ CODE; \
+ }else{ \
+ sqlite3_diskfull_pending--; \
+ } \
+ }
+#else
+#define SimulateIOErrorBenign(X)
+#define SimulateIOError(A)
+#define SimulateDiskfullError(A)
+#endif
+
+/*
+** When testing, keep a count of the number of open files.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_open_file_count = 0;
+#define OpenCounter(X) sqlite3_open_file_count+=(X)
+#else
+#define OpenCounter(X)
+#endif
+
+#endif /* !defined(_OS_COMMON_H_) */
+
+/************** End of os_common.h *******************************************/
+/************** Continuing where we left off in os_unix.c ********************/
+
+/*
+** Define various macros that are missing from some systems.
+*/
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+#ifdef SQLITE_DISABLE_LFS
+# undef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/*
+** The threadid macro resolves to the thread-id or to 0. Used for
+** testing and debugging only.
+*/
+#if SQLITE_THREADSAFE
+#define threadid pthread_self()
+#else
+#define threadid 0
+#endif
+
+/*
+** Different Unix systems declare open() in different ways. Same use
+** open(const char*,int,mode_t). Others use open(const char*,int,...).
+** The difference is important when using a pointer to the function.
+**
+** The safest way to deal with the problem is to always use this wrapper
+** which always has the same well-defined interface.
+*/
+static int posixOpen(const char *zFile, int flags, int mode){
+ return open(zFile, flags, mode);
+}
+
+/*
+** On some systems, calls to fchown() will trigger a message in a security
+** log if they come from non-root processes. So avoid calling fchown() if
+** we are not running as root.
+*/
+static int posixFchown(int fd, uid_t uid, gid_t gid){
+ return geteuid() ? 0 : fchown(fd,uid,gid);
+}
+
+/* Forward reference */
+static int openDirectory(const char*, int*);
+
+/*
+** Many system calls are accessed through pointer-to-functions so that
+** they may be overridden at runtime to facilitate fault injection during
+** testing and sandboxing. The following array holds the names and pointers
+** to all overrideable system calls.
+*/
+static struct unix_syscall {
+ const char *zName; /* Name of the system call */
+ sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
+ sqlite3_syscall_ptr pDefault; /* Default value */
+} aSyscall[] = {
+ { "open", (sqlite3_syscall_ptr)posixOpen, 0 },
+#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
+
+ { "close", (sqlite3_syscall_ptr)close, 0 },
+#define osClose ((int(*)(int))aSyscall[1].pCurrent)
+
+ { "access", (sqlite3_syscall_ptr)access, 0 },
+#define osAccess ((int(*)(const char*,int))aSyscall[2].pCurrent)
+
+ { "getcwd", (sqlite3_syscall_ptr)getcwd, 0 },
+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
+
+ { "stat", (sqlite3_syscall_ptr)stat, 0 },
+#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
+
+/*
+** The DJGPP compiler environment looks mostly like Unix, but it
+** lacks the fcntl() system call. So redefine fcntl() to be something
+** that always succeeds. This means that locking does not occur under
+** DJGPP. But it is DOS - what did you expect?
+*/
+#ifdef __DJGPP__
+ { "fstat", 0, 0 },
+#define osFstat(a,b,c) 0
+#else
+ { "fstat", (sqlite3_syscall_ptr)fstat, 0 },
+#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
+#endif
+
+ { "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 },
+#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
+
+ { "fcntl", (sqlite3_syscall_ptr)fcntl, 0 },
+#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
+
+ { "read", (sqlite3_syscall_ptr)read, 0 },
+#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
+
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
+ { "pread", (sqlite3_syscall_ptr)pread, 0 },
+#else
+ { "pread", (sqlite3_syscall_ptr)0, 0 },
+#endif
+#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
+
+#if defined(USE_PREAD64)
+ { "pread64", (sqlite3_syscall_ptr)pread64, 0 },
+#else
+ { "pread64", (sqlite3_syscall_ptr)0, 0 },
+#endif
+#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
+
+ { "write", (sqlite3_syscall_ptr)write, 0 },
+#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
+
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
+ { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
+#else
+ { "pwrite", (sqlite3_syscall_ptr)0, 0 },
+#endif
+#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
+ aSyscall[12].pCurrent)
+
+#if defined(USE_PREAD64)
+ { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 },
+#else
+ { "pwrite64", (sqlite3_syscall_ptr)0, 0 },
+#endif
+#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
+ aSyscall[13].pCurrent)
+
+ { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
+#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
+
+#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
+ { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
+#else
+ { "fallocate", (sqlite3_syscall_ptr)0, 0 },
+#endif
+#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
+
+ { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
+#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
+
+ { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
+#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
+
+ { "mkdir", (sqlite3_syscall_ptr)mkdir, 0 },
+#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
+
+ { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
+#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
+
+ { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
+#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
+
+}; /* End of the overrideable system calls */
+
+/*
+** This is the xSetSystemCall() method of sqlite3_vfs for all of the
+** "unix" VFSes. Return SQLITE_OK opon successfully updating the
+** system call pointer, or SQLITE_NOTFOUND if there is no configurable
+** system call named zName.
+*/
+static int unixSetSystemCall(
+ sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
+ const char *zName, /* Name of system call to override */
+ sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
+){
+ unsigned int i;
+ int rc = SQLITE_NOTFOUND;
+
+ UNUSED_PARAMETER(pNotUsed);
+ if( zName==0 ){
+ /* If no zName is given, restore all system calls to their default
+ ** settings and return NULL
+ */
+ rc = SQLITE_OK;
+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+ if( aSyscall[i].pDefault ){
+ aSyscall[i].pCurrent = aSyscall[i].pDefault;
+ }
+ }
+ }else{
+ /* If zName is specified, operate on only the one system call
+ ** specified.
+ */
+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+ if( strcmp(zName, aSyscall[i].zName)==0 ){
+ if( aSyscall[i].pDefault==0 ){
+ aSyscall[i].pDefault = aSyscall[i].pCurrent;
+ }
+ rc = SQLITE_OK;
+ if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
+ aSyscall[i].pCurrent = pNewFunc;
+ break;
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Return the value of a system call. Return NULL if zName is not a
+** recognized system call name. NULL is also returned if the system call
+** is currently undefined.
+*/
+static sqlite3_syscall_ptr unixGetSystemCall(
+ sqlite3_vfs *pNotUsed,
+ const char *zName
+){
+ unsigned int i;
+
+ UNUSED_PARAMETER(pNotUsed);
+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+ if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
+ }
+ return 0;
+}
+
+/*
+** Return the name of the first system call after zName. If zName==NULL
+** then return the name of the first system call. Return NULL if zName
+** is the last system call or if zName is not the name of a valid
+** system call.
+*/
+static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
+ int i = -1;
+
+ UNUSED_PARAMETER(p);
+ if( zName ){
+ for(i=0; i<ArraySize(aSyscall)-1; i++){
+ if( strcmp(zName, aSyscall[i].zName)==0 ) break;
+ }
+ }
+ for(i++; i<ArraySize(aSyscall); i++){
+ if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
+ }
+ return 0;
+}
+
+/*
+** Invoke open(). Do so multiple times, until it either succeeds or
+** fails for some reason other than EINTR.
+**
+** If the file creation mode "m" is 0 then set it to the default for
+** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
+** 0644) as modified by the system umask. If m is not 0, then
+** make the file creation mode be exactly m ignoring the umask.
+**
+** The m parameter will be non-zero only when creating -wal, -journal,
+** and -shm files. We want those files to have *exactly* the same
+** permissions as their original database, unadulterated by the umask.
+** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
+** transaction crashes and leaves behind hot journals, then any
+** process that is able to write to the database will also be able to
+** recover the hot journals.
+*/
+static int robust_open(const char *z, int f, mode_t m){
+ int fd;
+ mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
+ do{
+#if defined(O_CLOEXEC)
+ fd = osOpen(z,f|O_CLOEXEC,m2);
+#else
+ fd = osOpen(z,f,m2);
+#endif
+ }while( fd<0 && errno==EINTR );
+ if( fd>=0 ){
+ if( m!=0 ){
+ struct stat statbuf;
+ if( osFstat(fd, &statbuf)==0
+ && statbuf.st_size==0
+ && (statbuf.st_mode&0777)!=m
+ ){
+ osFchmod(fd, m);
+ }
+ }
+#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
+ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
+#endif
+ }
+ return fd;
+}
+
+/*
+** Helper functions to obtain and relinquish the global mutex. The
+** global mutex is used to protect the unixInodeInfo and
+** vxworksFileId objects used by this file, all of which may be
+** shared by multiple threads.
+**
+** Function unixMutexHeld() is used to assert() that the global mutex
+** is held when required. This function is only used as part of assert()
+** statements. e.g.
+**
+** unixEnterMutex()
+** assert( unixMutexHeld() );
+** unixEnterLeave()
+*/
+static void unixEnterMutex(void){
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+}
+static void unixLeaveMutex(void){
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+}
+#ifdef SQLITE_DEBUG
+static int unixMutexHeld(void) {
+ return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+}
+#endif
+
+
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+/*
+** Helper function for printing out trace information from debugging
+** binaries. This returns the string represetation of the supplied
+** integer lock-type.
+*/
+static const char *azFileLock(int eFileLock){
+ switch( eFileLock ){
+ case NO_LOCK: return "NONE";
+ case SHARED_LOCK: return "SHARED";
+ case RESERVED_LOCK: return "RESERVED";
+ case PENDING_LOCK: return "PENDING";
+ case EXCLUSIVE_LOCK: return "EXCLUSIVE";
+ }
+ return "ERROR";
+}
+#endif
+
+#ifdef SQLITE_LOCK_TRACE
+/*
+** Print out information about all locking operations.
+**
+** This routine is used for troubleshooting locks on multithreaded
+** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
+** command-line option on the compiler. This code is normally
+** turned off.
+*/
+static int lockTrace(int fd, int op, struct flock *p){
+ char *zOpName, *zType;
+ int s;
+ int savedErrno;
+ if( op==F_GETLK ){
+ zOpName = "GETLK";
+ }else if( op==F_SETLK ){
+ zOpName = "SETLK";
+ }else{
+ s = osFcntl(fd, op, p);
+ sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
+ return s;
+ }
+ if( p->l_type==F_RDLCK ){
+ zType = "RDLCK";
+ }else if( p->l_type==F_WRLCK ){
+ zType = "WRLCK";
+ }else if( p->l_type==F_UNLCK ){
+ zType = "UNLCK";
+ }else{
+ assert( 0 );
+ }
+ assert( p->l_whence==SEEK_SET );
+ s = osFcntl(fd, op, p);
+ savedErrno = errno;
+ sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
+ threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
+ (int)p->l_pid, s);
+ if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
+ struct flock l2;
+ l2 = *p;
+ osFcntl(fd, F_GETLK, &l2);
+ if( l2.l_type==F_RDLCK ){
+ zType = "RDLCK";
+ }else if( l2.l_type==F_WRLCK ){
+ zType = "WRLCK";
+ }else if( l2.l_type==F_UNLCK ){
+ zType = "UNLCK";
+ }else{
+ assert( 0 );
+ }
+ sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
+ zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
+ }
+ errno = savedErrno;
+ return s;
+}
+#undef osFcntl
+#define osFcntl lockTrace
+#endif /* SQLITE_LOCK_TRACE */
+
+/*
+** Retry ftruncate() calls that fail due to EINTR
+*/
+static int robust_ftruncate(int h, sqlite3_int64 sz){
+ int rc;
+ do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
+ return rc;
+}
+
+/*
+** This routine translates a standard POSIX errno code into something
+** useful to the clients of the sqlite3 functions. Specifically, it is
+** intended to translate a variety of "try again" errors into SQLITE_BUSY
+** and a variety of "please close the file descriptor NOW" errors into
+** SQLITE_IOERR
+**
+** Errors during initialization of locks, or file system support for locks,
+** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
+*/
+static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
+ switch (posixError) {
+#if 0
+ /* At one point this code was not commented out. In theory, this branch
+ ** should never be hit, as this function should only be called after
+ ** a locking-related function (i.e. fcntl()) has returned non-zero with
+ ** the value of errno as the first argument. Since a system call has failed,
+ ** errno should be non-zero.
+ **
+ ** Despite this, if errno really is zero, we still don't want to return
+ ** SQLITE_OK. The system call failed, and *some* SQLite error should be
+ ** propagated back to the caller. Commenting this branch out means errno==0
+ ** will be handled by the "default:" case below.
+ */
+ case 0:
+ return SQLITE_OK;
+#endif
+
+ case EAGAIN:
+ case ETIMEDOUT:
+ case EBUSY:
+ case EINTR:
+ case ENOLCK:
+ /* random NFS retry error, unless during file system support
+ * introspection, in which it actually means what it says */
+ return SQLITE_BUSY;
+
+ case EACCES:
+ /* EACCES is like EAGAIN during locking operations, but not any other time*/
+ if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
+ return SQLITE_BUSY;
+ }
+ /* else fall through */
+ case EPERM:
+ return SQLITE_PERM;
+
+ /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
+ ** this module never makes such a call. And the code in SQLite itself
+ ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
+ ** this case is also commented out. If the system does set errno to EDEADLK,
+ ** the default SQLITE_IOERR_XXX code will be returned. */
+#if 0
+ case EDEADLK:
+ return SQLITE_IOERR_BLOCKED;
+#endif
+
+#if EOPNOTSUPP!=ENOTSUP
+ case EOPNOTSUPP:
+ /* something went terribly awry, unless during file system support
+ * introspection, in which it actually means what it says */
+#endif
+#ifdef ENOTSUP
+ case ENOTSUP:
+ /* invalid fd, unless during file system support introspection, in which
+ * it actually means what it says */
+#endif
+ case EIO:
+ case EBADF:
+ case EINVAL:
+ case ENOTCONN:
+ case ENODEV:
+ case ENXIO:
+ case ENOENT:
+#ifdef ESTALE /* ESTALE is not defined on Interix systems */
+ case ESTALE:
+#endif
+ case ENOSYS:
+ /* these should force the client to close the file and reconnect */
+
+ default:
+ return sqliteIOErr;
+ }
+}
+
+
+
+/******************************************************************************
+****************** Begin Unique File ID Utility Used By VxWorks ***************
+**
+** On most versions of unix, we can get a unique ID for a file by concatenating
+** the device number and the inode number. But this does not work on VxWorks.
+** On VxWorks, a unique file id must be based on the canonical filename.
+**
+** A pointer to an instance of the following structure can be used as a
+** unique file ID in VxWorks. Each instance of this structure contains
+** a copy of the canonical filename. There is also a reference count.
+** The structure is reclaimed when the number of pointers to it drops to
+** zero.
+**
+** There are never very many files open at one time and lookups are not
+** a performance-critical path, so it is sufficient to put these
+** structures on a linked list.
+*/
+struct vxworksFileId {
+ struct vxworksFileId *pNext; /* Next in a list of them all */
+ int nRef; /* Number of references to this one */
+ int nName; /* Length of the zCanonicalName[] string */
+ char *zCanonicalName; /* Canonical filename */
+};
+
+#if OS_VXWORKS
+/*
+** All unique filenames are held on a linked list headed by this
+** variable:
+*/
+static struct vxworksFileId *vxworksFileList = 0;
+
+/*
+** Simplify a filename into its canonical form
+** by making the following changes:
+**
+** * removing any trailing and duplicate /
+** * convert /./ into just /
+** * convert /A/../ where A is any simple name into just /
+**
+** Changes are made in-place. Return the new name length.
+**
+** The original filename is in z[0..n-1]. Return the number of
+** characters in the simplified name.
+*/
+static int vxworksSimplifyName(char *z, int n){
+ int i, j;
+ while( n>1 && z[n-1]=='/' ){ n--; }
+ for(i=j=0; i<n; i++){
+ if( z[i]=='/' ){
+ if( z[i+1]=='/' ) continue;
+ if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
+ i += 1;
+ continue;
+ }
+ if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
+ while( j>0 && z[j-1]!='/' ){ j--; }
+ if( j>0 ){ j--; }
+ i += 2;
+ continue;
+ }
+ }
+ z[j++] = z[i];
+ }
+ z[j] = 0;
+ return j;
+}
+
+/*
+** Find a unique file ID for the given absolute pathname. Return
+** a pointer to the vxworksFileId object. This pointer is the unique
+** file ID.
+**
+** The nRef field of the vxworksFileId object is incremented before
+** the object is returned. A new vxworksFileId object is created
+** and added to the global list if necessary.
+**
+** If a memory allocation error occurs, return NULL.
+*/
+static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
+ struct vxworksFileId *pNew; /* search key and new file ID */
+ struct vxworksFileId *pCandidate; /* For looping over existing file IDs */
+ int n; /* Length of zAbsoluteName string */
+
+ assert( zAbsoluteName[0]=='/' );
+ n = (int)strlen(zAbsoluteName);
+ pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
+ if( pNew==0 ) return 0;
+ pNew->zCanonicalName = (char*)&pNew[1];
+ memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
+ n = vxworksSimplifyName(pNew->zCanonicalName, n);
+
+ /* Search for an existing entry that matching the canonical name.
+ ** If found, increment the reference count and return a pointer to
+ ** the existing file ID.
+ */
+ unixEnterMutex();
+ for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
+ if( pCandidate->nName==n
+ && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
+ ){
+ sqlite3_free(pNew);
+ pCandidate->nRef++;
+ unixLeaveMutex();
+ return pCandidate;
+ }
+ }
+
+ /* No match was found. We will make a new file ID */
+ pNew->nRef = 1;
+ pNew->nName = n;
+ pNew->pNext = vxworksFileList;
+ vxworksFileList = pNew;
+ unixLeaveMutex();
+ return pNew;
+}
+
+/*
+** Decrement the reference count on a vxworksFileId object. Free
+** the object when the reference count reaches zero.
+*/
+static void vxworksReleaseFileId(struct vxworksFileId *pId){
+ unixEnterMutex();
+ assert( pId->nRef>0 );
+ pId->nRef--;
+ if( pId->nRef==0 ){
+ struct vxworksFileId **pp;
+ for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
+ assert( *pp==pId );
+ *pp = pId->pNext;
+ sqlite3_free(pId);
+ }
+ unixLeaveMutex();
+}
+#endif /* OS_VXWORKS */
+/*************** End of Unique File ID Utility Used By VxWorks ****************
+******************************************************************************/
+
+
+/******************************************************************************
+*************************** Posix Advisory Locking ****************************
+**
+** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996)
+** section 6.5.2.2 lines 483 through 490 specify that when a process
+** sets or clears a lock, that operation overrides any prior locks set
+** by the same process. It does not explicitly say so, but this implies
+** that it overrides locks set by the same process using a different
+** file descriptor. Consider this test case:
+**
+** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
+** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
+**
+** Suppose ./file1 and ./file2 are really the same file (because
+** one is a hard or symbolic link to the other) then if you set
+** an exclusive lock on fd1, then try to get an exclusive lock
+** on fd2, it works. I would have expected the second lock to
+** fail since there was already a lock on the file due to fd1.
+** But not so. Since both locks came from the same process, the
+** second overrides the first, even though they were on different
+** file descriptors opened on different file names.
+**
+** This means that we cannot use POSIX locks to synchronize file access
+** among competing threads of the same process. POSIX locks will work fine
+** to synchronize access for threads in separate processes, but not
+** threads within the same process.
+**
+** To work around the problem, SQLite has to manage file locks internally
+** on its own. Whenever a new database is opened, we have to find the
+** specific inode of the database file (the inode is determined by the
+** st_dev and st_ino fields of the stat structure that fstat() fills in)
+** and check for locks already existing on that inode. When locks are
+** created or removed, we have to look at our own internal record of the
+** locks to see if another thread has previously set a lock on that same
+** inode.
+**
+** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
+** For VxWorks, we have to use the alternative unique ID system based on
+** canonical filename and implemented in the previous division.)
+**
+** The sqlite3_file structure for POSIX is no longer just an integer file
+** descriptor. It is now a structure that holds the integer file
+** descriptor and a pointer to a structure that describes the internal
+** locks on the corresponding inode. There is one locking structure
+** per inode, so if the same inode is opened twice, both unixFile structures
+** point to the same locking structure. The locking structure keeps
+** a reference count (so we will know when to delete it) and a "cnt"
+** field that tells us its internal lock status. cnt==0 means the
+** file is unlocked. cnt==-1 means the file has an exclusive lock.
+** cnt>0 means there are cnt shared locks on the file.
+**
+** Any attempt to lock or unlock a file first checks the locking
+** structure. The fcntl() system call is only invoked to set a
+** POSIX lock if the internal lock structure transitions between
+** a locked and an unlocked state.
+**
+** But wait: there are yet more problems with POSIX advisory locks.
+**
+** If you close a file descriptor that points to a file that has locks,
+** all locks on that file that are owned by the current process are
+** released. To work around this problem, each unixInodeInfo object
+** maintains a count of the number of pending locks on tha inode.
+** When an attempt is made to close an unixFile, if there are
+** other unixFile open on the same inode that are holding locks, the call
+** to close() the file descriptor is deferred until all of the locks clear.
+** The unixInodeInfo structure keeps a list of file descriptors that need to
+** be closed and that list is walked (and cleared) when the last lock
+** clears.
+**
+** Yet another problem: LinuxThreads do not play well with posix locks.
+**
+** Many older versions of linux use the LinuxThreads library which is
+** not posix compliant. Under LinuxThreads, a lock created by thread
+** A cannot be modified or overridden by a different thread B.
+** Only thread A can modify the lock. Locking behavior is correct
+** if the appliation uses the newer Native Posix Thread Library (NPTL)
+** on linux - with NPTL a lock created by thread A can override locks
+** in thread B. But there is no way to know at compile-time which
+** threading library is being used. So there is no way to know at
+** compile-time whether or not thread A can override locks on thread B.
+** One has to do a run-time check to discover the behavior of the
+** current process.
+**
+** SQLite used to support LinuxThreads. But support for LinuxThreads
+** was dropped beginning with version 3.7.0. SQLite will still work with
+** LinuxThreads provided that (1) there is no more than one connection
+** per database file in the same process and (2) database connections
+** do not move across threads.
+*/
+
+/*
+** An instance of the following structure serves as the key used
+** to locate a particular unixInodeInfo object.
+*/
+struct unixFileId {
+ dev_t dev; /* Device number */
+#if OS_VXWORKS
+ struct vxworksFileId *pId; /* Unique file ID for vxworks. */
+#else
+ ino_t ino; /* Inode number */
+#endif
+};
+
+/*
+** An instance of the following structure is allocated for each open
+** inode. Or, on LinuxThreads, there is one of these structures for
+** each inode opened by each thread.
+**
+** A single inode can have multiple file descriptors, so each unixFile
+** structure contains a pointer to an instance of this object and this
+** object keeps a count of the number of unixFile pointing to it.
+*/
+struct unixInodeInfo {
+ struct unixFileId fileId; /* The lookup key */
+ int nShared; /* Number of SHARED locks held */
+ unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
+ unsigned char bProcessLock; /* An exclusive process lock is held */
+ int nRef; /* Number of pointers to this structure */
+ unixShmNode *pShmNode; /* Shared memory associated with this inode */
+ int nLock; /* Number of outstanding file locks */
+ UnixUnusedFd *pUnused; /* Unused file descriptors to close */
+ unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
+ unixInodeInfo *pPrev; /* .... doubly linked */
+#if SQLITE_ENABLE_LOCKING_STYLE
+ unsigned long long sharedByte; /* for AFP simulated shared lock */
+#endif
+#if OS_VXWORKS
+ sem_t *pSem; /* Named POSIX semaphore */
+ char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
+#endif
+};
+
+/*
+** A lists of all unixInodeInfo objects.
+*/
+static unixInodeInfo *inodeList = 0;
+
+/*
+**
+** This function - unixLogError_x(), is only ever called via the macro
+** unixLogError().
+**
+** It is invoked after an error occurs in an OS function and errno has been
+** set. It logs a message using sqlite3_log() containing the current value of
+** errno and, if possible, the human-readable equivalent from strerror() or
+** strerror_r().
+**
+** The first argument passed to the macro should be the error code that
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
+** The two subsequent arguments should be the name of the OS function that
+** failed (e.g. "unlink", "open") and the associated file-system path,
+** if any.
+*/
+#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__)
+static int unixLogErrorAtLine(
+ int errcode, /* SQLite error code */
+ const char *zFunc, /* Name of OS function that failed */
+ const char *zPath, /* File path associated with error */
+ int iLine /* Source line number where error occurred */
+){
+ char *zErr; /* Message from strerror() or equivalent */
+ int iErrno = errno; /* Saved syscall error number */
+
+ /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
+ ** the strerror() function to obtain the human-readable error message
+ ** equivalent to errno. Otherwise, use strerror_r().
+ */
+#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
+ char aErr[80];
+ memset(aErr, 0, sizeof(aErr));
+ zErr = aErr;
+
+ /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
+ ** assume that the system provides the GNU version of strerror_r() that
+ ** returns a pointer to a buffer containing the error message. That pointer
+ ** may point to aErr[], or it may point to some static storage somewhere.
+ ** Otherwise, assume that the system provides the POSIX version of
+ ** strerror_r(), which always writes an error message into aErr[].
+ **
+ ** If the code incorrectly assumes that it is the POSIX version that is
+ ** available, the error message will often be an empty string. Not a
+ ** huge problem. Incorrectly concluding that the GNU version is available
+ ** could lead to a segfault though.
+ */
+#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
+ zErr =
+# endif
+ strerror_r(iErrno, aErr, sizeof(aErr)-1);
+
+#elif SQLITE_THREADSAFE
+ /* This is a threadsafe build, but strerror_r() is not available. */
+ zErr = "";
+#else
+ /* Non-threadsafe build, use strerror(). */
+ zErr = strerror(iErrno);
+#endif
+
+ assert( errcode!=SQLITE_OK );
+ if( zPath==0 ) zPath = "";
+ sqlite3_log(errcode,
+ "os_unix.c:%d: (%d) %s(%s) - %s",
+ iLine, iErrno, zFunc, zPath, zErr
+ );
+
+ return errcode;
+}
+
+/*
+** Close a file descriptor.
+**
+** We assume that close() almost always works, since it is only in a
+** very sick application or on a very sick platform that it might fail.
+** If it does fail, simply leak the file descriptor, but do log the
+** error.
+**
+** Note that it is not safe to retry close() after EINTR since the
+** file descriptor might have already been reused by another thread.
+** So we don't even try to recover from an EINTR. Just log the error
+** and move on.
+*/
+static void robust_close(unixFile *pFile, int h, int lineno){
+ if( osClose(h) ){
+ unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
+ pFile ? pFile->zPath : 0, lineno);
+ }
+}
+
+/*
+** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
+*/
+static void closePendingFds(unixFile *pFile){
+ unixInodeInfo *pInode = pFile->pInode;
+ UnixUnusedFd *p;
+ UnixUnusedFd *pNext;
+ for(p=pInode->pUnused; p; p=pNext){
+ pNext = p->pNext;
+ robust_close(pFile, p->fd, __LINE__);
+ sqlite3_free(p);
+ }
+ pInode->pUnused = 0;
+}
+
+/*
+** Release a unixInodeInfo structure previously allocated by findInodeInfo().
+**
+** The mutex entered using the unixEnterMutex() function must be held
+** when this function is called.
+*/
+static void releaseInodeInfo(unixFile *pFile){
+ unixInodeInfo *pInode = pFile->pInode;
+ assert( unixMutexHeld() );
+ if( ALWAYS(pInode) ){
+ pInode->nRef--;
+ if( pInode->nRef==0 ){
+ assert( pInode->pShmNode==0 );
+ closePendingFds(pFile);
+ if( pInode->pPrev ){
+ assert( pInode->pPrev->pNext==pInode );
+ pInode->pPrev->pNext = pInode->pNext;
+ }else{
+ assert( inodeList==pInode );
+ inodeList = pInode->pNext;
+ }
+ if( pInode->pNext ){
+ assert( pInode->pNext->pPrev==pInode );
+ pInode->pNext->pPrev = pInode->pPrev;
+ }
+ sqlite3_free(pInode);
+ }
+ }
+}
+
+/*
+** Given a file descriptor, locate the unixInodeInfo object that
+** describes that file descriptor. Create a new one if necessary. The
+** return value might be uninitialized if an error occurs.
+**
+** The mutex entered using the unixEnterMutex() function must be held
+** when this function is called.
+**
+** Return an appropriate error code.
+*/
+static int findInodeInfo(
+ unixFile *pFile, /* Unix file with file desc used in the key */
+ unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
+){
+ int rc; /* System call return code */
+ int fd; /* The file descriptor for pFile */
+ struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
+ struct stat statbuf; /* Low-level file information */
+ unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
+
+ assert( unixMutexHeld() );
+
+ /* Get low-level information about the file that we can used to
+ ** create a unique name for the file.
+ */
+ fd = pFile->h;
+ rc = osFstat(fd, &statbuf);
+ if( rc!=0 ){
+ pFile->lastErrno = errno;
+#ifdef EOVERFLOW
+ if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
+#endif
+ return SQLITE_IOERR;
+ }
+
+#ifdef __APPLE__
+ /* On OS X on an msdos filesystem, the inode number is reported
+ ** incorrectly for zero-size files. See ticket #3260. To work
+ ** around this problem (we consider it a bug in OS X, not SQLite)
+ ** we always increase the file size to 1 by writing a single byte
+ ** prior to accessing the inode number. The one byte written is
+ ** an ASCII 'S' character which also happens to be the first byte
+ ** in the header of every SQLite database. In this way, if there
+ ** is a race condition such that another thread has already populated
+ ** the first page of the database, no damage is done.
+ */
+ if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
+ do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
+ if( rc!=1 ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR;
+ }
+ rc = osFstat(fd, &statbuf);
+ if( rc!=0 ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR;
+ }
+ }
+#endif
+
+ memset(&fileId, 0, sizeof(fileId));
+ fileId.dev = statbuf.st_dev;
+#if OS_VXWORKS
+ fileId.pId = pFile->pId;
+#else
+ fileId.ino = statbuf.st_ino;
+#endif
+ pInode = inodeList;
+ while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
+ pInode = pInode->pNext;
+ }
+ if( pInode==0 ){
+ pInode = sqlite3_malloc( sizeof(*pInode) );
+ if( pInode==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(pInode, 0, sizeof(*pInode));
+ memcpy(&pInode->fileId, &fileId, sizeof(fileId));
+ pInode->nRef = 1;
+ pInode->pNext = inodeList;
+ pInode->pPrev = 0;
+ if( inodeList ) inodeList->pPrev = pInode;
+ inodeList = pInode;
+ }else{
+ pInode->nRef++;
+ }
+ *ppInode = pInode;
+ return SQLITE_OK;
+}
+
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
+static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
+ int rc = SQLITE_OK;
+ int reserved = 0;
+ unixFile *pFile = (unixFile*)id;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+ unixEnterMutex(); /* Because pFile->pInode is shared across threads */
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->pInode->eFileLock>SHARED_LOCK ){
+ reserved = 1;
+ }
+
+ /* Otherwise see if some other process holds it.
+ */
+#ifndef __DJGPP__
+ if( !reserved && !pFile->pInode->bProcessLock ){
+ struct flock lock;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = RESERVED_BYTE;
+ lock.l_len = 1;
+ lock.l_type = F_WRLCK;
+ if( osFcntl(pFile->h, F_GETLK, &lock) ){
+ rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
+ pFile->lastErrno = errno;
+ } else if( lock.l_type!=F_UNLCK ){
+ reserved = 1;
+ }
+ }
+#endif
+
+ unixLeaveMutex();
+ OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
+
+ *pResOut = reserved;
+ return rc;
+}
+
+/*
+** Attempt to set a system-lock on the file pFile. The lock is
+** described by pLock.
+**
+** If the pFile was opened read/write from unix-excl, then the only lock
+** ever obtained is an exclusive lock, and it is obtained exactly once
+** the first time any lock is attempted. All subsequent system locking
+** operations become no-ops. Locking operations still happen internally,
+** in order to coordinate access between separate database connections
+** within this process, but all of that is handled in memory and the
+** operating system does not participate.
+**
+** This function is a pass-through to fcntl(F_SETLK) if pFile is using
+** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
+** and is read-only.
+**
+** Zero is returned if the call completes successfully, or -1 if a call
+** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
+*/
+static int unixFileLock(unixFile *pFile, struct flock *pLock){
+ int rc;
+ unixInodeInfo *pInode = pFile->pInode;
+ assert( unixMutexHeld() );
+ assert( pInode!=0 );
+ if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
+ && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
+ ){
+ if( pInode->bProcessLock==0 ){
+ struct flock lock;
+ assert( pInode->nLock==0 );
+ lock.l_whence = SEEK_SET;
+ lock.l_start = SHARED_FIRST;
+ lock.l_len = SHARED_SIZE;
+ lock.l_type = F_WRLCK;
+ rc = osFcntl(pFile->h, F_SETLK, &lock);
+ if( rc<0 ) return rc;
+ pInode->bProcessLock = 1;
+ pInode->nLock++;
+ }else{
+ rc = 0;
+ }
+ }else{
+ rc = osFcntl(pFile->h, F_SETLK, pLock);
+ }
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter eFileLock - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int unixLock(sqlite3_file *id, int eFileLock){
+ /* The following describes the implementation of the various locks and
+ ** lock transitions in terms of the POSIX advisory shared and exclusive
+ ** lock primitives (called read-locks and write-locks below, to avoid
+ ** confusion with SQLite lock names). The algorithms are complicated
+ ** slightly in order to be compatible with windows systems simultaneously
+ ** accessing the same database file, in case that is ever required.
+ **
+ ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
+ ** byte', each single bytes at well known offsets, and the 'shared byte
+ ** range', a range of 510 bytes at a well known offset.
+ **
+ ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
+ ** byte'. If this is successful, a random byte from the 'shared byte
+ ** range' is read-locked and the lock on the 'pending byte' released.
+ **
+ ** A process may only obtain a RESERVED lock after it has a SHARED lock.
+ ** A RESERVED lock is implemented by grabbing a write-lock on the
+ ** 'reserved byte'.
+ **
+ ** A process may only obtain a PENDING lock after it has obtained a
+ ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
+ ** on the 'pending byte'. This ensures that no new SHARED locks can be
+ ** obtained, but existing SHARED locks are allowed to persist. A process
+ ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
+ ** This property is used by the algorithm for rolling back a journal file
+ ** after a crash.
+ **
+ ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
+ ** implemented by obtaining a write-lock on the entire 'shared byte
+ ** range'. Since all other locks require a read-lock on one of the bytes
+ ** within this range, this ensures that no other locks are held on the
+ ** database.
+ **
+ ** The reason a single byte cannot be used instead of the 'shared byte
+ ** range' is that some versions of windows do not support read-locks. By
+ ** locking a random byte from a range, concurrent SHARED locks may exist
+ ** even if the locking primitive used is always a write-lock.
+ */
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+ unixInodeInfo *pInode;
+ struct flock lock;
+ int tErrno = 0;
+
+ assert( pFile );
+ OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
+ azFileLock(eFileLock), azFileLock(pFile->eFileLock),
+ azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
+
+ /* If there is already a lock of this type or more restrictive on the
+ ** unixFile, do nothing. Don't use the end_lock: exit path, as
+ ** unixEnterMutex() hasn't been called yet.
+ */
+ if( pFile->eFileLock>=eFileLock ){
+ OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h,
+ azFileLock(eFileLock)));
+ return SQLITE_OK;
+ }
+
+ /* Make sure the locking sequence is correct.
+ ** (1) We never move from unlocked to anything higher than shared lock.
+ ** (2) SQLite never explicitly requests a pendig lock.
+ ** (3) A shared lock is always held when a reserve lock is requested.
+ */
+ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
+ assert( eFileLock!=PENDING_LOCK );
+ assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
+
+ /* This mutex is needed because pFile->pInode is shared across threads
+ */
+ unixEnterMutex();
+ pInode = pFile->pInode;
+
+ /* If some thread using this PID has a lock via a different unixFile*
+ ** handle that precludes the requested lock, return BUSY.
+ */
+ if( (pFile->eFileLock!=pInode->eFileLock &&
+ (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
+ ){
+ rc = SQLITE_BUSY;
+ goto end_lock;
+ }
+
+ /* If a SHARED lock is requested, and some thread using this PID already
+ ** has a SHARED or RESERVED lock, then increment reference counts and
+ ** return SQLITE_OK.
+ */
+ if( eFileLock==SHARED_LOCK &&
+ (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
+ assert( eFileLock==SHARED_LOCK );
+ assert( pFile->eFileLock==0 );
+ assert( pInode->nShared>0 );
+ pFile->eFileLock = SHARED_LOCK;
+ pInode->nShared++;
+ pInode->nLock++;
+ goto end_lock;
+ }
+
+
+ /* A PENDING lock is needed before acquiring a SHARED lock and before
+ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
+ ** be released.
+ */
+ lock.l_len = 1L;
+ lock.l_whence = SEEK_SET;
+ if( eFileLock==SHARED_LOCK
+ || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
+ ){
+ lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
+ lock.l_start = PENDING_BYTE;
+ if( unixFileLock(pFile, &lock) ){
+ tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( rc!=SQLITE_BUSY ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_lock;
+ }
+ }
+
+
+ /* If control gets to this point, then actually go ahead and make
+ ** operating system calls for the specified lock.
+ */
+ if( eFileLock==SHARED_LOCK ){
+ assert( pInode->nShared==0 );
+ assert( pInode->eFileLock==0 );
+ assert( rc==SQLITE_OK );
+
+ /* Now get the read-lock */
+ lock.l_start = SHARED_FIRST;
+ lock.l_len = SHARED_SIZE;
+ if( unixFileLock(pFile, &lock) ){
+ tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ }
+
+ /* Drop the temporary PENDING lock */
+ lock.l_start = PENDING_BYTE;
+ lock.l_len = 1L;
+ lock.l_type = F_UNLCK;
+ if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
+ /* This could happen with a network mount */
+ tErrno = errno;
+ rc = SQLITE_IOERR_UNLOCK;
+ }
+
+ if( rc ){
+ if( rc!=SQLITE_BUSY ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_lock;
+ }else{
+ pFile->eFileLock = SHARED_LOCK;
+ pInode->nLock++;
+ pInode->nShared = 1;
+ }
+ }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
+ /* We are trying for an exclusive lock but another thread in this
+ ** same process is still holding a shared lock. */
+ rc = SQLITE_BUSY;
+ }else{
+ /* The request was for a RESERVED or EXCLUSIVE lock. It is
+ ** assumed that there is a SHARED or greater lock on the file
+ ** already.
+ */
+ assert( 0!=pFile->eFileLock );
+ lock.l_type = F_WRLCK;
+
+ assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
+ if( eFileLock==RESERVED_LOCK ){
+ lock.l_start = RESERVED_BYTE;
+ lock.l_len = 1L;
+ }else{
+ lock.l_start = SHARED_FIRST;
+ lock.l_len = SHARED_SIZE;
+ }
+
+ if( unixFileLock(pFile, &lock) ){
+ tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( rc!=SQLITE_BUSY ){
+ pFile->lastErrno = tErrno;
+ }
+ }
+ }
+
+
+#ifdef SQLITE_DEBUG
+ /* Set up the transaction-counter change checking flags when
+ ** transitioning from a SHARED to a RESERVED lock. The change
+ ** from SHARED to RESERVED marks the beginning of a normal
+ ** write operation (not a hot journal rollback).
+ */
+ if( rc==SQLITE_OK
+ && pFile->eFileLock<=SHARED_LOCK
+ && eFileLock==RESERVED_LOCK
+ ){
+ pFile->transCntrChng = 0;
+ pFile->dbUpdate = 0;
+ pFile->inNormalWrite = 1;
+ }
+#endif
+
+
+ if( rc==SQLITE_OK ){
+ pFile->eFileLock = eFileLock;
+ pInode->eFileLock = eFileLock;
+ }else if( eFileLock==EXCLUSIVE_LOCK ){
+ pFile->eFileLock = PENDING_LOCK;
+ pInode->eFileLock = PENDING_LOCK;
+ }
+
+end_lock:
+ unixLeaveMutex();
+ OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
+ rc==SQLITE_OK ? "ok" : "failed"));
+ return rc;
+}
+
+/*
+** Add the file descriptor used by file handle pFile to the corresponding
+** pUnused list.
+*/
+static void setPendingFd(unixFile *pFile){
+ unixInodeInfo *pInode = pFile->pInode;
+ UnixUnusedFd *p = pFile->pUnused;
+ p->pNext = pInode->pUnused;
+ pInode->pUnused = p;
+ pFile->h = -1;
+ pFile->pUnused = 0;
+}
+
+/*
+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+**
+** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
+** the byte range is divided into 2 parts and the first part is unlocked then
+** set to a read lock, then the other part is simply unlocked. This works
+** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
+** remove the write lock on a region when a read lock is set.
+*/
+static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
+ unixFile *pFile = (unixFile*)id;
+ unixInodeInfo *pInode;
+ struct flock lock;
+ int rc = SQLITE_OK;
+
+ assert( pFile );
+ OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
+ pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
+ getpid()));
+
+ assert( eFileLock<=SHARED_LOCK );
+ if( pFile->eFileLock<=eFileLock ){
+ return SQLITE_OK;
+ }
+ unixEnterMutex();
+ pInode = pFile->pInode;
+ assert( pInode->nShared!=0 );
+ if( pFile->eFileLock>SHARED_LOCK ){
+ assert( pInode->eFileLock==pFile->eFileLock );
+
+#ifdef SQLITE_DEBUG
+ /* When reducing a lock such that other processes can start
+ ** reading the database file again, make sure that the
+ ** transaction counter was updated if any part of the database
+ ** file changed. If the transaction counter is not updated,
+ ** other connections to the same file might not realize that
+ ** the file has changed and hence might not know to flush their
+ ** cache. The use of a stale cache can lead to database corruption.
+ */
+ pFile->inNormalWrite = 0;
+#endif
+
+ /* downgrading to a shared lock on NFS involves clearing the write lock
+ ** before establishing the readlock - to avoid a race condition we downgrade
+ ** the lock in 2 blocks, so that part of the range will be covered by a
+ ** write lock until the rest is covered by a read lock:
+ ** 1: [WWWWW]
+ ** 2: [....W]
+ ** 3: [RRRRW]
+ ** 4: [RRRR.]
+ */
+ if( eFileLock==SHARED_LOCK ){
+
+#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
+ (void)handleNFSUnlock;
+ assert( handleNFSUnlock==0 );
+#endif
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+ if( handleNFSUnlock ){
+ int tErrno; /* Error code from system call errors */
+ off_t divSize = SHARED_SIZE - 1;
+
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = SHARED_FIRST;
+ lock.l_len = divSize;
+ if( unixFileLock(pFile, &lock)==(-1) ){
+ tErrno = errno;
+ rc = SQLITE_IOERR_UNLOCK;
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_unlock;
+ }
+ lock.l_type = F_RDLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = SHARED_FIRST;
+ lock.l_len = divSize;
+ if( unixFileLock(pFile, &lock)==(-1) ){
+ tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_unlock;
+ }
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = SHARED_FIRST+divSize;
+ lock.l_len = SHARED_SIZE-divSize;
+ if( unixFileLock(pFile, &lock)==(-1) ){
+ tErrno = errno;
+ rc = SQLITE_IOERR_UNLOCK;
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_unlock;
+ }
+ }else
+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+ {
+ lock.l_type = F_RDLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = SHARED_FIRST;
+ lock.l_len = SHARED_SIZE;
+ if( unixFileLock(pFile, &lock) ){
+ /* In theory, the call to unixFileLock() cannot fail because another
+ ** process is holding an incompatible lock. If it does, this
+ ** indicates that the other process is not following the locking
+ ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
+ ** SQLITE_BUSY would confuse the upper layer (in practice it causes
+ ** an assert to fail). */
+ rc = SQLITE_IOERR_RDLOCK;
+ pFile->lastErrno = errno;
+ goto end_unlock;
+ }
+ }
+ }
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = PENDING_BYTE;
+ lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
+ if( unixFileLock(pFile, &lock)==0 ){
+ pInode->eFileLock = SHARED_LOCK;
+ }else{
+ rc = SQLITE_IOERR_UNLOCK;
+ pFile->lastErrno = errno;
+ goto end_unlock;
+ }
+ }
+ if( eFileLock==NO_LOCK ){
+ /* Decrement the shared lock counter. Release the lock using an
+ ** OS call only when all threads in this same process have released
+ ** the lock.
+ */
+ pInode->nShared--;
+ if( pInode->nShared==0 ){
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = lock.l_len = 0L;
+ if( unixFileLock(pFile, &lock)==0 ){
+ pInode->eFileLock = NO_LOCK;
+ }else{
+ rc = SQLITE_IOERR_UNLOCK;
+ pFile->lastErrno = errno;
+ pInode->eFileLock = NO_LOCK;
+ pFile->eFileLock = NO_LOCK;
+ }
+ }
+
+ /* Decrement the count of locks against this same file. When the
+ ** count reaches zero, close any other file descriptors whose close
+ ** was deferred because of outstanding locks.
+ */
+ pInode->nLock--;
+ assert( pInode->nLock>=0 );
+ if( pInode->nLock==0 ){
+ closePendingFds(pFile);
+ }
+ }
+
+end_unlock:
+ unixLeaveMutex();
+ if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+ return rc;
+}
+
+/*
+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int unixUnlock(sqlite3_file *id, int eFileLock){
+ return posixUnlock(id, eFileLock, 0);
+}
+
+/*
+** This function performs the parts of the "close file" operation
+** common to all locking schemes. It closes the directory and file
+** handles, if they are valid, and sets all fields of the unixFile
+** structure to 0.
+**
+** It is *not* necessary to hold the mutex when this routine is called,
+** even on VxWorks. A mutex will be acquired on VxWorks by the
+** vxworksReleaseFileId() routine.
+*/
+static int closeUnixFile(sqlite3_file *id){
+ unixFile *pFile = (unixFile*)id;
+ if( pFile->h>=0 ){
+ robust_close(pFile, pFile->h, __LINE__);
+ pFile->h = -1;
+ }
+#if OS_VXWORKS
+ if( pFile->pId ){
+ if( pFile->ctrlFlags & UNIXFILE_DELETE ){
+ osUnlink(pFile->pId->zCanonicalName);
+ }
+ vxworksReleaseFileId(pFile->pId);
+ pFile->pId = 0;
+ }
+#endif
+ OSTRACE(("CLOSE %-3d\n", pFile->h));
+ OpenCounter(-1);
+ sqlite3_free(pFile->pUnused);
+ memset(pFile, 0, sizeof(unixFile));
+ return SQLITE_OK;
+}
+
+/*
+** Close a file.
+*/
+static int unixClose(sqlite3_file *id){
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile *)id;
+ unixUnlock(id, NO_LOCK);
+ unixEnterMutex();
+
+ /* unixFile.pInode is always valid here. Otherwise, a different close
+ ** routine (e.g. nolockClose()) would be called instead.
+ */
+ assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
+ if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
+ /* If there are outstanding locks, do not actually close the file just
+ ** yet because that would clear those locks. Instead, add the file
+ ** descriptor to pInode->pUnused list. It will be automatically closed
+ ** when the last lock is cleared.
+ */
+ setPendingFd(pFile);
+ }
+ releaseInodeInfo(pFile);
+ rc = closeUnixFile(id);
+ unixLeaveMutex();
+ return rc;
+}
+
+/************** End of the posix advisory lock implementation *****************
+******************************************************************************/
+
+/******************************************************************************
+****************************** No-op Locking **********************************
+**
+** Of the various locking implementations available, this is by far the
+** simplest: locking is ignored. No attempt is made to lock the database
+** file for reading or writing.
+**
+** This locking mode is appropriate for use on read-only databases
+** (ex: databases that are burned into CD-ROM, for example.) It can
+** also be used if the application employs some external mechanism to
+** prevent simultaneous access of the same database by two or more
+** database connections. But there is a serious risk of database
+** corruption if this locking mode is used in situations where multiple
+** database connections are accessing the same database file at the same
+** time and one or more of those connections are writing.
+*/
+
+static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
+ UNUSED_PARAMETER(NotUsed);
+ *pResOut = 0;
+ return SQLITE_OK;
+}
+static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ return SQLITE_OK;
+}
+static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ return SQLITE_OK;
+}
+
+/*
+** Close the file.
+*/
+static int nolockClose(sqlite3_file *id) {
+ return closeUnixFile(id);
+}
+
+/******************* End of the no-op lock implementation *********************
+******************************************************************************/
+
+/******************************************************************************
+************************* Begin dot-file Locking ******************************
+**
+** The dotfile locking implementation uses the existence of separate lock
+** files (really a directory) to control access to the database. This works
+** on just about every filesystem imaginable. But there are serious downsides:
+**
+** (1) There is zero concurrency. A single reader blocks all other
+** connections from reading or writing the database.
+**
+** (2) An application crash or power loss can leave stale lock files
+** sitting around that need to be cleared manually.
+**
+** Nevertheless, a dotlock is an appropriate locking mode for use if no
+** other locking strategy is available.
+**
+** Dotfile locking works by creating a subdirectory in the same directory as
+** the database and with the same name but with a ".lock" extension added.
+** The existence of a lock directory implies an EXCLUSIVE lock. All other
+** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
+*/
+
+/*
+** The file suffix added to the data base filename in order to create the
+** lock directory.
+*/
+#define DOTLOCK_SUFFIX ".lock"
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+**
+** In dotfile locking, either a lock exists or it does not. So in this
+** variation of CheckReservedLock(), *pResOut is set to true if any lock
+** is held on the file and false if the file is unlocked.
+*/
+static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
+ int rc = SQLITE_OK;
+ int reserved = 0;
+ unixFile *pFile = (unixFile*)id;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->eFileLock>SHARED_LOCK ){
+ /* Either this connection or some other connection in the same process
+ ** holds a lock on the file. No need to check further. */
+ reserved = 1;
+ }else{
+ /* The lock is held if and only if the lockfile exists */
+ const char *zLockFile = (const char*)pFile->lockingContext;
+ reserved = osAccess(zLockFile, 0)==0;
+ }
+ OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
+ *pResOut = reserved;
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter eFileLock - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+**
+** With dotfile locking, we really only support state (4): EXCLUSIVE.
+** But we track the other locking levels internally.
+*/
+static int dotlockLock(sqlite3_file *id, int eFileLock) {
+ unixFile *pFile = (unixFile*)id;
+ char *zLockFile = (char *)pFile->lockingContext;
+ int rc = SQLITE_OK;
+
+
+ /* If we have any lock, then the lock file already exists. All we have
+ ** to do is adjust our internal record of the lock level.
+ */
+ if( pFile->eFileLock > NO_LOCK ){
+ pFile->eFileLock = eFileLock;
+ /* Always update the timestamp on the old file */
+#ifdef HAVE_UTIME
+ utime(zLockFile, NULL);
+#else
+ utimes(zLockFile, NULL);
+#endif
+ return SQLITE_OK;
+ }
+
+ /* grab an exclusive lock */
+ rc = osMkdir(zLockFile, 0777);
+ if( rc<0 ){
+ /* failed to open/create the lock directory */
+ int tErrno = errno;
+ if( EEXIST == tErrno ){
+ rc = SQLITE_BUSY;
+ } else {
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ }
+ return rc;
+ }
+
+ /* got it, set the type and return ok */
+ pFile->eFileLock = eFileLock;
+ return rc;
+}
+
+/*
+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+**
+** When the locking level reaches NO_LOCK, delete the lock file.
+*/
+static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
+ unixFile *pFile = (unixFile*)id;
+ char *zLockFile = (char *)pFile->lockingContext;
+ int rc;
+
+ assert( pFile );
+ OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
+ pFile->eFileLock, getpid()));
+ assert( eFileLock<=SHARED_LOCK );
+
+ /* no-op if possible */
+ if( pFile->eFileLock==eFileLock ){
+ return SQLITE_OK;
+ }
+
+ /* To downgrade to shared, simply update our internal notion of the
+ ** lock state. No need to mess with the file on disk.
+ */
+ if( eFileLock==SHARED_LOCK ){
+ pFile->eFileLock = SHARED_LOCK;
+ return SQLITE_OK;
+ }
+
+ /* To fully unlock the database, delete the lock file */
+ assert( eFileLock==NO_LOCK );
+ rc = osRmdir(zLockFile);
+ if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
+ if( rc<0 ){
+ int tErrno = errno;
+ rc = 0;
+ if( ENOENT != tErrno ){
+ rc = SQLITE_IOERR_UNLOCK;
+ }
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ return rc;
+ }
+ pFile->eFileLock = NO_LOCK;
+ return SQLITE_OK;
+}
+
+/*
+** Close a file. Make sure the lock has been released before closing.
+*/
+static int dotlockClose(sqlite3_file *id) {
+ int rc = SQLITE_OK;
+ if( id ){
+ unixFile *pFile = (unixFile*)id;
+ dotlockUnlock(id, NO_LOCK);
+ sqlite3_free(pFile->lockingContext);
+ rc = closeUnixFile(id);
+ }
+ return rc;
+}
+/****************** End of the dot-file lock implementation *******************
+******************************************************************************/
+
+/******************************************************************************
+************************** Begin flock Locking ********************************
+**
+** Use the flock() system call to do file locking.
+**
+** flock() locking is like dot-file locking in that the various
+** fine-grain locking levels supported by SQLite are collapsed into
+** a single exclusive lock. In other words, SHARED, RESERVED, and
+** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
+** still works when you do this, but concurrency is reduced since
+** only a single process can be reading the database at a time.
+**
+** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
+** compiling for VXWORKS.
+*/
+#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+
+/*
+** Retry flock() calls that fail with EINTR
+*/
+#ifdef EINTR
+static int robust_flock(int fd, int op){
+ int rc;
+ do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
+ return rc;
+}
+#else
+# define robust_flock(a,b) flock(a,b)
+#endif
+
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
+static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
+ int rc = SQLITE_OK;
+ int reserved = 0;
+ unixFile *pFile = (unixFile*)id;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->eFileLock>SHARED_LOCK ){
+ reserved = 1;
+ }
+
+ /* Otherwise see if some other process holds it. */
+ if( !reserved ){
+ /* attempt to get the lock */
+ int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
+ if( !lrc ){
+ /* got the lock, unlock it */
+ lrc = robust_flock(pFile->h, LOCK_UN);
+ if ( lrc ) {
+ int tErrno = errno;
+ /* unlock failed with an error */
+ lrc = SQLITE_IOERR_UNLOCK;
+ if( IS_LOCK_ERROR(lrc) ){
+ pFile->lastErrno = tErrno;
+ rc = lrc;
+ }
+ }
+ } else {
+ int tErrno = errno;
+ reserved = 1;
+ /* someone else might have it reserved */
+ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(lrc) ){
+ pFile->lastErrno = tErrno;
+ rc = lrc;
+ }
+ }
+ }
+ OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
+
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ rc = SQLITE_OK;
+ reserved=1;
+ }
+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+ *pResOut = reserved;
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter eFileLock - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** flock() only really support EXCLUSIVE locks. We track intermediate
+** lock states in the sqlite3_file structure, but all locks SHARED or
+** above are really EXCLUSIVE locks and exclude all other processes from
+** access the file.
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int flockLock(sqlite3_file *id, int eFileLock) {
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+
+ assert( pFile );
+
+ /* if we already have a lock, it is exclusive.
+ ** Just adjust level and punt on outta here. */
+ if (pFile->eFileLock > NO_LOCK) {
+ pFile->eFileLock = eFileLock;
+ return SQLITE_OK;
+ }
+
+ /* grab an exclusive lock */
+
+ if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
+ int tErrno = errno;
+ /* didn't get, must be busy */
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ } else {
+ /* got it, set the type and return ok */
+ pFile->eFileLock = eFileLock;
+ }
+ OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
+ rc==SQLITE_OK ? "ok" : "failed"));
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ rc = SQLITE_BUSY;
+ }
+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+ return rc;
+}
+
+
+/*
+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int flockUnlock(sqlite3_file *id, int eFileLock) {
+ unixFile *pFile = (unixFile*)id;
+
+ assert( pFile );
+ OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
+ pFile->eFileLock, getpid()));
+ assert( eFileLock<=SHARED_LOCK );
+
+ /* no-op if possible */
+ if( pFile->eFileLock==eFileLock ){
+ return SQLITE_OK;
+ }
+
+ /* shared can just be set because we always have an exclusive */
+ if (eFileLock==SHARED_LOCK) {
+ pFile->eFileLock = eFileLock;
+ return SQLITE_OK;
+ }
+
+ /* no, really, unlock. */
+ if( robust_flock(pFile->h, LOCK_UN) ){
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ return SQLITE_OK;
+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+ return SQLITE_IOERR_UNLOCK;
+ }else{
+ pFile->eFileLock = NO_LOCK;
+ return SQLITE_OK;
+ }
+}
+
+/*
+** Close a file.
+*/
+static int flockClose(sqlite3_file *id) {
+ int rc = SQLITE_OK;
+ if( id ){
+ flockUnlock(id, NO_LOCK);
+ rc = closeUnixFile(id);
+ }
+ return rc;
+}
+
+#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
+
+/******************* End of the flock lock implementation *********************
+******************************************************************************/
+
+/******************************************************************************
+************************ Begin Named Semaphore Locking ************************
+**
+** Named semaphore locking is only supported on VxWorks.
+**
+** Semaphore locking is like dot-lock and flock in that it really only
+** supports EXCLUSIVE locking. Only a single process can read or write
+** the database file at a time. This reduces potential concurrency, but
+** makes the lock implementation much easier.
+*/
+#if OS_VXWORKS
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
+static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
+ int rc = SQLITE_OK;
+ int reserved = 0;
+ unixFile *pFile = (unixFile*)id;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->eFileLock>SHARED_LOCK ){
+ reserved = 1;
+ }
+
+ /* Otherwise see if some other process holds it. */
+ if( !reserved ){
+ sem_t *pSem = pFile->pInode->pSem;
+ struct stat statBuf;
+
+ if( sem_trywait(pSem)==-1 ){
+ int tErrno = errno;
+ if( EAGAIN != tErrno ){
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
+ pFile->lastErrno = tErrno;
+ } else {
+ /* someone else has the lock when we are in NO_LOCK */
+ reserved = (pFile->eFileLock < SHARED_LOCK);
+ }
+ }else{
+ /* we could have it if we want it */
+ sem_post(pSem);
+ }
+ }
+ OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
+
+ *pResOut = reserved;
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter eFileLock - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
+** lock states in the sqlite3_file structure, but all locks SHARED or
+** above are really EXCLUSIVE locks and exclude all other processes from
+** access the file.
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int semLock(sqlite3_file *id, int eFileLock) {
+ unixFile *pFile = (unixFile*)id;
+ int fd;
+ sem_t *pSem = pFile->pInode->pSem;
+ int rc = SQLITE_OK;
+
+ /* if we already have a lock, it is exclusive.
+ ** Just adjust level and punt on outta here. */
+ if (pFile->eFileLock > NO_LOCK) {
+ pFile->eFileLock = eFileLock;
+ rc = SQLITE_OK;
+ goto sem_end_lock;
+ }
+
+ /* lock semaphore now but bail out when already locked. */
+ if( sem_trywait(pSem)==-1 ){
+ rc = SQLITE_BUSY;
+ goto sem_end_lock;
+ }
+
+ /* got it, set the type and return ok */
+ pFile->eFileLock = eFileLock;
+
+ sem_end_lock:
+ return rc;
+}
+
+/*
+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int semUnlock(sqlite3_file *id, int eFileLock) {
+ unixFile *pFile = (unixFile*)id;
+ sem_t *pSem = pFile->pInode->pSem;
+
+ assert( pFile );
+ assert( pSem );
+ OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
+ pFile->eFileLock, getpid()));
+ assert( eFileLock<=SHARED_LOCK );
+
+ /* no-op if possible */
+ if( pFile->eFileLock==eFileLock ){
+ return SQLITE_OK;
+ }
+
+ /* shared can just be set because we always have an exclusive */
+ if (eFileLock==SHARED_LOCK) {
+ pFile->eFileLock = eFileLock;
+ return SQLITE_OK;
+ }
+
+ /* no, really unlock. */
+ if ( sem_post(pSem)==-1 ) {
+ int rc, tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ return rc;
+ }
+ pFile->eFileLock = NO_LOCK;
+ return SQLITE_OK;
+}
+
+/*
+ ** Close a file.
+ */
+static int semClose(sqlite3_file *id) {
+ if( id ){
+ unixFile *pFile = (unixFile*)id;
+ semUnlock(id, NO_LOCK);
+ assert( pFile );
+ unixEnterMutex();
+ releaseInodeInfo(pFile);
+ unixLeaveMutex();
+ closeUnixFile(id);
+ }
+ return SQLITE_OK;
+}
+
+#endif /* OS_VXWORKS */
+/*
+** Named semaphore locking is only available on VxWorks.
+**
+*************** End of the named semaphore lock implementation ****************
+******************************************************************************/
+
+
+/******************************************************************************
+*************************** Begin AFP Locking *********************************
+**
+** AFP is the Apple Filing Protocol. AFP is a network filesystem found
+** on Apple Macintosh computers - both OS9 and OSX.
+**
+** Third-party implementations of AFP are available. But this code here
+** only works on OSX.
+*/
+
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+/*
+** The afpLockingContext structure contains all afp lock specific state
+*/
+typedef struct afpLockingContext afpLockingContext;
+struct afpLockingContext {
+ int reserved;
+ const char *dbPath; /* Name of the open file */
+};
+
+struct ByteRangeLockPB2
+{
+ unsigned long long offset; /* offset to first byte to lock */
+ unsigned long long length; /* nbr of bytes to lock */
+ unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
+ unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
+ unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
+ int fd; /* file desc to assoc this lock with */
+};
+
+#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
+
+/*
+** This is a utility for setting or clearing a bit-range lock on an
+** AFP filesystem.
+**
+** Return SQLITE_OK on success, SQLITE_BUSY on failure.
+*/
+static int afpSetLock(
+ const char *path, /* Name of the file to be locked or unlocked */
+ unixFile *pFile, /* Open file descriptor on path */
+ unsigned long long offset, /* First byte to be locked */
+ unsigned long long length, /* Number of bytes to lock */
+ int setLockFlag /* True to set lock. False to clear lock */
+){
+ struct ByteRangeLockPB2 pb;
+ int err;
+
+ pb.unLockFlag = setLockFlag ? 0 : 1;
+ pb.startEndFlag = 0;
+ pb.offset = offset;
+ pb.length = length;
+ pb.fd = pFile->h;
+
+ OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
+ (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
+ offset, length));
+ err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
+ if ( err==-1 ) {
+ int rc;
+ int tErrno = errno;
+ OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
+ path, tErrno, strerror(tErrno)));
+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
+ rc = SQLITE_BUSY;
+#else
+ rc = sqliteErrorFromPosixError(tErrno,
+ setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
+#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ return rc;
+ } else {
+ return SQLITE_OK;
+ }
+}
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
+static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
+ int rc = SQLITE_OK;
+ int reserved = 0;
+ unixFile *pFile = (unixFile*)id;
+ afpLockingContext *context;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+ context = (afpLockingContext *) pFile->lockingContext;
+ if( context->reserved ){
+ *pResOut = 1;
+ return SQLITE_OK;
+ }
+ unixEnterMutex(); /* Because pFile->pInode is shared across threads */
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->pInode->eFileLock>SHARED_LOCK ){
+ reserved = 1;
+ }
+
+ /* Otherwise see if some other process holds it.
+ */
+ if( !reserved ){
+ /* lock the RESERVED byte */
+ int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
+ if( SQLITE_OK==lrc ){
+ /* if we succeeded in taking the reserved lock, unlock it to restore
+ ** the original state */
+ lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
+ } else {
+ /* if we failed to get the lock then someone else must have it */
+ reserved = 1;
+ }
+ if( IS_LOCK_ERROR(lrc) ){
+ rc=lrc;
+ }
+ }
+
+ unixLeaveMutex();
+ OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
+
+ *pResOut = reserved;
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter eFileLock - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int afpLock(sqlite3_file *id, int eFileLock){
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+ unixInodeInfo *pInode = pFile->pInode;
+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+
+ assert( pFile );
+ OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
+ azFileLock(eFileLock), azFileLock(pFile->eFileLock),
+ azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
+
+ /* If there is already a lock of this type or more restrictive on the
+ ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
+ ** unixEnterMutex() hasn't been called yet.
+ */
+ if( pFile->eFileLock>=eFileLock ){
+ OSTRACE(("LOCK %d %s ok (already held) (afp)\n", pFile->h,
+ azFileLock(eFileLock)));
+ return SQLITE_OK;
+ }
+
+ /* Make sure the locking sequence is correct
+ ** (1) We never move from unlocked to anything higher than shared lock.
+ ** (2) SQLite never explicitly requests a pendig lock.
+ ** (3) A shared lock is always held when a reserve lock is requested.
+ */
+ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
+ assert( eFileLock!=PENDING_LOCK );
+ assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
+
+ /* This mutex is needed because pFile->pInode is shared across threads
+ */
+ unixEnterMutex();
+ pInode = pFile->pInode;
+
+ /* If some thread using this PID has a lock via a different unixFile*
+ ** handle that precludes the requested lock, return BUSY.
+ */
+ if( (pFile->eFileLock!=pInode->eFileLock &&
+ (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
+ ){
+ rc = SQLITE_BUSY;
+ goto afp_end_lock;
+ }
+
+ /* If a SHARED lock is requested, and some thread using this PID already
+ ** has a SHARED or RESERVED lock, then increment reference counts and
+ ** return SQLITE_OK.
+ */
+ if( eFileLock==SHARED_LOCK &&
+ (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
+ assert( eFileLock==SHARED_LOCK );
+ assert( pFile->eFileLock==0 );
+ assert( pInode->nShared>0 );
+ pFile->eFileLock = SHARED_LOCK;
+ pInode->nShared++;
+ pInode->nLock++;
+ goto afp_end_lock;
+ }
+
+ /* A PENDING lock is needed before acquiring a SHARED lock and before
+ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
+ ** be released.
+ */
+ if( eFileLock==SHARED_LOCK
+ || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
+ ){
+ int failed;
+ failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
+ if (failed) {
+ rc = failed;
+ goto afp_end_lock;
+ }
+ }
+
+ /* If control gets to this point, then actually go ahead and make
+ ** operating system calls for the specified lock.
+ */
+ if( eFileLock==SHARED_LOCK ){
+ int lrc1, lrc2, lrc1Errno = 0;
+ long lk, mask;
+
+ assert( pInode->nShared==0 );
+ assert( pInode->eFileLock==0 );
+
+ mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
+ /* Now get the read-lock SHARED_LOCK */
+ /* note that the quality of the randomness doesn't matter that much */
+ lk = random();
+ pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
+ lrc1 = afpSetLock(context->dbPath, pFile,
+ SHARED_FIRST+pInode->sharedByte, 1, 1);
+ if( IS_LOCK_ERROR(lrc1) ){
+ lrc1Errno = pFile->lastErrno;
+ }
+ /* Drop the temporary PENDING lock */
+ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
+
+ if( IS_LOCK_ERROR(lrc1) ) {
+ pFile->lastErrno = lrc1Errno;
+ rc = lrc1;
+ goto afp_end_lock;
+ } else if( IS_LOCK_ERROR(lrc2) ){
+ rc = lrc2;
+ goto afp_end_lock;
+ } else if( lrc1 != SQLITE_OK ) {
+ rc = lrc1;
+ } else {
+ pFile->eFileLock = SHARED_LOCK;
+ pInode->nLock++;
+ pInode->nShared = 1;
+ }
+ }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
+ /* We are trying for an exclusive lock but another thread in this
+ ** same process is still holding a shared lock. */
+ rc = SQLITE_BUSY;
+ }else{
+ /* The request was for a RESERVED or EXCLUSIVE lock. It is
+ ** assumed that there is a SHARED or greater lock on the file
+ ** already.
+ */
+ int failed = 0;
+ assert( 0!=pFile->eFileLock );
+ if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
+ /* Acquire a RESERVED lock */
+ failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
+ if( !failed ){
+ context->reserved = 1;
+ }
+ }
+ if (!failed && eFileLock == EXCLUSIVE_LOCK) {
+ /* Acquire an EXCLUSIVE lock */
+
+ /* Remove the shared lock before trying the range. we'll need to
+ ** reestablish the shared lock if we can't get the afpUnlock
+ */
+ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
+ pInode->sharedByte, 1, 0)) ){
+ int failed2 = SQLITE_OK;
+ /* now attemmpt to get the exclusive lock range */
+ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
+ SHARED_SIZE, 1);
+ if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
+ SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
+ /* Can't reestablish the shared lock. Sqlite can't deal, this is
+ ** a critical I/O error
+ */
+ rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
+ SQLITE_IOERR_LOCK;
+ goto afp_end_lock;
+ }
+ }else{
+ rc = failed;
+ }
+ }
+ if( failed ){
+ rc = failed;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ pFile->eFileLock = eFileLock;
+ pInode->eFileLock = eFileLock;
+ }else if( eFileLock==EXCLUSIVE_LOCK ){
+ pFile->eFileLock = PENDING_LOCK;
+ pInode->eFileLock = PENDING_LOCK;
+ }
+
+afp_end_lock:
+ unixLeaveMutex();
+ OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
+ rc==SQLITE_OK ? "ok" : "failed"));
+ return rc;
+}
+
+/*
+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int afpUnlock(sqlite3_file *id, int eFileLock) {
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+ unixInodeInfo *pInode;
+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+ int skipShared = 0;
+#ifdef SQLITE_TEST
+ int h = pFile->h;
+#endif
+
+ assert( pFile );
+ OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
+ pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
+ getpid()));
+
+ assert( eFileLock<=SHARED_LOCK );
+ if( pFile->eFileLock<=eFileLock ){
+ return SQLITE_OK;
+ }
+ unixEnterMutex();
+ pInode = pFile->pInode;
+ assert( pInode->nShared!=0 );
+ if( pFile->eFileLock>SHARED_LOCK ){
+ assert( pInode->eFileLock==pFile->eFileLock );
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
+
+#ifdef SQLITE_DEBUG
+ /* When reducing a lock such that other processes can start
+ ** reading the database file again, make sure that the
+ ** transaction counter was updated if any part of the database
+ ** file changed. If the transaction counter is not updated,
+ ** other connections to the same file might not realize that
+ ** the file has changed and hence might not know to flush their
+ ** cache. The use of a stale cache can lead to database corruption.
+ */
+ assert( pFile->inNormalWrite==0
+ || pFile->dbUpdate==0
+ || pFile->transCntrChng==1 );
+ pFile->inNormalWrite = 0;
+#endif
+
+ if( pFile->eFileLock==EXCLUSIVE_LOCK ){
+ rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
+ if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
+ /* only re-establish the shared lock if necessary */
+ int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
+ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
+ } else {
+ skipShared = 1;
+ }
+ }
+ if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
+ rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
+ }
+ if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
+ rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
+ if( !rc ){
+ context->reserved = 0;
+ }
+ }
+ if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
+ pInode->eFileLock = SHARED_LOCK;
+ }
+ }
+ if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
+
+ /* Decrement the shared lock counter. Release the lock using an
+ ** OS call only when all threads in this same process have released
+ ** the lock.
+ */
+ unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
+ pInode->nShared--;
+ if( pInode->nShared==0 ){
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
+ if( !skipShared ){
+ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
+ }
+ if( !rc ){
+ pInode->eFileLock = NO_LOCK;
+ pFile->eFileLock = NO_LOCK;
+ }
+ }
+ if( rc==SQLITE_OK ){
+ pInode->nLock--;
+ assert( pInode->nLock>=0 );
+ if( pInode->nLock==0 ){
+ closePendingFds(pFile);
+ }
+ }
+ }
+
+ unixLeaveMutex();
+ if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+ return rc;
+}
+
+/*
+** Close a file & cleanup AFP specific locking context
+*/
+static int afpClose(sqlite3_file *id) {
+ int rc = SQLITE_OK;
+ if( id ){
+ unixFile *pFile = (unixFile*)id;
+ afpUnlock(id, NO_LOCK);
+ unixEnterMutex();
+ if( pFile->pInode && pFile->pInode->nLock ){
+ /* If there are outstanding locks, do not actually close the file just
+ ** yet because that would clear those locks. Instead, add the file
+ ** descriptor to pInode->aPending. It will be automatically closed when
+ ** the last lock is cleared.
+ */
+ setPendingFd(pFile);
+ }
+ releaseInodeInfo(pFile);
+ sqlite3_free(pFile->lockingContext);
+ rc = closeUnixFile(id);
+ unixLeaveMutex();
+ }
+ return rc;
+}
+
+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+/*
+** The code above is the AFP lock implementation. The code is specific
+** to MacOSX and does not work on other unix platforms. No alternative
+** is available. If you don't compile for a mac, then the "unix-afp"
+** VFS is not available.
+**
+********************* End of the AFP lock implementation **********************
+******************************************************************************/
+
+/******************************************************************************
+*************************** Begin NFS Locking ********************************/
+
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+/*
+ ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+ ** must be either NO_LOCK or SHARED_LOCK.
+ **
+ ** If the locking level of the file descriptor is already at or below
+ ** the requested locking level, this routine is a no-op.
+ */
+static int nfsUnlock(sqlite3_file *id, int eFileLock){
+ return posixUnlock(id, eFileLock, 1);
+}
+
+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+/*
+** The code above is the NFS lock implementation. The code is specific
+** to MacOSX and does not work on other unix platforms. No alternative
+** is available.
+**
+********************* End of the NFS lock implementation **********************
+******************************************************************************/
+
+/******************************************************************************
+**************** Non-locking sqlite3_file methods *****************************
+**
+** The next division contains implementations for all methods of the
+** sqlite3_file object other than the locking methods. The locking
+** methods were defined in divisions above (one locking method per
+** division). Those methods that are common to all locking modes
+** are gather together into this division.
+*/
+
+/*
+** Seek to the offset passed as the second argument, then read cnt
+** bytes into pBuf. Return the number of bytes actually read.
+**
+** NB: If you define USE_PREAD or USE_PREAD64, then it might also
+** be necessary to define _XOPEN_SOURCE to be 500. This varies from
+** one system to another. Since SQLite does not define USE_PREAD
+** any any form by default, we will not attempt to define _XOPEN_SOURCE.
+** See tickets #2741 and #2681.
+**
+** To avoid stomping the errno value on a failed read the lastErrno value
+** is set before returning.
+*/
+static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
+ int got;
+ int prior = 0;
+#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
+ i64 newOffset;
+#endif
+ TIMER_START;
+ assert( cnt==(cnt&0x1ffff) );
+ cnt &= 0x1ffff;
+ do{
+#if defined(USE_PREAD)
+ got = osPread(id->h, pBuf, cnt, offset);
+ SimulateIOError( got = -1 );
+#elif defined(USE_PREAD64)
+ got = osPread64(id->h, pBuf, cnt, offset);
+ SimulateIOError( got = -1 );
+#else
+ newOffset = lseek(id->h, offset, SEEK_SET);
+ SimulateIOError( newOffset-- );
+ if( newOffset!=offset ){
+ if( newOffset == -1 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }else{
+ ((unixFile*)id)->lastErrno = 0;
+ }
+ return -1;
+ }
+ got = osRead(id->h, pBuf, cnt);
+#endif
+ if( got==cnt ) break;
+ if( got<0 ){
+ if( errno==EINTR ){ got = 1; continue; }
+ prior = 0;
+ ((unixFile*)id)->lastErrno = errno;
+ break;
+ }else if( got>0 ){
+ cnt -= got;
+ offset += got;
+ prior += got;
+ pBuf = (void*)(got + (char*)pBuf);
+ }
+ }while( got>0 );
+ TIMER_END;
+ OSTRACE(("READ %-3d %5d %7lld %llu\n",
+ id->h, got+prior, offset-prior, TIMER_ELAPSED));
+ return got+prior;
+}
+
+/*
+** Read data from a file into a buffer. Return SQLITE_OK if all
+** bytes were read successfully and SQLITE_IOERR if anything goes
+** wrong.
+*/
+static int unixRead(
+ sqlite3_file *id,
+ void *pBuf,
+ int amt,
+ sqlite3_int64 offset
+){
+ unixFile *pFile = (unixFile *)id;
+ int got;
+ assert( id );
+
+ /* If this is a database file (not a journal, master-journal or temp
+ ** file), the bytes in the locking range should never be read or written. */
+#if 0
+ assert( pFile->pUnused==0
+ || offset>=PENDING_BYTE+512
+ || offset+amt<=PENDING_BYTE
+ );
+#endif
+
+ got = seekAndRead(pFile, offset, pBuf, amt);
+ if( got==amt ){
+ return SQLITE_OK;
+ }else if( got<0 ){
+ /* lastErrno set by seekAndRead */
+ return SQLITE_IOERR_READ;
+ }else{
+ pFile->lastErrno = 0; /* not a system error */
+ /* Unread parts of the buffer must be zero-filled */
+ memset(&((char*)pBuf)[got], 0, amt-got);
+ return SQLITE_IOERR_SHORT_READ;
+ }
+}
+
+/*
+** Seek to the offset in id->offset then read cnt bytes into pBuf.
+** Return the number of bytes actually read. Update the offset.
+**
+** To avoid stomping the errno value on a failed write the lastErrno value
+** is set before returning.
+*/
+static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
+ int got;
+#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
+ i64 newOffset;
+#endif
+ assert( cnt==(cnt&0x1ffff) );
+ cnt &= 0x1ffff;
+ TIMER_START;
+#if defined(USE_PREAD)
+ do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
+#elif defined(USE_PREAD64)
+ do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
+#else
+ do{
+ newOffset = lseek(id->h, offset, SEEK_SET);
+ SimulateIOError( newOffset-- );
+ if( newOffset!=offset ){
+ if( newOffset == -1 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }else{
+ ((unixFile*)id)->lastErrno = 0;
+ }
+ return -1;
+ }
+ got = osWrite(id->h, pBuf, cnt);
+ }while( got<0 && errno==EINTR );
+#endif
+ TIMER_END;
+ if( got<0 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }
+
+ OSTRACE(("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
+ return got;
+}
+
+
+/*
+** Write data from a buffer into a file. Return SQLITE_OK on success
+** or some other error code on failure.
+*/
+static int unixWrite(
+ sqlite3_file *id,
+ const void *pBuf,
+ int amt,
+ sqlite3_int64 offset
+){
+ unixFile *pFile = (unixFile*)id;
+ int wrote = 0;
+ assert( id );
+ assert( amt>0 );
+
+ /* If this is a database file (not a journal, master-journal or temp
+ ** file), the bytes in the locking range should never be read or written. */
+#if 0
+ assert( pFile->pUnused==0
+ || offset>=PENDING_BYTE+512
+ || offset+amt<=PENDING_BYTE
+ );
+#endif
+
+#ifdef SQLITE_DEBUG
+ /* If we are doing a normal write to a database file (as opposed to
+ ** doing a hot-journal rollback or a write to some file other than a
+ ** normal database file) then record the fact that the database
+ ** has changed. If the transaction counter is modified, record that
+ ** fact too.
+ */
+ if( pFile->inNormalWrite ){
+ pFile->dbUpdate = 1; /* The database has been modified */
+ if( offset<=24 && offset+amt>=27 ){
+ int rc;
+ char oldCntr[4];
+ SimulateIOErrorBenign(1);
+ rc = seekAndRead(pFile, 24, oldCntr, 4);
+ SimulateIOErrorBenign(0);
+ if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
+ pFile->transCntrChng = 1; /* The transaction counter has changed */
+ }
+ }
+ }
+#endif
+
+ while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
+ amt -= wrote;
+ offset += wrote;
+ pBuf = &((char*)pBuf)[wrote];
+ }
+ SimulateIOError(( wrote=(-1), amt=1 ));
+ SimulateDiskfullError(( wrote=0, amt=1 ));
+
+ if( amt>0 ){
+ if( wrote<0 && pFile->lastErrno!=ENOSPC ){
+ /* lastErrno set by seekAndWrite */
+ return SQLITE_IOERR_WRITE;
+ }else{
+ pFile->lastErrno = 0; /* not a system error */
+ return SQLITE_FULL;
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+#ifdef SQLITE_TEST
+/*
+** Count the number of fullsyncs and normal syncs. This is used to test
+** that syncs and fullsyncs are occurring at the right times.
+*/
+SQLITE_API int sqlite3_sync_count = 0;
+SQLITE_API int sqlite3_fullsync_count = 0;
+#endif
+
+/*
+** We do not trust systems to provide a working fdatasync(). Some do.
+** Others do no. To be safe, we will stick with the (slightly slower)
+** fsync(). If you know that your system does support fdatasync() correctly,
+** then simply compile with -Dfdatasync=fdatasync
+*/
+#if !defined(fdatasync)
+# define fdatasync fsync
+#endif
+
+/*
+** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
+** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
+** only available on Mac OS X. But that could change.
+*/
+#ifdef F_FULLFSYNC
+# define HAVE_FULLFSYNC 1
+#else
+# define HAVE_FULLFSYNC 0
+#endif
+
+
+/*
+** The fsync() system call does not work as advertised on many
+** unix systems. The following procedure is an attempt to make
+** it work better.
+**
+** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
+** for testing when we want to run through the test suite quickly.
+** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
+** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
+** or power failure will likely corrupt the database file.
+**
+** SQLite sets the dataOnly flag if the size of the file is unchanged.
+** The idea behind dataOnly is that it should only write the file content
+** to disk, not the inode. We only set dataOnly if the file size is
+** unchanged since the file size is part of the inode. However,
+** Ted Ts'o tells us that fdatasync() will also write the inode if the
+** file size has changed. The only real difference between fdatasync()
+** and fsync(), Ted tells us, is that fdatasync() will not flush the
+** inode if the mtime or owner or other inode attributes have changed.
+** We only care about the file size, not the other file attributes, so
+** as far as SQLite is concerned, an fdatasync() is always adequate.
+** So, we always use fdatasync() if it is available, regardless of
+** the value of the dataOnly flag.
+*/
+static int full_fsync(int fd, int fullSync, int dataOnly){
+ int rc;
+
+ /* The following "ifdef/elif/else/" block has the same structure as
+ ** the one below. It is replicated here solely to avoid cluttering
+ ** up the real code with the UNUSED_PARAMETER() macros.
+ */
+#ifdef SQLITE_NO_SYNC
+ UNUSED_PARAMETER(fd);
+ UNUSED_PARAMETER(fullSync);
+ UNUSED_PARAMETER(dataOnly);
+#elif HAVE_FULLFSYNC
+ UNUSED_PARAMETER(dataOnly);
+#else
+ UNUSED_PARAMETER(fullSync);
+ UNUSED_PARAMETER(dataOnly);
+#endif
+
+ /* Record the number of times that we do a normal fsync() and
+ ** FULLSYNC. This is used during testing to verify that this procedure
+ ** gets called with the correct arguments.
+ */
+#ifdef SQLITE_TEST
+ if( fullSync ) sqlite3_fullsync_count++;
+ sqlite3_sync_count++;
+#endif
+
+ /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
+ ** no-op
+ */
+#ifdef SQLITE_NO_SYNC
+ rc = SQLITE_OK;
+#elif HAVE_FULLFSYNC
+ if( fullSync ){
+ rc = osFcntl(fd, F_FULLFSYNC, 0);
+ }else{
+ rc = 1;
+ }
+ /* If the FULLFSYNC failed, fall back to attempting an fsync().
+ ** It shouldn't be possible for fullfsync to fail on the local
+ ** file system (on OSX), so failure indicates that FULLFSYNC
+ ** isn't supported for this file system. So, attempt an fsync
+ ** and (for now) ignore the overhead of a superfluous fcntl call.
+ ** It'd be better to detect fullfsync support once and avoid
+ ** the fcntl call every time sync is called.
+ */
+ if( rc ) rc = fsync(fd);
+
+#elif defined(__APPLE__)
+ /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
+ ** so currently we default to the macro that redefines fdatasync to fsync
+ */
+ rc = fsync(fd);
+#else
+ rc = fdatasync(fd);
+#if OS_VXWORKS
+ if( rc==-1 && errno==ENOTSUP ){
+ rc = fsync(fd);
+ }
+#endif /* OS_VXWORKS */
+#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
+
+ if( OS_VXWORKS && rc!= -1 ){
+ rc = 0;
+ }
+ return rc;
+}
+
+/*
+** Open a file descriptor to the directory containing file zFilename.
+** If successful, *pFd is set to the opened file descriptor and
+** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
+** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
+** value.
+**
+** The directory file descriptor is used for only one thing - to
+** fsync() a directory to make sure file creation and deletion events
+** are flushed to disk. Such fsyncs are not needed on newer
+** journaling filesystems, but are required on older filesystems.
+**
+** This routine can be overridden using the xSetSysCall interface.
+** The ability to override this routine was added in support of the
+** chromium sandbox. Opening a directory is a security risk (we are
+** told) so making it overrideable allows the chromium sandbox to
+** replace this routine with a harmless no-op. To make this routine
+** a no-op, replace it with a stub that returns SQLITE_OK but leaves
+** *pFd set to a negative number.
+**
+** If SQLITE_OK is returned, the caller is responsible for closing
+** the file descriptor *pFd using close().
+*/
+static int openDirectory(const char *zFilename, int *pFd){
+ int ii;
+ int fd = -1;
+ char zDirname[MAX_PATHNAME+1];
+
+ sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
+ for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
+ if( ii>0 ){
+ zDirname[ii] = '\0';
+ fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
+ if( fd>=0 ){
+ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
+ }
+ }
+ *pFd = fd;
+ return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
+}
+
+/*
+** Make sure all writes to a particular file are committed to disk.
+**
+** If dataOnly==0 then both the file itself and its metadata (file
+** size, access time, etc) are synced. If dataOnly!=0 then only the
+** file data is synced.
+**
+** Under Unix, also make sure that the directory entry for the file
+** has been created by fsync-ing the directory that contains the file.
+** If we do not do this and we encounter a power failure, the directory
+** entry for the journal might not exist after we reboot. The next
+** SQLite to access the file will not know that the journal exists (because
+** the directory entry for the journal was never created) and the transaction
+** will not roll back - possibly leading to database corruption.
+*/
+static int unixSync(sqlite3_file *id, int flags){
+ int rc;
+ unixFile *pFile = (unixFile*)id;
+
+ int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
+ int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
+
+ /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
+ assert((flags&0x0F)==SQLITE_SYNC_NORMAL
+ || (flags&0x0F)==SQLITE_SYNC_FULL
+ );
+
+ /* Unix cannot, but some systems may return SQLITE_FULL from here. This
+ ** line is to test that doing so does not cause any problems.
+ */
+ SimulateDiskfullError( return SQLITE_FULL );
+
+ assert( pFile );
+ OSTRACE(("SYNC %-3d\n", pFile->h));
+ rc = full_fsync(pFile->h, isFullsync, isDataOnly);
+ SimulateIOError( rc=1 );
+ if( rc ){
+ pFile->lastErrno = errno;
+ return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
+ }
+
+ /* Also fsync the directory containing the file if the DIRSYNC flag
+ ** is set. This is a one-time occurrence. Many systems (examples: AIX)
+ ** are unable to fsync a directory, so ignore errors on the fsync.
+ */
+ if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
+ int dirfd;
+ OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
+ HAVE_FULLFSYNC, isFullsync));
+ rc = osOpenDirectory(pFile->zPath, &dirfd);
+ if( rc==SQLITE_OK && dirfd>=0 ){
+ full_fsync(dirfd, 0, 0);
+ robust_close(pFile, dirfd, __LINE__);
+ }else if( rc==SQLITE_CANTOPEN ){
+ rc = SQLITE_OK;
+ }
+ pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
+ }
+ return rc;
+}
+
+/*
+** Truncate an open file to a specified size
+*/
+static int unixTruncate(sqlite3_file *id, i64 nByte){
+ unixFile *pFile = (unixFile *)id;
+ int rc;
+ assert( pFile );
+ SimulateIOError( return SQLITE_IOERR_TRUNCATE );
+
+ /* If the user has configured a chunk-size for this file, truncate the
+ ** file so that it consists of an integer number of chunks (i.e. the
+ ** actual file size after the operation may be larger than the requested
+ ** size).
+ */
+ if( pFile->szChunk>0 ){
+ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
+ }
+
+ rc = robust_ftruncate(pFile->h, (off_t)nByte);
+ if( rc ){
+ pFile->lastErrno = errno;
+ return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
+ }else{
+#ifdef SQLITE_DEBUG
+ /* If we are doing a normal write to a database file (as opposed to
+ ** doing a hot-journal rollback or a write to some file other than a
+ ** normal database file) and we truncate the file to zero length,
+ ** that effectively updates the change counter. This might happen
+ ** when restoring a database using the backup API from a zero-length
+ ** source.
+ */
+ if( pFile->inNormalWrite && nByte==0 ){
+ pFile->transCntrChng = 1;
+ }
+#endif
+
+ return SQLITE_OK;
+ }
+}
+
+/*
+** Determine the current size of a file in bytes
+*/
+static int unixFileSize(sqlite3_file *id, i64 *pSize){
+ int rc;
+ struct stat buf;
+ assert( id );
+ rc = osFstat(((unixFile*)id)->h, &buf);
+ SimulateIOError( rc=1 );
+ if( rc!=0 ){
+ ((unixFile*)id)->lastErrno = errno;
+ return SQLITE_IOERR_FSTAT;
+ }
+ *pSize = buf.st_size;
+
+ /* When opening a zero-size database, the findInodeInfo() procedure
+ ** writes a single byte into that file in order to work around a bug
+ ** in the OS-X msdos filesystem. In order to avoid problems with upper
+ ** layers, we need to report this file size as zero even though it is
+ ** really 1. Ticket #3260.
+ */
+ if( *pSize==1 ) *pSize = 0;
+
+
+ return SQLITE_OK;
+}
+
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+/*
+** Handler for proxy-locking file-control verbs. Defined below in the
+** proxying locking division.
+*/
+static int proxyFileControl(sqlite3_file*,int,void*);
+#endif
+
+/*
+** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
+** file-control operation. Enlarge the database to nBytes in size
+** (rounded up to the next chunk-size). If the database is already
+** nBytes or larger, this routine is a no-op.
+*/
+static int fcntlSizeHint(unixFile *pFile, i64 nByte){
+ if( pFile->szChunk>0 ){
+ i64 nSize; /* Required file size */
+ struct stat buf; /* Used to hold return values of fstat() */
+
+ if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
+
+ nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
+ if( nSize>(i64)buf.st_size ){
+
+#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
+ /* The code below is handling the return value of osFallocate()
+ ** correctly. posix_fallocate() is defined to "returns zero on success,
+ ** or an error number on failure". See the manpage for details. */
+ int err;
+ do{
+ err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
+ }while( err==EINTR );
+ if( err ) return SQLITE_IOERR_WRITE;
+#else
+ /* If the OS does not have posix_fallocate(), fake it. First use
+ ** ftruncate() to set the file size, then write a single byte to
+ ** the last byte in each block within the extended region. This
+ ** is the same technique used by glibc to implement posix_fallocate()
+ ** on systems that do not have a real fallocate() system call.
+ */
+ int nBlk = buf.st_blksize; /* File-system block size */
+ i64 iWrite; /* Next offset to write to */
+
+ if( robust_ftruncate(pFile->h, nSize) ){
+ pFile->lastErrno = errno;
+ return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
+ }
+ iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
+ while( iWrite<nSize ){
+ int nWrite = seekAndWrite(pFile, iWrite, "", 1);
+ if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
+ iWrite += nBlk;
+ }
+#endif
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** If *pArg is inititially negative then this is a query. Set *pArg to
+** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
+**
+** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
+*/
+static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
+ if( *pArg<0 ){
+ *pArg = (pFile->ctrlFlags & mask)!=0;
+ }else if( (*pArg)==0 ){
+ pFile->ctrlFlags &= ~mask;
+ }else{
+ pFile->ctrlFlags |= mask;
+ }
+}
+
+/* Forward declaration */
+static int unixGetTempname(int nBuf, char *zBuf);
+
+/*
+** Information and control of an open file handle.
+*/
+static int unixFileControl(sqlite3_file *id, int op, void *pArg){
+ unixFile *pFile = (unixFile*)id;
+ switch( op ){
+ case SQLITE_FCNTL_LOCKSTATE: {
+ *(int*)pArg = pFile->eFileLock;
+ return SQLITE_OK;
+ }
+ case SQLITE_LAST_ERRNO: {
+ *(int*)pArg = pFile->lastErrno;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_CHUNK_SIZE: {
+ pFile->szChunk = *(int *)pArg;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_SIZE_HINT: {
+ int rc;
+ SimulateIOErrorBenign(1);
+ rc = fcntlSizeHint(pFile, *(i64 *)pArg);
+ SimulateIOErrorBenign(0);
+ return rc;
+ }
+ case SQLITE_FCNTL_PERSIST_WAL: {
+ unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
+ unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_VFSNAME: {
+ *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_TEMPFILENAME: {
+ char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+ if( zTFile ){
+ unixGetTempname(pFile->pVfs->mxPathname, zTFile);
+ *(char**)pArg = zTFile;
+ }
+ return SQLITE_OK;
+ }
+#ifdef SQLITE_DEBUG
+ /* The pager calls this method to signal that it has done
+ ** a rollback and that the database is therefore unchanged and
+ ** it hence it is OK for the transaction change counter to be
+ ** unchanged.
+ */
+ case SQLITE_FCNTL_DB_UNCHANGED: {
+ ((unixFile*)id)->dbUpdate = 0;
+ return SQLITE_OK;
+ }
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+ case SQLITE_SET_LOCKPROXYFILE:
+ case SQLITE_GET_LOCKPROXYFILE: {
+ return proxyFileControl(id,op,pArg);
+ }
+#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
+ }
+ return SQLITE_NOTFOUND;
+}
+
+/*
+** Return the sector size in bytes of the underlying block device for
+** the specified file. This is almost always 512 bytes, but may be
+** larger for some devices.
+**
+** SQLite code assumes this function cannot fail. It also assumes that
+** if two files are created in the same file-system directory (i.e.
+** a database and its journal file) that the sector size will be the
+** same for both.
+*/
+#ifndef __QNXNTO__
+static int unixSectorSize(sqlite3_file *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ return SQLITE_DEFAULT_SECTOR_SIZE;
+}
+#endif
+
+/*
+** The following version of unixSectorSize() is optimized for QNX.
+*/
+#ifdef __QNXNTO__
+#include <sys/dcmd_blk.h>
+#include <sys/statvfs.h>
+static int unixSectorSize(sqlite3_file *id){
+ unixFile *pFile = (unixFile*)id;
+ if( pFile->sectorSize == 0 ){
+ struct statvfs fsInfo;
+
+ /* Set defaults for non-supported filesystems */
+ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+ pFile->deviceCharacteristics = 0;
+ if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
+ return pFile->sectorSize;
+ }
+
+ if( !strcmp(fsInfo.f_basetype, "tmp") ) {
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( strstr(fsInfo.f_basetype, "etfs") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ /* etfs cluster size writes are atomic */
+ (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ /* full bitset of atomics from max sector size and smaller */
+ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( strstr(fsInfo.f_basetype, "dos") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ /* full bitset of atomics from max sector size and smaller */
+ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else{
+ pFile->deviceCharacteristics =
+ SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ 0;
+ }
+ }
+ /* Last chance verification. If the sector size isn't a multiple of 512
+ ** then it isn't valid.*/
+ if( pFile->sectorSize % 512 != 0 ){
+ pFile->deviceCharacteristics = 0;
+ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+ }
+ return pFile->sectorSize;
+}
+#endif /* __QNXNTO__ */
+
+/*
+** Return the device characteristics for the file.
+**
+** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
+** However, that choice is contraversial since technically the underlying
+** file system does not always provide powersafe overwrites. (In other
+** words, after a power-loss event, parts of the file that were never
+** written might end up being altered.) However, non-PSOW behavior is very,
+** very rare. And asserting PSOW makes a large reduction in the amount
+** of required I/O for journaling, since a lot of padding is eliminated.
+** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
+** available to turn it off and URI query parameter available to turn it off.
+*/
+static int unixDeviceCharacteristics(sqlite3_file *id){
+ unixFile *p = (unixFile*)id;
+ int rc = 0;
+#ifdef __QNXNTO__
+ if( p->sectorSize==0 ) unixSectorSize(id);
+ rc = p->deviceCharacteristics;
+#endif
+ if( p->ctrlFlags & UNIXFILE_PSOW ){
+ rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
+ }
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_WAL
+
+
+/*
+** Object used to represent an shared memory buffer.
+**
+** When multiple threads all reference the same wal-index, each thread
+** has its own unixShm object, but they all point to a single instance
+** of this unixShmNode object. In other words, each wal-index is opened
+** only once per process.
+**
+** Each unixShmNode object is connected to a single unixInodeInfo object.
+** We could coalesce this object into unixInodeInfo, but that would mean
+** every open file that does not use shared memory (in other words, most
+** open files) would have to carry around this extra information. So
+** the unixInodeInfo object contains a pointer to this unixShmNode object
+** and the unixShmNode object is created only when needed.
+**
+** unixMutexHeld() must be true when creating or destroying
+** this object or while reading or writing the following fields:
+**
+** nRef
+**
+** The following fields are read-only after the object is created:
+**
+** fid
+** zFilename
+**
+** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
+** unixMutexHeld() is true when reading or writing any other field
+** in this structure.
+*/
+struct unixShmNode {
+ unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
+ sqlite3_mutex *mutex; /* Mutex to access this object */
+ char *zFilename; /* Name of the mmapped file */
+ int h; /* Open file descriptor */
+ int szRegion; /* Size of shared-memory regions */
+ u16 nRegion; /* Size of array apRegion */
+ u8 isReadonly; /* True if read-only */
+ char **apRegion; /* Array of mapped shared-memory regions */
+ int nRef; /* Number of unixShm objects pointing to this */
+ unixShm *pFirst; /* All unixShm objects pointing to this */
+#ifdef SQLITE_DEBUG
+ u8 exclMask; /* Mask of exclusive locks held */
+ u8 sharedMask; /* Mask of shared locks held */
+ u8 nextShmId; /* Next available unixShm.id value */
+#endif
+};
+
+/*
+** Structure used internally by this VFS to record the state of an
+** open shared memory connection.
+**
+** The following fields are initialized when this object is created and
+** are read-only thereafter:
+**
+** unixShm.pFile
+** unixShm.id
+**
+** All other fields are read/write. The unixShm.pFile->mutex must be held
+** while accessing any read/write fields.
+*/
+struct unixShm {
+ unixShmNode *pShmNode; /* The underlying unixShmNode object */
+ unixShm *pNext; /* Next unixShm with the same unixShmNode */
+ u8 hasMutex; /* True if holding the unixShmNode mutex */
+ u8 id; /* Id of this connection within its unixShmNode */
+ u16 sharedMask; /* Mask of shared locks held */
+ u16 exclMask; /* Mask of exclusive locks held */
+};
+
+/*
+** Constants used for locking
+*/
+#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
+#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
+
+/*
+** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
+**
+** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
+** otherwise.
+*/
+static int unixShmSystemLock(
+ unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
+ int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
+ int ofst, /* First byte of the locking range */
+ int n /* Number of bytes to lock */
+){
+ struct flock f; /* The posix advisory locking structure */
+ int rc = SQLITE_OK; /* Result code form fcntl() */
+
+ /* Access to the unixShmNode object is serialized by the caller */
+ assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
+
+ /* Shared locks never span more than one byte */
+ assert( n==1 || lockType!=F_RDLCK );
+
+ /* Locks are within range */
+ assert( n>=1 && n<SQLITE_SHM_NLOCK );
+
+ if( pShmNode->h>=0 ){
+ /* Initialize the locking parameters */
+ memset(&f, 0, sizeof(f));
+ f.l_type = lockType;
+ f.l_whence = SEEK_SET;
+ f.l_start = ofst;
+ f.l_len = n;
+
+ rc = osFcntl(pShmNode->h, F_SETLK, &f);
+ rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
+ }
+
+ /* Update the global lock state and do debug tracing */
+#ifdef SQLITE_DEBUG
+ { u16 mask;
+ OSTRACE(("SHM-LOCK "));
+ mask = (1<<(ofst+n)) - (1<<ofst);
+ if( rc==SQLITE_OK ){
+ if( lockType==F_UNLCK ){
+ OSTRACE(("unlock %d ok", ofst));
+ pShmNode->exclMask &= ~mask;
+ pShmNode->sharedMask &= ~mask;
+ }else if( lockType==F_RDLCK ){
+ OSTRACE(("read-lock %d ok", ofst));
+ pShmNode->exclMask &= ~mask;
+ pShmNode->sharedMask |= mask;
+ }else{
+ assert( lockType==F_WRLCK );
+ OSTRACE(("write-lock %d ok", ofst));
+ pShmNode->exclMask |= mask;
+ pShmNode->sharedMask &= ~mask;
+ }
+ }else{
+ if( lockType==F_UNLCK ){
+ OSTRACE(("unlock %d failed", ofst));
+ }else if( lockType==F_RDLCK ){
+ OSTRACE(("read-lock failed"));
+ }else{
+ assert( lockType==F_WRLCK );
+ OSTRACE(("write-lock %d failed", ofst));
+ }
+ }
+ OSTRACE((" - afterwards %03x,%03x\n",
+ pShmNode->sharedMask, pShmNode->exclMask));
+ }
+#endif
+
+ return rc;
+}
+
+
+/*
+** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
+**
+** This is not a VFS shared-memory method; it is a utility function called
+** by VFS shared-memory methods.
+*/
+static void unixShmPurge(unixFile *pFd){
+ unixShmNode *p = pFd->pInode->pShmNode;
+ assert( unixMutexHeld() );
+ if( p && p->nRef==0 ){
+ int i;
+ assert( p->pInode==pFd->pInode );
+ sqlite3_mutex_free(p->mutex);
+ for(i=0; i<p->nRegion; i++){
+ if( p->h>=0 ){
+ munmap(p->apRegion[i], p->szRegion);
+ }else{
+ sqlite3_free(p->apRegion[i]);
+ }
+ }
+ sqlite3_free(p->apRegion);
+ if( p->h>=0 ){
+ robust_close(pFd, p->h, __LINE__);
+ p->h = -1;
+ }
+ p->pInode->pShmNode = 0;
+ sqlite3_free(p);
+ }
+}
+
+/*
+** Open a shared-memory area associated with open database file pDbFd.
+** This particular implementation uses mmapped files.
+**
+** The file used to implement shared-memory is in the same directory
+** as the open database file and has the same name as the open database
+** file with the "-shm" suffix added. For example, if the database file
+** is "/home/user1/config.db" then the file that is created and mmapped
+** for shared memory will be called "/home/user1/config.db-shm".
+**
+** Another approach to is to use files in /dev/shm or /dev/tmp or an
+** some other tmpfs mount. But if a file in a different directory
+** from the database file is used, then differing access permissions
+** or a chroot() might cause two different processes on the same
+** database to end up using different files for shared memory -
+** meaning that their memory would not really be shared - resulting
+** in database corruption. Nevertheless, this tmpfs file usage
+** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
+** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time
+** option results in an incompatible build of SQLite; builds of SQLite
+** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
+** same database file at the same time, database corruption will likely
+** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
+** "unsupported" and may go away in a future SQLite release.
+**
+** When opening a new shared-memory file, if no other instances of that
+** file are currently open, in this process or in other processes, then
+** the file must be truncated to zero length or have its header cleared.
+**
+** If the original database file (pDbFd) is using the "unix-excl" VFS
+** that means that an exclusive lock is held on the database file and
+** that no other processes are able to read or write the database. In
+** that case, we do not really need shared memory. No shared memory
+** file is created. The shared memory will be simulated with heap memory.
+*/
+static int unixOpenSharedMemory(unixFile *pDbFd){
+ struct unixShm *p = 0; /* The connection to be opened */
+ struct unixShmNode *pShmNode; /* The underlying mmapped file */
+ int rc; /* Result code */
+ unixInodeInfo *pInode; /* The inode of fd */
+ char *zShmFilename; /* Name of the file used for SHM */
+ int nShmFilename; /* Size of the SHM filename in bytes */
+
+ /* Allocate space for the new unixShm object. */
+ p = sqlite3_malloc( sizeof(*p) );
+ if( p==0 ) return SQLITE_NOMEM;
+ memset(p, 0, sizeof(*p));
+ assert( pDbFd->pShm==0 );
+
+ /* Check to see if a unixShmNode object already exists. Reuse an existing
+ ** one if present. Create a new one if necessary.
+ */
+ unixEnterMutex();
+ pInode = pDbFd->pInode;
+ pShmNode = pInode->pShmNode;
+ if( pShmNode==0 ){
+ struct stat sStat; /* fstat() info for database file */
+
+ /* Call fstat() to figure out the permissions on the database file. If
+ ** a new *-shm file is created, an attempt will be made to create it
+ ** with the same permissions.
+ */
+ if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
+ rc = SQLITE_IOERR_FSTAT;
+ goto shm_open_err;
+ }
+
+#ifdef SQLITE_SHM_DIRECTORY
+ nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
+#else
+ nShmFilename = 6 + (int)strlen(pDbFd->zPath);
+#endif
+ pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
+ if( pShmNode==0 ){
+ rc = SQLITE_NOMEM;
+ goto shm_open_err;
+ }
+ memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
+ zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
+#ifdef SQLITE_SHM_DIRECTORY
+ sqlite3_snprintf(nShmFilename, zShmFilename,
+ SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
+ (u32)sStat.st_ino, (u32)sStat.st_dev);
+#else
+ sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
+ sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
+#endif
+ pShmNode->h = -1;
+ pDbFd->pInode->pShmNode = pShmNode;
+ pShmNode->pInode = pDbFd->pInode;
+ pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pShmNode->mutex==0 ){
+ rc = SQLITE_NOMEM;
+ goto shm_open_err;
+ }
+
+ if( pInode->bProcessLock==0 ){
+ int openFlags = O_RDWR | O_CREAT;
+ if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
+ openFlags = O_RDONLY;
+ pShmNode->isReadonly = 1;
+ }
+ pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
+ if( pShmNode->h<0 ){
+ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
+ goto shm_open_err;
+ }
+
+ /* If this process is running as root, make sure that the SHM file
+ ** is owned by the same user that owns the original database. Otherwise,
+ ** the original owner will not be able to connect.
+ */
+ osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
+
+ /* Check to see if another process is holding the dead-man switch.
+ ** If not, truncate the file to zero length.
+ */
+ rc = SQLITE_OK;
+ if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
+ if( robust_ftruncate(pShmNode->h, 0) ){
+ rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
+ }
+ if( rc ) goto shm_open_err;
+ }
+ }
+
+ /* Make the new connection a child of the unixShmNode */
+ p->pShmNode = pShmNode;
+#ifdef SQLITE_DEBUG
+ p->id = pShmNode->nextShmId++;
+#endif
+ pShmNode->nRef++;
+ pDbFd->pShm = p;
+ unixLeaveMutex();
+
+ /* The reference count on pShmNode has already been incremented under
+ ** the cover of the unixEnterMutex() mutex and the pointer from the
+ ** new (struct unixShm) object to the pShmNode has been set. All that is
+ ** left to do is to link the new object into the linked list starting
+ ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
+ ** mutex.
+ */
+ sqlite3_mutex_enter(pShmNode->mutex);
+ p->pNext = pShmNode->pFirst;
+ pShmNode->pFirst = p;
+ sqlite3_mutex_leave(pShmNode->mutex);
+ return SQLITE_OK;
+
+ /* Jump here on any error */
+shm_open_err:
+ unixShmPurge(pDbFd); /* This call frees pShmNode if required */
+ sqlite3_free(p);
+ unixLeaveMutex();
+ return rc;
+}
+
+/*
+** This function is called to obtain a pointer to region iRegion of the
+** shared-memory associated with the database file fd. Shared-memory regions
+** are numbered starting from zero. Each shared-memory region is szRegion
+** bytes in size.
+**
+** If an error occurs, an error code is returned and *pp is set to NULL.
+**
+** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
+** region has not been allocated (by any client, including one running in a
+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
+** bExtend is non-zero and the requested shared-memory region has not yet
+** been allocated, it is allocated by this function.
+**
+** If the shared-memory region has already been allocated or is allocated by
+** this call as described above, then it is mapped into this processes
+** address space (if it is not already), *pp is set to point to the mapped
+** memory and SQLITE_OK returned.
+*/
+static int unixShmMap(
+ sqlite3_file *fd, /* Handle open on database file */
+ int iRegion, /* Region to retrieve */
+ int szRegion, /* Size of regions */
+ int bExtend, /* True to extend file if necessary */
+ void volatile **pp /* OUT: Mapped memory */
+){
+ unixFile *pDbFd = (unixFile*)fd;
+ unixShm *p;
+ unixShmNode *pShmNode;
+ int rc = SQLITE_OK;
+
+ /* If the shared-memory file has not yet been opened, open it now. */
+ if( pDbFd->pShm==0 ){
+ rc = unixOpenSharedMemory(pDbFd);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+
+ p = pDbFd->pShm;
+ pShmNode = p->pShmNode;
+ sqlite3_mutex_enter(pShmNode->mutex);
+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+ assert( pShmNode->pInode==pDbFd->pInode );
+ assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+
+ if( pShmNode->nRegion<=iRegion ){
+ char **apNew; /* New apRegion[] array */
+ int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
+ struct stat sStat; /* Used by fstat() */
+
+ pShmNode->szRegion = szRegion;
+
+ if( pShmNode->h>=0 ){
+ /* The requested region is not mapped into this processes address space.
+ ** Check to see if it has been allocated (i.e. if the wal-index file is
+ ** large enough to contain the requested region).
+ */
+ if( osFstat(pShmNode->h, &sStat) ){
+ rc = SQLITE_IOERR_SHMSIZE;
+ goto shmpage_out;
+ }
+
+ if( sStat.st_size<nByte ){
+ /* The requested memory region does not exist. If bExtend is set to
+ ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
+ **
+ ** Alternatively, if bExtend is true, use ftruncate() to allocate
+ ** the requested memory region.
+ */
+ if( !bExtend ) goto shmpage_out;
+#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
+ if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){
+ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate",
+ pShmNode->zFilename);
+ goto shmpage_out;
+ }
+#else
+ if( robust_ftruncate(pShmNode->h, nByte) ){
+ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
+ pShmNode->zFilename);
+ goto shmpage_out;
+ }
+#endif
+ }
+ }
+
+ /* Map the requested memory region into this processes address space. */
+ apNew = (char **)sqlite3_realloc(
+ pShmNode->apRegion, (iRegion+1)*sizeof(char *)
+ );
+ if( !apNew ){
+ rc = SQLITE_IOERR_NOMEM;
+ goto shmpage_out;
+ }
+ pShmNode->apRegion = apNew;
+ while(pShmNode->nRegion<=iRegion){
+ void *pMem;
+ if( pShmNode->h>=0 ){
+ pMem = mmap(0, szRegion,
+ pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
+ MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
+ );
+ if( pMem==MAP_FAILED ){
+ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
+ goto shmpage_out;
+ }
+ }else{
+ pMem = sqlite3_malloc(szRegion);
+ if( pMem==0 ){
+ rc = SQLITE_NOMEM;
+ goto shmpage_out;
+ }
+ memset(pMem, 0, szRegion);
+ }
+ pShmNode->apRegion[pShmNode->nRegion] = pMem;
+ pShmNode->nRegion++;
+ }
+ }
+
+shmpage_out:
+ if( pShmNode->nRegion>iRegion ){
+ *pp = pShmNode->apRegion[iRegion];
+ }else{
+ *pp = 0;
+ }
+ if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
+ sqlite3_mutex_leave(pShmNode->mutex);
+ return rc;
+}
+
+/*
+** Change the lock state for a shared-memory segment.
+**
+** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
+** different here than in posix. In xShmLock(), one can go from unlocked
+** to shared and back or from unlocked to exclusive and back. But one may
+** not go from shared to exclusive or from exclusive to shared.
+*/
+static int unixShmLock(
+ sqlite3_file *fd, /* Database file holding the shared memory */
+ int ofst, /* First lock to acquire or release */
+ int n, /* Number of locks to acquire or release */
+ int flags /* What to do with the lock */
+){
+ unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
+ unixShm *p = pDbFd->pShm; /* The shared memory being locked */
+ unixShm *pX; /* For looping over all siblings */
+ unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
+ int rc = SQLITE_OK; /* Result code */
+ u16 mask; /* Mask of locks to take or release */
+
+ assert( pShmNode==pDbFd->pInode->pShmNode );
+ assert( pShmNode->pInode==pDbFd->pInode );
+ assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
+ assert( n>=1 );
+ assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
+ || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
+ assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
+ assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+
+ mask = (1<<(ofst+n)) - (1<<ofst);
+ assert( n>1 || mask==(1<<ofst) );
+ sqlite3_mutex_enter(pShmNode->mutex);
+ if( flags & SQLITE_SHM_UNLOCK ){
+ u16 allMask = 0; /* Mask of locks held by siblings */
+
+ /* See if any siblings hold this same lock */
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ if( pX==p ) continue;
+ assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
+ allMask |= pX->sharedMask;
+ }
+
+ /* Unlock the system-level locks */
+ if( (mask & allMask)==0 ){
+ rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ }else{
+ rc = SQLITE_OK;
+ }
+
+ /* Undo the local locks */
+ if( rc==SQLITE_OK ){
+ p->exclMask &= ~mask;
+ p->sharedMask &= ~mask;
+ }
+ }else if( flags & SQLITE_SHM_SHARED ){
+ u16 allShared = 0; /* Union of locks held by connections other than "p" */
+
+ /* Find out which shared locks are already held by sibling connections.
+ ** If any sibling already holds an exclusive lock, go ahead and return
+ ** SQLITE_BUSY.
+ */
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ if( (pX->exclMask & mask)!=0 ){
+ rc = SQLITE_BUSY;
+ break;
+ }
+ allShared |= pX->sharedMask;
+ }
+
+ /* Get shared locks at the system level, if necessary */
+ if( rc==SQLITE_OK ){
+ if( (allShared & mask)==0 ){
+ rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
+ }else{
+ rc = SQLITE_OK;
+ }
+ }
+
+ /* Get the local shared locks */
+ if( rc==SQLITE_OK ){
+ p->sharedMask |= mask;
+ }
+ }else{
+ /* Make sure no sibling connections hold locks that will block this
+ ** lock. If any do, return SQLITE_BUSY right away.
+ */
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+ rc = SQLITE_BUSY;
+ break;
+ }
+ }
+
+ /* Get the exclusive locks at the system level. Then if successful
+ ** also mark the local connection as being locked.
+ */
+ if( rc==SQLITE_OK ){
+ rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
+ if( rc==SQLITE_OK ){
+ assert( (p->sharedMask & mask)==0 );
+ p->exclMask |= mask;
+ }
+ }
+ }
+ sqlite3_mutex_leave(pShmNode->mutex);
+ OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
+ p->id, getpid(), p->sharedMask, p->exclMask));
+ return rc;
+}
+
+/*
+** Implement a memory barrier or memory fence on shared memory.
+**
+** All loads and stores begun before the barrier must complete before
+** any load or store begun after the barrier.
+*/
+static void unixShmBarrier(
+ sqlite3_file *fd /* Database file holding the shared memory */
+){
+ UNUSED_PARAMETER(fd);
+ unixEnterMutex();
+ unixLeaveMutex();
+}
+
+/*
+** Close a connection to shared-memory. Delete the underlying
+** storage if deleteFlag is true.
+**
+** If there is no shared memory associated with the connection then this
+** routine is a harmless no-op.
+*/
+static int unixShmUnmap(
+ sqlite3_file *fd, /* The underlying database file */
+ int deleteFlag /* Delete shared-memory if true */
+){
+ unixShm *p; /* The connection to be closed */
+ unixShmNode *pShmNode; /* The underlying shared-memory file */
+ unixShm **pp; /* For looping over sibling connections */
+ unixFile *pDbFd; /* The underlying database file */
+
+ pDbFd = (unixFile*)fd;
+ p = pDbFd->pShm;
+ if( p==0 ) return SQLITE_OK;
+ pShmNode = p->pShmNode;
+
+ assert( pShmNode==pDbFd->pInode->pShmNode );
+ assert( pShmNode->pInode==pDbFd->pInode );
+
+ /* Remove connection p from the set of connections associated
+ ** with pShmNode */
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
+ *pp = p->pNext;
+
+ /* Free the connection p */
+ sqlite3_free(p);
+ pDbFd->pShm = 0;
+ sqlite3_mutex_leave(pShmNode->mutex);
+
+ /* If pShmNode->nRef has reached 0, then close the underlying
+ ** shared-memory file, too */
+ unixEnterMutex();
+ assert( pShmNode->nRef>0 );
+ pShmNode->nRef--;
+ if( pShmNode->nRef==0 ){
+ if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
+ unixShmPurge(pDbFd);
+ }
+ unixLeaveMutex();
+
+ return SQLITE_OK;
+}
+
+
+#else
+# define unixShmMap 0
+# define unixShmLock 0
+# define unixShmBarrier 0
+# define unixShmUnmap 0
+#endif /* #ifndef SQLITE_OMIT_WAL */
+
+/*
+** Here ends the implementation of all sqlite3_file methods.
+**
+********************** End sqlite3_file Methods *******************************
+******************************************************************************/
+
+/*
+** This division contains definitions of sqlite3_io_methods objects that
+** implement various file locking strategies. It also contains definitions
+** of "finder" functions. A finder-function is used to locate the appropriate
+** sqlite3_io_methods object for a particular database file. The pAppData
+** field of the sqlite3_vfs VFS objects are initialized to be pointers to
+** the correct finder-function for that VFS.
+**
+** Most finder functions return a pointer to a fixed sqlite3_io_methods
+** object. The only interesting finder-function is autolockIoFinder, which
+** looks at the filesystem type and tries to guess the best locking
+** strategy from that.
+**
+** For finder-funtion F, two objects are created:
+**
+** (1) The real finder-function named "FImpt()".
+**
+** (2) A constant pointer to this function named just "F".
+**
+**
+** A pointer to the F pointer is used as the pAppData value for VFS
+** objects. We have to do this instead of letting pAppData point
+** directly at the finder-function since C90 rules prevent a void*
+** from be cast into a function pointer.
+**
+**
+** Each instance of this macro generates two objects:
+**
+** * A constant sqlite3_io_methods object call METHOD that has locking
+** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
+**
+** * An I/O method finder function called FINDER that returns a pointer
+** to the METHOD object in the previous bullet.
+*/
+#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \
+static const sqlite3_io_methods METHOD = { \
+ VERSION, /* iVersion */ \
+ CLOSE, /* xClose */ \
+ unixRead, /* xRead */ \
+ unixWrite, /* xWrite */ \
+ unixTruncate, /* xTruncate */ \
+ unixSync, /* xSync */ \
+ unixFileSize, /* xFileSize */ \
+ LOCK, /* xLock */ \
+ UNLOCK, /* xUnlock */ \
+ CKLOCK, /* xCheckReservedLock */ \
+ unixFileControl, /* xFileControl */ \
+ unixSectorSize, /* xSectorSize */ \
+ unixDeviceCharacteristics, /* xDeviceCapabilities */ \
+ unixShmMap, /* xShmMap */ \
+ unixShmLock, /* xShmLock */ \
+ unixShmBarrier, /* xShmBarrier */ \
+ unixShmUnmap /* xShmUnmap */ \
+}; \
+static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
+ UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
+ return &METHOD; \
+} \
+static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \
+ = FINDER##Impl;
+
+/*
+** Here are all of the sqlite3_io_methods objects for each of the
+** locking strategies. Functions that return pointers to these methods
+** are also created.
+*/
+IOMETHODS(
+ posixIoFinder, /* Finder function name */
+ posixIoMethods, /* sqlite3_io_methods object name */
+ 2, /* shared memory is enabled */
+ unixClose, /* xClose method */
+ unixLock, /* xLock method */
+ unixUnlock, /* xUnlock method */
+ unixCheckReservedLock /* xCheckReservedLock method */
+)
+IOMETHODS(
+ nolockIoFinder, /* Finder function name */
+ nolockIoMethods, /* sqlite3_io_methods object name */
+ 1, /* shared memory is disabled */
+ nolockClose, /* xClose method */
+ nolockLock, /* xLock method */
+ nolockUnlock, /* xUnlock method */
+ nolockCheckReservedLock /* xCheckReservedLock method */
+)
+IOMETHODS(
+ dotlockIoFinder, /* Finder function name */
+ dotlockIoMethods, /* sqlite3_io_methods object name */
+ 1, /* shared memory is disabled */
+ dotlockClose, /* xClose method */
+ dotlockLock, /* xLock method */
+ dotlockUnlock, /* xUnlock method */
+ dotlockCheckReservedLock /* xCheckReservedLock method */
+)
+
+#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+IOMETHODS(
+ flockIoFinder, /* Finder function name */
+ flockIoMethods, /* sqlite3_io_methods object name */
+ 1, /* shared memory is disabled */
+ flockClose, /* xClose method */
+ flockLock, /* xLock method */
+ flockUnlock, /* xUnlock method */
+ flockCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+#if OS_VXWORKS
+IOMETHODS(
+ semIoFinder, /* Finder function name */
+ semIoMethods, /* sqlite3_io_methods object name */
+ 1, /* shared memory is disabled */
+ semClose, /* xClose method */
+ semLock, /* xLock method */
+ semUnlock, /* xUnlock method */
+ semCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+IOMETHODS(
+ afpIoFinder, /* Finder function name */
+ afpIoMethods, /* sqlite3_io_methods object name */
+ 1, /* shared memory is disabled */
+ afpClose, /* xClose method */
+ afpLock, /* xLock method */
+ afpUnlock, /* xUnlock method */
+ afpCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+/*
+** The proxy locking method is a "super-method" in the sense that it
+** opens secondary file descriptors for the conch and lock files and
+** it uses proxy, dot-file, AFP, and flock() locking methods on those
+** secondary files. For this reason, the division that implements
+** proxy locking is located much further down in the file. But we need
+** to go ahead and define the sqlite3_io_methods and finder function
+** for proxy locking here. So we forward declare the I/O methods.
+*/
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+static int proxyClose(sqlite3_file*);
+static int proxyLock(sqlite3_file*, int);
+static int proxyUnlock(sqlite3_file*, int);
+static int proxyCheckReservedLock(sqlite3_file*, int*);
+IOMETHODS(
+ proxyIoFinder, /* Finder function name */
+ proxyIoMethods, /* sqlite3_io_methods object name */
+ 1, /* shared memory is disabled */
+ proxyClose, /* xClose method */
+ proxyLock, /* xLock method */
+ proxyUnlock, /* xUnlock method */
+ proxyCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+IOMETHODS(
+ nfsIoFinder, /* Finder function name */
+ nfsIoMethods, /* sqlite3_io_methods object name */
+ 1, /* shared memory is disabled */
+ unixClose, /* xClose method */
+ unixLock, /* xLock method */
+ nfsUnlock, /* xUnlock method */
+ unixCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+/*
+** This "finder" function attempts to determine the best locking strategy
+** for the database file "filePath". It then returns the sqlite3_io_methods
+** object that implements that strategy.
+**
+** This is for MacOSX only.
+*/
+static const sqlite3_io_methods *autolockIoFinderImpl(
+ const char *filePath, /* name of the database file */
+ unixFile *pNew /* open file object for the database file */
+){
+ static const struct Mapping {
+ const char *zFilesystem; /* Filesystem type name */
+ const sqlite3_io_methods *pMethods; /* Appropriate locking method */
+ } aMap[] = {
+ { "hfs", &posixIoMethods },
+ { "ufs", &posixIoMethods },
+ { "afpfs", &afpIoMethods },
+ { "smbfs", &afpIoMethods },
+ { "webdav", &nolockIoMethods },
+ { 0, 0 }
+ };
+ int i;
+ struct statfs fsInfo;
+ struct flock lockInfo;
+
+ if( !filePath ){
+ /* If filePath==NULL that means we are dealing with a transient file
+ ** that does not need to be locked. */
+ return &nolockIoMethods;
+ }
+ if( statfs(filePath, &fsInfo) != -1 ){
+ if( fsInfo.f_flags & MNT_RDONLY ){
+ return &nolockIoMethods;
+ }
+ for(i=0; aMap[i].zFilesystem; i++){
+ if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
+ return aMap[i].pMethods;
+ }
+ }
+ }
+
+ /* Default case. Handles, amongst others, "nfs".
+ ** Test byte-range lock using fcntl(). If the call succeeds,
+ ** assume that the file-system supports POSIX style locks.
+ */
+ lockInfo.l_len = 1;
+ lockInfo.l_start = 0;
+ lockInfo.l_whence = SEEK_SET;
+ lockInfo.l_type = F_RDLCK;
+ if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
+ if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
+ return &nfsIoMethods;
+ } else {
+ return &posixIoMethods;
+ }
+ }else{
+ return &dotlockIoMethods;
+ }
+}
+static const sqlite3_io_methods
+ *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
+
+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+
+#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
+/*
+** This "finder" function attempts to determine the best locking strategy
+** for the database file "filePath". It then returns the sqlite3_io_methods
+** object that implements that strategy.
+**
+** This is for VXWorks only.
+*/
+static const sqlite3_io_methods *autolockIoFinderImpl(
+ const char *filePath, /* name of the database file */
+ unixFile *pNew /* the open file object */
+){
+ struct flock lockInfo;
+
+ if( !filePath ){
+ /* If filePath==NULL that means we are dealing with a transient file
+ ** that does not need to be locked. */
+ return &nolockIoMethods;
+ }
+
+ /* Test if fcntl() is supported and use POSIX style locks.
+ ** Otherwise fall back to the named semaphore method.
+ */
+ lockInfo.l_len = 1;
+ lockInfo.l_start = 0;
+ lockInfo.l_whence = SEEK_SET;
+ lockInfo.l_type = F_RDLCK;
+ if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
+ return &posixIoMethods;
+ }else{
+ return &semIoMethods;
+ }
+}
+static const sqlite3_io_methods
+ *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
+
+#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
+
+/*
+** An abstract type for a pointer to a IO method finder function:
+*/
+typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
+
+
+/****************************************************************************
+**************************** sqlite3_vfs methods ****************************
+**
+** This division contains the implementation of methods on the
+** sqlite3_vfs object.
+*/
+
+/*
+** Initialize the contents of the unixFile structure pointed to by pId.
+*/
+static int fillInUnixFile(
+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
+ int h, /* Open file descriptor of file being opened */
+ sqlite3_file *pId, /* Write to the unixFile structure here */
+ const char *zFilename, /* Name of the file being opened */
+ int ctrlFlags /* Zero or more UNIXFILE_* values */
+){
+ const sqlite3_io_methods *pLockingStyle;
+ unixFile *pNew = (unixFile *)pId;
+ int rc = SQLITE_OK;
+
+ assert( pNew->pInode==NULL );
+
+ /* Usually the path zFilename should not be a relative pathname. The
+ ** exception is when opening the proxy "conch" file in builds that
+ ** include the special Apple locking styles.
+ */
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+ assert( zFilename==0 || zFilename[0]=='/'
+ || pVfs->pAppData==(void*)&autolockIoFinder );
+#else
+ assert( zFilename==0 || zFilename[0]=='/' );
+#endif
+
+ /* No locking occurs in temporary files */
+ assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
+
+ OSTRACE(("OPEN %-3d %s\n", h, zFilename));
+ pNew->h = h;
+ pNew->pVfs = pVfs;
+ pNew->zPath = zFilename;
+ pNew->ctrlFlags = (u8)ctrlFlags;
+ if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
+ "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+ pNew->ctrlFlags |= UNIXFILE_PSOW;
+ }
+ if( strcmp(pVfs->zName,"unix-excl")==0 ){
+ pNew->ctrlFlags |= UNIXFILE_EXCL;
+ }
+
+#if OS_VXWORKS
+ pNew->pId = vxworksFindFileId(zFilename);
+ if( pNew->pId==0 ){
+ ctrlFlags |= UNIXFILE_NOLOCK;
+ rc = SQLITE_NOMEM;
+ }
+#endif
+
+ if( ctrlFlags & UNIXFILE_NOLOCK ){
+ pLockingStyle = &nolockIoMethods;
+ }else{
+ pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
+#if SQLITE_ENABLE_LOCKING_STYLE
+ /* Cache zFilename in the locking context (AFP and dotlock override) for
+ ** proxyLock activation is possible (remote proxy is based on db name)
+ ** zFilename remains valid until file is closed, to support */
+ pNew->lockingContext = (void*)zFilename;
+#endif
+ }
+
+ if( pLockingStyle == &posixIoMethods
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+ || pLockingStyle == &nfsIoMethods
+#endif
+ ){
+ unixEnterMutex();
+ rc = findInodeInfo(pNew, &pNew->pInode);
+ if( rc!=SQLITE_OK ){
+ /* If an error occurred in findInodeInfo(), close the file descriptor
+ ** immediately, before releasing the mutex. findInodeInfo() may fail
+ ** in two scenarios:
+ **
+ ** (a) A call to fstat() failed.
+ ** (b) A malloc failed.
+ **
+ ** Scenario (b) may only occur if the process is holding no other
+ ** file descriptors open on the same file. If there were other file
+ ** descriptors on this file, then no malloc would be required by
+ ** findInodeInfo(). If this is the case, it is quite safe to close
+ ** handle h - as it is guaranteed that no posix locks will be released
+ ** by doing so.
+ **
+ ** If scenario (a) caused the error then things are not so safe. The
+ ** implicit assumption here is that if fstat() fails, things are in
+ ** such bad shape that dropping a lock or two doesn't matter much.
+ */
+ robust_close(pNew, h, __LINE__);
+ h = -1;
+ }
+ unixLeaveMutex();
+ }
+
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+ else if( pLockingStyle == &afpIoMethods ){
+ /* AFP locking uses the file path so it needs to be included in
+ ** the afpLockingContext.
+ */
+ afpLockingContext *pCtx;
+ pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
+ if( pCtx==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ /* NB: zFilename exists and remains valid until the file is closed
+ ** according to requirement F11141. So we do not need to make a
+ ** copy of the filename. */
+ pCtx->dbPath = zFilename;
+ pCtx->reserved = 0;
+ srandomdev();
+ unixEnterMutex();
+ rc = findInodeInfo(pNew, &pNew->pInode);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pNew->lockingContext);
+ robust_close(pNew, h, __LINE__);
+ h = -1;
+ }
+ unixLeaveMutex();
+ }
+ }
+#endif
+
+ else if( pLockingStyle == &dotlockIoMethods ){
+ /* Dotfile locking uses the file path so it needs to be included in
+ ** the dotlockLockingContext
+ */
+ char *zLockFile;
+ int nFilename;
+ assert( zFilename!=0 );
+ nFilename = (int)strlen(zFilename) + 6;
+ zLockFile = (char *)sqlite3_malloc(nFilename);
+ if( zLockFile==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
+ }
+ pNew->lockingContext = zLockFile;
+ }
+
+#if OS_VXWORKS
+ else if( pLockingStyle == &semIoMethods ){
+ /* Named semaphore locking uses the file path so it needs to be
+ ** included in the semLockingContext
+ */
+ unixEnterMutex();
+ rc = findInodeInfo(pNew, &pNew->pInode);
+ if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
+ char *zSemName = pNew->pInode->aSemName;
+ int n;
+ sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
+ pNew->pId->zCanonicalName);
+ for( n=1; zSemName[n]; n++ )
+ if( zSemName[n]=='/' ) zSemName[n] = '_';
+ pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
+ if( pNew->pInode->pSem == SEM_FAILED ){
+ rc = SQLITE_NOMEM;
+ pNew->pInode->aSemName[0] = '\0';
+ }
+ }
+ unixLeaveMutex();
+ }
+#endif
+
+ pNew->lastErrno = 0;
+#if OS_VXWORKS
+ if( rc!=SQLITE_OK ){
+ if( h>=0 ) robust_close(pNew, h, __LINE__);
+ h = -1;
+ osUnlink(zFilename);
+ isDelete = 0;
+ }
+ if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
+#endif
+ if( rc!=SQLITE_OK ){
+ if( h>=0 ) robust_close(pNew, h, __LINE__);
+ }else{
+ pNew->pMethod = pLockingStyle;
+ OpenCounter(+1);
+ }
+ return rc;
+}
+
+/*
+** Return the name of a directory in which to put temporary files.
+** If no suitable temporary file directory can be found, return NULL.
+*/
+static const char *unixTempFileDir(void){
+ static const char *azDirs[] = {
+ 0,
+ 0,
+ "/var/tmp",
+ "/usr/tmp",
+ "/tmp",
+ 0 /* List terminator */
+ };
+ unsigned int i;
+ struct stat buf;
+ const char *zDir = 0;
+
+ azDirs[0] = sqlite3_temp_directory;
+ if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
+ for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
+ if( zDir==0 ) continue;
+ if( osStat(zDir, &buf) ) continue;
+ if( !S_ISDIR(buf.st_mode) ) continue;
+ if( osAccess(zDir, 07) ) continue;
+ break;
+ }
+ return zDir;
+}
+
+/*
+** Create a temporary file name in zBuf. zBuf must be allocated
+** by the calling process and must be big enough to hold at least
+** pVfs->mxPathname bytes.
+*/
+static int unixGetTempname(int nBuf, char *zBuf){
+ static const unsigned char zChars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
+ unsigned int i, j;
+ const char *zDir;
+
+ /* It's odd to simulate an io-error here, but really this is just
+ ** using the io-error infrastructure to test that SQLite handles this
+ ** function failing.
+ */
+ SimulateIOError( return SQLITE_IOERR );
+
+ zDir = unixTempFileDir();
+ if( zDir==0 ) zDir = ".";
+
+ /* Check that the output buffer is large enough for the temporary file
+ ** name. If it is not, return SQLITE_ERROR.
+ */
+ if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
+ return SQLITE_ERROR;
+ }
+
+ do{
+ sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
+ j = (int)strlen(zBuf);
+ sqlite3_randomness(15, &zBuf[j]);
+ for(i=0; i<15; i++, j++){
+ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
+ }
+ zBuf[j] = 0;
+ zBuf[j+1] = 0;
+ }while( osAccess(zBuf,0)==0 );
+ return SQLITE_OK;
+}
+
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+/*
+** Routine to transform a unixFile into a proxy-locking unixFile.
+** Implementation in the proxy-lock division, but used by unixOpen()
+** if SQLITE_PREFER_PROXY_LOCKING is defined.
+*/
+static int proxyTransformUnixFile(unixFile*, const char*);
+#endif
+
+/*
+** Search for an unused file descriptor that was opened on the database
+** file (not a journal or master-journal file) identified by pathname
+** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
+** argument to this function.
+**
+** Such a file descriptor may exist if a database connection was closed
+** but the associated file descriptor could not be closed because some
+** other file descriptor open on the same file is holding a file-lock.
+** Refer to comments in the unixClose() function and the lengthy comment
+** describing "Posix Advisory Locking" at the start of this file for
+** further details. Also, ticket #4018.
+**
+** If a suitable file descriptor is found, then it is returned. If no
+** such file descriptor is located, -1 is returned.
+*/
+static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
+ UnixUnusedFd *pUnused = 0;
+
+ /* Do not search for an unused file descriptor on vxworks. Not because
+ ** vxworks would not benefit from the change (it might, we're not sure),
+ ** but because no way to test it is currently available. It is better
+ ** not to risk breaking vxworks support for the sake of such an obscure
+ ** feature. */
+#if !OS_VXWORKS
+ struct stat sStat; /* Results of stat() call */
+
+ /* A stat() call may fail for various reasons. If this happens, it is
+ ** almost certain that an open() call on the same path will also fail.
+ ** For this reason, if an error occurs in the stat() call here, it is
+ ** ignored and -1 is returned. The caller will try to open a new file
+ ** descriptor on the same path, fail, and return an error to SQLite.
+ **
+ ** Even if a subsequent open() call does succeed, the consequences of
+ ** not searching for a resusable file descriptor are not dire. */
+ if( 0==osStat(zPath, &sStat) ){
+ unixInodeInfo *pInode;
+
+ unixEnterMutex();
+ pInode = inodeList;
+ while( pInode && (pInode->fileId.dev!=sStat.st_dev
+ || pInode->fileId.ino!=sStat.st_ino) ){
+ pInode = pInode->pNext;
+ }
+ if( pInode ){
+ UnixUnusedFd **pp;
+ for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
+ pUnused = *pp;
+ if( pUnused ){
+ *pp = pUnused->pNext;
+ }
+ }
+ unixLeaveMutex();
+ }
+#endif /* if !OS_VXWORKS */
+ return pUnused;
+}
+
+/*
+** This function is called by unixOpen() to determine the unix permissions
+** to create new files with. If no error occurs, then SQLITE_OK is returned
+** and a value suitable for passing as the third argument to open(2) is
+** written to *pMode. If an IO error occurs, an SQLite error code is
+** returned and the value of *pMode is not modified.
+**
+** In most cases cases, this routine sets *pMode to 0, which will become
+** an indication to robust_open() to create the file using
+** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
+** But if the file being opened is a WAL or regular journal file, then
+** this function queries the file-system for the permissions on the
+** corresponding database file and sets *pMode to this value. Whenever
+** possible, WAL and journal files are created using the same permissions
+** as the associated database file.
+**
+** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
+** original filename is unavailable. But 8_3_NAMES is only used for
+** FAT filesystems and permissions do not matter there, so just use
+** the default permissions.
+*/
+static int findCreateFileMode(
+ const char *zPath, /* Path of file (possibly) being created */
+ int flags, /* Flags passed as 4th argument to xOpen() */
+ mode_t *pMode, /* OUT: Permissions to open file with */
+ uid_t *pUid, /* OUT: uid to set on the file */
+ gid_t *pGid /* OUT: gid to set on the file */
+){
+ int rc = SQLITE_OK; /* Return Code */
+ *pMode = 0;
+ *pUid = 0;
+ *pGid = 0;
+ if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
+ char zDb[MAX_PATHNAME+1]; /* Database file path */
+ int nDb; /* Number of valid bytes in zDb */
+ struct stat sStat; /* Output of stat() on database file */
+
+ /* zPath is a path to a WAL or journal file. The following block derives
+ ** the path to the associated database file from zPath. This block handles
+ ** the following naming conventions:
+ **
+ ** "<path to db>-journal"
+ ** "<path to db>-wal"
+ ** "<path to db>-journalNN"
+ ** "<path to db>-walNN"
+ **
+ ** where NN is a decimal number. The NN naming schemes are
+ ** used by the test_multiplex.c module.
+ */
+ nDb = sqlite3Strlen30(zPath) - 1;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
+ if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
+#else
+ while( zPath[nDb]!='-' ){
+ assert( nDb>0 );
+ assert( zPath[nDb]!='\n' );
+ nDb--;
+ }
+#endif
+ memcpy(zDb, zPath, nDb);
+ zDb[nDb] = '\0';
+
+ if( 0==osStat(zDb, &sStat) ){
+ *pMode = sStat.st_mode & 0777;
+ *pUid = sStat.st_uid;
+ *pGid = sStat.st_gid;
+ }else{
+ rc = SQLITE_IOERR_FSTAT;
+ }
+ }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
+ *pMode = 0600;
+ }
+ return rc;
+}
+
+/*
+** Open the file zPath.
+**
+** Previously, the SQLite OS layer used three functions in place of this
+** one:
+**
+** sqlite3OsOpenReadWrite();
+** sqlite3OsOpenReadOnly();
+** sqlite3OsOpenExclusive();
+**
+** These calls correspond to the following combinations of flags:
+**
+** ReadWrite() -> (READWRITE | CREATE)
+** ReadOnly() -> (READONLY)
+** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
+**
+** The old OpenExclusive() accepted a boolean argument - "delFlag". If
+** true, the file was configured to be automatically deleted when the
+** file handle closed. To achieve the same effect using this new
+** interface, add the DELETEONCLOSE flag to those specified above for
+** OpenExclusive().
+*/
+static int unixOpen(
+ sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
+ const char *zPath, /* Pathname of file to be opened */
+ sqlite3_file *pFile, /* The file descriptor to be filled in */
+ int flags, /* Input flags to control the opening */
+ int *pOutFlags /* Output flags returned to SQLite core */
+){
+ unixFile *p = (unixFile *)pFile;
+ int fd = -1; /* File descriptor returned by open() */
+ int openFlags = 0; /* Flags to pass to open() */
+ int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int noLock; /* True to omit locking primitives */
+ int rc = SQLITE_OK; /* Function Return Code */
+ int ctrlFlags = 0; /* UNIXFILE_* flags */
+
+ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
+ int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
+ int isCreate = (flags & SQLITE_OPEN_CREATE);
+ int isReadonly = (flags & SQLITE_OPEN_READONLY);
+ int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
+#if SQLITE_ENABLE_LOCKING_STYLE
+ int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
+#endif
+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
+ struct statfs fsInfo;
+#endif
+
+ /* If creating a master or main-file journal, this function will open
+ ** a file-descriptor on the directory too. The first time unixSync()
+ ** is called the directory file descriptor will be fsync()ed and close()d.
+ */
+ int syncDir = (isCreate && (
+ eType==SQLITE_OPEN_MASTER_JOURNAL
+ || eType==SQLITE_OPEN_MAIN_JOURNAL
+ || eType==SQLITE_OPEN_WAL
+ ));
+
+ /* If argument zPath is a NULL pointer, this function is required to open
+ ** a temporary file. Use this buffer to store the file name in.
+ */
+ char zTmpname[MAX_PATHNAME+2];
+ const char *zName = zPath;
+
+ /* Check the following statements are true:
+ **
+ ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
+ ** (b) if CREATE is set, then READWRITE must also be set, and
+ ** (c) if EXCLUSIVE is set, then CREATE must also be set.
+ ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
+ */
+ assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
+ assert(isCreate==0 || isReadWrite);
+ assert(isExclusive==0 || isCreate);
+ assert(isDelete==0 || isCreate);
+
+ /* The main DB, main journal, WAL file and master journal are never
+ ** automatically deleted. Nor are they ever temporary files. */
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
+
+ /* Assert that the upper layer has set one of the "file-type" flags. */
+ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
+ || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
+ || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
+ );
+
+ memset(p, 0, sizeof(unixFile));
+
+ if( eType==SQLITE_OPEN_MAIN_DB ){
+ UnixUnusedFd *pUnused;
+ pUnused = findReusableFd(zName, flags);
+ if( pUnused ){
+ fd = pUnused->fd;
+ }else{
+ pUnused = sqlite3_malloc(sizeof(*pUnused));
+ if( !pUnused ){
+ return SQLITE_NOMEM;
+ }
+ }
+ p->pUnused = pUnused;
+
+ /* Database filenames are double-zero terminated if they are not
+ ** URIs with parameters. Hence, they can always be passed into
+ ** sqlite3_uri_parameter(). */
+ assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
+
+ }else if( !zName ){
+ /* If zName is NULL, the upper layer is requesting a temp file. */
+ assert(isDelete && !syncDir);
+ rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ zName = zTmpname;
+
+ /* Generated temporary filenames are always double-zero terminated
+ ** for use by sqlite3_uri_parameter(). */
+ assert( zName[strlen(zName)+1]==0 );
+ }
+
+ /* Determine the value of the flags parameter passed to POSIX function
+ ** open(). These must be calculated even if open() is not called, as
+ ** they may be stored as part of the file handle and used by the
+ ** 'conch file' locking functions later on. */
+ if( isReadonly ) openFlags |= O_RDONLY;
+ if( isReadWrite ) openFlags |= O_RDWR;
+ if( isCreate ) openFlags |= O_CREAT;
+ if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
+ openFlags |= (O_LARGEFILE|O_BINARY);
+
+ if( fd<0 ){
+ mode_t openMode; /* Permissions to create file with */
+ uid_t uid; /* Userid for the file */
+ gid_t gid; /* Groupid for the file */
+ rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
+ if( rc!=SQLITE_OK ){
+ assert( !p->pUnused );
+ assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
+ return rc;
+ }
+ fd = robust_open(zName, openFlags, openMode);
+ OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
+ if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
+ /* Failed to open the file for read/write access. Try read-only. */
+ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
+ openFlags &= ~(O_RDWR|O_CREAT);
+ flags |= SQLITE_OPEN_READONLY;
+ openFlags |= O_RDONLY;
+ isReadonly = 1;
+ fd = robust_open(zName, openFlags, openMode);
+ }
+ if( fd<0 ){
+ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
+ goto open_finished;
+ }
+
+ /* If this process is running as root and if creating a new rollback
+ ** journal or WAL file, set the ownership of the journal or WAL to be
+ ** the same as the original database.
+ */
+ if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
+ osFchown(fd, uid, gid);
+ }
+ }
+ assert( fd>=0 );
+ if( pOutFlags ){
+ *pOutFlags = flags;
+ }
+
+ if( p->pUnused ){
+ p->pUnused->fd = fd;
+ p->pUnused->flags = flags;
+ }
+
+ if( isDelete ){
+#if OS_VXWORKS
+ zPath = zName;
+#else
+ osUnlink(zName);
+#endif
+ }
+#if SQLITE_ENABLE_LOCKING_STYLE
+ else{
+ p->openFlags = openFlags;
+ }
+#endif
+
+ noLock = eType!=SQLITE_OPEN_MAIN_DB;
+
+
+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
+ if( fstatfs(fd, &fsInfo) == -1 ){
+ ((unixFile*)pFile)->lastErrno = errno;
+ robust_close(p, fd, __LINE__);
+ return SQLITE_IOERR_ACCESS;
+ }
+ if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
+ ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
+ }
+#endif
+
+ /* Set up appropriate ctrlFlags */
+ if( isDelete ) ctrlFlags |= UNIXFILE_DELETE;
+ if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
+ if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
+ if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC;
+ if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
+
+#if SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_PREFER_PROXY_LOCKING
+ isAutoProxy = 1;
+#endif
+ if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
+ char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
+ int useProxy = 0;
+
+ /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
+ ** never use proxy, NULL means use proxy for non-local files only. */
+ if( envforce!=NULL ){
+ useProxy = atoi(envforce)>0;
+ }else{
+ if( statfs(zPath, &fsInfo) == -1 ){
+ /* In theory, the close(fd) call is sub-optimal. If the file opened
+ ** with fd is a database file, and there are other connections open
+ ** on that file that are currently holding advisory locks on it,
+ ** then the call to close() will cancel those locks. In practice,
+ ** we're assuming that statfs() doesn't fail very often. At least
+ ** not while other file descriptors opened by the same process on
+ ** the same file are working. */
+ p->lastErrno = errno;
+ robust_close(p, fd, __LINE__);
+ rc = SQLITE_IOERR_ACCESS;
+ goto open_finished;
+ }
+ useProxy = !(fsInfo.f_flags&MNT_LOCAL);
+ }
+ if( useProxy ){
+ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
+ if( rc==SQLITE_OK ){
+ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
+ if( rc!=SQLITE_OK ){
+ /* Use unixClose to clean up the resources added in fillInUnixFile
+ ** and clear all the structure's references. Specifically,
+ ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
+ */
+ unixClose(pFile);
+ return rc;
+ }
+ }
+ goto open_finished;
+ }
+ }
+#endif
+
+ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
+
+open_finished:
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(p->pUnused);
+ }
+ return rc;
+}
+
+
+/*
+** Delete the file at zPath. If the dirSync argument is true, fsync()
+** the directory after deleting the file.
+*/
+static int unixDelete(
+ sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */
+ const char *zPath, /* Name of file to be deleted */
+ int dirSync /* If true, fsync() directory after deleting file */
+){
+ int rc = SQLITE_OK;
+ UNUSED_PARAMETER(NotUsed);
+ SimulateIOError(return SQLITE_IOERR_DELETE);
+ if( osUnlink(zPath)==(-1) ){
+ if( errno==ENOENT ){
+ rc = SQLITE_IOERR_DELETE_NOENT;
+ }else{
+ rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+ }
+ return rc;
+ }
+#ifndef SQLITE_DISABLE_DIRSYNC
+ if( (dirSync & 1)!=0 ){
+ int fd;
+ rc = osOpenDirectory(zPath, &fd);
+ if( rc==SQLITE_OK ){
+#if OS_VXWORKS
+ if( fsync(fd)==-1 )
+#else
+ if( fsync(fd) )
+#endif
+ {
+ rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
+ }
+ robust_close(0, fd, __LINE__);
+ }else if( rc==SQLITE_CANTOPEN ){
+ rc = SQLITE_OK;
+ }
+ }
+#endif
+ return rc;
+}
+
+/*
+** Test the existence of or access permissions of file zPath. The
+** test performed depends on the value of flags:
+**
+** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
+** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
+** SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
+**
+** Otherwise return 0.
+*/
+static int unixAccess(
+ sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */
+ const char *zPath, /* Path of the file to examine */
+ int flags, /* What do we want to learn about the zPath file? */
+ int *pResOut /* Write result boolean here */
+){
+ int amode = 0;
+ UNUSED_PARAMETER(NotUsed);
+ SimulateIOError( return SQLITE_IOERR_ACCESS; );
+ switch( flags ){
+ case SQLITE_ACCESS_EXISTS:
+ amode = F_OK;
+ break;
+ case SQLITE_ACCESS_READWRITE:
+ amode = W_OK|R_OK;
+ break;
+ case SQLITE_ACCESS_READ:
+ amode = R_OK;
+ break;
+
+ default:
+ assert(!"Invalid flags argument");
+ }
+ *pResOut = (osAccess(zPath, amode)==0);
+ if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
+ struct stat buf;
+ if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
+ *pResOut = 0;
+ }
+ }
+ return SQLITE_OK;
+}
+
+
+/*
+** Turn a relative pathname into a full pathname. The relative path
+** is stored as a nul-terminated string in the buffer pointed to by
+** zPath.
+**
+** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
+** (in this case, MAX_PATHNAME bytes). The full-path is written to
+** this buffer before returning.
+*/
+static int unixFullPathname(
+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
+ const char *zPath, /* Possibly relative input path */
+ int nOut, /* Size of output buffer in bytes */
+ char *zOut /* Output buffer */
+){
+
+ /* It's odd to simulate an io-error here, but really this is just
+ ** using the io-error infrastructure to test that SQLite handles this
+ ** function failing. This function could fail if, for example, the
+ ** current working directory has been unlinked.
+ */
+ SimulateIOError( return SQLITE_ERROR );
+
+ assert( pVfs->mxPathname==MAX_PATHNAME );
+ UNUSED_PARAMETER(pVfs);
+
+ zOut[nOut-1] = '\0';
+ if( zPath[0]=='/' ){
+ sqlite3_snprintf(nOut, zOut, "%s", zPath);
+ }else{
+ int nCwd;
+ if( osGetcwd(zOut, nOut-1)==0 ){
+ return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
+ }
+ nCwd = (int)strlen(zOut);
+ sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
+ }
+ return SQLITE_OK;
+}
+
+
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+/*
+** Interfaces for opening a shared library, finding entry points
+** within the shared library, and closing the shared library.
+*/
+#include <dlfcn.h>
+static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
+ UNUSED_PARAMETER(NotUsed);
+ return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
+}
+
+/*
+** SQLite calls this function immediately after a call to unixDlSym() or
+** unixDlOpen() fails (returns a null pointer). If a more detailed error
+** message is available, it is written to zBufOut. If no error message
+** is available, zBufOut is left unmodified and SQLite uses a default
+** error message.
+*/
+static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
+ const char *zErr;
+ UNUSED_PARAMETER(NotUsed);
+ unixEnterMutex();
+ zErr = dlerror();
+ if( zErr ){
+ sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
+ }
+ unixLeaveMutex();
+}
+static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
+ /*
+ ** GCC with -pedantic-errors says that C90 does not allow a void* to be
+ ** cast into a pointer to a function. And yet the library dlsym() routine
+ ** returns a void* which is really a pointer to a function. So how do we
+ ** use dlsym() with -pedantic-errors?
+ **
+ ** Variable x below is defined to be a pointer to a function taking
+ ** parameters void* and const char* and returning a pointer to a function.
+ ** We initialize x by assigning it a pointer to the dlsym() function.
+ ** (That assignment requires a cast.) Then we call the function that
+ ** x points to.
+ **
+ ** This work-around is unlikely to work correctly on any system where
+ ** you really cannot cast a function pointer into void*. But then, on the
+ ** other hand, dlsym() will not work on such a system either, so we have
+ ** not really lost anything.
+ */
+ void (*(*x)(void*,const char*))(void);
+ UNUSED_PARAMETER(NotUsed);
+ x = (void(*(*)(void*,const char*))(void))dlsym;
+ return (*x)(p, zSym);
+}
+static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
+ UNUSED_PARAMETER(NotUsed);
+ dlclose(pHandle);
+}
+#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
+ #define unixDlOpen 0
+ #define unixDlError 0
+ #define unixDlSym 0
+ #define unixDlClose 0
+#endif
+
+/*
+** Write nBuf bytes of random data to the supplied buffer zBuf.
+*/
+static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
+ UNUSED_PARAMETER(NotUsed);
+ assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
+
+ /* We have to initialize zBuf to prevent valgrind from reporting
+ ** errors. The reports issued by valgrind are incorrect - we would
+ ** prefer that the randomness be increased by making use of the
+ ** uninitialized space in zBuf - but valgrind errors tend to worry
+ ** some users. Rather than argue, it seems easier just to initialize
+ ** the whole array and silence valgrind, even if that means less randomness
+ ** in the random seed.
+ **
+ ** When testing, initializing zBuf[] to zero is all we do. That means
+ ** that we always use the same random number sequence. This makes the
+ ** tests repeatable.
+ */
+ memset(zBuf, 0, nBuf);
+#if !defined(SQLITE_TEST)
+ {
+ int pid, fd, got;
+ fd = robust_open("/dev/urandom", O_RDONLY, 0);
+ if( fd<0 ){
+ time_t t;
+ time(&t);
+ memcpy(zBuf, &t, sizeof(t));
+ pid = getpid();
+ memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
+ assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
+ nBuf = sizeof(t) + sizeof(pid);
+ }else{
+ do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
+ robust_close(0, fd, __LINE__);
+ }
+ }
+#endif
+ return nBuf;
+}
+
+
+/*
+** Sleep for a little while. Return the amount of time slept.
+** The argument is the number of microseconds we want to sleep.
+** The return value is the number of microseconds of sleep actually
+** requested from the underlying operating system, a number which
+** might be greater than or equal to the argument, but not less
+** than the argument.
+*/
+static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
+#if OS_VXWORKS
+ struct timespec sp;
+
+ sp.tv_sec = microseconds / 1000000;
+ sp.tv_nsec = (microseconds % 1000000) * 1000;
+ nanosleep(&sp, NULL);
+ UNUSED_PARAMETER(NotUsed);
+ return microseconds;
+#elif defined(HAVE_USLEEP) && HAVE_USLEEP
+ usleep(microseconds);
+ UNUSED_PARAMETER(NotUsed);
+ return microseconds;
+#else
+ int seconds = (microseconds+999999)/1000000;
+ sleep(seconds);
+ UNUSED_PARAMETER(NotUsed);
+ return seconds*1000000;
+#endif
+}
+
+/*
+** The following variable, if set to a non-zero value, is interpreted as
+** the number of seconds since 1970 and is used to set the result of
+** sqlite3OsCurrentTime() during testing.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
+#endif
+
+/*
+** Find the current time (in Universal Coordinated Time). Write into *piNow
+** the current time and date as a Julian Day number times 86_400_000. In
+** other words, write into *piNow the number of milliseconds since the Julian
+** epoch of noon in Greenwich on November 24, 4714 B.C according to the
+** proleptic Gregorian calendar.
+**
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
+** cannot be found.
+*/
+static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
+ static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
+ int rc = SQLITE_OK;
+#if defined(NO_GETTOD)
+ time_t t;
+ time(&t);
+ *piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
+#elif OS_VXWORKS
+ struct timespec sNow;
+ clock_gettime(CLOCK_REALTIME, &sNow);
+ *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
+#else
+ struct timeval sNow;
+ if( gettimeofday(&sNow, 0)==0 ){
+ *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+ }else{
+ rc = SQLITE_ERROR;
+ }
+#endif
+
+#ifdef SQLITE_TEST
+ if( sqlite3_current_time ){
+ *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
+ }
+#endif
+ UNUSED_PARAMETER(NotUsed);
+ return rc;
+}
+
+/*
+** Find the current time (in Universal Coordinated Time). Write the
+** current time and date as a Julian Day number into *prNow and
+** return 0. Return 1 if the time and date cannot be found.
+*/
+static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
+ sqlite3_int64 i = 0;
+ int rc;
+ UNUSED_PARAMETER(NotUsed);
+ rc = unixCurrentTimeInt64(0, &i);
+ *prNow = i/86400000.0;
+ return rc;
+}
+
+/*
+** We added the xGetLastError() method with the intention of providing
+** better low-level error messages when operating-system problems come up
+** during SQLite operation. But so far, none of that has been implemented
+** in the core. So this routine is never called. For now, it is merely
+** a place-holder.
+*/
+static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
+ UNUSED_PARAMETER(NotUsed);
+ UNUSED_PARAMETER(NotUsed2);
+ UNUSED_PARAMETER(NotUsed3);
+ return 0;
+}
+
+
+/*
+************************ End of sqlite3_vfs methods ***************************
+******************************************************************************/
+
+/******************************************************************************
+************************** Begin Proxy Locking ********************************
+**
+** Proxy locking is a "uber-locking-method" in this sense: It uses the
+** other locking methods on secondary lock files. Proxy locking is a
+** meta-layer over top of the primitive locking implemented above. For
+** this reason, the division that implements of proxy locking is deferred
+** until late in the file (here) after all of the other I/O methods have
+** been defined - so that the primitive locking methods are available
+** as services to help with the implementation of proxy locking.
+**
+****
+**
+** The default locking schemes in SQLite use byte-range locks on the
+** database file to coordinate safe, concurrent access by multiple readers
+** and writers [http://sqlite.org/lockingv3.html]. The five file locking
+** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
+** as POSIX read & write locks over fixed set of locations (via fsctl),
+** on AFP and SMB only exclusive byte-range locks are available via fsctl
+** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
+** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
+** address in the shared range is taken for a SHARED lock, the entire
+** shared range is taken for an EXCLUSIVE lock):
+**
+** PENDING_BYTE 0x40000000
+** RESERVED_BYTE 0x40000001
+** SHARED_RANGE 0x40000002 -> 0x40000200
+**
+** This works well on the local file system, but shows a nearly 100x
+** slowdown in read performance on AFP because the AFP client disables
+** the read cache when byte-range locks are present. Enabling the read
+** cache exposes a cache coherency problem that is present on all OS X
+** supported network file systems. NFS and AFP both observe the
+** close-to-open semantics for ensuring cache coherency
+** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
+** address the requirements for concurrent database access by multiple
+** readers and writers
+** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
+**
+** To address the performance and cache coherency issues, proxy file locking
+** changes the way database access is controlled by limiting access to a
+** single host at a time and moving file locks off of the database file
+** and onto a proxy file on the local file system.
+**
+**
+** Using proxy locks
+** -----------------
+**
+** C APIs
+**
+** sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
+** <proxy_path> | ":auto:");
+** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
+**
+**
+** SQL pragmas
+**
+** PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
+** PRAGMA [database.]lock_proxy_file
+**
+** Specifying ":auto:" means that if there is a conch file with a matching
+** host ID in it, the proxy path in the conch file will be used, otherwise
+** a proxy path based on the user's temp dir
+** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
+** actual proxy file name is generated from the name and path of the
+** database file. For example:
+**
+** For database path "/Users/me/foo.db"
+** The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
+**
+** Once a lock proxy is configured for a database connection, it can not
+** be removed, however it may be switched to a different proxy path via
+** the above APIs (assuming the conch file is not being held by another
+** connection or process).
+**
+**
+** How proxy locking works
+** -----------------------
+**
+** Proxy file locking relies primarily on two new supporting files:
+**
+** * conch file to limit access to the database file to a single host
+** at a time
+**
+** * proxy file to act as a proxy for the advisory locks normally
+** taken on the database
+**
+** The conch file - to use a proxy file, sqlite must first "hold the conch"
+** by taking an sqlite-style shared lock on the conch file, reading the
+** contents and comparing the host's unique host ID (see below) and lock
+** proxy path against the values stored in the conch. The conch file is
+** stored in the same directory as the database file and the file name
+** is patterned after the database file name as ".<databasename>-conch".
+** If the conch file does not exist, or it's contents do not match the
+** host ID and/or proxy path, then the lock is escalated to an exclusive
+** lock and the conch file contents is updated with the host ID and proxy
+** path and the lock is downgraded to a shared lock again. If the conch
+** is held by another process (with a shared lock), the exclusive lock
+** will fail and SQLITE_BUSY is returned.
+**
+** The proxy file - a single-byte file used for all advisory file locks
+** normally taken on the database file. This allows for safe sharing
+** of the database file for multiple readers and writers on the same
+** host (the conch ensures that they all use the same local lock file).
+**
+** Requesting the lock proxy does not immediately take the conch, it is
+** only taken when the first request to lock database file is made.
+** This matches the semantics of the traditional locking behavior, where
+** opening a connection to a database file does not take a lock on it.
+** The shared lock and an open file descriptor are maintained until
+** the connection to the database is closed.
+**
+** The proxy file and the lock file are never deleted so they only need
+** to be created the first time they are used.
+**
+** Configuration options
+** ---------------------
+**
+** SQLITE_PREFER_PROXY_LOCKING
+**
+** Database files accessed on non-local file systems are
+** automatically configured for proxy locking, lock files are
+** named automatically using the same logic as
+** PRAGMA lock_proxy_file=":auto:"
+**
+** SQLITE_PROXY_DEBUG
+**
+** Enables the logging of error messages during host id file
+** retrieval and creation
+**
+** LOCKPROXYDIR
+**
+** Overrides the default directory used for lock proxy files that
+** are named automatically via the ":auto:" setting
+**
+** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+**
+** Permissions to use when creating a directory for storing the
+** lock proxy files, only used when LOCKPROXYDIR is not set.
+**
+**
+** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
+** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
+** force proxy locking to be used for every database file opened, and 0
+** will force automatic proxy locking to be disabled for all database
+** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
+** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
+*/
+
+/*
+** Proxy locking is only available on MacOSX
+*/
+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+
+/*
+** The proxyLockingContext has the path and file structures for the remote
+** and local proxy files in it
+*/
+typedef struct proxyLockingContext proxyLockingContext;
+struct proxyLockingContext {
+ unixFile *conchFile; /* Open conch file */
+ char *conchFilePath; /* Name of the conch file */
+ unixFile *lockProxy; /* Open proxy lock file */
+ char *lockProxyPath; /* Name of the proxy lock file */
+ char *dbPath; /* Name of the open file */
+ int conchHeld; /* 1 if the conch is held, -1 if lockless */
+ void *oldLockingContext; /* Original lockingcontext to restore on close */
+ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
+};
+
+/*
+** The proxy lock file path for the database at dbPath is written into lPath,
+** which must point to valid, writable memory large enough for a maxLen length
+** file path.
+*/
+static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
+ int len;
+ int dbLen;
+ int i;
+
+#ifdef LOCKPROXYDIR
+ len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
+#else
+# ifdef _CS_DARWIN_USER_TEMP_DIR
+ {
+ if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
+ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
+ lPath, errno, getpid()));
+ return SQLITE_IOERR_LOCK;
+ }
+ len = strlcat(lPath, "sqliteplocks", maxLen);
+ }
+# else
+ len = strlcpy(lPath, "/tmp/", maxLen);
+# endif
+#endif
+
+ if( lPath[len-1]!='/' ){
+ len = strlcat(lPath, "/", maxLen);
+ }
+
+ /* transform the db path to a unique cache name */
+ dbLen = (int)strlen(dbPath);
+ for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
+ char c = dbPath[i];
+ lPath[i+len] = (c=='/')?'_':c;
+ }
+ lPath[i+len]='\0';
+ strlcat(lPath, ":auto:", maxLen);
+ OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
+ return SQLITE_OK;
+}
+
+/*
+ ** Creates the lock file and any missing directories in lockPath
+ */
+static int proxyCreateLockPath(const char *lockPath){
+ int i, len;
+ char buf[MAXPATHLEN];
+ int start = 0;
+
+ assert(lockPath!=NULL);
+ /* try to create all the intermediate directories */
+ len = (int)strlen(lockPath);
+ buf[0] = lockPath[0];
+ for( i=1; i<len; i++ ){
+ if( lockPath[i] == '/' && (i - start > 0) ){
+ /* only mkdir if leaf dir != "." or "/" or ".." */
+ if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
+ || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
+ buf[i]='\0';
+ if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
+ int err=errno;
+ if( err!=EEXIST ) {
+ OSTRACE(("CREATELOCKPATH FAILED creating %s, "
+ "'%s' proxy lock path=%s pid=%d\n",
+ buf, strerror(err), lockPath, getpid()));
+ return err;
+ }
+ }
+ }
+ start=i+1;
+ }
+ buf[i] = lockPath[i];
+ }
+ OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()));
+ return 0;
+}
+
+/*
+** Create a new VFS file descriptor (stored in memory obtained from
+** sqlite3_malloc) and open the file named "path" in the file descriptor.
+**
+** The caller is responsible not only for closing the file descriptor
+** but also for freeing the memory associated with the file descriptor.
+*/
+static int proxyCreateUnixFile(
+ const char *path, /* path for the new unixFile */
+ unixFile **ppFile, /* unixFile created and returned by ref */
+ int islockfile /* if non zero missing dirs will be created */
+) {
+ int fd = -1;
+ unixFile *pNew;
+ int rc = SQLITE_OK;
+ int openFlags = O_RDWR | O_CREAT;
+ sqlite3_vfs dummyVfs;
+ int terrno = 0;
+ UnixUnusedFd *pUnused = NULL;
+
+ /* 1. first try to open/create the file
+ ** 2. if that fails, and this is a lock file (not-conch), try creating
+ ** the parent directories and then try again.
+ ** 3. if that fails, try to open the file read-only
+ ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
+ */
+ pUnused = findReusableFd(path, openFlags);
+ if( pUnused ){
+ fd = pUnused->fd;
+ }else{
+ pUnused = sqlite3_malloc(sizeof(*pUnused));
+ if( !pUnused ){
+ return SQLITE_NOMEM;
+ }
+ }
+ if( fd<0 ){
+ fd = robust_open(path, openFlags, 0);
+ terrno = errno;
+ if( fd<0 && errno==ENOENT && islockfile ){
+ if( proxyCreateLockPath(path) == SQLITE_OK ){
+ fd = robust_open(path, openFlags, 0);
+ }
+ }
+ }
+ if( fd<0 ){
+ openFlags = O_RDONLY;
+ fd = robust_open(path, openFlags, 0);
+ terrno = errno;
+ }
+ if( fd<0 ){
+ if( islockfile ){
+ return SQLITE_BUSY;
+ }
+ switch (terrno) {
+ case EACCES:
+ return SQLITE_PERM;
+ case EIO:
+ return SQLITE_IOERR_LOCK; /* even though it is the conch */
+ default:
+ return SQLITE_CANTOPEN_BKPT;
+ }
+ }
+
+ pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
+ if( pNew==NULL ){
+ rc = SQLITE_NOMEM;
+ goto end_create_proxy;
+ }
+ memset(pNew, 0, sizeof(unixFile));
+ pNew->openFlags = openFlags;
+ memset(&dummyVfs, 0, sizeof(dummyVfs));
+ dummyVfs.pAppData = (void*)&autolockIoFinder;
+ dummyVfs.zName = "dummy";
+ pUnused->fd = fd;
+ pUnused->flags = openFlags;
+ pNew->pUnused = pUnused;
+
+ rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
+ if( rc==SQLITE_OK ){
+ *ppFile = pNew;
+ return SQLITE_OK;
+ }
+end_create_proxy:
+ robust_close(pNew, fd, __LINE__);
+ sqlite3_free(pNew);
+ sqlite3_free(pUnused);
+ return rc;
+}
+
+#ifdef SQLITE_TEST
+/* simulate multiple hosts by creating unique hostid file paths */
+SQLITE_API int sqlite3_hostid_num = 0;
+#endif
+
+#define PROXY_HOSTIDLEN 16 /* conch file host id length */
+
+/* Not always defined in the headers as it ought to be */
+extern int gethostuuid(uuid_t id, const struct timespec *wait);
+
+/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
+** bytes of writable memory.
+*/
+static int proxyGetHostID(unsigned char *pHostID, int *pError){
+ assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
+ memset(pHostID, 0, PROXY_HOSTIDLEN);
+#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\
+ && __MAC_OS_X_VERSION_MIN_REQUIRED<1050
+ {
+ static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
+ if( gethostuuid(pHostID, &timeout) ){
+ int err = errno;
+ if( pError ){
+ *pError = err;
+ }
+ return SQLITE_IOERR;
+ }
+ }
+#else
+ UNUSED_PARAMETER(pError);
+#endif
+#ifdef SQLITE_TEST
+ /* simulate multiple hosts by creating unique hostid file paths */
+ if( sqlite3_hostid_num != 0){
+ pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
+ }
+#endif
+
+ return SQLITE_OK;
+}
+
+/* The conch file contains the header, host id and lock file path
+ */
+#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */
+#define PROXY_HEADERLEN 1 /* conch file header length */
+#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
+#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
+
+/*
+** Takes an open conch file, copies the contents to a new path and then moves
+** it back. The newly created file's file descriptor is assigned to the
+** conch file structure and finally the original conch file descriptor is
+** closed. Returns zero if successful.
+*/
+static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ unixFile *conchFile = pCtx->conchFile;
+ char tPath[MAXPATHLEN];
+ char buf[PROXY_MAXCONCHLEN];
+ char *cPath = pCtx->conchFilePath;
+ size_t readLen = 0;
+ size_t pathLen = 0;
+ char errmsg[64] = "";
+ int fd = -1;
+ int rc = -1;
+ UNUSED_PARAMETER(myHostID);
+
+ /* create a new path by replace the trailing '-conch' with '-break' */
+ pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
+ if( pathLen>MAXPATHLEN || pathLen<6 ||
+ (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
+ sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
+ goto end_breaklock;
+ }
+ /* read the conch content */
+ readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
+ if( readLen<PROXY_PATHINDEX ){
+ sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
+ goto end_breaklock;
+ }
+ /* write it out to the temporary break file */
+ fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
+ if( fd<0 ){
+ sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
+ goto end_breaklock;
+ }
+ if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
+ sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
+ goto end_breaklock;
+ }
+ if( rename(tPath, cPath) ){
+ sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
+ goto end_breaklock;
+ }
+ rc = 0;
+ fprintf(stderr, "broke stale lock on %s\n", cPath);
+ robust_close(pFile, conchFile->h, __LINE__);
+ conchFile->h = fd;
+ conchFile->openFlags = O_RDWR | O_CREAT;
+
+end_breaklock:
+ if( rc ){
+ if( fd>=0 ){
+ osUnlink(tPath);
+ robust_close(pFile, fd, __LINE__);
+ }
+ fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
+ }
+ return rc;
+}
+
+/* Take the requested lock on the conch file and break a stale lock if the
+** host id matches.
+*/
+static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ unixFile *conchFile = pCtx->conchFile;
+ int rc = SQLITE_OK;
+ int nTries = 0;
+ struct timespec conchModTime;
+
+ memset(&conchModTime, 0, sizeof(conchModTime));
+ do {
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
+ nTries ++;
+ if( rc==SQLITE_BUSY ){
+ /* If the lock failed (busy):
+ * 1st try: get the mod time of the conch, wait 0.5s and try again.
+ * 2nd try: fail if the mod time changed or host id is different, wait
+ * 10 sec and try again
+ * 3rd try: break the lock unless the mod time has changed.
+ */
+ struct stat buf;
+ if( osFstat(conchFile->h, &buf) ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR_LOCK;
+ }
+
+ if( nTries==1 ){
+ conchModTime = buf.st_mtimespec;
+ usleep(500000); /* wait 0.5 sec and try the lock again*/
+ continue;
+ }
+
+ assert( nTries>1 );
+ if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
+ conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
+ return SQLITE_BUSY;
+ }
+
+ if( nTries==2 ){
+ char tBuf[PROXY_MAXCONCHLEN];
+ int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
+ if( len<0 ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR_LOCK;
+ }
+ if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
+ /* don't break the lock if the host id doesn't match */
+ if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
+ return SQLITE_BUSY;
+ }
+ }else{
+ /* don't break the lock on short read or a version mismatch */
+ return SQLITE_BUSY;
+ }
+ usleep(10000000); /* wait 10 sec and try the lock again */
+ continue;
+ }
+
+ assert( nTries==3 );
+ if( 0==proxyBreakConchLock(pFile, myHostID) ){
+ rc = SQLITE_OK;
+ if( lockType==EXCLUSIVE_LOCK ){
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
+ }
+ if( !rc ){
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
+ }
+ }
+ }
+ } while( rc==SQLITE_BUSY && nTries<3 );
+
+ return rc;
+}
+
+/* Takes the conch by taking a shared lock and read the contents conch, if
+** lockPath is non-NULL, the host ID and lock file path must match. A NULL
+** lockPath means that the lockPath in the conch file will be used if the
+** host IDs match, or a new lock path will be generated automatically
+** and written to the conch file.
+*/
+static int proxyTakeConch(unixFile *pFile){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+
+ if( pCtx->conchHeld!=0 ){
+ return SQLITE_OK;
+ }else{
+ unixFile *conchFile = pCtx->conchFile;
+ uuid_t myHostID;
+ int pError = 0;
+ char readBuf[PROXY_MAXCONCHLEN];
+ char lockPath[MAXPATHLEN];
+ char *tempLockPath = NULL;
+ int rc = SQLITE_OK;
+ int createConch = 0;
+ int hostIdMatch = 0;
+ int readLen = 0;
+ int tryOldLockPath = 0;
+ int forceNewLockPath = 0;
+
+ OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
+
+ rc = proxyGetHostID(myHostID, &pError);
+ if( (rc&0xff)==SQLITE_IOERR ){
+ pFile->lastErrno = pError;
+ goto end_takeconch;
+ }
+ rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
+ if( rc!=SQLITE_OK ){
+ goto end_takeconch;
+ }
+ /* read the existing conch file */
+ readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
+ if( readLen<0 ){
+ /* I/O error: lastErrno set by seekAndRead */
+ pFile->lastErrno = conchFile->lastErrno;
+ rc = SQLITE_IOERR_READ;
+ goto end_takeconch;
+ }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
+ readBuf[0]!=(char)PROXY_CONCHVERSION ){
+ /* a short read or version format mismatch means we need to create a new
+ ** conch file.
+ */
+ createConch = 1;
+ }
+ /* if the host id matches and the lock path already exists in the conch
+ ** we'll try to use the path there, if we can't open that path, we'll
+ ** retry with a new auto-generated path
+ */
+ do { /* in case we need to try again for an :auto: named lock file */
+
+ if( !createConch && !forceNewLockPath ){
+ hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
+ PROXY_HOSTIDLEN);
+ /* if the conch has data compare the contents */
+ if( !pCtx->lockProxyPath ){
+ /* for auto-named local lock file, just check the host ID and we'll
+ ** use the local lock file path that's already in there
+ */
+ if( hostIdMatch ){
+ size_t pathLen = (readLen - PROXY_PATHINDEX);
+
+ if( pathLen>=MAXPATHLEN ){
+ pathLen=MAXPATHLEN-1;
+ }
+ memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
+ lockPath[pathLen] = 0;
+ tempLockPath = lockPath;
+ tryOldLockPath = 1;
+ /* create a copy of the lock path if the conch is taken */
+ goto end_takeconch;
+ }
+ }else if( hostIdMatch
+ && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
+ readLen-PROXY_PATHINDEX)
+ ){
+ /* conch host and lock path match */
+ goto end_takeconch;
+ }
+ }
+
+ /* if the conch isn't writable and doesn't match, we can't take it */
+ if( (conchFile->openFlags&O_RDWR) == 0 ){
+ rc = SQLITE_BUSY;
+ goto end_takeconch;
+ }
+
+ /* either the conch didn't match or we need to create a new one */
+ if( !pCtx->lockProxyPath ){
+ proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
+ tempLockPath = lockPath;
+ /* create a copy of the lock path _only_ if the conch is taken */
+ }
+
+ /* update conch with host and path (this will fail if other process
+ ** has a shared lock already), if the host id matches, use the big
+ ** stick.
+ */
+ futimes(conchFile->h, NULL);
+ if( hostIdMatch && !createConch ){
+ if( conchFile->pInode && conchFile->pInode->nShared>1 ){
+ /* We are trying for an exclusive lock but another thread in this
+ ** same process is still holding a shared lock. */
+ rc = SQLITE_BUSY;
+ } else {
+ rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
+ }
+ }else{
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
+ }
+ if( rc==SQLITE_OK ){
+ char writeBuffer[PROXY_MAXCONCHLEN];
+ int writeSize = 0;
+
+ writeBuffer[0] = (char)PROXY_CONCHVERSION;
+ memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
+ if( pCtx->lockProxyPath!=NULL ){
+ strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
+ }else{
+ strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
+ }
+ writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
+ robust_ftruncate(conchFile->h, writeSize);
+ rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
+ fsync(conchFile->h);
+ /* If we created a new conch file (not just updated the contents of a
+ ** valid conch file), try to match the permissions of the database
+ */
+ if( rc==SQLITE_OK && createConch ){
+ struct stat buf;
+ int err = osFstat(pFile->h, &buf);
+ if( err==0 ){
+ mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
+ S_IROTH|S_IWOTH);
+ /* try to match the database file R/W permissions, ignore failure */
+#ifndef SQLITE_PROXY_DEBUG
+ osFchmod(conchFile->h, cmode);
+#else
+ do{
+ rc = osFchmod(conchFile->h, cmode);
+ }while( rc==(-1) && errno==EINTR );
+ if( rc!=0 ){
+ int code = errno;
+ fprintf(stderr, "fchmod %o FAILED with %d %s\n",
+ cmode, code, strerror(code));
+ } else {
+ fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
+ }
+ }else{
+ int code = errno;
+ fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
+ err, code, strerror(code));
+#endif
+ }
+ }
+ }
+ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
+
+ end_takeconch:
+ OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
+ if( rc==SQLITE_OK && pFile->openFlags ){
+ int fd;
+ if( pFile->h>=0 ){
+ robust_close(pFile, pFile->h, __LINE__);
+ }
+ pFile->h = -1;
+ fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);
+ OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
+ if( fd>=0 ){
+ pFile->h = fd;
+ }else{
+ rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
+ during locking */
+ }
+ }
+ if( rc==SQLITE_OK && !pCtx->lockProxy ){
+ char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
+ rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
+ if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
+ /* we couldn't create the proxy lock file with the old lock file path
+ ** so try again via auto-naming
+ */
+ forceNewLockPath = 1;
+ tryOldLockPath = 0;
+ continue; /* go back to the do {} while start point, try again */
+ }
+ }
+ if( rc==SQLITE_OK ){
+ /* Need to make a copy of path if we extracted the value
+ ** from the conch file or the path was allocated on the stack
+ */
+ if( tempLockPath ){
+ pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
+ if( !pCtx->lockProxyPath ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ pCtx->conchHeld = 1;
+
+ if( pCtx->lockProxy->pMethod == &afpIoMethods ){
+ afpLockingContext *afpCtx;
+ afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
+ afpCtx->dbPath = pCtx->lockProxyPath;
+ }
+ } else {
+ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
+ }
+ OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
+ rc==SQLITE_OK?"ok":"failed"));
+ return rc;
+ } while (1); /* in case we need to retry the :auto: lock file -
+ ** we should never get here except via the 'continue' call. */
+ }
+}
+
+/*
+** If pFile holds a lock on a conch file, then release that lock.
+*/
+static int proxyReleaseConch(unixFile *pFile){
+ int rc = SQLITE_OK; /* Subroutine return code */
+ proxyLockingContext *pCtx; /* The locking context for the proxy lock */
+ unixFile *conchFile; /* Name of the conch file */
+
+ pCtx = (proxyLockingContext *)pFile->lockingContext;
+ conchFile = pCtx->conchFile;
+ OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
+ getpid()));
+ if( pCtx->conchHeld>0 ){
+ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
+ }
+ pCtx->conchHeld = 0;
+ OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
+ (rc==SQLITE_OK ? "ok" : "failed")));
+ return rc;
+}
+
+/*
+** Given the name of a database file, compute the name of its conch file.
+** Store the conch filename in memory obtained from sqlite3_malloc().
+** Make *pConchPath point to the new name. Return SQLITE_OK on success
+** or SQLITE_NOMEM if unable to obtain memory.
+**
+** The caller is responsible for ensuring that the allocated memory
+** space is eventually freed.
+**
+** *pConchPath is set to NULL if a memory allocation error occurs.
+*/
+static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
+ int i; /* Loop counter */
+ int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
+ char *conchPath; /* buffer in which to construct conch name */
+
+ /* Allocate space for the conch filename and initialize the name to
+ ** the name of the original database file. */
+ *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
+ if( conchPath==0 ){
+ return SQLITE_NOMEM;
+ }
+ memcpy(conchPath, dbPath, len+1);
+
+ /* now insert a "." before the last / character */
+ for( i=(len-1); i>=0; i-- ){
+ if( conchPath[i]=='/' ){
+ i++;
+ break;
+ }
+ }
+ conchPath[i]='.';
+ while ( i<len ){
+ conchPath[i+1]=dbPath[i];
+ i++;
+ }
+
+ /* append the "-conch" suffix to the file */
+ memcpy(&conchPath[i+1], "-conch", 7);
+ assert( (int)strlen(conchPath) == len+7 );
+
+ return SQLITE_OK;
+}
+
+
+/* Takes a fully configured proxy locking-style unix file and switches
+** the local lock file path
+*/
+static int switchLockProxyPath(unixFile *pFile, const char *path) {
+ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
+ char *oldPath = pCtx->lockProxyPath;
+ int rc = SQLITE_OK;
+
+ if( pFile->eFileLock!=NO_LOCK ){
+ return SQLITE_BUSY;
+ }
+
+ /* nothing to do if the path is NULL, :auto: or matches the existing path */
+ if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
+ (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
+ return SQLITE_OK;
+ }else{
+ unixFile *lockProxy = pCtx->lockProxy;
+ pCtx->lockProxy=NULL;
+ pCtx->conchHeld = 0;
+ if( lockProxy!=NULL ){
+ rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
+ if( rc ) return rc;
+ sqlite3_free(lockProxy);
+ }
+ sqlite3_free(oldPath);
+ pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
+ }
+
+ return rc;
+}
+
+/*
+** pFile is a file that has been opened by a prior xOpen call. dbPath
+** is a string buffer at least MAXPATHLEN+1 characters in size.
+**
+** This routine find the filename associated with pFile and writes it
+** int dbPath.
+*/
+static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
+#if defined(__APPLE__)
+ if( pFile->pMethod == &afpIoMethods ){
+ /* afp style keeps a reference to the db path in the filePath field
+ ** of the struct */
+ assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+ strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
+ } else
+#endif
+ if( pFile->pMethod == &dotlockIoMethods ){
+ /* dot lock style uses the locking context to store the dot lock
+ ** file path */
+ int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
+ memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
+ }else{
+ /* all other styles use the locking context to store the db file path */
+ assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+ strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Takes an already filled in unix file and alters it so all file locking
+** will be performed on the local proxy lock file. The following fields
+** are preserved in the locking context so that they can be restored and
+** the unix structure properly cleaned up at close time:
+** ->lockingContext
+** ->pMethod
+*/
+static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
+ proxyLockingContext *pCtx;
+ char dbPath[MAXPATHLEN+1]; /* Name of the database file */
+ char *lockPath=NULL;
+ int rc = SQLITE_OK;
+
+ if( pFile->eFileLock!=NO_LOCK ){
+ return SQLITE_BUSY;
+ }
+ proxyGetDbPathForUnixFile(pFile, dbPath);
+ if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
+ lockPath=NULL;
+ }else{
+ lockPath=(char *)path;
+ }
+
+ OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
+ (lockPath ? lockPath : ":auto:"), getpid()));
+
+ pCtx = sqlite3_malloc( sizeof(*pCtx) );
+ if( pCtx==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(pCtx, 0, sizeof(*pCtx));
+
+ rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
+ if( rc==SQLITE_OK ){
+ rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
+ if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
+ /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
+ ** (c) the file system is read-only, then enable no-locking access.
+ ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
+ ** that openFlags will have only one of O_RDONLY or O_RDWR.
+ */
+ struct statfs fsInfo;
+ struct stat conchInfo;
+ int goLockless = 0;
+
+ if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
+ int err = errno;
+ if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
+ goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
+ }
+ }
+ if( goLockless ){
+ pCtx->conchHeld = -1; /* read only FS/ lockless */
+ rc = SQLITE_OK;
+ }
+ }
+ }
+ if( rc==SQLITE_OK && lockPath ){
+ pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
+ }
+
+ if( rc==SQLITE_OK ){
+ pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
+ if( pCtx->dbPath==NULL ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+ if( rc==SQLITE_OK ){
+ /* all memory is allocated, proxys are created and assigned,
+ ** switch the locking context and pMethod then return.
+ */
+ pCtx->oldLockingContext = pFile->lockingContext;
+ pFile->lockingContext = pCtx;
+ pCtx->pOldMethod = pFile->pMethod;
+ pFile->pMethod = &proxyIoMethods;
+ }else{
+ if( pCtx->conchFile ){
+ pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
+ sqlite3_free(pCtx->conchFile);
+ }
+ sqlite3DbFree(0, pCtx->lockProxyPath);
+ sqlite3_free(pCtx->conchFilePath);
+ sqlite3_free(pCtx);
+ }
+ OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
+ (rc==SQLITE_OK ? "ok" : "failed")));
+ return rc;
+}
+
+
+/*
+** This routine handles sqlite3_file_control() calls that are specific
+** to proxy locking.
+*/
+static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
+ switch( op ){
+ case SQLITE_GET_LOCKPROXYFILE: {
+ unixFile *pFile = (unixFile*)id;
+ if( pFile->pMethod == &proxyIoMethods ){
+ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
+ proxyTakeConch(pFile);
+ if( pCtx->lockProxyPath ){
+ *(const char **)pArg = pCtx->lockProxyPath;
+ }else{
+ *(const char **)pArg = ":auto: (not held)";
+ }
+ } else {
+ *(const char **)pArg = NULL;
+ }
+ return SQLITE_OK;
+ }
+ case SQLITE_SET_LOCKPROXYFILE: {
+ unixFile *pFile = (unixFile*)id;
+ int rc = SQLITE_OK;
+ int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
+ if( pArg==NULL || (const char *)pArg==0 ){
+ if( isProxyStyle ){
+ /* turn off proxy locking - not supported */
+ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
+ }else{
+ /* turn off proxy locking - already off - NOOP */
+ rc = SQLITE_OK;
+ }
+ }else{
+ const char *proxyPath = (const char *)pArg;
+ if( isProxyStyle ){
+ proxyLockingContext *pCtx =
+ (proxyLockingContext*)pFile->lockingContext;
+ if( !strcmp(pArg, ":auto:")
+ || (pCtx->lockProxyPath &&
+ !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
+ ){
+ rc = SQLITE_OK;
+ }else{
+ rc = switchLockProxyPath(pFile, proxyPath);
+ }
+ }else{
+ /* turn on proxy file locking */
+ rc = proxyTransformUnixFile(pFile, proxyPath);
+ }
+ }
+ return rc;
+ }
+ default: {
+ assert( 0 ); /* The call assures that only valid opcodes are sent */
+ }
+ }
+ /*NOTREACHED*/
+ return SQLITE_ERROR;
+}
+
+/*
+** Within this division (the proxying locking implementation) the procedures
+** above this point are all utilities. The lock-related methods of the
+** proxy-locking sqlite3_io_method object follow.
+*/
+
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
+static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
+ unixFile *pFile = (unixFile*)id;
+ int rc = proxyTakeConch(pFile);
+ if( rc==SQLITE_OK ){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ if( pCtx->conchHeld>0 ){
+ unixFile *proxy = pCtx->lockProxy;
+ return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
+ }else{ /* conchHeld < 0 is lockless */
+ pResOut=0;
+ }
+ }
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter eFileLock - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int proxyLock(sqlite3_file *id, int eFileLock) {
+ unixFile *pFile = (unixFile*)id;
+ int rc = proxyTakeConch(pFile);
+ if( rc==SQLITE_OK ){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ if( pCtx->conchHeld>0 ){
+ unixFile *proxy = pCtx->lockProxy;
+ rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
+ pFile->eFileLock = proxy->eFileLock;
+ }else{
+ /* conchHeld < 0 is lockless */
+ }
+ }
+ return rc;
+}
+
+
+/*
+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int proxyUnlock(sqlite3_file *id, int eFileLock) {
+ unixFile *pFile = (unixFile*)id;
+ int rc = proxyTakeConch(pFile);
+ if( rc==SQLITE_OK ){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ if( pCtx->conchHeld>0 ){
+ unixFile *proxy = pCtx->lockProxy;
+ rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
+ pFile->eFileLock = proxy->eFileLock;
+ }else{
+ /* conchHeld < 0 is lockless */
+ }
+ }
+ return rc;
+}
+
+/*
+** Close a file that uses proxy locks.
+*/
+static int proxyClose(sqlite3_file *id) {
+ if( id ){
+ unixFile *pFile = (unixFile*)id;
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ unixFile *lockProxy = pCtx->lockProxy;
+ unixFile *conchFile = pCtx->conchFile;
+ int rc = SQLITE_OK;
+
+ if( lockProxy ){
+ rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
+ if( rc ) return rc;
+ rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
+ if( rc ) return rc;
+ sqlite3_free(lockProxy);
+ pCtx->lockProxy = 0;
+ }
+ if( conchFile ){
+ if( pCtx->conchHeld ){
+ rc = proxyReleaseConch(pFile);
+ if( rc ) return rc;
+ }
+ rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
+ if( rc ) return rc;
+ sqlite3_free(conchFile);
+ }
+ sqlite3DbFree(0, pCtx->lockProxyPath);
+ sqlite3_free(pCtx->conchFilePath);
+ sqlite3DbFree(0, pCtx->dbPath);
+ /* restore the original locking context and pMethod then close it */
+ pFile->lockingContext = pCtx->oldLockingContext;
+ pFile->pMethod = pCtx->pOldMethod;
+ sqlite3_free(pCtx);
+ return pFile->pMethod->xClose(id);
+ }
+ return SQLITE_OK;
+}
+
+
+
+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
+/*
+** The proxy locking style is intended for use with AFP filesystems.
+** And since AFP is only supported on MacOSX, the proxy locking is also
+** restricted to MacOSX.
+**
+**
+******************* End of the proxy lock implementation **********************
+******************************************************************************/
+
+/*
+** Initialize the operating system interface.
+**
+** This routine registers all VFS implementations for unix-like operating
+** systems. This routine, and the sqlite3_os_end() routine that follows,
+** should be the only routines in this file that are visible from other
+** files.
+**
+** This routine is called once during SQLite initialization and by a
+** single thread. The memory allocation and mutex subsystems have not
+** necessarily been initialized when this routine is called, and so they
+** should not be used.
+*/
+SQLITE_API int sqlite3_os_init(void){
+ /*
+ ** The following macro defines an initializer for an sqlite3_vfs object.
+ ** The name of the VFS is NAME. The pAppData is a pointer to a pointer
+ ** to the "finder" function. (pAppData is a pointer to a pointer because
+ ** silly C90 rules prohibit a void* from being cast to a function pointer
+ ** and so we have to go through the intermediate pointer to avoid problems
+ ** when compiling with -pedantic-errors on GCC.)
+ **
+ ** The FINDER parameter to this macro is the name of the pointer to the
+ ** finder-function. The finder-function returns a pointer to the
+ ** sqlite_io_methods object that implements the desired locking
+ ** behaviors. See the division above that contains the IOMETHODS
+ ** macro for addition information on finder-functions.
+ **
+ ** Most finders simply return a pointer to a fixed sqlite3_io_methods
+ ** object. But the "autolockIoFinder" available on MacOSX does a little
+ ** more than that; it looks at the filesystem type that hosts the
+ ** database file and tries to choose an locking method appropriate for
+ ** that filesystem time.
+ */
+ #define UNIXVFS(VFSNAME, FINDER) { \
+ 3, /* iVersion */ \
+ sizeof(unixFile), /* szOsFile */ \
+ MAX_PATHNAME, /* mxPathname */ \
+ 0, /* pNext */ \
+ VFSNAME, /* zName */ \
+ (void*)&FINDER, /* pAppData */ \
+ unixOpen, /* xOpen */ \
+ unixDelete, /* xDelete */ \
+ unixAccess, /* xAccess */ \
+ unixFullPathname, /* xFullPathname */ \
+ unixDlOpen, /* xDlOpen */ \
+ unixDlError, /* xDlError */ \
+ unixDlSym, /* xDlSym */ \
+ unixDlClose, /* xDlClose */ \
+ unixRandomness, /* xRandomness */ \
+ unixSleep, /* xSleep */ \
+ unixCurrentTime, /* xCurrentTime */ \
+ unixGetLastError, /* xGetLastError */ \
+ unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
+ unixSetSystemCall, /* xSetSystemCall */ \
+ unixGetSystemCall, /* xGetSystemCall */ \
+ unixNextSystemCall, /* xNextSystemCall */ \
+ }
+
+ /*
+ ** All default VFSes for unix are contained in the following array.
+ **
+ ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
+ ** by the SQLite core when the VFS is registered. So the following
+ ** array cannot be const.
+ */
+ static sqlite3_vfs aVfs[] = {
+#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
+ UNIXVFS("unix", autolockIoFinder ),
+#else
+ UNIXVFS("unix", posixIoFinder ),
+#endif
+ UNIXVFS("unix-none", nolockIoFinder ),
+ UNIXVFS("unix-dotfile", dotlockIoFinder ),
+ UNIXVFS("unix-excl", posixIoFinder ),
+#if OS_VXWORKS
+ UNIXVFS("unix-namedsem", semIoFinder ),
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE
+ UNIXVFS("unix-posix", posixIoFinder ),
+#if !OS_VXWORKS
+ UNIXVFS("unix-flock", flockIoFinder ),
+#endif
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
+ UNIXVFS("unix-afp", afpIoFinder ),
+ UNIXVFS("unix-nfs", nfsIoFinder ),
+ UNIXVFS("unix-proxy", proxyIoFinder ),
+#endif
+ };
+ unsigned int i; /* Loop counter */
+
+ /* Double-check that the aSyscall[] array has been constructed
+ ** correctly. See ticket [bb3a86e890c8e96ab] */
+ assert( ArraySize(aSyscall)==21 );
+
+ /* Register all VFSes defined in the aVfs[] array */
+ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
+ sqlite3_vfs_register(&aVfs[i], i==0);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Shutdown the operating system interface.
+**
+** Some operating systems might need to do some cleanup in this routine,
+** to release dynamically allocated objects. But not on unix.
+** This routine is a no-op for unix.
+*/
+SQLITE_API int sqlite3_os_end(void){
+ return SQLITE_OK;
+}
+
+#endif /* SQLITE_OS_UNIX */
+
+/************** End of os_unix.c *********************************************/
+/************** Begin file os_win.c ******************************************/
+/*
+** 2004 May 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains code that is specific to Windows.
+*/
+#if SQLITE_OS_WIN /* This file is used for Windows only */
+
+#ifdef __CYGWIN__
+# include <sys/cygwin.h>
+#endif
+
+/*
+** Include code that is common to all os_*.c files
+*/
+/************** Include os_common.h in the middle of os_win.c ****************/
+/************** Begin file os_common.h ***************************************/
+/*
+** 2004 May 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains macros and a little bit of code that is common to
+** all of the platform-specific files (os_*.c) and is #included into those
+** files.
+**
+** This file should be #included by the os_*.c files only. It is not a
+** general purpose header file.
+*/
+#ifndef _OS_COMMON_H_
+#define _OS_COMMON_H_
+
+/*
+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
+** switch. The following code should catch this problem at compile-time.
+*/
+#ifdef MEMORY_DEBUG
+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
+#endif
+
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+# ifndef SQLITE_DEBUG_OS_TRACE
+# define SQLITE_DEBUG_OS_TRACE 0
+# endif
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
+#else
+# define OSTRACE(X)
+#endif
+
+/*
+** Macros for performance tracing. Normally turned off. Only works
+** on i486 hardware.
+*/
+#ifdef SQLITE_PERFORMANCE_TRACE
+
+/*
+** hwtime.h contains inline assembler code for implementing
+** high-performance timing routines.
+*/
+/************** Include hwtime.h in the middle of os_common.h ****************/
+/************** Begin file hwtime.h ******************************************/
+/*
+** 2008 May 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains inline asm code for retrieving "high-performance"
+** counters for x86 class CPUs.
+*/
+#ifndef _HWTIME_H_
+#define _HWTIME_H_
+
+/*
+** The following routine only works on pentium-class (or newer) processors.
+** It uses the RDTSC opcode to read the cycle count value out of the
+** processor and returns that value. This can be used for high-res
+** profiling.
+*/
+#if (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
+
+ #if defined(__GNUC__)
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+ #elif defined(_MSC_VER)
+
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+ __asm {
+ rdtsc
+ ret ; return value at EDX:EAX
+ }
+ }
+
+ #endif
+
+#elif (defined(__GNUC__) && defined(__x86_64__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long val;
+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
+ return val;
+ }
+
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
+ }
+
+#else
+
+ #error Need implementation of sqlite3Hwtime() for your platform.
+
+ /*
+ ** To compile without implementing sqlite3Hwtime() for your platform,
+ ** you can remove the above #error and use the following
+ ** stub function. You will lose timing support for many
+ ** of the debugging and testing utilities, but it should at
+ ** least compile and run.
+ */
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+
+#endif
+
+#endif /* !defined(_HWTIME_H_) */
+
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in os_common.h ******************/
+
+static sqlite_uint64 g_start;
+static sqlite_uint64 g_elapsed;
+#define TIMER_START g_start=sqlite3Hwtime()
+#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
+#define TIMER_ELAPSED g_elapsed
+#else
+#define TIMER_START
+#define TIMER_END
+#define TIMER_ELAPSED ((sqlite_uint64)0)
+#endif
+
+/*
+** If we compile with the SQLITE_TEST macro set, then the following block
+** of code will give us the ability to simulate a disk I/O error. This
+** is used for testing the I/O recovery logic.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
+SQLITE_API int sqlite3_diskfull_pending = 0;
+SQLITE_API int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
+#define SimulateIOError(CODE) \
+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+ || sqlite3_io_error_pending-- == 1 ) \
+ { local_ioerr(); CODE; }
+static void local_ioerr(){
+ IOTRACE(("IOERR\n"));
+ sqlite3_io_error_hit++;
+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
+}
+#define SimulateDiskfullError(CODE) \
+ if( sqlite3_diskfull_pending ){ \
+ if( sqlite3_diskfull_pending == 1 ){ \
+ local_ioerr(); \
+ sqlite3_diskfull = 1; \
+ sqlite3_io_error_hit = 1; \
+ CODE; \
+ }else{ \
+ sqlite3_diskfull_pending--; \
+ } \
+ }
+#else
+#define SimulateIOErrorBenign(X)
+#define SimulateIOError(A)
+#define SimulateDiskfullError(A)
+#endif
+
+/*
+** When testing, keep a count of the number of open files.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_open_file_count = 0;
+#define OpenCounter(X) sqlite3_open_file_count+=(X)
+#else
+#define OpenCounter(X)
+#endif
+
+#endif /* !defined(_OS_COMMON_H_) */
+
+/************** End of os_common.h *******************************************/
+/************** Continuing where we left off in os_win.c *********************/
+
+/*
+** Compiling and using WAL mode requires several APIs that are only
+** available in Windows platforms based on the NT kernel.
+*/
+#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
+# error "WAL mode requires support from the Windows NT kernel, compile\
+ with SQLITE_OMIT_WAL."
+#endif
+
+/*
+** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+# define SQLITE_WIN32_HAS_ANSI
+#endif
+
+/*
+** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
+# define SQLITE_WIN32_HAS_WIDE
+#endif
+
+/*
+** Do we need to manually define the Win32 file mapping APIs for use with WAL
+** mode (e.g. these APIs are available in the Windows CE SDK; however, they
+** are not present in the header file)?
+*/
+#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
+/*
+** Two of the file mapping APIs are different under WinRT. Figure out which
+** set we need.
+*/
+#if SQLITE_OS_WINRT
+WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
+ LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
+
+WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
+#else
+#if defined(SQLITE_WIN32_HAS_ANSI)
+WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
+ DWORD, DWORD, DWORD, LPCSTR);
+#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
+ DWORD, DWORD, DWORD, LPCWSTR);
+#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
+
+WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
+#endif /* SQLITE_OS_WINRT */
+
+/*
+** This file mapping API is common to both Win32 and WinRT.
+*/
+WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
+#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
+
+/*
+** Macro to find the minimum of two numeric values.
+*/
+#ifndef MIN
+# define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+/*
+** Some Microsoft compilers lack this definition.
+*/
+#ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+#endif
+
+#ifndef FILE_FLAG_MASK
+# define FILE_FLAG_MASK (0xFF3C0000)
+#endif
+
+#ifndef FILE_ATTRIBUTE_MASK
+# define FILE_ATTRIBUTE_MASK (0x0003FFF7)
+#endif
+
+#ifndef SQLITE_OMIT_WAL
+/* Forward references */
+typedef struct winShm winShm; /* A connection to shared-memory */
+typedef struct winShmNode winShmNode; /* A region of shared-memory */
+#endif
+
+/*
+** WinCE lacks native support for file locking so we have to fake it
+** with some code of our own.
+*/
+#if SQLITE_OS_WINCE
+typedef struct winceLock {
+ int nReaders; /* Number of reader locks obtained */
+ BOOL bPending; /* Indicates a pending lock has been obtained */
+ BOOL bReserved; /* Indicates a reserved lock has been obtained */
+ BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
+} winceLock;
+#endif
+
+/*
+** The winFile structure is a subclass of sqlite3_file* specific to the win32
+** portability layer.
+*/
+typedef struct winFile winFile;
+struct winFile {
+ const sqlite3_io_methods *pMethod; /*** Must be first ***/
+ sqlite3_vfs *pVfs; /* The VFS used to open this file */
+ HANDLE h; /* Handle for accessing the file */
+ u8 locktype; /* Type of lock currently held on this file */
+ short sharedLockByte; /* Randomly chosen byte used as a shared lock */
+ u8 ctrlFlags; /* Flags. See WINFILE_* below */
+ DWORD lastErrno; /* The Windows errno from the last I/O error */
+#ifndef SQLITE_OMIT_WAL
+ winShm *pShm; /* Instance of shared memory on this file */
+#endif
+ const char *zPath; /* Full pathname of this file */
+ int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
+#if SQLITE_OS_WINCE
+ LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
+ HANDLE hMutex; /* Mutex used to control access to shared lock */
+ HANDLE hShared; /* Shared memory segment used for locking */
+ winceLock local; /* Locks obtained by this instance of winFile */
+ winceLock *shared; /* Global shared lock memory for the file */
+#endif
+};
+
+/*
+** Allowed values for winFile.ctrlFlags
+*/
+#define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
+#define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
+
+/*
+ * The size of the buffer used by sqlite3_win32_write_debug().
+ */
+#ifndef SQLITE_WIN32_DBG_BUF_SIZE
+# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
+#endif
+
+/*
+ * The value used with sqlite3_win32_set_directory() to specify that
+ * the data directory should be changed.
+ */
+#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
+# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
+#endif
+
+/*
+ * The value used with sqlite3_win32_set_directory() to specify that
+ * the temporary directory should be changed.
+ */
+#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
+# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
+#endif
+
+/*
+ * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
+ * various Win32 API heap functions instead of our own.
+ */
+#ifdef SQLITE_WIN32_MALLOC
+
+/*
+ * If this is non-zero, an isolated heap will be created by the native Win32
+ * allocator subsystem; otherwise, the default process heap will be used. This
+ * setting has no effect when compiling for WinRT. By default, this is enabled
+ * and an isolated heap will be created to store all allocated data.
+ *
+ ******************************************************************************
+ * WARNING: It is important to note that when this setting is non-zero and the
+ * winMemShutdown function is called (e.g. by the sqlite3_shutdown
+ * function), all data that was allocated using the isolated heap will
+ * be freed immediately and any attempt to access any of that freed
+ * data will almost certainly result in an immediate access violation.
+ ******************************************************************************
+ */
+#ifndef SQLITE_WIN32_HEAP_CREATE
+# define SQLITE_WIN32_HEAP_CREATE (TRUE)
+#endif
+
+/*
+ * The initial size of the Win32-specific heap. This value may be zero.
+ */
+#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
+# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
+ (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
+#endif
+
+/*
+ * The maximum size of the Win32-specific heap. This value may be zero.
+ */
+#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
+# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
+#endif
+
+/*
+ * The extra flags to use in calls to the Win32 heap APIs. This value may be
+ * zero for the default behavior.
+ */
+#ifndef SQLITE_WIN32_HEAP_FLAGS
+# define SQLITE_WIN32_HEAP_FLAGS (0)
+#endif
+
+/*
+** The winMemData structure stores information required by the Win32-specific
+** sqlite3_mem_methods implementation.
+*/
+typedef struct winMemData winMemData;
+struct winMemData {
+#ifndef NDEBUG
+ u32 magic; /* Magic number to detect structure corruption. */
+#endif
+ HANDLE hHeap; /* The handle to our heap. */
+ BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
+};
+
+#ifndef NDEBUG
+#define WINMEM_MAGIC 0x42b2830b
+#endif
+
+static struct winMemData win_mem_data = {
+#ifndef NDEBUG
+ WINMEM_MAGIC,
+#endif
+ NULL, FALSE
+};
+
+#ifndef NDEBUG
+#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
+#else
+#define winMemAssertMagic()
+#endif
+
+#define winMemGetHeap() win_mem_data.hHeap
+
+static void *winMemMalloc(int nBytes);
+static void winMemFree(void *pPrior);
+static void *winMemRealloc(void *pPrior, int nBytes);
+static int winMemSize(void *p);
+static int winMemRoundup(int n);
+static int winMemInit(void *pAppData);
+static void winMemShutdown(void *pAppData);
+
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
+#endif /* SQLITE_WIN32_MALLOC */
+
+/*
+** The following variable is (normally) set once and never changes
+** thereafter. It records whether the operating system is Win9x
+** or WinNT.
+**
+** 0: Operating system unknown.
+** 1: Operating system is Win9x.
+** 2: Operating system is WinNT.
+**
+** In order to facilitate testing on a WinNT system, the test fixture
+** can manually set this value to 1 to emulate Win98 behavior.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_os_type = 0;
+#else
+static int sqlite3_os_type = 0;
+#endif
+
+#ifndef SYSCALL
+# define SYSCALL sqlite3_syscall_ptr
+#endif
+
+/*
+** This function is not available on Windows CE or WinRT.
+ */
+
+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
+# define osAreFileApisANSI() 1
+#endif
+
+/*
+** Many system calls are accessed through pointer-to-functions so that
+** they may be overridden at runtime to facilitate fault injection during
+** testing and sandboxing. The following array holds the names and pointers
+** to all overrideable system calls.
+*/
+static struct win_syscall {
+ const char *zName; /* Name of the system call */
+ sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
+ sqlite3_syscall_ptr pDefault; /* Default value */
+} aSyscall[] = {
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+ { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
+#else
+ { "AreFileApisANSI", (SYSCALL)0, 0 },
+#endif
+
+#ifndef osAreFileApisANSI
+#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
+#endif
+
+#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
+ { "CharLowerW", (SYSCALL)CharLowerW, 0 },
+#else
+ { "CharLowerW", (SYSCALL)0, 0 },
+#endif
+
+#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
+
+#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
+ { "CharUpperW", (SYSCALL)CharUpperW, 0 },
+#else
+ { "CharUpperW", (SYSCALL)0, 0 },
+#endif
+
+#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
+
+ { "CloseHandle", (SYSCALL)CloseHandle, 0 },
+
+#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "CreateFileA", (SYSCALL)CreateFileA, 0 },
+#else
+ { "CreateFileA", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
+ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
+
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+ { "CreateFileW", (SYSCALL)CreateFileW, 0 },
+#else
+ { "CreateFileW", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
+ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
+
+#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
+ !defined(SQLITE_OMIT_WAL))
+ { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
+#else
+ { "CreateFileMappingA", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
+ DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
+
+#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+ !defined(SQLITE_OMIT_WAL))
+ { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
+#else
+ { "CreateFileMappingW", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
+ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
+
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+ { "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
+#else
+ { "CreateMutexW", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
+ LPCWSTR))aSyscall[8].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
+#else
+ { "DeleteFileA", (SYSCALL)0, 0 },
+#endif
+
+#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ { "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
+#else
+ { "DeleteFileW", (SYSCALL)0, 0 },
+#endif
+
+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
+
+#if SQLITE_OS_WINCE
+ { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
+#else
+ { "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
+#endif
+
+#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+ LPFILETIME))aSyscall[11].pCurrent)
+
+#if SQLITE_OS_WINCE
+ { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
+#else
+ { "FileTimeToSystemTime", (SYSCALL)0, 0 },
+#endif
+
+#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+ LPSYSTEMTIME))aSyscall[12].pCurrent)
+
+ { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
+
+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
+#else
+ { "FormatMessageA", (SYSCALL)0, 0 },
+#endif
+
+#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
+ DWORD,va_list*))aSyscall[14].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ { "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
+#else
+ { "FormatMessageW", (SYSCALL)0, 0 },
+#endif
+
+#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
+ DWORD,va_list*))aSyscall[15].pCurrent)
+
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
+ { "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
+#else
+ { "FreeLibrary", (SYSCALL)0, 0 },
+#endif
+
+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
+
+ { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
+
+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
+
+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
+ { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
+#else
+ { "GetDiskFreeSpaceA", (SYSCALL)0, 0 },
+#endif
+
+#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
+ LPDWORD))aSyscall[18].pCurrent)
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+ { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
+#else
+ { "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
+#endif
+
+#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
+ LPDWORD))aSyscall[19].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
+#else
+ { "GetFileAttributesA", (SYSCALL)0, 0 },
+#endif
+
+#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
+
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+ { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
+#else
+ { "GetFileAttributesW", (SYSCALL)0, 0 },
+#endif
+
+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
+#else
+ { "GetFileAttributesExW", (SYSCALL)0, 0 },
+#endif
+
+#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
+ LPVOID))aSyscall[22].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "GetFileSize", (SYSCALL)GetFileSize, 0 },
+#else
+ { "GetFileSize", (SYSCALL)0, 0 },
+#endif
+
+#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
+
+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
+ { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
+#else
+ { "GetFullPathNameA", (SYSCALL)0, 0 },
+#endif
+
+#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
+ LPSTR*))aSyscall[24].pCurrent)
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+ { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
+#else
+ { "GetFullPathNameW", (SYSCALL)0, 0 },
+#endif
+
+#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
+ LPWSTR*))aSyscall[25].pCurrent)
+
+ { "GetLastError", (SYSCALL)GetLastError, 0 },
+
+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
+
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
+#if SQLITE_OS_WINCE
+ /* The GetProcAddressA() routine is only available on Windows CE. */
+ { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
+#else
+ /* All other Windows platforms expect GetProcAddress() to take
+ ** an ANSI string regardless of the _UNICODE setting */
+ { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
+#endif
+#else
+ { "GetProcAddressA", (SYSCALL)0, 0 },
+#endif
+
+#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
+ LPCSTR))aSyscall[27].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
+#else
+ { "GetSystemInfo", (SYSCALL)0, 0 },
+#endif
+
+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
+
+ { "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
+
+#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
+
+#if !SQLITE_OS_WINCE
+ { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
+#else
+ { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 },
+#endif
+
+#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
+ LPFILETIME))aSyscall[30].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
+#else
+ { "GetTempPathA", (SYSCALL)0, 0 },
+#endif
+
+#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
+
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+ { "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
+#else
+ { "GetTempPathW", (SYSCALL)0, 0 },
+#endif
+
+#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "GetTickCount", (SYSCALL)GetTickCount, 0 },
+#else
+ { "GetTickCount", (SYSCALL)0, 0 },
+#endif
+
+#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
+#else
+ { "GetVersionExA", (SYSCALL)0, 0 },
+#endif
+
+#define osGetVersionExA ((BOOL(WINAPI*)( \
+ LPOSVERSIONINFOA))aSyscall[34].pCurrent)
+
+ { "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
+
+#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
+ SIZE_T))aSyscall[35].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "HeapCreate", (SYSCALL)HeapCreate, 0 },
+#else
+ { "HeapCreate", (SYSCALL)0, 0 },
+#endif
+
+#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
+ SIZE_T))aSyscall[36].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
+#else
+ { "HeapDestroy", (SYSCALL)0, 0 },
+#endif
+
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
+
+ { "HeapFree", (SYSCALL)HeapFree, 0 },
+
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
+
+ { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
+
+#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
+ SIZE_T))aSyscall[39].pCurrent)
+
+ { "HeapSize", (SYSCALL)HeapSize, 0 },
+
+#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
+ LPCVOID))aSyscall[40].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "HeapValidate", (SYSCALL)HeapValidate, 0 },
+#else
+ { "HeapValidate", (SYSCALL)0, 0 },
+#endif
+
+#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
+ LPCVOID))aSyscall[41].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+ { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
+#else
+ { "LoadLibraryA", (SYSCALL)0, 0 },
+#endif
+
+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
+
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+ !defined(SQLITE_OMIT_LOAD_EXTENSION)
+ { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
+#else
+ { "LoadLibraryW", (SYSCALL)0, 0 },
+#endif
+
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "LocalFree", (SYSCALL)LocalFree, 0 },
+#else
+ { "LocalFree", (SYSCALL)0, 0 },
+#endif
+
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+ { "LockFile", (SYSCALL)LockFile, 0 },
+#else
+ { "LockFile", (SYSCALL)0, 0 },
+#endif
+
+#ifndef osLockFile
+#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+ DWORD))aSyscall[45].pCurrent)
+#endif
+
+#if !SQLITE_OS_WINCE
+ { "LockFileEx", (SYSCALL)LockFileEx, 0 },
+#else
+ { "LockFileEx", (SYSCALL)0, 0 },
+#endif
+
+#ifndef osLockFileEx
+#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
+ LPOVERLAPPED))aSyscall[46].pCurrent)
+#endif
+
+#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
+ { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
+#else
+ { "MapViewOfFile", (SYSCALL)0, 0 },
+#endif
+
+#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+ SIZE_T))aSyscall[47].pCurrent)
+
+ { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
+
+#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
+ int))aSyscall[48].pCurrent)
+
+ { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
+
+#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
+ LARGE_INTEGER*))aSyscall[49].pCurrent)
+
+ { "ReadFile", (SYSCALL)ReadFile, 0 },
+
+#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
+ LPOVERLAPPED))aSyscall[50].pCurrent)
+
+ { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
+
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
+#else
+ { "SetFilePointer", (SYSCALL)0, 0 },
+#endif
+
+#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
+ DWORD))aSyscall[52].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "Sleep", (SYSCALL)Sleep, 0 },
+#else
+ { "Sleep", (SYSCALL)0, 0 },
+#endif
+
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
+
+ { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
+
+#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
+ LPFILETIME))aSyscall[54].pCurrent)
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+ { "UnlockFile", (SYSCALL)UnlockFile, 0 },
+#else
+ { "UnlockFile", (SYSCALL)0, 0 },
+#endif
+
+#ifndef osUnlockFile
+#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+ DWORD))aSyscall[55].pCurrent)
+#endif
+
+#if !SQLITE_OS_WINCE
+ { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
+#else
+ { "UnlockFileEx", (SYSCALL)0, 0 },
+#endif
+
+#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
+ LPOVERLAPPED))aSyscall[56].pCurrent)
+
+#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
+ { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
+#else
+ { "UnmapViewOfFile", (SYSCALL)0, 0 },
+#endif
+
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
+
+ { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
+
+#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
+ LPCSTR,LPBOOL))aSyscall[58].pCurrent)
+
+ { "WriteFile", (SYSCALL)WriteFile, 0 },
+
+#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
+ LPOVERLAPPED))aSyscall[59].pCurrent)
+
+#if SQLITE_OS_WINRT
+ { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
+#else
+ { "CreateEventExW", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
+ DWORD,DWORD))aSyscall[60].pCurrent)
+
+#if !SQLITE_OS_WINRT
+ { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
+#else
+ { "WaitForSingleObject", (SYSCALL)0, 0 },
+#endif
+
+#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
+ DWORD))aSyscall[61].pCurrent)
+
+#if SQLITE_OS_WINRT
+ { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
+#else
+ { "WaitForSingleObjectEx", (SYSCALL)0, 0 },
+#endif
+
+#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
+ BOOL))aSyscall[62].pCurrent)
+
+#if SQLITE_OS_WINRT
+ { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
+#else
+ { "SetFilePointerEx", (SYSCALL)0, 0 },
+#endif
+
+#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
+ PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
+
+#if SQLITE_OS_WINRT
+ { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
+#else
+ { "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
+#endif
+
+#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
+ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
+
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
+ { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
+#else
+ { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
+#endif
+
+#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
+ SIZE_T))aSyscall[65].pCurrent)
+
+#if SQLITE_OS_WINRT
+ { "CreateFile2", (SYSCALL)CreateFile2, 0 },
+#else
+ { "CreateFile2", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
+ LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
+
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+ { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
+#else
+ { "LoadPackagedLibrary", (SYSCALL)0, 0 },
+#endif
+
+#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
+ DWORD))aSyscall[67].pCurrent)
+
+#if SQLITE_OS_WINRT
+ { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
+#else
+ { "GetTickCount64", (SYSCALL)0, 0 },
+#endif
+
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
+
+#if SQLITE_OS_WINRT
+ { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
+#else
+ { "GetNativeSystemInfo", (SYSCALL)0, 0 },
+#endif
+
+#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
+ LPSYSTEM_INFO))aSyscall[69].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
+#else
+ { "OutputDebugStringA", (SYSCALL)0, 0 },
+#endif
+
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
+#else
+ { "OutputDebugStringW", (SYSCALL)0, 0 },
+#endif
+
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
+
+ { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
+
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
+
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
+ { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
+#else
+ { "CreateFileMappingFromApp", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
+ LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
+
+}; /* End of the overrideable system calls */
+
+/*
+** This is the xSetSystemCall() method of sqlite3_vfs for all of the
+** "win32" VFSes. Return SQLITE_OK opon successfully updating the
+** system call pointer, or SQLITE_NOTFOUND if there is no configurable
+** system call named zName.
+*/
+static int winSetSystemCall(
+ sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
+ const char *zName, /* Name of system call to override */
+ sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
+){
+ unsigned int i;
+ int rc = SQLITE_NOTFOUND;
+
+ UNUSED_PARAMETER(pNotUsed);
+ if( zName==0 ){
+ /* If no zName is given, restore all system calls to their default
+ ** settings and return NULL
+ */
+ rc = SQLITE_OK;
+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+ if( aSyscall[i].pDefault ){
+ aSyscall[i].pCurrent = aSyscall[i].pDefault;
+ }
+ }
+ }else{
+ /* If zName is specified, operate on only the one system call
+ ** specified.
+ */
+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+ if( strcmp(zName, aSyscall[i].zName)==0 ){
+ if( aSyscall[i].pDefault==0 ){
+ aSyscall[i].pDefault = aSyscall[i].pCurrent;
+ }
+ rc = SQLITE_OK;
+ if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
+ aSyscall[i].pCurrent = pNewFunc;
+ break;
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Return the value of a system call. Return NULL if zName is not a
+** recognized system call name. NULL is also returned if the system call
+** is currently undefined.
+*/
+static sqlite3_syscall_ptr winGetSystemCall(
+ sqlite3_vfs *pNotUsed,
+ const char *zName
+){
+ unsigned int i;
+
+ UNUSED_PARAMETER(pNotUsed);
+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
+ if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
+ }
+ return 0;
+}
+
+/*
+** Return the name of the first system call after zName. If zName==NULL
+** then return the name of the first system call. Return NULL if zName
+** is the last system call or if zName is not the name of a valid
+** system call.
+*/
+static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
+ int i = -1;
+
+ UNUSED_PARAMETER(p);
+ if( zName ){
+ for(i=0; i<ArraySize(aSyscall)-1; i++){
+ if( strcmp(zName, aSyscall[i].zName)==0 ) break;
+ }
+ }
+ for(i++; i<ArraySize(aSyscall); i++){
+ if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
+ }
+ return 0;
+}
+
+/*
+** This function outputs the specified (ANSI) string to the Win32 debugger
+** (if available).
+*/
+
+SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
+ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
+ int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
+ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
+ assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ if( nMin>0 ){
+ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
+ memcpy(zDbgBuf, zBuf, nMin);
+ osOutputDebugStringA(zDbgBuf);
+ }else{
+ osOutputDebugStringA(zBuf);
+ }
+#elif defined(SQLITE_WIN32_HAS_WIDE)
+ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
+ if ( osMultiByteToWideChar(
+ osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
+ nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
+ return;
+ }
+ osOutputDebugStringW((LPCWSTR)zDbgBuf);
+#else
+ if( nMin>0 ){
+ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
+ memcpy(zDbgBuf, zBuf, nMin);
+ fprintf(stderr, "%s", zDbgBuf);
+ }else{
+ fprintf(stderr, "%s", zBuf);
+ }
+#endif
+}
+
+/*
+** The following routine suspends the current thread for at least ms
+** milliseconds. This is equivalent to the Win32 Sleep() interface.
+*/
+#if SQLITE_OS_WINRT
+static HANDLE sleepObj = NULL;
+#endif
+
+SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
+#if SQLITE_OS_WINRT
+ if ( sleepObj==NULL ){
+ sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
+ SYNCHRONIZE);
+ }
+ assert( sleepObj!=NULL );
+ osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
+#else
+ osSleep(milliseconds);
+#endif
+}
+
+/*
+** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
+** or WinCE. Return false (zero) for Win95, Win98, or WinME.
+**
+** Here is an interesting observation: Win95, Win98, and WinME lack
+** the LockFileEx() API. But we can still statically link against that
+** API as long as we don't call it when running Win95/98/ME. A call to
+** this routine is used to determine if the host is Win95/98/ME or
+** WinNT/2K/XP so that we will know whether or not we can safely call
+** the LockFileEx() API.
+*/
+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
+# define isNT() (1)
+#elif !defined(SQLITE_WIN32_HAS_WIDE)
+# define isNT() (0)
+#else
+ static int isNT(void){
+ if( sqlite3_os_type==0 ){
+ OSVERSIONINFOA sInfo;
+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+ osGetVersionExA(&sInfo);
+ sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
+ }
+ return sqlite3_os_type==2;
+ }
+#endif
+
+#ifdef SQLITE_WIN32_MALLOC
+/*
+** Allocate nBytes of memory.
+*/
+static void *winMemMalloc(int nBytes){
+ HANDLE hHeap;
+ void *p;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ assert( nBytes>=0 );
+ p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+ if( !p ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
+ nBytes, osGetLastError(), (void*)hHeap);
+ }
+ return p;
+}
+
+/*
+** Free memory.
+*/
+static void winMemFree(void *pPrior){
+ HANDLE hHeap;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+#endif
+ if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
+ if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
+ pPrior, osGetLastError(), (void*)hHeap);
+ }
+}
+
+/*
+** Change the size of an existing memory allocation
+*/
+static void *winMemRealloc(void *pPrior, int nBytes){
+ HANDLE hHeap;
+ void *p;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+#endif
+ assert( nBytes>=0 );
+ if( !pPrior ){
+ p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
+ }else{
+ p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
+ }
+ if( !p ){
+ sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
+ pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
+ (void*)hHeap);
+ }
+ return p;
+}
+
+/*
+** Return the size of an outstanding allocation, in bytes.
+*/
+static int winMemSize(void *p){
+ HANDLE hHeap;
+ SIZE_T n;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ if( !p ) return 0;
+ n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
+ if( n==(SIZE_T)-1 ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
+ p, osGetLastError(), (void*)hHeap);
+ return 0;
+ }
+ return (int)n;
+}
+
+/*
+** Round up a request size to the next valid allocation size.
+*/
+static int winMemRoundup(int n){
+ return n;
+}
+
+/*
+** Initialize this module.
+*/
+static int winMemInit(void *pAppData){
+ winMemData *pWinMemData = (winMemData *)pAppData;
+
+ if( !pWinMemData ) return SQLITE_ERROR;
+ assert( pWinMemData->magic==WINMEM_MAGIC );
+
+#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
+ if( !pWinMemData->hHeap ){
+ pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
+ SQLITE_WIN32_HEAP_INIT_SIZE,
+ SQLITE_WIN32_HEAP_MAX_SIZE);
+ if( !pWinMemData->hHeap ){
+ sqlite3_log(SQLITE_NOMEM,
+ "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
+ osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
+ SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
+ return SQLITE_NOMEM;
+ }
+ pWinMemData->bOwned = TRUE;
+ assert( pWinMemData->bOwned );
+ }
+#else
+ pWinMemData->hHeap = osGetProcessHeap();
+ if( !pWinMemData->hHeap ){
+ sqlite3_log(SQLITE_NOMEM,
+ "failed to GetProcessHeap (%d)", osGetLastError());
+ return SQLITE_NOMEM;
+ }
+ pWinMemData->bOwned = FALSE;
+ assert( !pWinMemData->bOwned );
+#endif
+ assert( pWinMemData->hHeap!=0 );
+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+ assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** Deinitialize this module.
+*/
+static void winMemShutdown(void *pAppData){
+ winMemData *pWinMemData = (winMemData *)pAppData;
+
+ if( !pWinMemData ) return;
+ if( pWinMemData->hHeap ){
+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+ assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+ if( pWinMemData->bOwned ){
+ if( !osHeapDestroy(pWinMemData->hHeap) ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
+ osGetLastError(), (void*)pWinMemData->hHeap);
+ }
+ pWinMemData->bOwned = FALSE;
+ }
+ pWinMemData->hHeap = NULL;
+ }
+}
+
+/*
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
+** arguments specify the block of memory to manage.
+**
+** This routine is only called by sqlite3_config(), and therefore
+** is not required to be threadsafe (it is not).
+*/
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
+ static const sqlite3_mem_methods winMemMethods = {
+ winMemMalloc,
+ winMemFree,
+ winMemRealloc,
+ winMemSize,
+ winMemRoundup,
+ winMemInit,
+ winMemShutdown,
+ &win_mem_data
+ };
+ return &winMemMethods;
+}
+
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
+}
+#endif /* SQLITE_WIN32_MALLOC */
+
+/*
+** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
+**
+** Space to hold the returned string is obtained from malloc.
+*/
+static LPWSTR utf8ToUnicode(const char *zFilename){
+ int nChar;
+ LPWSTR zWideFilename;
+
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
+ if( nChar==0 ){
+ return 0;
+ }
+ zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
+ if( zWideFilename==0 ){
+ return 0;
+ }
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
+ nChar);
+ if( nChar==0 ){
+ sqlite3_free(zWideFilename);
+ zWideFilename = 0;
+ }
+ return zWideFilename;
+}
+
+/*
+** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is
+** obtained from sqlite3_malloc().
+*/
+static char *unicodeToUtf8(LPCWSTR zWideFilename){
+ int nByte;
+ char *zFilename;
+
+ nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
+ if( nByte == 0 ){
+ return 0;
+ }
+ zFilename = sqlite3MallocZero( nByte );
+ if( zFilename==0 ){
+ return 0;
+ }
+ nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
+ 0, 0);
+ if( nByte == 0 ){
+ sqlite3_free(zFilename);
+ zFilename = 0;
+ }
+ return zFilename;
+}
+
+/*
+** Convert an ANSI string to Microsoft Unicode, based on the
+** current codepage settings for file apis.
+**
+** Space to hold the returned string is obtained
+** from sqlite3_malloc.
+*/
+static LPWSTR mbcsToUnicode(const char *zFilename){
+ int nByte;
+ LPWSTR zMbcsFilename;
+ int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
+ 0)*sizeof(WCHAR);
+ if( nByte==0 ){
+ return 0;
+ }
+ zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
+ if( zMbcsFilename==0 ){
+ return 0;
+ }
+ nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename,
+ nByte);
+ if( nByte==0 ){
+ sqlite3_free(zMbcsFilename);
+ zMbcsFilename = 0;
+ }
+ return zMbcsFilename;
+}
+
+/*
+** Convert Microsoft Unicode to multi-byte character string, based on the
+** user's ANSI codepage.
+**
+** Space to hold the returned string is obtained from
+** sqlite3_malloc().
+*/
+static char *unicodeToMbcs(LPCWSTR zWideFilename){
+ int nByte;
+ char *zFilename;
+ int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
+ if( nByte == 0 ){
+ return 0;
+ }
+ zFilename = sqlite3MallocZero( nByte );
+ if( zFilename==0 ){
+ return 0;
+ }
+ nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename,
+ nByte, 0, 0);
+ if( nByte == 0 ){
+ sqlite3_free(zFilename);
+ zFilename = 0;
+ }
+ return zFilename;
+}
+
+/*
+** Convert multibyte character string to UTF-8. Space to hold the
+** returned string is obtained from sqlite3_malloc().
+*/
+SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
+ char *zFilenameUtf8;
+ LPWSTR zTmpWide;
+
+ zTmpWide = mbcsToUnicode(zFilename);
+ if( zTmpWide==0 ){
+ return 0;
+ }
+ zFilenameUtf8 = unicodeToUtf8(zTmpWide);
+ sqlite3_free(zTmpWide);
+ return zFilenameUtf8;
+}
+
+/*
+** Convert UTF-8 to multibyte character string. Space to hold the
+** returned string is obtained from sqlite3_malloc().
+*/
+SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
+ char *zFilenameMbcs;
+ LPWSTR zTmpWide;
+
+ zTmpWide = utf8ToUnicode(zFilename);
+ if( zTmpWide==0 ){
+ return 0;
+ }
+ zFilenameMbcs = unicodeToMbcs(zTmpWide);
+ sqlite3_free(zTmpWide);
+ return zFilenameMbcs;
+}
+
+/*
+** This function sets the data directory or the temporary directory based on
+** the provided arguments. The type argument must be 1 in order to set the
+** data directory or 2 in order to set the temporary directory. The zValue
+** argument is the name of the directory to use. The return value will be
+** SQLITE_OK if successful.
+*/
+SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
+ char **ppDirectory = 0;
+#ifndef SQLITE_OMIT_AUTOINIT
+ int rc = sqlite3_initialize();
+ if( rc ) return rc;
+#endif
+ if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
+ ppDirectory = &sqlite3_data_directory;
+ }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
+ ppDirectory = &sqlite3_temp_directory;
+ }
+ assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
+ || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
+ );
+ assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
+ if( ppDirectory ){
+ char *zValueUtf8 = 0;
+ if( zValue && zValue[0] ){
+ zValueUtf8 = unicodeToUtf8(zValue);
+ if ( zValueUtf8==0 ){
+ return SQLITE_NOMEM;
+ }
+ }
+ sqlite3_free(*ppDirectory);
+ *ppDirectory = zValueUtf8;
+ return SQLITE_OK;
+ }
+ return SQLITE_ERROR;
+}
+
+/*
+** The return value of getLastErrorMsg
+** is zero if the error message fits in the buffer, or non-zero
+** otherwise (if the message was truncated).
+*/
+static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
+ /* FormatMessage returns 0 on failure. Otherwise it
+ ** returns the number of TCHARs written to the output
+ ** buffer, excluding the terminating null char.
+ */
+ DWORD dwLen = 0;
+ char *zOut = 0;
+
+ if( isNT() ){
+#if SQLITE_OS_WINRT
+ WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
+ dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ lastErrno,
+ 0,
+ zTempWide,
+ MAX_PATH,
+ 0);
+#else
+ LPWSTR zTempWide = NULL;
+ dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ lastErrno,
+ 0,
+ (LPWSTR) &zTempWide,
+ 0,
+ 0);
+#endif
+ if( dwLen > 0 ){
+ /* allocate a buffer and convert to UTF8 */
+ sqlite3BeginBenignMalloc();
+ zOut = unicodeToUtf8(zTempWide);
+ sqlite3EndBenignMalloc();
+#if !SQLITE_OS_WINRT
+ /* free the system buffer allocated by FormatMessage */
+ osLocalFree(zTempWide);
+#endif
+ }
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ char *zTemp = NULL;
+ dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ lastErrno,
+ 0,
+ (LPSTR) &zTemp,
+ 0,
+ 0);
+ if( dwLen > 0 ){
+ /* allocate a buffer and convert to UTF8 */
+ sqlite3BeginBenignMalloc();
+ zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
+ sqlite3EndBenignMalloc();
+ /* free the system buffer allocated by FormatMessage */
+ osLocalFree(zTemp);
+ }
+ }
+#endif
+ if( 0 == dwLen ){
+ sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno);
+ }else{
+ /* copy a maximum of nBuf chars to output buffer */
+ sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
+ /* free the UTF8 buffer */
+ sqlite3_free(zOut);
+ }
+ return 0;
+}
+
+/*
+**
+** This function - winLogErrorAtLine() - is only ever called via the macro
+** winLogError().
+**
+** This routine is invoked after an error occurs in an OS function.
+** It logs a message using sqlite3_log() containing the current value of
+** error code and, if possible, the human-readable equivalent from
+** FormatMessage.
+**
+** The first argument passed to the macro should be the error code that
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
+** The two subsequent arguments should be the name of the OS function that
+** failed and the associated file-system path, if any.
+*/
+#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
+static int winLogErrorAtLine(
+ int errcode, /* SQLite error code */
+ DWORD lastErrno, /* Win32 last error */
+ const char *zFunc, /* Name of OS function that failed */
+ const char *zPath, /* File path associated with error */
+ int iLine /* Source line number where error occurred */
+){
+ char zMsg[500]; /* Human readable error text */
+ int i; /* Loop counter */
+
+ zMsg[0] = 0;
+ getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
+ assert( errcode!=SQLITE_OK );
+ if( zPath==0 ) zPath = "";
+ for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
+ zMsg[i] = 0;
+ sqlite3_log(errcode,
+ "os_win.c:%d: (%d) %s(%s) - %s",
+ iLine, lastErrno, zFunc, zPath, zMsg
+ );
+
+ return errcode;
+}
+
+/*
+** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
+** will be retried following a locking error - probably caused by
+** antivirus software. Also the initial delay before the first retry.
+** The delay increases linearly with each retry.
+*/
+#ifndef SQLITE_WIN32_IOERR_RETRY
+# define SQLITE_WIN32_IOERR_RETRY 10
+#endif
+#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
+# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
+#endif
+static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
+static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+
+/*
+** If a ReadFile() or WriteFile() error occurs, invoke this routine
+** to see if it should be retried. Return TRUE to retry. Return FALSE
+** to give up with an error.
+*/
+static int retryIoerr(int *pnRetry, DWORD *pError){
+ DWORD e = osGetLastError();
+ if( *pnRetry>=win32IoerrRetry ){
+ if( pError ){
+ *pError = e;
+ }
+ return 0;
+ }
+ if( e==ERROR_ACCESS_DENIED ||
+ e==ERROR_LOCK_VIOLATION ||
+ e==ERROR_SHARING_VIOLATION ){
+ sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
+ ++*pnRetry;
+ return 1;
+ }
+ if( pError ){
+ *pError = e;
+ }
+ return 0;
+}
+
+/*
+** Log a I/O error retry episode.
+*/
+static void logIoerr(int nRetry){
+ if( nRetry ){
+ sqlite3_log(SQLITE_IOERR,
+ "delayed %dms for lock/sharing conflict",
+ win32IoerrRetryDelay*nRetry*(nRetry+1)/2
+ );
+ }
+}
+
+#if SQLITE_OS_WINCE
+/*************************************************************************
+** This section contains code for WinCE only.
+*/
+#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
+/*
+** The MSVC CRT on Windows CE may not have a localtime() function. So
+** create a substitute.
+*/
+/* #include <time.h> */
+struct tm *__cdecl localtime(const time_t *t)
+{
+ static struct tm y;
+ FILETIME uTm, lTm;
+ SYSTEMTIME pTm;
+ sqlite3_int64 t64;
+ t64 = *t;
+ t64 = (t64 + 11644473600)*10000000;
+ uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
+ uTm.dwHighDateTime= (DWORD)(t64 >> 32);
+ osFileTimeToLocalFileTime(&uTm,&lTm);
+ osFileTimeToSystemTime(&lTm,&pTm);
+ y.tm_year = pTm.wYear - 1900;
+ y.tm_mon = pTm.wMonth - 1;
+ y.tm_wday = pTm.wDayOfWeek;
+ y.tm_mday = pTm.wDay;
+ y.tm_hour = pTm.wHour;
+ y.tm_min = pTm.wMinute;
+ y.tm_sec = pTm.wSecond;
+ return &y;
+}
+#endif
+
+#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
+
+/*
+** Acquire a lock on the handle h
+*/
+static void winceMutexAcquire(HANDLE h){
+ DWORD dwErr;
+ do {
+ dwErr = osWaitForSingleObject(h, INFINITE);
+ } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
+}
+/*
+** Release a lock acquired by winceMutexAcquire()
+*/
+#define winceMutexRelease(h) ReleaseMutex(h)
+
+/*
+** Create the mutex and shared memory used for locking in the file
+** descriptor pFile
+*/
+static int winceCreateLock(const char *zFilename, winFile *pFile){
+ LPWSTR zTok;
+ LPWSTR zName;
+ DWORD lastErrno;
+ BOOL bLogged = FALSE;
+ BOOL bInit = TRUE;
+
+ zName = utf8ToUnicode(zFilename);
+ if( zName==0 ){
+ /* out of memory */
+ return SQLITE_IOERR_NOMEM;
+ }
+
+ /* Initialize the local lockdata */
+ memset(&pFile->local, 0, sizeof(pFile->local));
+
+ /* Replace the backslashes from the filename and lowercase it
+ ** to derive a mutex name. */
+ zTok = osCharLowerW(zName);
+ for (;*zTok;zTok++){
+ if (*zTok == '\\') *zTok = '_';
+ }
+
+ /* Create/open the named mutex */
+ pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
+ if (!pFile->hMutex){
+ pFile->lastErrno = osGetLastError();
+ winLogError(SQLITE_IOERR, pFile->lastErrno,
+ "winceCreateLock1", zFilename);
+ sqlite3_free(zName);
+ return SQLITE_IOERR;
+ }
+
+ /* Acquire the mutex before continuing */
+ winceMutexAcquire(pFile->hMutex);
+
+ /* Since the names of named mutexes, semaphores, file mappings etc are
+ ** case-sensitive, take advantage of that by uppercasing the mutex name
+ ** and using that as the shared filemapping name.
+ */
+ osCharUpperW(zName);
+ pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
+ PAGE_READWRITE, 0, sizeof(winceLock),
+ zName);
+
+ /* Set a flag that indicates we're the first to create the memory so it
+ ** must be zero-initialized */
+ lastErrno = osGetLastError();
+ if (lastErrno == ERROR_ALREADY_EXISTS){
+ bInit = FALSE;
+ }
+
+ sqlite3_free(zName);
+
+ /* If we succeeded in making the shared memory handle, map it. */
+ if( pFile->hShared ){
+ pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
+ FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
+ /* If mapping failed, close the shared memory handle and erase it */
+ if( !pFile->shared ){
+ pFile->lastErrno = osGetLastError();
+ winLogError(SQLITE_IOERR, pFile->lastErrno,
+ "winceCreateLock2", zFilename);
+ bLogged = TRUE;
+ osCloseHandle(pFile->hShared);
+ pFile->hShared = NULL;
+ }
+ }
+
+ /* If shared memory could not be created, then close the mutex and fail */
+ if( pFile->hShared==NULL ){
+ if( !bLogged ){
+ pFile->lastErrno = lastErrno;
+ winLogError(SQLITE_IOERR, pFile->lastErrno,
+ "winceCreateLock3", zFilename);
+ bLogged = TRUE;
+ }
+ winceMutexRelease(pFile->hMutex);
+ osCloseHandle(pFile->hMutex);
+ pFile->hMutex = NULL;
+ return SQLITE_IOERR;
+ }
+
+ /* Initialize the shared memory if we're supposed to */
+ if( bInit ){
+ memset(pFile->shared, 0, sizeof(winceLock));
+ }
+
+ winceMutexRelease(pFile->hMutex);
+ return SQLITE_OK;
+}
+
+/*
+** Destroy the part of winFile that deals with wince locks
+*/
+static void winceDestroyLock(winFile *pFile){
+ if (pFile->hMutex){
+ /* Acquire the mutex */
+ winceMutexAcquire(pFile->hMutex);
+
+ /* The following blocks should probably assert in debug mode, but they
+ are to cleanup in case any locks remained open */
+ if (pFile->local.nReaders){
+ pFile->shared->nReaders --;
+ }
+ if (pFile->local.bReserved){
+ pFile->shared->bReserved = FALSE;
+ }
+ if (pFile->local.bPending){
+ pFile->shared->bPending = FALSE;
+ }
+ if (pFile->local.bExclusive){
+ pFile->shared->bExclusive = FALSE;
+ }
+
+ /* De-reference and close our copy of the shared memory handle */
+ osUnmapViewOfFile(pFile->shared);
+ osCloseHandle(pFile->hShared);
+
+ /* Done with the mutex */
+ winceMutexRelease(pFile->hMutex);
+ osCloseHandle(pFile->hMutex);
+ pFile->hMutex = NULL;
+ }
+}
+
+/*
+** An implementation of the LockFile() API of Windows for CE
+*/
+static BOOL winceLockFile(
+ LPHANDLE phFile,
+ DWORD dwFileOffsetLow,
+ DWORD dwFileOffsetHigh,
+ DWORD nNumberOfBytesToLockLow,
+ DWORD nNumberOfBytesToLockHigh
+){
+ winFile *pFile = HANDLE_TO_WINFILE(phFile);
+ BOOL bReturn = FALSE;
+
+ UNUSED_PARAMETER(dwFileOffsetHigh);
+ UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
+
+ if (!pFile->hMutex) return TRUE;
+ winceMutexAcquire(pFile->hMutex);
+
+ /* Wanting an exclusive lock? */
+ if (dwFileOffsetLow == (DWORD)SHARED_FIRST
+ && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
+ if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
+ pFile->shared->bExclusive = TRUE;
+ pFile->local.bExclusive = TRUE;
+ bReturn = TRUE;
+ }
+ }
+
+ /* Want a read-only lock? */
+ else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
+ nNumberOfBytesToLockLow == 1){
+ if (pFile->shared->bExclusive == 0){
+ pFile->local.nReaders ++;
+ if (pFile->local.nReaders == 1){
+ pFile->shared->nReaders ++;
+ }
+ bReturn = TRUE;
+ }
+ }
+
+ /* Want a pending lock? */
+ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+ && nNumberOfBytesToLockLow == 1){
+ /* If no pending lock has been acquired, then acquire it */
+ if (pFile->shared->bPending == 0) {
+ pFile->shared->bPending = TRUE;
+ pFile->local.bPending = TRUE;
+ bReturn = TRUE;
+ }
+ }
+
+ /* Want a reserved lock? */
+ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+ && nNumberOfBytesToLockLow == 1){
+ if (pFile->shared->bReserved == 0) {
+ pFile->shared->bReserved = TRUE;
+ pFile->local.bReserved = TRUE;
+ bReturn = TRUE;
+ }
+ }
+
+ winceMutexRelease(pFile->hMutex);
+ return bReturn;
+}
+
+/*
+** An implementation of the UnlockFile API of Windows for CE
+*/
+static BOOL winceUnlockFile(
+ LPHANDLE phFile,
+ DWORD dwFileOffsetLow,
+ DWORD dwFileOffsetHigh,
+ DWORD nNumberOfBytesToUnlockLow,
+ DWORD nNumberOfBytesToUnlockHigh
+){
+ winFile *pFile = HANDLE_TO_WINFILE(phFile);
+ BOOL bReturn = FALSE;
+
+ UNUSED_PARAMETER(dwFileOffsetHigh);
+ UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
+
+ if (!pFile->hMutex) return TRUE;
+ winceMutexAcquire(pFile->hMutex);
+
+ /* Releasing a reader lock or an exclusive lock */
+ if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
+ /* Did we have an exclusive lock? */
+ if (pFile->local.bExclusive){
+ assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
+ pFile->local.bExclusive = FALSE;
+ pFile->shared->bExclusive = FALSE;
+ bReturn = TRUE;
+ }
+
+ /* Did we just have a reader lock? */
+ else if (pFile->local.nReaders){
+ assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
+ || nNumberOfBytesToUnlockLow == 1);
+ pFile->local.nReaders --;
+ if (pFile->local.nReaders == 0)
+ {
+ pFile->shared->nReaders --;
+ }
+ bReturn = TRUE;
+ }
+ }
+
+ /* Releasing a pending lock */
+ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+ && nNumberOfBytesToUnlockLow == 1){
+ if (pFile->local.bPending){
+ pFile->local.bPending = FALSE;
+ pFile->shared->bPending = FALSE;
+ bReturn = TRUE;
+ }
+ }
+ /* Releasing a reserved lock */
+ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+ && nNumberOfBytesToUnlockLow == 1){
+ if (pFile->local.bReserved) {
+ pFile->local.bReserved = FALSE;
+ pFile->shared->bReserved = FALSE;
+ bReturn = TRUE;
+ }
+ }
+
+ winceMutexRelease(pFile->hMutex);
+ return bReturn;
+}
+/*
+** End of the special code for wince
+*****************************************************************************/
+#endif /* SQLITE_OS_WINCE */
+
+/*
+** Lock a file region.
+*/
+static BOOL winLockFile(
+ LPHANDLE phFile,
+ DWORD flags,
+ DWORD offsetLow,
+ DWORD offsetHigh,
+ DWORD numBytesLow,
+ DWORD numBytesHigh
+){
+#if SQLITE_OS_WINCE
+ /*
+ ** NOTE: Windows CE is handled differently here due its lack of the Win32
+ ** API LockFile.
+ */
+ return winceLockFile(phFile, offsetLow, offsetHigh,
+ numBytesLow, numBytesHigh);
+#else
+ if( isNT() ){
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offsetLow;
+ ovlp.OffsetHigh = offsetHigh;
+ return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
+ }else{
+ return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
+ numBytesHigh);
+ }
+#endif
+}
+
+/*
+** Unlock a file region.
+ */
+static BOOL winUnlockFile(
+ LPHANDLE phFile,
+ DWORD offsetLow,
+ DWORD offsetHigh,
+ DWORD numBytesLow,
+ DWORD numBytesHigh
+){
+#if SQLITE_OS_WINCE
+ /*
+ ** NOTE: Windows CE is handled differently here due its lack of the Win32
+ ** API UnlockFile.
+ */
+ return winceUnlockFile(phFile, offsetLow, offsetHigh,
+ numBytesLow, numBytesHigh);
+#else
+ if( isNT() ){
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offsetLow;
+ ovlp.OffsetHigh = offsetHigh;
+ return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
+ }else{
+ return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
+ numBytesHigh);
+ }
+#endif
+}
+
+/*****************************************************************************
+** The next group of routines implement the I/O methods specified
+** by the sqlite3_io_methods object.
+******************************************************************************/
+
+/*
+** Some Microsoft compilers lack this definition.
+*/
+#ifndef INVALID_SET_FILE_POINTER
+# define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+
+/*
+** Move the current position of the file handle passed as the first
+** argument to offset iOffset within the file. If successful, return 0.
+** Otherwise, set pFile->lastErrno and return non-zero.
+*/
+static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
+#if !SQLITE_OS_WINRT
+ LONG upperBits; /* Most sig. 32 bits of new offset */
+ LONG lowerBits; /* Least sig. 32 bits of new offset */
+ DWORD dwRet; /* Value returned by SetFilePointer() */
+ DWORD lastErrno; /* Value returned by GetLastError() */
+
+ upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
+ lowerBits = (LONG)(iOffset & 0xffffffff);
+
+ /* API oddity: If successful, SetFilePointer() returns a dword
+ ** containing the lower 32-bits of the new file-offset. Or, if it fails,
+ ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
+ ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
+ ** whether an error has actually occurred, it is also necessary to call
+ ** GetLastError().
+ */
+ dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
+
+ if( (dwRet==INVALID_SET_FILE_POINTER
+ && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
+ pFile->lastErrno = lastErrno;
+ winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
+ "seekWinFile", pFile->zPath);
+ return 1;
+ }
+
+ return 0;
+#else
+ /*
+ ** Same as above, except that this implementation works for WinRT.
+ */
+
+ LARGE_INTEGER x; /* The new offset */
+ BOOL bRet; /* Value returned by SetFilePointerEx() */
+
+ x.QuadPart = iOffset;
+ bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
+
+ if(!bRet){
+ pFile->lastErrno = osGetLastError();
+ winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
+ "seekWinFile", pFile->zPath);
+ return 1;
+ }
+
+ return 0;
+#endif
+}
+
+/*
+** Close a file.
+**
+** It is reported that an attempt to close a handle might sometimes
+** fail. This is a very unreasonable result, but Windows is notorious
+** for being unreasonable so I do not doubt that it might happen. If
+** the close fails, we pause for 100 milliseconds and try again. As
+** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
+** giving up and returning an error.
+*/
+#define MX_CLOSE_ATTEMPT 3
+static int winClose(sqlite3_file *id){
+ int rc, cnt = 0;
+ winFile *pFile = (winFile*)id;
+
+ assert( id!=0 );
+#ifndef SQLITE_OMIT_WAL
+ assert( pFile->pShm==0 );
+#endif
+ OSTRACE(("CLOSE %d\n", pFile->h));
+ assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
+ do{
+ rc = osCloseHandle(pFile->h);
+ /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
+ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
+#if SQLITE_OS_WINCE
+#define WINCE_DELETION_ATTEMPTS 3
+ winceDestroyLock(pFile);
+ if( pFile->zDeleteOnClose ){
+ int cnt = 0;
+ while(
+ osDeleteFileW(pFile->zDeleteOnClose)==0
+ && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
+ && cnt++ < WINCE_DELETION_ATTEMPTS
+ ){
+ sqlite3_win32_sleep(100); /* Wait a little before trying again */
+ }
+ sqlite3_free(pFile->zDeleteOnClose);
+ }
+#endif
+ OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
+ if( rc ){
+ pFile->h = NULL;
+ }
+ OpenCounter(-1);
+ return rc ? SQLITE_OK
+ : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
+ "winClose", pFile->zPath);
+}
+
+/*
+** Read data from a file into a buffer. Return SQLITE_OK if all
+** bytes were read successfully and SQLITE_IOERR if anything goes
+** wrong.
+*/
+static int winRead(
+ sqlite3_file *id, /* File to read from */
+ void *pBuf, /* Write content into this buffer */
+ int amt, /* Number of bytes to read */
+ sqlite3_int64 offset /* Begin reading at this offset */
+){
+#if !SQLITE_OS_WINCE
+ OVERLAPPED overlapped; /* The offset for ReadFile. */
+#endif
+ winFile *pFile = (winFile*)id; /* file handle */
+ DWORD nRead; /* Number of bytes actually read from file */
+ int nRetry = 0; /* Number of retrys */
+
+ assert( id!=0 );
+ SimulateIOError(return SQLITE_IOERR_READ);
+ OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
+
+#if SQLITE_OS_WINCE
+ if( seekWinFile(pFile, offset) ){
+ return SQLITE_FULL;
+ }
+ while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
+#else
+ memset(&overlapped, 0, sizeof(OVERLAPPED));
+ overlapped.Offset = (LONG)(offset & 0xffffffff);
+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
+ while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
+ osGetLastError()!=ERROR_HANDLE_EOF ){
+#endif
+ DWORD lastErrno;
+ if( retryIoerr(&nRetry, &lastErrno) ) continue;
+ pFile->lastErrno = lastErrno;
+ return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
+ "winRead", pFile->zPath);
+ }
+ logIoerr(nRetry);
+ if( nRead<(DWORD)amt ){
+ /* Unread parts of the buffer must be zero-filled */
+ memset(&((char*)pBuf)[nRead], 0, amt-nRead);
+ return SQLITE_IOERR_SHORT_READ;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Write data from a buffer into a file. Return SQLITE_OK on success
+** or some other error code on failure.
+*/
+static int winWrite(
+ sqlite3_file *id, /* File to write into */
+ const void *pBuf, /* The bytes to be written */
+ int amt, /* Number of bytes to write */
+ sqlite3_int64 offset /* Offset into the file to begin writing at */
+){
+ int rc = 0; /* True if error has occurred, else false */
+ winFile *pFile = (winFile*)id; /* File handle */
+ int nRetry = 0; /* Number of retries */
+
+ assert( amt>0 );
+ assert( pFile );
+ SimulateIOError(return SQLITE_IOERR_WRITE);
+ SimulateDiskfullError(return SQLITE_FULL);
+
+ OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
+
+#if SQLITE_OS_WINCE
+ rc = seekWinFile(pFile, offset);
+ if( rc==0 ){
+#else
+ {
+#endif
+#if !SQLITE_OS_WINCE
+ OVERLAPPED overlapped; /* The offset for WriteFile. */
+#endif
+ u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
+ int nRem = amt; /* Number of bytes yet to be written */
+ DWORD nWrite; /* Bytes written by each WriteFile() call */
+ DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
+
+#if !SQLITE_OS_WINCE
+ memset(&overlapped, 0, sizeof(OVERLAPPED));
+ overlapped.Offset = (LONG)(offset & 0xffffffff);
+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
+#endif
+
+ while( nRem>0 ){
+#if SQLITE_OS_WINCE
+ if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
+#else
+ if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
+#endif
+ if( retryIoerr(&nRetry, &lastErrno) ) continue;
+ break;
+ }
+ assert( nWrite==0 || nWrite<=(DWORD)nRem );
+ if( nWrite==0 || nWrite>(DWORD)nRem ){
+ lastErrno = osGetLastError();
+ break;
+ }
+#if !SQLITE_OS_WINCE
+ offset += nWrite;
+ overlapped.Offset = (LONG)(offset & 0xffffffff);
+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
+#endif
+ aRem += nWrite;
+ nRem -= nWrite;
+ }
+ if( nRem>0 ){
+ pFile->lastErrno = lastErrno;
+ rc = 1;
+ }
+ }
+
+ if( rc ){
+ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
+ || ( pFile->lastErrno==ERROR_DISK_FULL )){
+ return SQLITE_FULL;
+ }
+ return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
+ "winWrite", pFile->zPath);
+ }else{
+ logIoerr(nRetry);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Truncate an open file to a specified size
+*/
+static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
+ winFile *pFile = (winFile*)id; /* File handle object */
+ int rc = SQLITE_OK; /* Return code for this function */
+
+ assert( pFile );
+
+ OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
+ SimulateIOError(return SQLITE_IOERR_TRUNCATE);
+
+ /* If the user has configured a chunk-size for this file, truncate the
+ ** file so that it consists of an integer number of chunks (i.e. the
+ ** actual file size after the operation may be larger than the requested
+ ** size).
+ */
+ if( pFile->szChunk>0 ){
+ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
+ }
+
+ /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
+ if( seekWinFile(pFile, nByte) ){
+ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
+ "winTruncate1", pFile->zPath);
+ }else if( 0==osSetEndOfFile(pFile->h) ){
+ pFile->lastErrno = osGetLastError();
+ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
+ "winTruncate2", pFile->zPath);
+ }
+
+ OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
+ return rc;
+}
+
+#ifdef SQLITE_TEST
+/*
+** Count the number of fullsyncs and normal syncs. This is used to test
+** that syncs and fullsyncs are occuring at the right times.
+*/
+SQLITE_API int sqlite3_sync_count = 0;
+SQLITE_API int sqlite3_fullsync_count = 0;
+#endif
+
+/*
+** Make sure all writes to a particular file are committed to disk.
+*/
+static int winSync(sqlite3_file *id, int flags){
+#ifndef SQLITE_NO_SYNC
+ /*
+ ** Used only when SQLITE_NO_SYNC is not defined.
+ */
+ BOOL rc;
+#endif
+#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
+ (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
+ /*
+ ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
+ ** OSTRACE() macros.
+ */
+ winFile *pFile = (winFile*)id;
+#else
+ UNUSED_PARAMETER(id);
+#endif
+
+ assert( pFile );
+ /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
+ assert((flags&0x0F)==SQLITE_SYNC_NORMAL
+ || (flags&0x0F)==SQLITE_SYNC_FULL
+ );
+
+ OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
+
+ /* Unix cannot, but some systems may return SQLITE_FULL from here. This
+ ** line is to test that doing so does not cause any problems.
+ */
+ SimulateDiskfullError( return SQLITE_FULL );
+
+#ifndef SQLITE_TEST
+ UNUSED_PARAMETER(flags);
+#else
+ if( (flags&0x0F)==SQLITE_SYNC_FULL ){
+ sqlite3_fullsync_count++;
+ }
+ sqlite3_sync_count++;
+#endif
+
+ /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
+ ** no-op
+ */
+#ifdef SQLITE_NO_SYNC
+ return SQLITE_OK;
+#else
+ rc = osFlushFileBuffers(pFile->h);
+ SimulateIOError( rc=FALSE );
+ if( rc ){
+ return SQLITE_OK;
+ }else{
+ pFile->lastErrno = osGetLastError();
+ return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
+ "winSync", pFile->zPath);
+ }
+#endif
+}
+
+/*
+** Determine the current size of a file in bytes
+*/
+static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
+ winFile *pFile = (winFile*)id;
+ int rc = SQLITE_OK;
+
+ assert( id!=0 );
+ SimulateIOError(return SQLITE_IOERR_FSTAT);
+#if SQLITE_OS_WINRT
+ {
+ FILE_STANDARD_INFO info;
+ if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
+ &info, sizeof(info)) ){
+ *pSize = info.EndOfFile.QuadPart;
+ }else{
+ pFile->lastErrno = osGetLastError();
+ rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
+ "winFileSize", pFile->zPath);
+ }
+ }
+#else
+ {
+ DWORD upperBits;
+ DWORD lowerBits;
+ DWORD lastErrno;
+
+ lowerBits = osGetFileSize(pFile->h, &upperBits);
+ *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
+ if( (lowerBits == INVALID_FILE_SIZE)
+ && ((lastErrno = osGetLastError())!=NO_ERROR) ){
+ pFile->lastErrno = lastErrno;
+ rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
+ "winFileSize", pFile->zPath);
+ }
+ }
+#endif
+ return rc;
+}
+
+/*
+** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
+*/
+#ifndef LOCKFILE_FAIL_IMMEDIATELY
+# define LOCKFILE_FAIL_IMMEDIATELY 1
+#endif
+
+#ifndef LOCKFILE_EXCLUSIVE_LOCK
+# define LOCKFILE_EXCLUSIVE_LOCK 2
+#endif
+
+/*
+** Historically, SQLite has used both the LockFile and LockFileEx functions.
+** When the LockFile function was used, it was always expected to fail
+** immediately if the lock could not be obtained. Also, it always expected to
+** obtain an exclusive lock. These flags are used with the LockFileEx function
+** and reflect those expectations; therefore, they should not be changed.
+*/
+#ifndef SQLITE_LOCKFILE_FLAGS
+# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \
+ LOCKFILE_EXCLUSIVE_LOCK)
+#endif
+
+/*
+** Currently, SQLite never calls the LockFileEx function without wanting the
+** call to fail immediately if the lock cannot be obtained.
+*/
+#ifndef SQLITE_LOCKFILEEX_FLAGS
+# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY)
+#endif
+
+/*
+** Acquire a reader lock.
+** Different API routines are called depending on whether or not this
+** is Win9x or WinNT.
+*/
+static int getReadLock(winFile *pFile){
+ int res;
+ if( isNT() ){
+#if SQLITE_OS_WINCE
+ /*
+ ** NOTE: Windows CE is handled differently here due its lack of the Win32
+ ** API LockFileEx.
+ */
+ res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
+#else
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
+ SHARED_SIZE, 0);
+#endif
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ int lk;
+ sqlite3_randomness(sizeof(lk), &lk);
+ pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+ SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
+ }
+#endif
+ if( res == 0 ){
+ pFile->lastErrno = osGetLastError();
+ /* No need to log a failure to lock */
+ }
+ return res;
+}
+
+/*
+** Undo a readlock
+*/
+static int unlockReadLock(winFile *pFile){
+ int res;
+ DWORD lastErrno;
+ if( isNT() ){
+ res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
+ }
+#endif
+ if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
+ pFile->lastErrno = lastErrno;
+ winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
+ "unlockReadLock", pFile->zPath);
+ }
+ return res;
+}
+
+/*
+** Lock the file with the lock specified by parameter locktype - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. The winUnlock() routine
+** erases all locks at once and returns us immediately to locking level 0.
+** It is not possible to lower the locking level one step at a time. You
+** must go straight to locking level 0.
+*/
+static int winLock(sqlite3_file *id, int locktype){
+ int rc = SQLITE_OK; /* Return code from subroutines */
+ int res = 1; /* Result of a Windows lock call */
+ int newLocktype; /* Set pFile->locktype to this value before exiting */
+ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
+ winFile *pFile = (winFile*)id;
+ DWORD lastErrno = NO_ERROR;
+
+ assert( id!=0 );
+ OSTRACE(("LOCK %d %d was %d(%d)\n",
+ pFile->h, locktype, pFile->locktype, pFile->sharedLockByte));
+
+ /* If there is already a lock of this type or more restrictive on the
+ ** OsFile, do nothing. Don't use the end_lock: exit path, as
+ ** sqlite3OsEnterMutex() hasn't been called yet.
+ */
+ if( pFile->locktype>=locktype ){
+ return SQLITE_OK;
+ }
+
+ /* Make sure the locking sequence is correct
+ */
+ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+ assert( locktype!=PENDING_LOCK );
+ assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
+
+ /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
+ ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
+ ** the PENDING_LOCK byte is temporary.
+ */
+ newLocktype = pFile->locktype;
+ if( (pFile->locktype==NO_LOCK)
+ || ( (locktype==EXCLUSIVE_LOCK)
+ && (pFile->locktype==RESERVED_LOCK))
+ ){
+ int cnt = 3;
+ while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+ PENDING_BYTE, 0, 1, 0))==0 ){
+ /* Try 3 times to get the pending lock. This is needed to work
+ ** around problems caused by indexing and/or anti-virus software on
+ ** Windows systems.
+ ** If you are using this code as a model for alternative VFSes, do not
+ ** copy this retry logic. It is a hack intended for Windows only.
+ */
+ OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
+ if( cnt ) sqlite3_win32_sleep(1);
+ }
+ gotPendingLock = res;
+ if( !res ){
+ lastErrno = osGetLastError();
+ }
+ }
+
+ /* Acquire a shared lock
+ */
+ if( locktype==SHARED_LOCK && res ){
+ assert( pFile->locktype==NO_LOCK );
+ res = getReadLock(pFile);
+ if( res ){
+ newLocktype = SHARED_LOCK;
+ }else{
+ lastErrno = osGetLastError();
+ }
+ }
+
+ /* Acquire a RESERVED lock
+ */
+ if( locktype==RESERVED_LOCK && res ){
+ assert( pFile->locktype==SHARED_LOCK );
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
+ if( res ){
+ newLocktype = RESERVED_LOCK;
+ }else{
+ lastErrno = osGetLastError();
+ }
+ }
+
+ /* Acquire a PENDING lock
+ */
+ if( locktype==EXCLUSIVE_LOCK && res ){
+ newLocktype = PENDING_LOCK;
+ gotPendingLock = 0;
+ }
+
+ /* Acquire an EXCLUSIVE lock
+ */
+ if( locktype==EXCLUSIVE_LOCK && res ){
+ assert( pFile->locktype>=SHARED_LOCK );
+ res = unlockReadLock(pFile);
+ OSTRACE(("unreadlock = %d\n", res));
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
+ SHARED_SIZE, 0);
+ if( res ){
+ newLocktype = EXCLUSIVE_LOCK;
+ }else{
+ lastErrno = osGetLastError();
+ OSTRACE(("error-code = %d\n", lastErrno));
+ getReadLock(pFile);
+ }
+ }
+
+ /* If we are holding a PENDING lock that ought to be released, then
+ ** release it now.
+ */
+ if( gotPendingLock && locktype==SHARED_LOCK ){
+ winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
+ }
+
+ /* Update the state of the lock has held in the file descriptor then
+ ** return the appropriate result code.
+ */
+ if( res ){
+ rc = SQLITE_OK;
+ }else{
+ OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
+ locktype, newLocktype));
+ pFile->lastErrno = lastErrno;
+ rc = SQLITE_BUSY;
+ }
+ pFile->locktype = (u8)newLocktype;
+ return rc;
+}
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, return
+** non-zero, otherwise zero.
+*/
+static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
+ int rc;
+ winFile *pFile = (winFile*)id;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( id!=0 );
+ if( pFile->locktype>=RESERVED_LOCK ){
+ rc = 1;
+ OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
+ }else{
+ rc = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
+ if( rc ){
+ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
+ }
+ rc = !rc;
+ OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
+ }
+ *pResOut = rc;
+ return SQLITE_OK;
+}
+
+/*
+** Lower the locking level on file descriptor id to locktype. locktype
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+**
+** It is not possible for this routine to fail if the second argument
+** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
+** might return SQLITE_IOERR;
+*/
+static int winUnlock(sqlite3_file *id, int locktype){
+ int type;
+ winFile *pFile = (winFile*)id;
+ int rc = SQLITE_OK;
+ assert( pFile!=0 );
+ assert( locktype<=SHARED_LOCK );
+ OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
+ pFile->locktype, pFile->sharedLockByte));
+ type = pFile->locktype;
+ if( type>=EXCLUSIVE_LOCK ){
+ winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+ if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
+ /* This should never happen. We should always be able to
+ ** reacquire the read lock */
+ rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
+ "winUnlock", pFile->zPath);
+ }
+ }
+ if( type>=RESERVED_LOCK ){
+ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
+ }
+ if( locktype==NO_LOCK && type>=SHARED_LOCK ){
+ unlockReadLock(pFile);
+ }
+ if( type>=PENDING_LOCK ){
+ winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
+ }
+ pFile->locktype = (u8)locktype;
+ return rc;
+}
+
+/*
+** If *pArg is inititially negative then this is a query. Set *pArg to
+** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
+**
+** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
+*/
+static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
+ if( *pArg<0 ){
+ *pArg = (pFile->ctrlFlags & mask)!=0;
+ }else if( (*pArg)==0 ){
+ pFile->ctrlFlags &= ~mask;
+ }else{
+ pFile->ctrlFlags |= mask;
+ }
+}
+
+/* Forward declaration */
+static int getTempname(int nBuf, char *zBuf);
+
+/*
+** Control and query of the open file handle.
+*/
+static int winFileControl(sqlite3_file *id, int op, void *pArg){
+ winFile *pFile = (winFile*)id;
+ switch( op ){
+ case SQLITE_FCNTL_LOCKSTATE: {
+ *(int*)pArg = pFile->locktype;
+ return SQLITE_OK;
+ }
+ case SQLITE_LAST_ERRNO: {
+ *(int*)pArg = (int)pFile->lastErrno;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_CHUNK_SIZE: {
+ pFile->szChunk = *(int *)pArg;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_SIZE_HINT: {
+ if( pFile->szChunk>0 ){
+ sqlite3_int64 oldSz;
+ int rc = winFileSize(id, &oldSz);
+ if( rc==SQLITE_OK ){
+ sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
+ if( newSz>oldSz ){
+ SimulateIOErrorBenign(1);
+ rc = winTruncate(id, newSz);
+ SimulateIOErrorBenign(0);
+ }
+ }
+ return rc;
+ }
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_PERSIST_WAL: {
+ winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
+ winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_VFSNAME: {
+ *(char**)pArg = sqlite3_mprintf("win32");
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_WIN32_AV_RETRY: {
+ int *a = (int*)pArg;
+ if( a[0]>0 ){
+ win32IoerrRetry = a[0];
+ }else{
+ a[0] = win32IoerrRetry;
+ }
+ if( a[1]>0 ){
+ win32IoerrRetryDelay = a[1];
+ }else{
+ a[1] = win32IoerrRetryDelay;
+ }
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_TEMPFILENAME: {
+ char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
+ if( zTFile ){
+ getTempname(pFile->pVfs->mxPathname, zTFile);
+ *(char**)pArg = zTFile;
+ }
+ return SQLITE_OK;
+ }
+ }
+ return SQLITE_NOTFOUND;
+}
+
+/*
+** Return the sector size in bytes of the underlying block device for
+** the specified file. This is almost always 512 bytes, but may be
+** larger for some devices.
+**
+** SQLite code assumes this function cannot fail. It also assumes that
+** if two files are created in the same file-system directory (i.e.
+** a database and its journal file) that the sector size will be the
+** same for both.
+*/
+static int winSectorSize(sqlite3_file *id){
+ (void)id;
+ return SQLITE_DEFAULT_SECTOR_SIZE;
+}
+
+/*
+** Return a vector of device characteristics.
+*/
+static int winDeviceCharacteristics(sqlite3_file *id){
+ winFile *p = (winFile*)id;
+ return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
+ ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
+}
+
+#ifndef SQLITE_OMIT_WAL
+
+/*
+** Windows will only let you create file view mappings
+** on allocation size granularity boundaries.
+** During sqlite3_os_init() we do a GetSystemInfo()
+** to get the granularity size.
+*/
+SYSTEM_INFO winSysInfo;
+
+/*
+** Helper functions to obtain and relinquish the global mutex. The
+** global mutex is used to protect the winLockInfo objects used by
+** this file, all of which may be shared by multiple threads.
+**
+** Function winShmMutexHeld() is used to assert() that the global mutex
+** is held when required. This function is only used as part of assert()
+** statements. e.g.
+**
+** winShmEnterMutex()
+** assert( winShmMutexHeld() );
+** winShmLeaveMutex()
+*/
+static void winShmEnterMutex(void){
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+}
+static void winShmLeaveMutex(void){
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+}
+#ifdef SQLITE_DEBUG
+static int winShmMutexHeld(void) {
+ return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+}
+#endif
+
+/*
+** Object used to represent a single file opened and mmapped to provide
+** shared memory. When multiple threads all reference the same
+** log-summary, each thread has its own winFile object, but they all
+** point to a single instance of this object. In other words, each
+** log-summary is opened only once per process.
+**
+** winShmMutexHeld() must be true when creating or destroying
+** this object or while reading or writing the following fields:
+**
+** nRef
+** pNext
+**
+** The following fields are read-only after the object is created:
+**
+** fid
+** zFilename
+**
+** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
+** winShmMutexHeld() is true when reading or writing any other field
+** in this structure.
+**
+*/
+struct winShmNode {
+ sqlite3_mutex *mutex; /* Mutex to access this object */
+ char *zFilename; /* Name of the file */
+ winFile hFile; /* File handle from winOpen */
+
+ int szRegion; /* Size of shared-memory regions */
+ int nRegion; /* Size of array apRegion */
+ struct ShmRegion {
+ HANDLE hMap; /* File handle from CreateFileMapping */
+ void *pMap;
+ } *aRegion;
+ DWORD lastErrno; /* The Windows errno from the last I/O error */
+
+ int nRef; /* Number of winShm objects pointing to this */
+ winShm *pFirst; /* All winShm objects pointing to this */
+ winShmNode *pNext; /* Next in list of all winShmNode objects */
+#ifdef SQLITE_DEBUG
+ u8 nextShmId; /* Next available winShm.id value */
+#endif
+};
+
+/*
+** A global array of all winShmNode objects.
+**
+** The winShmMutexHeld() must be true while reading or writing this list.
+*/
+static winShmNode *winShmNodeList = 0;
+
+/*
+** Structure used internally by this VFS to record the state of an
+** open shared memory connection.
+**
+** The following fields are initialized when this object is created and
+** are read-only thereafter:
+**
+** winShm.pShmNode
+** winShm.id
+**
+** All other fields are read/write. The winShm.pShmNode->mutex must be held
+** while accessing any read/write fields.
+*/
+struct winShm {
+ winShmNode *pShmNode; /* The underlying winShmNode object */
+ winShm *pNext; /* Next winShm with the same winShmNode */
+ u8 hasMutex; /* True if holding the winShmNode mutex */
+ u16 sharedMask; /* Mask of shared locks held */
+ u16 exclMask; /* Mask of exclusive locks held */
+#ifdef SQLITE_DEBUG
+ u8 id; /* Id of this connection with its winShmNode */
+#endif
+};
+
+/*
+** Constants used for locking
+*/
+#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
+#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
+
+/*
+** Apply advisory locks for all n bytes beginning at ofst.
+*/
+#define _SHM_UNLCK 1
+#define _SHM_RDLCK 2
+#define _SHM_WRLCK 3
+static int winShmSystemLock(
+ winShmNode *pFile, /* Apply locks to this open shared-memory segment */
+ int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
+ int ofst, /* Offset to first byte to be locked/unlocked */
+ int nByte /* Number of bytes to lock or unlock */
+){
+ int rc = 0; /* Result code form Lock/UnlockFileEx() */
+
+ /* Access to the winShmNode object is serialized by the caller */
+ assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
+
+ /* Release/Acquire the system-level lock */
+ if( lockType==_SHM_UNLCK ){
+ rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
+ }else{
+ /* Initialize the locking parameters */
+ DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
+ if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
+ rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
+ }
+
+ if( rc!= 0 ){
+ rc = SQLITE_OK;
+ }else{
+ pFile->lastErrno = osGetLastError();
+ rc = SQLITE_BUSY;
+ }
+
+ OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n",
+ pFile->hFile.h,
+ rc==SQLITE_OK ? "ok" : "failed",
+ lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
+ pFile->lastErrno));
+
+ return rc;
+}
+
+/* Forward references to VFS methods */
+static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
+static int winDelete(sqlite3_vfs *,const char*,int);
+
+/*
+** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
+**
+** This is not a VFS shared-memory method; it is a utility function called
+** by VFS shared-memory methods.
+*/
+static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
+ winShmNode **pp;
+ winShmNode *p;
+ BOOL bRc;
+ assert( winShmMutexHeld() );
+ pp = &winShmNodeList;
+ while( (p = *pp)!=0 ){
+ if( p->nRef==0 ){
+ int i;
+ if( p->mutex ) sqlite3_mutex_free(p->mutex);
+ for(i=0; i<p->nRegion; i++){
+ bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
+ OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
+ (int)osGetCurrentProcessId(), i,
+ bRc ? "ok" : "failed"));
+ bRc = osCloseHandle(p->aRegion[i].hMap);
+ OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n",
+ (int)osGetCurrentProcessId(), i,
+ bRc ? "ok" : "failed"));
+ }
+ if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
+ SimulateIOErrorBenign(1);
+ winClose((sqlite3_file *)&p->hFile);
+ SimulateIOErrorBenign(0);
+ }
+ if( deleteFlag ){
+ SimulateIOErrorBenign(1);
+ sqlite3BeginBenignMalloc();
+ winDelete(pVfs, p->zFilename, 0);
+ sqlite3EndBenignMalloc();
+ SimulateIOErrorBenign(0);
+ }
+ *pp = p->pNext;
+ sqlite3_free(p->aRegion);
+ sqlite3_free(p);
+ }else{
+ pp = &p->pNext;
+ }
+ }
+}
+
+/*
+** Open the shared-memory area associated with database file pDbFd.
+**
+** When opening a new shared-memory file, if no other instances of that
+** file are currently open, in this process or in other processes, then
+** the file must be truncated to zero length or have its header cleared.
+*/
+static int winOpenSharedMemory(winFile *pDbFd){
+ struct winShm *p; /* The connection to be opened */
+ struct winShmNode *pShmNode = 0; /* The underlying mmapped file */
+ int rc; /* Result code */
+ struct winShmNode *pNew; /* Newly allocated winShmNode */
+ int nName; /* Size of zName in bytes */
+
+ assert( pDbFd->pShm==0 ); /* Not previously opened */
+
+ /* Allocate space for the new sqlite3_shm object. Also speculatively
+ ** allocate space for a new winShmNode and filename.
+ */
+ p = sqlite3MallocZero( sizeof(*p) );
+ if( p==0 ) return SQLITE_IOERR_NOMEM;
+ nName = sqlite3Strlen30(pDbFd->zPath);
+ pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
+ if( pNew==0 ){
+ sqlite3_free(p);
+ return SQLITE_IOERR_NOMEM;
+ }
+ pNew->zFilename = (char*)&pNew[1];
+ sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
+ sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
+
+ /* Look to see if there is an existing winShmNode that can be used.
+ ** If no matching winShmNode currently exists, create a new one.
+ */
+ winShmEnterMutex();
+ for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
+ /* TBD need to come up with better match here. Perhaps
+ ** use FILE_ID_BOTH_DIR_INFO Structure.
+ */
+ if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
+ }
+ if( pShmNode ){
+ sqlite3_free(pNew);
+ }else{
+ pShmNode = pNew;
+ pNew = 0;
+ ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
+ pShmNode->pNext = winShmNodeList;
+ winShmNodeList = pShmNode;
+
+ pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pShmNode->mutex==0 ){
+ rc = SQLITE_IOERR_NOMEM;
+ goto shm_open_err;
+ }
+
+ rc = winOpen(pDbFd->pVfs,
+ pShmNode->zFilename, /* Name of the file (UTF-8) */
+ (sqlite3_file*)&pShmNode->hFile, /* File handle here */
+ SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+ 0);
+ if( SQLITE_OK!=rc ){
+ goto shm_open_err;
+ }
+
+ /* Check to see if another process is holding the dead-man switch.
+ ** If not, truncate the file to zero length.
+ */
+ if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
+ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
+ if( rc!=SQLITE_OK ){
+ rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
+ "winOpenShm", pDbFd->zPath);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
+ rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
+ }
+ if( rc ) goto shm_open_err;
+ }
+
+ /* Make the new connection a child of the winShmNode */
+ p->pShmNode = pShmNode;
+#ifdef SQLITE_DEBUG
+ p->id = pShmNode->nextShmId++;
+#endif
+ pShmNode->nRef++;
+ pDbFd->pShm = p;
+ winShmLeaveMutex();
+
+ /* The reference count on pShmNode has already been incremented under
+ ** the cover of the winShmEnterMutex() mutex and the pointer from the
+ ** new (struct winShm) object to the pShmNode has been set. All that is
+ ** left to do is to link the new object into the linked list starting
+ ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
+ ** mutex.
+ */
+ sqlite3_mutex_enter(pShmNode->mutex);
+ p->pNext = pShmNode->pFirst;
+ pShmNode->pFirst = p;
+ sqlite3_mutex_leave(pShmNode->mutex);
+ return SQLITE_OK;
+
+ /* Jump here on any error */
+shm_open_err:
+ winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
+ winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
+ sqlite3_free(p);
+ sqlite3_free(pNew);
+ winShmLeaveMutex();
+ return rc;
+}
+
+/*
+** Close a connection to shared-memory. Delete the underlying
+** storage if deleteFlag is true.
+*/
+static int winShmUnmap(
+ sqlite3_file *fd, /* Database holding shared memory */
+ int deleteFlag /* Delete after closing if true */
+){
+ winFile *pDbFd; /* Database holding shared-memory */
+ winShm *p; /* The connection to be closed */
+ winShmNode *pShmNode; /* The underlying shared-memory file */
+ winShm **pp; /* For looping over sibling connections */
+
+ pDbFd = (winFile*)fd;
+ p = pDbFd->pShm;
+ if( p==0 ) return SQLITE_OK;
+ pShmNode = p->pShmNode;
+
+ /* Remove connection p from the set of connections associated
+ ** with pShmNode */
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
+ *pp = p->pNext;
+
+ /* Free the connection p */
+ sqlite3_free(p);
+ pDbFd->pShm = 0;
+ sqlite3_mutex_leave(pShmNode->mutex);
+
+ /* If pShmNode->nRef has reached 0, then close the underlying
+ ** shared-memory file, too */
+ winShmEnterMutex();
+ assert( pShmNode->nRef>0 );
+ pShmNode->nRef--;
+ if( pShmNode->nRef==0 ){
+ winShmPurge(pDbFd->pVfs, deleteFlag);
+ }
+ winShmLeaveMutex();
+
+ return SQLITE_OK;
+}
+
+/*
+** Change the lock state for a shared-memory segment.
+*/
+static int winShmLock(
+ sqlite3_file *fd, /* Database file holding the shared memory */
+ int ofst, /* First lock to acquire or release */
+ int n, /* Number of locks to acquire or release */
+ int flags /* What to do with the lock */
+){
+ winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
+ winShm *p = pDbFd->pShm; /* The shared memory being locked */
+ winShm *pX; /* For looping over all siblings */
+ winShmNode *pShmNode = p->pShmNode;
+ int rc = SQLITE_OK; /* Result code */
+ u16 mask; /* Mask of locks to take or release */
+
+ assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
+ assert( n>=1 );
+ assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
+ || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
+ assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
+
+ mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
+ assert( n>1 || mask==(1<<ofst) );
+ sqlite3_mutex_enter(pShmNode->mutex);
+ if( flags & SQLITE_SHM_UNLOCK ){
+ u16 allMask = 0; /* Mask of locks held by siblings */
+
+ /* See if any siblings hold this same lock */
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ if( pX==p ) continue;
+ assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
+ allMask |= pX->sharedMask;
+ }
+
+ /* Unlock the system-level locks */
+ if( (mask & allMask)==0 ){
+ rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
+ }else{
+ rc = SQLITE_OK;
+ }
+
+ /* Undo the local locks */
+ if( rc==SQLITE_OK ){
+ p->exclMask &= ~mask;
+ p->sharedMask &= ~mask;
+ }
+ }else if( flags & SQLITE_SHM_SHARED ){
+ u16 allShared = 0; /* Union of locks held by connections other than "p" */
+
+ /* Find out which shared locks are already held by sibling connections.
+ ** If any sibling already holds an exclusive lock, go ahead and return
+ ** SQLITE_BUSY.
+ */
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ if( (pX->exclMask & mask)!=0 ){
+ rc = SQLITE_BUSY;
+ break;
+ }
+ allShared |= pX->sharedMask;
+ }
+
+ /* Get shared locks at the system level, if necessary */
+ if( rc==SQLITE_OK ){
+ if( (allShared & mask)==0 ){
+ rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
+ }else{
+ rc = SQLITE_OK;
+ }
+ }
+
+ /* Get the local shared locks */
+ if( rc==SQLITE_OK ){
+ p->sharedMask |= mask;
+ }
+ }else{
+ /* Make sure no sibling connections hold locks that will block this
+ ** lock. If any do, return SQLITE_BUSY right away.
+ */
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+ rc = SQLITE_BUSY;
+ break;
+ }
+ }
+
+ /* Get the exclusive locks at the system level. Then if successful
+ ** also mark the local connection as being locked.
+ */
+ if( rc==SQLITE_OK ){
+ rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
+ if( rc==SQLITE_OK ){
+ assert( (p->sharedMask & mask)==0 );
+ p->exclMask |= mask;
+ }
+ }
+ }
+ sqlite3_mutex_leave(pShmNode->mutex);
+ OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
+ p->id, (int)osGetCurrentProcessId(), p->sharedMask, p->exclMask,
+ rc ? "failed" : "ok"));
+ return rc;
+}
+
+/*
+** Implement a memory barrier or memory fence on shared memory.
+**
+** All loads and stores begun before the barrier must complete before
+** any load or store begun after the barrier.
+*/
+static void winShmBarrier(
+ sqlite3_file *fd /* Database holding the shared memory */
+){
+ UNUSED_PARAMETER(fd);
+ /* MemoryBarrier(); // does not work -- do not know why not */
+ winShmEnterMutex();
+ winShmLeaveMutex();
+}
+
+/*
+** This function is called to obtain a pointer to region iRegion of the
+** shared-memory associated with the database file fd. Shared-memory regions
+** are numbered starting from zero. Each shared-memory region is szRegion
+** bytes in size.
+**
+** If an error occurs, an error code is returned and *pp is set to NULL.
+**
+** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
+** region has not been allocated (by any client, including one running in a
+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
+** isWrite is non-zero and the requested shared-memory region has not yet
+** been allocated, it is allocated by this function.
+**
+** If the shared-memory region has already been allocated or is allocated by
+** this call as described above, then it is mapped into this processes
+** address space (if it is not already), *pp is set to point to the mapped
+** memory and SQLITE_OK returned.
+*/
+static int winShmMap(
+ sqlite3_file *fd, /* Handle open on database file */
+ int iRegion, /* Region to retrieve */
+ int szRegion, /* Size of regions */
+ int isWrite, /* True to extend file if necessary */
+ void volatile **pp /* OUT: Mapped memory */
+){
+ winFile *pDbFd = (winFile*)fd;
+ winShm *p = pDbFd->pShm;
+ winShmNode *pShmNode;
+ int rc = SQLITE_OK;
+
+ if( !p ){
+ rc = winOpenSharedMemory(pDbFd);
+ if( rc!=SQLITE_OK ) return rc;
+ p = pDbFd->pShm;
+ }
+ pShmNode = p->pShmNode;
+
+ sqlite3_mutex_enter(pShmNode->mutex);
+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+
+ if( pShmNode->nRegion<=iRegion ){
+ struct ShmRegion *apNew; /* New aRegion[] array */
+ int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
+ sqlite3_int64 sz; /* Current size of wal-index file */
+
+ pShmNode->szRegion = szRegion;
+
+ /* The requested region is not mapped into this processes address space.
+ ** Check to see if it has been allocated (i.e. if the wal-index file is
+ ** large enough to contain the requested region).
+ */
+ rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
+ if( rc!=SQLITE_OK ){
+ rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
+ "winShmMap1", pDbFd->zPath);
+ goto shmpage_out;
+ }
+
+ if( sz<nByte ){
+ /* The requested memory region does not exist. If isWrite is set to
+ ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
+ **
+ ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
+ ** the requested memory region.
+ */
+ if( !isWrite ) goto shmpage_out;
+ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
+ if( rc!=SQLITE_OK ){
+ rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
+ "winShmMap2", pDbFd->zPath);
+ goto shmpage_out;
+ }
+ }
+
+ /* Map the requested memory region into this processes address space. */
+ apNew = (struct ShmRegion *)sqlite3_realloc(
+ pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
+ );
+ if( !apNew ){
+ rc = SQLITE_IOERR_NOMEM;
+ goto shmpage_out;
+ }
+ pShmNode->aRegion = apNew;
+
+ while( pShmNode->nRegion<=iRegion ){
+ HANDLE hMap = NULL; /* file-mapping handle */
+ void *pMap = 0; /* Mapped memory region */
+
+#if SQLITE_OS_WINRT
+ hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
+ NULL, PAGE_READWRITE, nByte, NULL
+ );
+#elif defined(SQLITE_WIN32_HAS_WIDE)
+ hMap = osCreateFileMappingW(pShmNode->hFile.h,
+ NULL, PAGE_READWRITE, 0, nByte, NULL
+ );
+#elif defined(SQLITE_WIN32_HAS_ANSI)
+ hMap = osCreateFileMappingA(pShmNode->hFile.h,
+ NULL, PAGE_READWRITE, 0, nByte, NULL
+ );
+#endif
+ OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n",
+ (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte,
+ hMap ? "ok" : "failed"));
+ if( hMap ){
+ int iOffset = pShmNode->nRegion*szRegion;
+ int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
+#if SQLITE_OS_WINRT
+ pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
+ iOffset - iOffsetShift, szRegion + iOffsetShift
+ );
+#else
+ pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
+ 0, iOffset - iOffsetShift, szRegion + iOffsetShift
+ );
+#endif
+ OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n",
+ (int)osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
+ szRegion, pMap ? "ok" : "failed"));
+ }
+ if( !pMap ){
+ pShmNode->lastErrno = osGetLastError();
+ rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
+ "winShmMap3", pDbFd->zPath);
+ if( hMap ) osCloseHandle(hMap);
+ goto shmpage_out;
+ }
+
+ pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
+ pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
+ pShmNode->nRegion++;
+ }
+ }
+
+shmpage_out:
+ if( pShmNode->nRegion>iRegion ){
+ int iOffset = iRegion*szRegion;
+ int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
+ char *p = (char *)pShmNode->aRegion[iRegion].pMap;
+ *pp = (void *)&p[iOffsetShift];
+ }else{
+ *pp = 0;
+ }
+ sqlite3_mutex_leave(pShmNode->mutex);
+ return rc;
+}
+
+#else
+# define winShmMap 0
+# define winShmLock 0
+# define winShmBarrier 0
+# define winShmUnmap 0
+#endif /* #ifndef SQLITE_OMIT_WAL */
+
+/*
+** Here ends the implementation of all sqlite3_file methods.
+**
+********************** End sqlite3_file Methods *******************************
+******************************************************************************/
+
+/*
+** This vector defines all the methods that can operate on an
+** sqlite3_file for win32.
+*/
+static const sqlite3_io_methods winIoMethod = {
+ 2, /* iVersion */
+ winClose, /* xClose */
+ winRead, /* xRead */
+ winWrite, /* xWrite */
+ winTruncate, /* xTruncate */
+ winSync, /* xSync */
+ winFileSize, /* xFileSize */
+ winLock, /* xLock */
+ winUnlock, /* xUnlock */
+ winCheckReservedLock, /* xCheckReservedLock */
+ winFileControl, /* xFileControl */
+ winSectorSize, /* xSectorSize */
+ winDeviceCharacteristics, /* xDeviceCharacteristics */
+ winShmMap, /* xShmMap */
+ winShmLock, /* xShmLock */
+ winShmBarrier, /* xShmBarrier */
+ winShmUnmap /* xShmUnmap */
+};
+
+/****************************************************************************
+**************************** sqlite3_vfs methods ****************************
+**
+** This division contains the implementation of methods on the
+** sqlite3_vfs object.
+*/
+
+/*
+** Convert a UTF-8 filename into whatever form the underlying
+** operating system wants filenames in. Space to hold the result
+** is obtained from malloc and must be freed by the calling
+** function.
+*/
+static void *convertUtf8Filename(const char *zFilename){
+ void *zConverted = 0;
+ if( isNT() ){
+ zConverted = utf8ToUnicode(zFilename);
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
+ }
+#endif
+ /* caller will handle out of memory */
+ return zConverted;
+}
+
+/*
+** Create a temporary file name in zBuf. zBuf must be big enough to
+** hold at pVfs->mxPathname characters.
+*/
+static int getTempname(int nBuf, char *zBuf){
+ static char zChars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
+ size_t i, j;
+ int nTempPath;
+ char zTempPath[MAX_PATH+2];
+
+ /* It's odd to simulate an io-error here, but really this is just
+ ** using the io-error infrastructure to test that SQLite handles this
+ ** function failing.
+ */
+ SimulateIOError( return SQLITE_IOERR );
+
+ memset(zTempPath, 0, MAX_PATH+2);
+
+ if( sqlite3_temp_directory ){
+ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
+ }
+#if !SQLITE_OS_WINRT
+ else if( isNT() ){
+ char *zMulti;
+ WCHAR zWidePath[MAX_PATH];
+ osGetTempPathW(MAX_PATH-30, zWidePath);
+ zMulti = unicodeToUtf8(zWidePath);
+ if( zMulti ){
+ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
+ sqlite3_free(zMulti);
+ }else{
+ return SQLITE_IOERR_NOMEM;
+ }
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ char *zUtf8;
+ char zMbcsPath[MAX_PATH];
+ osGetTempPathA(MAX_PATH-30, zMbcsPath);
+ zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
+ if( zUtf8 ){
+ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
+ sqlite3_free(zUtf8);
+ }else{
+ return SQLITE_IOERR_NOMEM;
+ }
+ }
+#endif
+#endif
+
+ /* Check that the output buffer is large enough for the temporary file
+ ** name. If it is not, return SQLITE_ERROR.
+ */
+ nTempPath = sqlite3Strlen30(zTempPath);
+
+ if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
+ return SQLITE_ERROR;
+ }
+
+ for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
+ zTempPath[i] = 0;
+
+ sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
+ "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
+ zTempPath);
+ j = sqlite3Strlen30(zBuf);
+ sqlite3_randomness(15, &zBuf[j]);
+ for(i=0; i<15; i++, j++){
+ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
+ }
+ zBuf[j] = 0;
+ zBuf[j+1] = 0;
+
+ OSTRACE(("TEMP FILENAME: %s\n", zBuf));
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the named file is really a directory. Return false if
+** it is something other than a directory, or if there is any kind of memory
+** allocation failure.
+*/
+static int winIsDir(const void *zConverted){
+ DWORD attr;
+ int rc = 0;
+ DWORD lastErrno;
+
+ if( isNT() ){
+ int cnt = 0;
+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+ memset(&sAttrData, 0, sizeof(sAttrData));
+ while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
+ GetFileExInfoStandard,
+ &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+ if( !rc ){
+ return 0; /* Invalid name? */
+ }
+ attr = sAttrData.dwFileAttributes;
+#if SQLITE_OS_WINCE==0
+ }else{
+ attr = osGetFileAttributesA((char*)zConverted);
+#endif
+ }
+ return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
+}
+
+/*
+** Open a file.
+*/
+static int winOpen(
+ sqlite3_vfs *pVfs, /* Not used */
+ const char *zName, /* Name of the file (UTF-8) */
+ sqlite3_file *id, /* Write the SQLite file handle here */
+ int flags, /* Open mode flags */
+ int *pOutFlags /* Status return flags */
+){
+ HANDLE h;
+ DWORD lastErrno;
+ DWORD dwDesiredAccess;
+ DWORD dwShareMode;
+ DWORD dwCreationDisposition;
+ DWORD dwFlagsAndAttributes = 0;
+#if SQLITE_OS_WINCE
+ int isTemp = 0;
+#endif
+ winFile *pFile = (winFile*)id;
+ void *zConverted; /* Filename in OS encoding */
+ const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
+ int cnt = 0;
+
+ /* If argument zPath is a NULL pointer, this function is required to open
+ ** a temporary file. Use this buffer to store the file name in.
+ */
+ char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */
+
+ int rc = SQLITE_OK; /* Function Return Code */
+#if !defined(NDEBUG) || SQLITE_OS_WINCE
+ int eType = flags&0xFFFFFF00; /* Type of file to open */
+#endif
+
+ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
+ int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
+ int isCreate = (flags & SQLITE_OPEN_CREATE);
+#ifndef NDEBUG
+ int isReadonly = (flags & SQLITE_OPEN_READONLY);
+#endif
+ int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
+
+#ifndef NDEBUG
+ int isOpenJournal = (isCreate && (
+ eType==SQLITE_OPEN_MASTER_JOURNAL
+ || eType==SQLITE_OPEN_MAIN_JOURNAL
+ || eType==SQLITE_OPEN_WAL
+ ));
+#endif
+
+ /* Check the following statements are true:
+ **
+ ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
+ ** (b) if CREATE is set, then READWRITE must also be set, and
+ ** (c) if EXCLUSIVE is set, then CREATE must also be set.
+ ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
+ */
+ assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
+ assert(isCreate==0 || isReadWrite);
+ assert(isExclusive==0 || isCreate);
+ assert(isDelete==0 || isCreate);
+
+ /* The main DB, main journal, WAL file and master journal are never
+ ** automatically deleted. Nor are they ever temporary files. */
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
+
+ /* Assert that the upper layer has set one of the "file-type" flags. */
+ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
+ || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
+ || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
+ );
+
+ assert( pFile!=0 );
+ memset(pFile, 0, sizeof(winFile));
+ pFile->h = INVALID_HANDLE_VALUE;
+
+#if SQLITE_OS_WINRT
+ if( !sqlite3_temp_directory ){
+ sqlite3_log(SQLITE_ERROR,
+ "sqlite3_temp_directory variable should be set for WinRT");
+ }
+#endif
+
+ /* If the second argument to this function is NULL, generate a
+ ** temporary file name to use
+ */
+ if( !zUtf8Name ){
+ assert(isDelete && !isOpenJournal);
+ memset(zTmpname, 0, MAX_PATH+2);
+ rc = getTempname(MAX_PATH+2, zTmpname);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ zUtf8Name = zTmpname;
+ }
+
+ /* Database filenames are double-zero terminated if they are not
+ ** URIs with parameters. Hence, they can always be passed into
+ ** sqlite3_uri_parameter().
+ */
+ assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
+ zUtf8Name[strlen(zUtf8Name)+1]==0 );
+
+ /* Convert the filename to the system encoding. */
+ zConverted = convertUtf8Filename(zUtf8Name);
+ if( zConverted==0 ){
+ return SQLITE_IOERR_NOMEM;
+ }
+
+ if( winIsDir(zConverted) ){
+ sqlite3_free(zConverted);
+ return SQLITE_CANTOPEN_ISDIR;
+ }
+
+ if( isReadWrite ){
+ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ }else{
+ dwDesiredAccess = GENERIC_READ;
+ }
+
+ /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
+ ** created. SQLite doesn't use it to indicate "exclusive access"
+ ** as it is usually understood.
+ */
+ if( isExclusive ){
+ /* Creates a new file, only if it does not already exist. */
+ /* If the file exists, it fails. */
+ dwCreationDisposition = CREATE_NEW;
+ }else if( isCreate ){
+ /* Open existing file, or create if it doesn't exist */
+ dwCreationDisposition = OPEN_ALWAYS;
+ }else{
+ /* Opens a file, only if it exists. */
+ dwCreationDisposition = OPEN_EXISTING;
+ }
+
+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ if( isDelete ){
+#if SQLITE_OS_WINCE
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
+ isTemp = 1;
+#else
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
+ | FILE_ATTRIBUTE_HIDDEN
+ | FILE_FLAG_DELETE_ON_CLOSE;
+#endif
+ }else{
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+ }
+ /* Reports from the internet are that performance is always
+ ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
+#if SQLITE_OS_WINCE
+ dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
+#endif
+
+ if( isNT() ){
+#if SQLITE_OS_WINRT
+ CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
+ extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+ extendedParameters.dwFileAttributes =
+ dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
+ extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
+ extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+ extendedParameters.lpSecurityAttributes = NULL;
+ extendedParameters.hTemplateFile = NULL;
+ while( (h = osCreateFile2((LPCWSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode,
+ dwCreationDisposition,
+ &extendedParameters))==INVALID_HANDLE_VALUE &&
+ retryIoerr(&cnt, &lastErrno) ){
+ /* Noop */
+ }
+#else
+ while( (h = osCreateFileW((LPCWSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL))==INVALID_HANDLE_VALUE &&
+ retryIoerr(&cnt, &lastErrno) ){
+ /* Noop */
+ }
+#endif
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ while( (h = osCreateFileA((LPCSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL))==INVALID_HANDLE_VALUE &&
+ retryIoerr(&cnt, &lastErrno) ){
+ /* Noop */
+ }
+ }
+#endif
+ logIoerr(cnt);
+
+ OSTRACE(("OPEN %d %s 0x%lx %s\n",
+ h, zName, dwDesiredAccess,
+ h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
+
+ if( h==INVALID_HANDLE_VALUE ){
+ pFile->lastErrno = lastErrno;
+ winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
+ sqlite3_free(zConverted);
+ if( isReadWrite && !isExclusive ){
+ return winOpen(pVfs, zName, id,
+ ((flags|SQLITE_OPEN_READONLY) &
+ ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
+ pOutFlags);
+ }else{
+ return SQLITE_CANTOPEN_BKPT;
+ }
+ }
+
+ if( pOutFlags ){
+ if( isReadWrite ){
+ *pOutFlags = SQLITE_OPEN_READWRITE;
+ }else{
+ *pOutFlags = SQLITE_OPEN_READONLY;
+ }
+ }
+
+#if SQLITE_OS_WINCE
+ if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
+ && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
+ ){
+ osCloseHandle(h);
+ sqlite3_free(zConverted);
+ return rc;
+ }
+ if( isTemp ){
+ pFile->zDeleteOnClose = zConverted;
+ }else
+#endif
+ {
+ sqlite3_free(zConverted);
+ }
+
+ pFile->pMethod = &winIoMethod;
+ pFile->pVfs = pVfs;
+ pFile->h = h;
+ if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+ pFile->ctrlFlags |= WINFILE_PSOW;
+ }
+ pFile->lastErrno = NO_ERROR;
+ pFile->zPath = zName;
+
+ OpenCounter(+1);
+ return rc;
+}
+
+/*
+** Delete the named file.
+**
+** Note that Windows does not allow a file to be deleted if some other
+** process has it open. Sometimes a virus scanner or indexing program
+** will open a journal file shortly after it is created in order to do
+** whatever it does. While this other process is holding the
+** file open, we will be unable to delete it. To work around this
+** problem, we delay 100 milliseconds and try to delete again. Up
+** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
+** up and returning an error.
+*/
+static int winDelete(
+ sqlite3_vfs *pVfs, /* Not used on win32 */
+ const char *zFilename, /* Name of file to delete */
+ int syncDir /* Not used on win32 */
+){
+ int cnt = 0;
+ int rc;
+ DWORD attr;
+ DWORD lastErrno;
+ void *zConverted;
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(syncDir);
+
+ SimulateIOError(return SQLITE_IOERR_DELETE);
+ zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( isNT() ){
+ do {
+#if SQLITE_OS_WINRT
+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+ memset(&sAttrData, 0, sizeof(sAttrData));
+ if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
+ &sAttrData) ){
+ attr = sAttrData.dwFileAttributes;
+ }else{
+ lastErrno = osGetLastError();
+ if( lastErrno==ERROR_FILE_NOT_FOUND
+ || lastErrno==ERROR_PATH_NOT_FOUND ){
+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ break;
+ }
+#else
+ attr = osGetFileAttributesW(zConverted);
+#endif
+ if ( attr==INVALID_FILE_ATTRIBUTES ){
+ lastErrno = osGetLastError();
+ if( lastErrno==ERROR_FILE_NOT_FOUND
+ || lastErrno==ERROR_PATH_NOT_FOUND ){
+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ break;
+ }
+ if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
+ rc = SQLITE_ERROR; /* Files only. */
+ break;
+ }
+ if ( osDeleteFileW(zConverted) ){
+ rc = SQLITE_OK; /* Deleted OK. */
+ break;
+ }
+ if ( !retryIoerr(&cnt, &lastErrno) ){
+ rc = SQLITE_ERROR; /* No more retries. */
+ break;
+ }
+ } while(1);
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ do {
+ attr = osGetFileAttributesA(zConverted);
+ if ( attr==INVALID_FILE_ATTRIBUTES ){
+ lastErrno = osGetLastError();
+ if( lastErrno==ERROR_FILE_NOT_FOUND
+ || lastErrno==ERROR_PATH_NOT_FOUND ){
+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ break;
+ }
+ if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
+ rc = SQLITE_ERROR; /* Files only. */
+ break;
+ }
+ if ( osDeleteFileA(zConverted) ){
+ rc = SQLITE_OK; /* Deleted OK. */
+ break;
+ }
+ if ( !retryIoerr(&cnt, &lastErrno) ){
+ rc = SQLITE_ERROR; /* No more retries. */
+ break;
+ }
+ } while(1);
+ }
+#endif
+ if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
+ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
+ "winDelete", zFilename);
+ }else{
+ logIoerr(cnt);
+ }
+ sqlite3_free(zConverted);
+ OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
+ return rc;
+}
+
+/*
+** Check the existence and status of a file.
+*/
+static int winAccess(
+ sqlite3_vfs *pVfs, /* Not used on win32 */
+ const char *zFilename, /* Name of file to check */
+ int flags, /* Type of test to make on this file */
+ int *pResOut /* OUT: Result */
+){
+ DWORD attr;
+ int rc = 0;
+ DWORD lastErrno;
+ void *zConverted;
+ UNUSED_PARAMETER(pVfs);
+
+ SimulateIOError( return SQLITE_IOERR_ACCESS; );
+ zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( isNT() ){
+ int cnt = 0;
+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+ memset(&sAttrData, 0, sizeof(sAttrData));
+ while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
+ GetFileExInfoStandard,
+ &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+ if( rc ){
+ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
+ ** as if it does not exist.
+ */
+ if( flags==SQLITE_ACCESS_EXISTS
+ && sAttrData.nFileSizeHigh==0
+ && sAttrData.nFileSizeLow==0 ){
+ attr = INVALID_FILE_ATTRIBUTES;
+ }else{
+ attr = sAttrData.dwFileAttributes;
+ }
+ }else{
+ logIoerr(cnt);
+ if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
+ winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
+ sqlite3_free(zConverted);
+ return SQLITE_IOERR_ACCESS;
+ }else{
+ attr = INVALID_FILE_ATTRIBUTES;
+ }
+ }
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ attr = osGetFileAttributesA((char*)zConverted);
+ }
+#endif
+ sqlite3_free(zConverted);
+ switch( flags ){
+ case SQLITE_ACCESS_READ:
+ case SQLITE_ACCESS_EXISTS:
+ rc = attr!=INVALID_FILE_ATTRIBUTES;
+ break;
+ case SQLITE_ACCESS_READWRITE:
+ rc = attr!=INVALID_FILE_ATTRIBUTES &&
+ (attr & FILE_ATTRIBUTE_READONLY)==0;
+ break;
+ default:
+ assert(!"Invalid flags argument");
+ }
+ *pResOut = rc;
+ return SQLITE_OK;
+}
+
+
+/*
+** Returns non-zero if the specified path name should be used verbatim. If
+** non-zero is returned from this function, the calling function must simply
+** use the provided path name verbatim -OR- resolve it into a full path name
+** using the GetFullPathName Win32 API function (if available).
+*/
+static BOOL winIsVerbatimPathname(
+ const char *zPathname
+){
+ /*
+ ** If the path name starts with a forward slash or a backslash, it is either
+ ** a legal UNC name, a volume relative path, or an absolute path name in the
+ ** "Unix" format on Windows. There is no easy way to differentiate between
+ ** the final two cases; therefore, we return the safer return value of TRUE
+ ** so that callers of this function will simply use it verbatim.
+ */
+ if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
+ return TRUE;
+ }
+
+ /*
+ ** If the path name starts with a letter and a colon it is either a volume
+ ** relative path or an absolute path. Callers of this function must not
+ ** attempt to treat it as a relative path name (i.e. they should simply use
+ ** it verbatim).
+ */
+ if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){
+ return TRUE;
+ }
+
+ /*
+ ** If we get to this point, the path name should almost certainly be a purely
+ ** relative one (i.e. not a UNC name, not absolute, and not volume relative).
+ */
+ return FALSE;
+}
+
+/*
+** Turn a relative pathname into a full pathname. Write the full
+** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
+** bytes in size.
+*/
+static int winFullPathname(
+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
+ const char *zRelative, /* Possibly relative input path */
+ int nFull, /* Size of output buffer in bytes */
+ char *zFull /* Output buffer */
+){
+
+#if defined(__CYGWIN__)
+ SimulateIOError( return SQLITE_ERROR );
+ UNUSED_PARAMETER(nFull);
+ assert( pVfs->mxPathname>=MAX_PATH );
+ assert( nFull>=pVfs->mxPathname );
+ if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
+ /*
+ ** NOTE: We are dealing with a relative path name and the data
+ ** directory has been set. Therefore, use it as the basis
+ ** for converting the relative path name to an absolute
+ ** one by prepending the data directory and a slash.
+ */
+ char zOut[MAX_PATH+1];
+ memset(zOut, 0, MAX_PATH+1);
+ cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
+ MAX_PATH+1);
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
+ sqlite3_data_directory, zOut);
+ }else{
+ cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
+ }
+ return SQLITE_OK;
+#endif
+
+#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
+ SimulateIOError( return SQLITE_ERROR );
+ /* WinCE has no concept of a relative pathname, or so I am told. */
+ /* WinRT has no way to convert a relative path to an absolute one. */
+ if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
+ /*
+ ** NOTE: We are dealing with a relative path name and the data
+ ** directory has been set. Therefore, use it as the basis
+ ** for converting the relative path name to an absolute
+ ** one by prepending the data directory and a backslash.
+ */
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
+ sqlite3_data_directory, zRelative);
+ }else{
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
+ }
+ return SQLITE_OK;
+#endif
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+ DWORD nByte;
+ void *zConverted;
+ char *zOut;
+
+ /* If this path name begins with "/X:", where "X" is any alphabetic
+ ** character, discard the initial "/" from the pathname.
+ */
+ if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
+ zRelative++;
+ }
+
+ /* It's odd to simulate an io-error here, but really this is just
+ ** using the io-error infrastructure to test that SQLite handles this
+ ** function failing. This function could fail if, for example, the
+ ** current working directory has been unlinked.
+ */
+ SimulateIOError( return SQLITE_ERROR );
+ if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
+ /*
+ ** NOTE: We are dealing with a relative path name and the data
+ ** directory has been set. Therefore, use it as the basis
+ ** for converting the relative path name to an absolute
+ ** one by prepending the data directory and a backslash.
+ */
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
+ sqlite3_data_directory, zRelative);
+ return SQLITE_OK;
+ }
+ zConverted = convertUtf8Filename(zRelative);
+ if( zConverted==0 ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( isNT() ){
+ LPWSTR zTemp;
+ nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameW1", zConverted);
+ sqlite3_free(zConverted);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
+ nByte += 3;
+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+ if( zTemp==0 ){
+ sqlite3_free(zConverted);
+ return SQLITE_IOERR_NOMEM;
+ }
+ nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameW2", zConverted);
+ sqlite3_free(zConverted);
+ sqlite3_free(zTemp);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
+ sqlite3_free(zConverted);
+ zOut = unicodeToUtf8(zTemp);
+ sqlite3_free(zTemp);
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ char *zTemp;
+ nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameA1", zConverted);
+ sqlite3_free(zConverted);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
+ nByte += 3;
+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+ if( zTemp==0 ){
+ sqlite3_free(zConverted);
+ return SQLITE_IOERR_NOMEM;
+ }
+ nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameA2", zConverted);
+ sqlite3_free(zConverted);
+ sqlite3_free(zTemp);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
+ sqlite3_free(zConverted);
+ zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
+ sqlite3_free(zTemp);
+ }
+#endif
+ if( zOut ){
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+ sqlite3_free(zOut);
+ return SQLITE_OK;
+ }else{
+ return SQLITE_IOERR_NOMEM;
+ }
+#endif
+}
+
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+/*
+** Interfaces for opening a shared library, finding entry points
+** within the shared library, and closing the shared library.
+*/
+/*
+** Interfaces for opening a shared library, finding entry points
+** within the shared library, and closing the shared library.
+*/
+static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
+ HANDLE h;
+ void *zConverted = convertUtf8Filename(zFilename);
+ UNUSED_PARAMETER(pVfs);
+ if( zConverted==0 ){
+ return 0;
+ }
+ if( isNT() ){
+#if SQLITE_OS_WINRT
+ h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
+#else
+ h = osLoadLibraryW((LPCWSTR)zConverted);
+#endif
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ h = osLoadLibraryA((char*)zConverted);
+ }
+#endif
+ sqlite3_free(zConverted);
+ return (void*)h;
+}
+static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
+ UNUSED_PARAMETER(pVfs);
+ getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
+}
+static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
+ UNUSED_PARAMETER(pVfs);
+ return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
+}
+static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
+ UNUSED_PARAMETER(pVfs);
+ osFreeLibrary((HANDLE)pHandle);
+}
+#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
+ #define winDlOpen 0
+ #define winDlError 0
+ #define winDlSym 0
+ #define winDlClose 0
+#endif
+
+
+/*
+** Write up to nBuf bytes of randomness into zBuf.
+*/
+static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+ int n = 0;
+ UNUSED_PARAMETER(pVfs);
+#if defined(SQLITE_TEST)
+ n = nBuf;
+ memset(zBuf, 0, nBuf);
+#else
+ if( sizeof(SYSTEMTIME)<=nBuf-n ){
+ SYSTEMTIME x;
+ osGetSystemTime(&x);
+ memcpy(&zBuf[n], &x, sizeof(x));
+ n += sizeof(x);
+ }
+ if( sizeof(DWORD)<=nBuf-n ){
+ DWORD pid = osGetCurrentProcessId();
+ memcpy(&zBuf[n], &pid, sizeof(pid));
+ n += sizeof(pid);
+ }
+#if SQLITE_OS_WINRT
+ if( sizeof(ULONGLONG)<=nBuf-n ){
+ ULONGLONG cnt = osGetTickCount64();
+ memcpy(&zBuf[n], &cnt, sizeof(cnt));
+ n += sizeof(cnt);
+ }
+#else
+ if( sizeof(DWORD)<=nBuf-n ){
+ DWORD cnt = osGetTickCount();
+ memcpy(&zBuf[n], &cnt, sizeof(cnt));
+ n += sizeof(cnt);
+ }
+#endif
+ if( sizeof(LARGE_INTEGER)<=nBuf-n ){
+ LARGE_INTEGER i;
+ osQueryPerformanceCounter(&i);
+ memcpy(&zBuf[n], &i, sizeof(i));
+ n += sizeof(i);
+ }
+#endif
+ return n;
+}
+
+
+/*
+** Sleep for a little while. Return the amount of time slept.
+*/
+static int winSleep(sqlite3_vfs *pVfs, int microsec){
+ sqlite3_win32_sleep((microsec+999)/1000);
+ UNUSED_PARAMETER(pVfs);
+ return ((microsec+999)/1000)*1000;
+}
+
+/*
+** The following variable, if set to a non-zero value, is interpreted as
+** the number of seconds since 1970 and is used to set the result of
+** sqlite3OsCurrentTime() during testing.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
+#endif
+
+/*
+** Find the current time (in Universal Coordinated Time). Write into *piNow
+** the current time and date as a Julian Day number times 86_400_000. In
+** other words, write into *piNow the number of milliseconds since the Julian
+** epoch of noon in Greenwich on November 24, 4714 B.C according to the
+** proleptic Gregorian calendar.
+**
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
+** cannot be found.
+*/
+static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
+ /* FILETIME structure is a 64-bit value representing the number of
+ 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
+ */
+ FILETIME ft;
+ static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
+#ifdef SQLITE_TEST
+ static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
+#endif
+ /* 2^32 - to avoid use of LL and warnings in gcc */
+ static const sqlite3_int64 max32BitValue =
+ (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
+ (sqlite3_int64)294967296;
+
+#if SQLITE_OS_WINCE
+ SYSTEMTIME time;
+ osGetSystemTime(&time);
+ /* if SystemTimeToFileTime() fails, it returns zero. */
+ if (!osSystemTimeToFileTime(&time,&ft)){
+ return SQLITE_ERROR;
+ }
+#else
+ osGetSystemTimeAsFileTime( &ft );
+#endif
+
+ *piNow = winFiletimeEpoch +
+ ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
+ (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
+
+#ifdef SQLITE_TEST
+ if( sqlite3_current_time ){
+ *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
+ }
+#endif
+ UNUSED_PARAMETER(pVfs);
+ return SQLITE_OK;
+}
+
+/*
+** Find the current time (in Universal Coordinated Time). Write the
+** current time and date as a Julian Day number into *prNow and
+** return 0. Return 1 if the time and date cannot be found.
+*/
+static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
+ int rc;
+ sqlite3_int64 i;
+ rc = winCurrentTimeInt64(pVfs, &i);
+ if( !rc ){
+ *prNow = i/86400000.0;
+ }
+ return rc;
+}
+
+/*
+** The idea is that this function works like a combination of
+** GetLastError() and FormatMessage() on Windows (or errno and
+** strerror_r() on Unix). After an error is returned by an OS
+** function, SQLite calls this function with zBuf pointing to
+** a buffer of nBuf bytes. The OS layer should populate the
+** buffer with a nul-terminated UTF-8 encoded error message
+** describing the last IO error to have occurred within the calling
+** thread.
+**
+** If the error message is too large for the supplied buffer,
+** it should be truncated. The return value of xGetLastError
+** is zero if the error message fits in the buffer, or non-zero
+** otherwise (if the message was truncated). If non-zero is returned,
+** then it is not necessary to include the nul-terminator character
+** in the output buffer.
+**
+** Not supplying an error message will have no adverse effect
+** on SQLite. It is fine to have an implementation that never
+** returns an error message:
+**
+** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+** assert(zBuf[0]=='\0');
+** return 0;
+** }
+**
+** However if an error message is supplied, it will be incorporated
+** by sqlite into the error message available to the user using
+** sqlite3_errmsg(), possibly making IO errors easier to debug.
+*/
+static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+ UNUSED_PARAMETER(pVfs);
+ return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
+}
+
+/*
+** Initialize and deinitialize the operating system interface.
+*/
+SQLITE_API int sqlite3_os_init(void){
+ static sqlite3_vfs winVfs = {
+ 3, /* iVersion */
+ sizeof(winFile), /* szOsFile */
+ MAX_PATH, /* mxPathname */
+ 0, /* pNext */
+ "win32", /* zName */
+ 0, /* pAppData */
+ winOpen, /* xOpen */
+ winDelete, /* xDelete */
+ winAccess, /* xAccess */
+ winFullPathname, /* xFullPathname */
+ winDlOpen, /* xDlOpen */
+ winDlError, /* xDlError */
+ winDlSym, /* xDlSym */
+ winDlClose, /* xDlClose */
+ winRandomness, /* xRandomness */
+ winSleep, /* xSleep */
+ winCurrentTime, /* xCurrentTime */
+ winGetLastError, /* xGetLastError */
+ winCurrentTimeInt64, /* xCurrentTimeInt64 */
+ winSetSystemCall, /* xSetSystemCall */
+ winGetSystemCall, /* xGetSystemCall */
+ winNextSystemCall, /* xNextSystemCall */
+ };
+
+ /* Double-check that the aSyscall[] array has been constructed
+ ** correctly. See ticket [bb3a86e890c8e96ab] */
+ assert( ArraySize(aSyscall)==74 );
+
+#ifndef SQLITE_OMIT_WAL
+ /* get memory map allocation granularity */
+ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
+#if SQLITE_OS_WINRT
+ osGetNativeSystemInfo(&winSysInfo);
+#else
+ osGetSystemInfo(&winSysInfo);
+#endif
+ assert(winSysInfo.dwAllocationGranularity > 0);
+#endif
+
+ sqlite3_vfs_register(&winVfs, 1);
+ return SQLITE_OK;
+}
+
+SQLITE_API int sqlite3_os_end(void){
+#if SQLITE_OS_WINRT
+ if( sleepObj!=NULL ){
+ osCloseHandle(sleepObj);
+ sleepObj = NULL;
+ }
+#endif
+ return SQLITE_OK;
+}
+
+#endif /* SQLITE_OS_WIN */
+
+/************** End of os_win.c **********************************************/
+/************** Begin file bitvec.c ******************************************/
+/*
+** 2008 February 16
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements an object that represents a fixed-length
+** bitmap. Bits are numbered starting with 1.
+**
+** A bitmap is used to record which pages of a database file have been
+** journalled during a transaction, or which pages have the "dont-write"
+** property. Usually only a few pages are meet either condition.
+** So the bitmap is usually sparse and has low cardinality.
+** But sometimes (for example when during a DROP of a large table) most
+** or all of the pages in a database can get journalled. In those cases,
+** the bitmap becomes dense with high cardinality. The algorithm needs
+** to handle both cases well.
+**
+** The size of the bitmap is fixed when the object is created.
+**
+** All bits are clear when the bitmap is created. Individual bits
+** may be set or cleared one at a time.
+**
+** Test operations are about 100 times more common that set operations.
+** Clear operations are exceedingly rare. There are usually between
+** 5 and 500 set operations per Bitvec object, though the number of sets can
+** sometimes grow into tens of thousands or larger. The size of the
+** Bitvec object is the number of pages in the database file at the
+** start of a transaction, and is thus usually less than a few thousand,
+** but can be as large as 2 billion for a really big database.
+*/
+
+/* Size of the Bitvec structure in bytes. */
+#define BITVEC_SZ 512
+
+/* Round the union size down to the nearest pointer boundary, since that's how
+** it will be aligned within the Bitvec struct. */
+#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
+
+/* Type of the array "element" for the bitmap representation.
+** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
+** Setting this to the "natural word" size of your CPU may improve
+** performance. */
+#define BITVEC_TELEM u8
+/* Size, in bits, of the bitmap element. */
+#define BITVEC_SZELEM 8
+/* Number of elements in a bitmap array. */
+#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM))
+/* Number of bits in the bitmap array. */
+#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM)
+
+/* Number of u32 values in hash table. */
+#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
+/* Maximum number of entries in hash table before
+** sub-dividing and re-hashing. */
+#define BITVEC_MXHASH (BITVEC_NINT/2)
+/* Hashing function for the aHash representation.
+** Empirical testing showed that the *37 multiplier
+** (an arbitrary prime)in the hash function provided
+** no fewer collisions than the no-op *1. */
+#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
+
+#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
+
+
+/*
+** A bitmap is an instance of the following structure.
+**
+** This bitmap records the existence of zero or more bits
+** with values between 1 and iSize, inclusive.
+**
+** There are three possible representations of the bitmap.
+** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
+** bitmap. The least significant bit is bit 1.
+**
+** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
+** a hash table that will hold up to BITVEC_MXHASH distinct values.
+**
+** Otherwise, the value i is redirected into one of BITVEC_NPTR
+** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
+** handles up to iDivisor separate values of i. apSub[0] holds
+** values between 1 and iDivisor. apSub[1] holds values between
+** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
+** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
+** to hold deal with values between 1 and iDivisor.
+*/
+struct Bitvec {
+ u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */
+ u32 nSet; /* Number of bits that are set - only valid for aHash
+ ** element. Max is BITVEC_NINT. For BITVEC_SZ of 512,
+ ** this would be 125. */
+ u32 iDivisor; /* Number of bits handled by each apSub[] entry. */
+ /* Should >=0 for apSub element. */
+ /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */
+ /* For a BITVEC_SZ of 512, this would be 34,359,739. */
+ union {
+ BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */
+ u32 aHash[BITVEC_NINT]; /* Hash table representation */
+ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
+ } u;
+};
+
+/*
+** Create a new bitmap object able to handle bits between 0 and iSize,
+** inclusive. Return a pointer to the new object. Return NULL if
+** malloc fails.
+*/
+SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
+ Bitvec *p;
+ assert( sizeof(*p)==BITVEC_SZ );
+ p = sqlite3MallocZero( sizeof(*p) );
+ if( p ){
+ p->iSize = iSize;
+ }
+ return p;
+}
+
+/*
+** Check to see if the i-th bit is set. Return true or false.
+** If p is NULL (if the bitmap has not been created) or if
+** i is out of range, then return false.
+*/
+SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
+ if( p==0 ) return 0;
+ if( i>p->iSize || i==0 ) return 0;
+ i--;
+ while( p->iDivisor ){
+ u32 bin = i/p->iDivisor;
+ i = i%p->iDivisor;
+ p = p->u.apSub[bin];
+ if (!p) {
+ return 0;
+ }
+ }
+ if( p->iSize<=BITVEC_NBIT ){
+ return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
+ } else{
+ u32 h = BITVEC_HASH(i++);
+ while( p->u.aHash[h] ){
+ if( p->u.aHash[h]==i ) return 1;
+ h = (h+1) % BITVEC_NINT;
+ }
+ return 0;
+ }
+}
+
+/*
+** Set the i-th bit. Return 0 on success and an error code if
+** anything goes wrong.
+**
+** This routine might cause sub-bitmaps to be allocated. Failing
+** to get the memory needed to hold the sub-bitmap is the only
+** that can go wrong with an insert, assuming p and i are valid.
+**
+** The calling function must ensure that p is a valid Bitvec object
+** and that the value for "i" is within range of the Bitvec object.
+** Otherwise the behavior is undefined.
+*/
+SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
+ u32 h;
+ if( p==0 ) return SQLITE_OK;
+ assert( i>0 );
+ assert( i<=p->iSize );
+ i--;
+ while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
+ u32 bin = i/p->iDivisor;
+ i = i%p->iDivisor;
+ if( p->u.apSub[bin]==0 ){
+ p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
+ if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
+ }
+ p = p->u.apSub[bin];
+ }
+ if( p->iSize<=BITVEC_NBIT ){
+ p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
+ return SQLITE_OK;
+ }
+ h = BITVEC_HASH(i++);
+ /* if there wasn't a hash collision, and this doesn't */
+ /* completely fill the hash, then just add it without */
+ /* worring about sub-dividing and re-hashing. */
+ if( !p->u.aHash[h] ){
+ if (p->nSet<(BITVEC_NINT-1)) {
+ goto bitvec_set_end;
+ } else {
+ goto bitvec_set_rehash;
+ }
+ }
+ /* there was a collision, check to see if it's already */
+ /* in hash, if not, try to find a spot for it */
+ do {
+ if( p->u.aHash[h]==i ) return SQLITE_OK;
+ h++;
+ if( h>=BITVEC_NINT ) h = 0;
+ } while( p->u.aHash[h] );
+ /* we didn't find it in the hash. h points to the first */
+ /* available free spot. check to see if this is going to */
+ /* make our hash too "full". */
+bitvec_set_rehash:
+ if( p->nSet>=BITVEC_MXHASH ){
+ unsigned int j;
+ int rc;
+ u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
+ if( aiValues==0 ){
+ return SQLITE_NOMEM;
+ }else{
+ memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
+ memset(p->u.apSub, 0, sizeof(p->u.apSub));
+ p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
+ rc = sqlite3BitvecSet(p, i);
+ for(j=0; j<BITVEC_NINT; j++){
+ if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
+ }
+ sqlite3StackFree(0, aiValues);
+ return rc;
+ }
+ }
+bitvec_set_end:
+ p->nSet++;
+ p->u.aHash[h] = i;
+ return SQLITE_OK;
+}
+
+/*
+** Clear the i-th bit.
+**
+** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage
+** that BitvecClear can use to rebuilt its hash table.
+*/
+SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
+ if( p==0 ) return;
+ assert( i>0 );
+ i--;
+ while( p->iDivisor ){
+ u32 bin = i/p->iDivisor;
+ i = i%p->iDivisor;
+ p = p->u.apSub[bin];
+ if (!p) {
+ return;
+ }
+ }
+ if( p->iSize<=BITVEC_NBIT ){
+ p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
+ }else{
+ unsigned int j;
+ u32 *aiValues = pBuf;
+ memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
+ memset(p->u.aHash, 0, sizeof(p->u.aHash));
+ p->nSet = 0;
+ for(j=0; j<BITVEC_NINT; j++){
+ if( aiValues[j] && aiValues[j]!=(i+1) ){
+ u32 h = BITVEC_HASH(aiValues[j]-1);
+ p->nSet++;
+ while( p->u.aHash[h] ){
+ h++;
+ if( h>=BITVEC_NINT ) h = 0;
+ }
+ p->u.aHash[h] = aiValues[j];
+ }
+ }
+ }
+}
+
+/*
+** Destroy a bitmap object. Reclaim all memory used.
+*/
+SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
+ if( p==0 ) return;
+ if( p->iDivisor ){
+ unsigned int i;
+ for(i=0; i<BITVEC_NPTR; i++){
+ sqlite3BitvecDestroy(p->u.apSub[i]);
+ }
+ }
+ sqlite3_free(p);
+}
+
+/*
+** Return the value of the iSize parameter specified when Bitvec *p
+** was created.
+*/
+SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
+ return p->iSize;
+}
+
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+/*
+** Let V[] be an array of unsigned characters sufficient to hold
+** up to N bits. Let I be an integer between 0 and N. 0<=I<N.
+** Then the following macros can be used to set, clear, or test
+** individual bits within V.
+*/
+#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
+#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
+#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
+
+/*
+** This routine runs an extensive test of the Bitvec code.
+**
+** The input is an array of integers that acts as a program
+** to test the Bitvec. The integers are opcodes followed
+** by 0, 1, or 3 operands, depending on the opcode. Another
+** opcode follows immediately after the last operand.
+**
+** There are 6 opcodes numbered from 0 through 5. 0 is the
+** "halt" opcode and causes the test to end.
+**
+** 0 Halt and return the number of errors
+** 1 N S X Set N bits beginning with S and incrementing by X
+** 2 N S X Clear N bits beginning with S and incrementing by X
+** 3 N Set N randomly chosen bits
+** 4 N Clear N randomly chosen bits
+** 5 N S X Set N bits from S increment X in array only, not in bitvec
+**
+** The opcodes 1 through 4 perform set and clear operations are performed
+** on both a Bitvec object and on a linear array of bits obtained from malloc.
+** Opcode 5 works on the linear array only, not on the Bitvec.
+** Opcode 5 is used to deliberately induce a fault in order to
+** confirm that error detection works.
+**
+** At the conclusion of the test the linear array is compared
+** against the Bitvec object. If there are any differences,
+** an error is returned. If they are the same, zero is returned.
+**
+** If a memory allocation error occurs, return -1.
+*/
+SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
+ Bitvec *pBitvec = 0;
+ unsigned char *pV = 0;
+ int rc = -1;
+ int i, nx, pc, op;
+ void *pTmpSpace;
+
+ /* Allocate the Bitvec to be tested and a linear array of
+ ** bits to act as the reference */
+ pBitvec = sqlite3BitvecCreate( sz );
+ pV = sqlite3MallocZero( (sz+7)/8 + 1 );
+ pTmpSpace = sqlite3_malloc(BITVEC_SZ);
+ if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
+
+ /* NULL pBitvec tests */
+ sqlite3BitvecSet(0, 1);
+ sqlite3BitvecClear(0, 1, pTmpSpace);
+
+ /* Run the program */
+ pc = 0;
+ while( (op = aOp[pc])!=0 ){
+ switch( op ){
+ case 1:
+ case 2:
+ case 5: {
+ nx = 4;
+ i = aOp[pc+2] - 1;
+ aOp[pc+2] += aOp[pc+3];
+ break;
+ }
+ case 3:
+ case 4:
+ default: {
+ nx = 2;
+ sqlite3_randomness(sizeof(i), &i);
+ break;
+ }
+ }
+ if( (--aOp[pc+1]) > 0 ) nx = 0;
+ pc += nx;
+ i = (i & 0x7fffffff)%sz;
+ if( (op & 1)!=0 ){
+ SETBIT(pV, (i+1));
+ if( op!=5 ){
+ if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
+ }
+ }else{
+ CLEARBIT(pV, (i+1));
+ sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
+ }
+ }
+
+ /* Test to make sure the linear array exactly matches the
+ ** Bitvec object. Start with the assumption that they do
+ ** match (rc==0). Change rc to non-zero if a discrepancy
+ ** is found.
+ */
+ rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ + sqlite3BitvecTest(pBitvec, 0)
+ + (sqlite3BitvecSize(pBitvec) - sz);
+ for(i=1; i<=sz; i++){
+ if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
+ rc = i;
+ break;
+ }
+ }
+
+ /* Free allocated structure */
+bitvec_end:
+ sqlite3_free(pTmpSpace);
+ sqlite3_free(pV);
+ sqlite3BitvecDestroy(pBitvec);
+ return rc;
+}
+#endif /* SQLITE_OMIT_BUILTIN_TEST */
+
+/************** End of bitvec.c **********************************************/
+/************** Begin file pcache.c ******************************************/
+/*
+** 2008 August 05
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements that page cache.
+*/
+
+/*
+** A complete page cache is an instance of this structure.
+*/
+struct PCache {
+ PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
+ PgHdr *pSynced; /* Last synced page in dirty page list */
+ int nRef; /* Number of referenced pages */
+ int szCache; /* Configured cache size */
+ int szPage; /* Size of every page in this cache */
+ int szExtra; /* Size of extra space for each page */
+ int bPurgeable; /* True if pages are on backing store */
+ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
+ void *pStress; /* Argument to xStress */
+ sqlite3_pcache *pCache; /* Pluggable cache module */
+ PgHdr *pPage1; /* Reference to page 1 */
+};
+
+/*
+** Some of the assert() macros in this code are too expensive to run
+** even during normal debugging. Use them only rarely on long-running
+** tests. Enable the expensive asserts using the
+** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
+*/
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+# define expensive_assert(X) assert(X)
+#else
+# define expensive_assert(X)
+#endif
+
+/********************************** Linked List Management ********************/
+
+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
+/*
+** Check that the pCache->pSynced variable is set correctly. If it
+** is not, either fail an assert or return zero. Otherwise, return
+** non-zero. This is only used in debugging builds, as follows:
+**
+** expensive_assert( pcacheCheckSynced(pCache) );
+*/
+static int pcacheCheckSynced(PCache *pCache){
+ PgHdr *p;
+ for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
+ assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
+ }
+ return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
+}
+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
+
+/*
+** Remove page pPage from the list of dirty pages.
+*/
+static void pcacheRemoveFromDirtyList(PgHdr *pPage){
+ PCache *p = pPage->pCache;
+
+ assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
+ assert( pPage->pDirtyPrev || pPage==p->pDirty );
+
+ /* Update the PCache1.pSynced variable if necessary. */
+ if( p->pSynced==pPage ){
+ PgHdr *pSynced = pPage->pDirtyPrev;
+ while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
+ pSynced = pSynced->pDirtyPrev;
+ }
+ p->pSynced = pSynced;
+ }
+
+ if( pPage->pDirtyNext ){
+ pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
+ }else{
+ assert( pPage==p->pDirtyTail );
+ p->pDirtyTail = pPage->pDirtyPrev;
+ }
+ if( pPage->pDirtyPrev ){
+ pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
+ }else{
+ assert( pPage==p->pDirty );
+ p->pDirty = pPage->pDirtyNext;
+ }
+ pPage->pDirtyNext = 0;
+ pPage->pDirtyPrev = 0;
+
+ expensive_assert( pcacheCheckSynced(p) );
+}
+
+/*
+** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
+** pPage).
+*/
+static void pcacheAddToDirtyList(PgHdr *pPage){
+ PCache *p = pPage->pCache;
+
+ assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
+
+ pPage->pDirtyNext = p->pDirty;
+ if( pPage->pDirtyNext ){
+ assert( pPage->pDirtyNext->pDirtyPrev==0 );
+ pPage->pDirtyNext->pDirtyPrev = pPage;
+ }
+ p->pDirty = pPage;
+ if( !p->pDirtyTail ){
+ p->pDirtyTail = pPage;
+ }
+ if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
+ p->pSynced = pPage;
+ }
+ expensive_assert( pcacheCheckSynced(p) );
+}
+
+/*
+** Wrapper around the pluggable caches xUnpin method. If the cache is
+** being used for an in-memory database, this function is a no-op.
+*/
+static void pcacheUnpin(PgHdr *p){
+ PCache *pCache = p->pCache;
+ if( pCache->bPurgeable ){
+ if( p->pgno==1 ){
+ pCache->pPage1 = 0;
+ }
+ sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
+ }
+}
+
+/*************************************************** General Interfaces ******
+**
+** Initialize and shutdown the page cache subsystem. Neither of these
+** functions are threadsafe.
+*/
+SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
+ if( sqlite3GlobalConfig.pcache2.xInit==0 ){
+ /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
+ ** built-in default page cache is used instead of the application defined
+ ** page cache. */
+ sqlite3PCacheSetDefault();
+ }
+ return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
+}
+SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
+ if( sqlite3GlobalConfig.pcache2.xShutdown ){
+ /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
+ sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
+ }
+}
+
+/*
+** Return the size in bytes of a PCache object.
+*/
+SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
+
+/*
+** Create a new PCache object. Storage space to hold the object
+** has already been allocated and is passed in as the p pointer.
+** The caller discovers how much space needs to be allocated by
+** calling sqlite3PcacheSize().
+*/
+SQLITE_PRIVATE void sqlite3PcacheOpen(
+ int szPage, /* Size of every page */
+ int szExtra, /* Extra space associated with each page */
+ int bPurgeable, /* True if pages are on backing store */
+ int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
+ void *pStress, /* Argument to xStress */
+ PCache *p /* Preallocated space for the PCache */
+){
+ memset(p, 0, sizeof(PCache));
+ p->szPage = szPage;
+ p->szExtra = szExtra;
+ p->bPurgeable = bPurgeable;
+ p->xStress = xStress;
+ p->pStress = pStress;
+ p->szCache = 100;
+}
+
+/*
+** Change the page size for PCache object. The caller must ensure that there
+** are no outstanding page references when this function is called.
+*/
+SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
+ assert( pCache->nRef==0 && pCache->pDirty==0 );
+ if( pCache->pCache ){
+ sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
+ pCache->pCache = 0;
+ pCache->pPage1 = 0;
+ }
+ pCache->szPage = szPage;
+}
+
+/*
+** Compute the number of pages of cache requested.
+*/
+static int numberOfCachePages(PCache *p){
+ if( p->szCache>=0 ){
+ return p->szCache;
+ }else{
+ return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
+ }
+}
+
+/*
+** Try to obtain a page from the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcacheFetch(
+ PCache *pCache, /* Obtain the page from this cache */
+ Pgno pgno, /* Page number to obtain */
+ int createFlag, /* If true, create page if it does not exist already */
+ PgHdr **ppPage /* Write the page here */
+){
+ sqlite3_pcache_page *pPage = 0;
+ PgHdr *pPgHdr = 0;
+ int eCreate;
+
+ assert( pCache!=0 );
+ assert( createFlag==1 || createFlag==0 );
+ assert( pgno>0 );
+
+ /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
+ ** allocate it now.
+ */
+ if( !pCache->pCache && createFlag ){
+ sqlite3_pcache *p;
+ p = sqlite3GlobalConfig.pcache2.xCreate(
+ pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
+ );
+ if( !p ){
+ return SQLITE_NOMEM;
+ }
+ sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
+ pCache->pCache = p;
+ }
+
+ eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
+ if( pCache->pCache ){
+ pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
+ }
+
+ if( !pPage && eCreate==1 ){
+ PgHdr *pPg;
+
+ /* Find a dirty page to write-out and recycle. First try to find a
+ ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
+ ** cleared), but if that is not possible settle for any other
+ ** unreferenced dirty page.
+ */
+ expensive_assert( pcacheCheckSynced(pCache) );
+ for(pPg=pCache->pSynced;
+ pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
+ pPg=pPg->pDirtyPrev
+ );
+ pCache->pSynced = pPg;
+ if( !pPg ){
+ for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
+ }
+ if( pPg ){
+ int rc;
+#ifdef SQLITE_LOG_CACHE_SPILL
+ sqlite3_log(SQLITE_FULL,
+ "spill page %d making room for %d - cache used: %d/%d",
+ pPg->pgno, pgno,
+ sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
+ numberOfCachePages(pCache));
+#endif
+ rc = pCache->xStress(pCache->pStress, pPg);
+ if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+
+ pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
+ }
+
+ if( pPage ){
+ pPgHdr = (PgHdr *)pPage->pExtra;
+
+ if( !pPgHdr->pPage ){
+ memset(pPgHdr, 0, sizeof(PgHdr));
+ pPgHdr->pPage = pPage;
+ pPgHdr->pData = pPage->pBuf;
+ pPgHdr->pExtra = (void *)&pPgHdr[1];
+ memset(pPgHdr->pExtra, 0, pCache->szExtra);
+ pPgHdr->pCache = pCache;
+ pPgHdr->pgno = pgno;
+ }
+ assert( pPgHdr->pCache==pCache );
+ assert( pPgHdr->pgno==pgno );
+ assert( pPgHdr->pData==pPage->pBuf );
+ assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
+
+ if( 0==pPgHdr->nRef ){
+ pCache->nRef++;
+ }
+ pPgHdr->nRef++;
+ if( pgno==1 ){
+ pCache->pPage1 = pPgHdr;
+ }
+ }
+ *ppPage = pPgHdr;
+ return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
+}
+
+/*
+** Decrement the reference count on a page. If the page is clean and the
+** reference count drops to 0, then it is made elible for recycling.
+*/
+SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
+ assert( p->nRef>0 );
+ p->nRef--;
+ if( p->nRef==0 ){
+ PCache *pCache = p->pCache;
+ pCache->nRef--;
+ if( (p->flags&PGHDR_DIRTY)==0 ){
+ pcacheUnpin(p);
+ }else{
+ /* Move the page to the head of the dirty list. */
+ pcacheRemoveFromDirtyList(p);
+ pcacheAddToDirtyList(p);
+ }
+ }
+}
+
+/*
+** Increase the reference count of a supplied page by 1.
+*/
+SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
+ assert(p->nRef>0);
+ p->nRef++;
+}
+
+/*
+** Drop a page from the cache. There must be exactly one reference to the
+** page. This function deletes that reference, so after it returns the
+** page pointed to by p is invalid.
+*/
+SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
+ PCache *pCache;
+ assert( p->nRef==1 );
+ if( p->flags&PGHDR_DIRTY ){
+ pcacheRemoveFromDirtyList(p);
+ }
+ pCache = p->pCache;
+ pCache->nRef--;
+ if( p->pgno==1 ){
+ pCache->pPage1 = 0;
+ }
+ sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
+}
+
+/*
+** Make sure the page is marked as dirty. If it isn't dirty already,
+** make it so.
+*/
+SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
+ p->flags &= ~PGHDR_DONT_WRITE;
+ assert( p->nRef>0 );
+ if( 0==(p->flags & PGHDR_DIRTY) ){
+ p->flags |= PGHDR_DIRTY;
+ pcacheAddToDirtyList( p);
+ }
+}
+
+/*
+** Make sure the page is marked as clean. If it isn't clean already,
+** make it so.
+*/
+SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
+ if( (p->flags & PGHDR_DIRTY) ){
+ pcacheRemoveFromDirtyList(p);
+ p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
+ if( p->nRef==0 ){
+ pcacheUnpin(p);
+ }
+ }
+}
+
+/*
+** Make every page in the cache clean.
+*/
+SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
+ PgHdr *p;
+ while( (p = pCache->pDirty)!=0 ){
+ sqlite3PcacheMakeClean(p);
+ }
+}
+
+/*
+** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
+*/
+SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
+ PgHdr *p;
+ for(p=pCache->pDirty; p; p=p->pDirtyNext){
+ p->flags &= ~PGHDR_NEED_SYNC;
+ }
+ pCache->pSynced = pCache->pDirtyTail;
+}
+
+/*
+** Change the page number of page p to newPgno.
+*/
+SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
+ PCache *pCache = p->pCache;
+ assert( p->nRef>0 );
+ assert( newPgno>0 );
+ sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
+ p->pgno = newPgno;
+ if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
+ pcacheRemoveFromDirtyList(p);
+ pcacheAddToDirtyList(p);
+ }
+}
+
+/*
+** Drop every cache entry whose page number is greater than "pgno". The
+** caller must ensure that there are no outstanding references to any pages
+** other than page 1 with a page number greater than pgno.
+**
+** If there is a reference to page 1 and the pgno parameter passed to this
+** function is 0, then the data area associated with page 1 is zeroed, but
+** the page object is not dropped.
+*/
+SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
+ if( pCache->pCache ){
+ PgHdr *p;
+ PgHdr *pNext;
+ for(p=pCache->pDirty; p; p=pNext){
+ pNext = p->pDirtyNext;
+ /* This routine never gets call with a positive pgno except right
+ ** after sqlite3PcacheCleanAll(). So if there are dirty pages,
+ ** it must be that pgno==0.
+ */
+ assert( p->pgno>0 );
+ if( ALWAYS(p->pgno>pgno) ){
+ assert( p->flags&PGHDR_DIRTY );
+ sqlite3PcacheMakeClean(p);
+ }
+ }
+ if( pgno==0 && pCache->pPage1 ){
+ memset(pCache->pPage1->pData, 0, pCache->szPage);
+ pgno = 1;
+ }
+ sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
+ }
+}
+
+/*
+** Close a cache.
+*/
+SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
+ if( pCache->pCache ){
+ sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
+ }
+}
+
+/*
+** Discard the contents of the cache.
+*/
+SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
+ sqlite3PcacheTruncate(pCache, 0);
+}
+
+/*
+** Merge two lists of pages connected by pDirty and in pgno order.
+** Do not both fixing the pDirtyPrev pointers.
+*/
+static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
+ PgHdr result, *pTail;
+ pTail = &result;
+ while( pA && pB ){
+ if( pA->pgno<pB->pgno ){
+ pTail->pDirty = pA;
+ pTail = pA;
+ pA = pA->pDirty;
+ }else{
+ pTail->pDirty = pB;
+ pTail = pB;
+ pB = pB->pDirty;
+ }
+ }
+ if( pA ){
+ pTail->pDirty = pA;
+ }else if( pB ){
+ pTail->pDirty = pB;
+ }else{
+ pTail->pDirty = 0;
+ }
+ return result.pDirty;
+}
+
+/*
+** Sort the list of pages in accending order by pgno. Pages are
+** connected by pDirty pointers. The pDirtyPrev pointers are
+** corrupted by this sort.
+**
+** Since there cannot be more than 2^31 distinct pages in a database,
+** there cannot be more than 31 buckets required by the merge sorter.
+** One extra bucket is added to catch overflow in case something
+** ever changes to make the previous sentence incorrect.
+*/
+#define N_SORT_BUCKET 32
+static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
+ PgHdr *a[N_SORT_BUCKET], *p;
+ int i;
+ memset(a, 0, sizeof(a));
+ while( pIn ){
+ p = pIn;
+ pIn = p->pDirty;
+ p->pDirty = 0;
+ for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
+ if( a[i]==0 ){
+ a[i] = p;
+ break;
+ }else{
+ p = pcacheMergeDirtyList(a[i], p);
+ a[i] = 0;
+ }
+ }
+ if( NEVER(i==N_SORT_BUCKET-1) ){
+ /* To get here, there need to be 2^(N_SORT_BUCKET) elements in
+ ** the input list. But that is impossible.
+ */
+ a[i] = pcacheMergeDirtyList(a[i], p);
+ }
+ }
+ p = a[0];
+ for(i=1; i<N_SORT_BUCKET; i++){
+ p = pcacheMergeDirtyList(p, a[i]);
+ }
+ return p;
+}
+
+/*
+** Return a list of all dirty pages in the cache, sorted by page number.
+*/
+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
+ PgHdr *p;
+ for(p=pCache->pDirty; p; p=p->pDirtyNext){
+ p->pDirty = p->pDirtyNext;
+ }
+ return pcacheSortDirtyList(pCache->pDirty);
+}
+
+/*
+** Return the total number of referenced pages held by the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
+ return pCache->nRef;
+}
+
+/*
+** Return the number of references to the page supplied as an argument.
+*/
+SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
+ return p->nRef;
+}
+
+/*
+** Return the total number of pages in the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
+ int nPage = 0;
+ if( pCache->pCache ){
+ nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
+ }
+ return nPage;
+}
+
+#ifdef SQLITE_TEST
+/*
+** Get the suggested cache-size value.
+*/
+SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
+ return numberOfCachePages(pCache);
+}
+#endif
+
+/*
+** Set the suggested cache-size value.
+*/
+SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
+ pCache->szCache = mxPage;
+ if( pCache->pCache ){
+ sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
+ numberOfCachePages(pCache));
+ }
+}
+
+/*
+** Free up as much memory as possible from the page cache.
+*/
+SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){
+ if( pCache->pCache ){
+ sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
+ }
+}
+
+#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
+/*
+** For all dirty pages currently in the cache, invoke the specified
+** callback. This is only used if the SQLITE_CHECK_PAGES macro is
+** defined.
+*/
+SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
+ PgHdr *pDirty;
+ for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
+ xIter(pDirty);
+ }
+}
+#endif
+
+/************** End of pcache.c **********************************************/
+/************** Begin file pcache1.c *****************************************/
+/*
+** 2008 November 05
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements the default page cache implementation (the
+** sqlite3_pcache interface). It also contains part of the implementation
+** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
+** If the default page cache implementation is overriden, then neither of
+** these two features are available.
+*/
+
+
+typedef struct PCache1 PCache1;
+typedef struct PgHdr1 PgHdr1;
+typedef struct PgFreeslot PgFreeslot;
+typedef struct PGroup PGroup;
+
+/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
+** of one or more PCaches that are able to recycle each others unpinned
+** pages when they are under memory pressure. A PGroup is an instance of
+** the following object.
+**
+** This page cache implementation works in one of two modes:
+**
+** (1) Every PCache is the sole member of its own PGroup. There is
+** one PGroup per PCache.
+**
+** (2) There is a single global PGroup that all PCaches are a member
+** of.
+**
+** Mode 1 uses more memory (since PCache instances are not able to rob
+** unused pages from other PCaches) but it also operates without a mutex,
+** and is therefore often faster. Mode 2 requires a mutex in order to be
+** threadsafe, but recycles pages more efficiently.
+**
+** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single
+** PGroup which is the pcache1.grp global variable and its mutex is
+** SQLITE_MUTEX_STATIC_LRU.
+*/
+struct PGroup {
+ sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */
+ unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
+ unsigned int nMinPage; /* Sum of nMin for purgeable caches */
+ unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
+ unsigned int nCurrentPage; /* Number of purgeable pages allocated */
+ PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
+};
+
+/* Each page cache is an instance of the following object. Every
+** open database file (including each in-memory database and each
+** temporary or transient database) has a single page cache which
+** is an instance of this object.
+**
+** Pointers to structures of this type are cast and returned as
+** opaque sqlite3_pcache* handles.
+*/
+struct PCache1 {
+ /* Cache configuration parameters. Page size (szPage) and the purgeable
+ ** flag (bPurgeable) are set when the cache is created. nMax may be
+ ** modified at any time by a call to the pcache1Cachesize() method.
+ ** The PGroup mutex must be held when accessing nMax.
+ */
+ PGroup *pGroup; /* PGroup this cache belongs to */
+ int szPage; /* Size of allocated pages in bytes */
+ int szExtra; /* Size of extra space in bytes */
+ int bPurgeable; /* True if cache is purgeable */
+ unsigned int nMin; /* Minimum number of pages reserved */
+ unsigned int nMax; /* Configured "cache_size" value */
+ unsigned int n90pct; /* nMax*9/10 */
+ unsigned int iMaxKey; /* Largest key seen since xTruncate() */
+
+ /* Hash table of all pages. The following variables may only be accessed
+ ** when the accessor is holding the PGroup mutex.
+ */
+ unsigned int nRecyclable; /* Number of pages in the LRU list */
+ unsigned int nPage; /* Total number of pages in apHash */
+ unsigned int nHash; /* Number of slots in apHash[] */
+ PgHdr1 **apHash; /* Hash table for fast lookup by key */
+};
+
+/*
+** Each cache entry is represented by an instance of the following
+** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
+** PgHdr1.pCache->szPage bytes is allocated directly before this structure
+** in memory.
+*/
+struct PgHdr1 {
+ sqlite3_pcache_page page;
+ unsigned int iKey; /* Key value (page number) */
+ PgHdr1 *pNext; /* Next in hash table chain */
+ PCache1 *pCache; /* Cache that currently owns this page */
+ PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
+ PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
+};
+
+/*
+** Free slots in the allocator used to divide up the buffer provided using
+** the SQLITE_CONFIG_PAGECACHE mechanism.
+*/
+struct PgFreeslot {
+ PgFreeslot *pNext; /* Next free slot */
+};
+
+/*
+** Global data used by this cache.
+*/
+static SQLITE_WSD struct PCacheGlobal {
+ PGroup grp; /* The global PGroup for mode (2) */
+
+ /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The
+ ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all
+ ** fixed at sqlite3_initialize() time and do not require mutex protection.
+ ** The nFreeSlot and pFree values do require mutex protection.
+ */
+ int isInit; /* True if initialized */
+ int szSlot; /* Size of each free slot */
+ int nSlot; /* The number of pcache slots */
+ int nReserve; /* Try to keep nFreeSlot above this */
+ void *pStart, *pEnd; /* Bounds of pagecache malloc range */
+ /* Above requires no mutex. Use mutex below for variable that follow. */
+ sqlite3_mutex *mutex; /* Mutex for accessing the following: */
+ PgFreeslot *pFree; /* Free page blocks */
+ int nFreeSlot; /* Number of unused pcache slots */
+ /* The following value requires a mutex to change. We skip the mutex on
+ ** reading because (1) most platforms read a 32-bit integer atomically and
+ ** (2) even if an incorrect value is read, no great harm is done since this
+ ** is really just an optimization. */
+ int bUnderPressure; /* True if low on PAGECACHE memory */
+} pcache1_g;
+
+/*
+** All code in this file should access the global structure above via the
+** alias "pcache1". This ensures that the WSD emulation is used when
+** compiling for systems that do not support real WSD.
+*/
+#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
+
+/*
+** Macros to enter and leave the PCache LRU mutex.
+*/
+#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
+#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
+
+/******************************************************************************/
+/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
+
+/*
+** This function is called during initialization if a static buffer is
+** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
+** verb to sqlite3_config(). Parameter pBuf points to an allocation large
+** enough to contain 'n' buffers of 'sz' bytes each.
+**
+** This routine is called from sqlite3_initialize() and so it is guaranteed
+** to be serialized already. There is no need for further mutexing.
+*/
+SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
+ if( pcache1.isInit ){
+ PgFreeslot *p;
+ sz = ROUNDDOWN8(sz);
+ pcache1.szSlot = sz;
+ pcache1.nSlot = pcache1.nFreeSlot = n;
+ pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
+ pcache1.pStart = pBuf;
+ pcache1.pFree = 0;
+ pcache1.bUnderPressure = 0;
+ while( n-- ){
+ p = (PgFreeslot*)pBuf;
+ p->pNext = pcache1.pFree;
+ pcache1.pFree = p;
+ pBuf = (void*)&((char*)pBuf)[sz];
+ }
+ pcache1.pEnd = pBuf;
+ }
+}
+
+/*
+** Malloc function used within this file to allocate space from the buffer
+** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
+** such buffer exists or there is no space left in it, this function falls
+** back to sqlite3Malloc().
+**
+** Multiple threads can run this routine at the same time. Global variables
+** in pcache1 need to be protected via mutex.
+*/
+static void *pcache1Alloc(int nByte){
+ void *p = 0;
+ assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
+ sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
+ if( nByte<=pcache1.szSlot ){
+ sqlite3_mutex_enter(pcache1.mutex);
+ p = (PgHdr1 *)pcache1.pFree;
+ if( p ){
+ pcache1.pFree = pcache1.pFree->pNext;
+ pcache1.nFreeSlot--;
+ pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
+ assert( pcache1.nFreeSlot>=0 );
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
+ }
+ sqlite3_mutex_leave(pcache1.mutex);
+ }
+ if( p==0 ){
+ /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get
+ ** it from sqlite3Malloc instead.
+ */
+ p = sqlite3Malloc(nByte);
+#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+ if( p ){
+ int sz = sqlite3MallocSize(p);
+ sqlite3_mutex_enter(pcache1.mutex);
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
+ sqlite3_mutex_leave(pcache1.mutex);
+ }
+#endif
+ sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
+ }
+ return p;
+}
+
+/*
+** Free an allocated buffer obtained from pcache1Alloc().
+*/
+static int pcache1Free(void *p){
+ int nFreed = 0;
+ if( p==0 ) return 0;
+ if( p>=pcache1.pStart && p<pcache1.pEnd ){
+ PgFreeslot *pSlot;
+ sqlite3_mutex_enter(pcache1.mutex);
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
+ pSlot = (PgFreeslot*)p;
+ pSlot->pNext = pcache1.pFree;
+ pcache1.pFree = pSlot;
+ pcache1.nFreeSlot++;
+ pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
+ assert( pcache1.nFreeSlot<=pcache1.nSlot );
+ sqlite3_mutex_leave(pcache1.mutex);
+ }else{
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+ nFreed = sqlite3MallocSize(p);
+#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+ sqlite3_mutex_enter(pcache1.mutex);
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
+ sqlite3_mutex_leave(pcache1.mutex);
+#endif
+ sqlite3_free(p);
+ }
+ return nFreed;
+}
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/*
+** Return the size of a pcache allocation
+*/
+static int pcache1MemSize(void *p){
+ if( p>=pcache1.pStart && p<pcache1.pEnd ){
+ return pcache1.szSlot;
+ }else{
+ int iSize;
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+ iSize = sqlite3MallocSize(p);
+ sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
+ return iSize;
+ }
+}
+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+
+/*
+** Allocate a new page object initially associated with cache pCache.
+*/
+static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
+ PgHdr1 *p = 0;
+ void *pPg;
+
+ /* The group mutex must be released before pcache1Alloc() is called. This
+ ** is because it may call sqlite3_release_memory(), which assumes that
+ ** this mutex is not held. */
+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+ pcache1LeaveMutex(pCache->pGroup);
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+ pPg = pcache1Alloc(pCache->szPage);
+ p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
+ if( !pPg || !p ){
+ pcache1Free(pPg);
+ sqlite3_free(p);
+ pPg = 0;
+ }
+#else
+ pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
+ p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
+#endif
+ pcache1EnterMutex(pCache->pGroup);
+
+ if( pPg ){
+ p->page.pBuf = pPg;
+ p->page.pExtra = &p[1];
+ if( pCache->bPurgeable ){
+ pCache->pGroup->nCurrentPage++;
+ }
+ return p;
+ }
+ return 0;
+}
+
+/*
+** Free a page object allocated by pcache1AllocPage().
+**
+** The pointer is allowed to be NULL, which is prudent. But it turns out
+** that the current implementation happens to never call this routine
+** with a NULL pointer, so we mark the NULL test with ALWAYS().
+*/
+static void pcache1FreePage(PgHdr1 *p){
+ if( ALWAYS(p) ){
+ PCache1 *pCache = p->pCache;
+ assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
+ pcache1Free(p->page.pBuf);
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+ sqlite3_free(p);
+#endif
+ if( pCache->bPurgeable ){
+ pCache->pGroup->nCurrentPage--;
+ }
+ }
+}
+
+/*
+** Malloc function used by SQLite to obtain space from the buffer configured
+** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
+** exists, this function falls back to sqlite3Malloc().
+*/
+SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
+ return pcache1Alloc(sz);
+}
+
+/*
+** Free an allocated buffer obtained from sqlite3PageMalloc().
+*/
+SQLITE_PRIVATE void sqlite3PageFree(void *p){
+ pcache1Free(p);
+}
+
+
+/*
+** Return true if it desirable to avoid allocating a new page cache
+** entry.
+**
+** If memory was allocated specifically to the page cache using
+** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
+** it is desirable to avoid allocating a new page cache entry because
+** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
+** for all page cache needs and we should not need to spill the
+** allocation onto the heap.
+**
+** Or, the heap is used for all page cache memory but the heap is
+** under memory pressure, then again it is desirable to avoid
+** allocating a new page cache entry in order to avoid stressing
+** the heap even further.
+*/
+static int pcache1UnderMemoryPressure(PCache1 *pCache){
+ if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
+ return pcache1.bUnderPressure;
+ }else{
+ return sqlite3HeapNearlyFull();
+ }
+}
+
+/******************************************************************************/
+/******** General Implementation Functions ************************************/
+
+/*
+** This function is used to resize the hash table used by the cache passed
+** as the first argument.
+**
+** The PCache mutex must be held when this function is called.
+*/
+static int pcache1ResizeHash(PCache1 *p){
+ PgHdr1 **apNew;
+ unsigned int nNew;
+ unsigned int i;
+
+ assert( sqlite3_mutex_held(p->pGroup->mutex) );
+
+ nNew = p->nHash*2;
+ if( nNew<256 ){
+ nNew = 256;
+ }
+
+ pcache1LeaveMutex(p->pGroup);
+ if( p->nHash ){ sqlite3BeginBenignMalloc(); }
+ apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
+ if( p->nHash ){ sqlite3EndBenignMalloc(); }
+ pcache1EnterMutex(p->pGroup);
+ if( apNew ){
+ for(i=0; i<p->nHash; i++){
+ PgHdr1 *pPage;
+ PgHdr1 *pNext = p->apHash[i];
+ while( (pPage = pNext)!=0 ){
+ unsigned int h = pPage->iKey % nNew;
+ pNext = pPage->pNext;
+ pPage->pNext = apNew[h];
+ apNew[h] = pPage;
+ }
+ }
+ sqlite3_free(p->apHash);
+ p->apHash = apNew;
+ p->nHash = nNew;
+ }
+
+ return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
+}
+
+/*
+** This function is used internally to remove the page pPage from the
+** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
+** LRU list, then this function is a no-op.
+**
+** The PGroup mutex must be held when this function is called.
+**
+** If pPage is NULL then this routine is a no-op.
+*/
+static void pcache1PinPage(PgHdr1 *pPage){
+ PCache1 *pCache;
+ PGroup *pGroup;
+
+ if( pPage==0 ) return;
+ pCache = pPage->pCache;
+ pGroup = pCache->pGroup;
+ assert( sqlite3_mutex_held(pGroup->mutex) );
+ if( pPage->pLruNext || pPage==pGroup->pLruTail ){
+ if( pPage->pLruPrev ){
+ pPage->pLruPrev->pLruNext = pPage->pLruNext;
+ }
+ if( pPage->pLruNext ){
+ pPage->pLruNext->pLruPrev = pPage->pLruPrev;
+ }
+ if( pGroup->pLruHead==pPage ){
+ pGroup->pLruHead = pPage->pLruNext;
+ }
+ if( pGroup->pLruTail==pPage ){
+ pGroup->pLruTail = pPage->pLruPrev;
+ }
+ pPage->pLruNext = 0;
+ pPage->pLruPrev = 0;
+ pPage->pCache->nRecyclable--;
+ }
+}
+
+
+/*
+** Remove the page supplied as an argument from the hash table
+** (PCache1.apHash structure) that it is currently stored in.
+**
+** The PGroup mutex must be held when this function is called.
+*/
+static void pcache1RemoveFromHash(PgHdr1 *pPage){
+ unsigned int h;
+ PCache1 *pCache = pPage->pCache;
+ PgHdr1 **pp;
+
+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+ h = pPage->iKey % pCache->nHash;
+ for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
+ *pp = (*pp)->pNext;
+
+ pCache->nPage--;
+}
+
+/*
+** If there are currently more than nMaxPage pages allocated, try
+** to recycle pages to reduce the number allocated to nMaxPage.
+*/
+static void pcache1EnforceMaxPage(PGroup *pGroup){
+ assert( sqlite3_mutex_held(pGroup->mutex) );
+ while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
+ PgHdr1 *p = pGroup->pLruTail;
+ assert( p->pCache->pGroup==pGroup );
+ pcache1PinPage(p);
+ pcache1RemoveFromHash(p);
+ pcache1FreePage(p);
+ }
+}
+
+/*
+** Discard all pages from cache pCache with a page number (key value)
+** greater than or equal to iLimit. Any pinned pages that meet this
+** criteria are unpinned before they are discarded.
+**
+** The PCache mutex must be held when this function is called.
+*/
+static void pcache1TruncateUnsafe(
+ PCache1 *pCache, /* The cache to truncate */
+ unsigned int iLimit /* Drop pages with this pgno or larger */
+){
+ TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */
+ unsigned int h;
+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+ for(h=0; h<pCache->nHash; h++){
+ PgHdr1 **pp = &pCache->apHash[h];
+ PgHdr1 *pPage;
+ while( (pPage = *pp)!=0 ){
+ if( pPage->iKey>=iLimit ){
+ pCache->nPage--;
+ *pp = pPage->pNext;
+ pcache1PinPage(pPage);
+ pcache1FreePage(pPage);
+ }else{
+ pp = &pPage->pNext;
+ TESTONLY( nPage++; )
+ }
+ }
+ }
+ assert( pCache->nPage==nPage );
+}
+
+/******************************************************************************/
+/******** sqlite3_pcache Methods **********************************************/
+
+/*
+** Implementation of the sqlite3_pcache.xInit method.
+*/
+static int pcache1Init(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ assert( pcache1.isInit==0 );
+ memset(&pcache1, 0, sizeof(pcache1));
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
+ pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
+ }
+ pcache1.grp.mxPinned = 10;
+ pcache1.isInit = 1;
+ return SQLITE_OK;
+}
+
+/*
+** Implementation of the sqlite3_pcache.xShutdown method.
+** Note that the static mutex allocated in xInit does
+** not need to be freed.
+*/
+static void pcache1Shutdown(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ assert( pcache1.isInit!=0 );
+ memset(&pcache1, 0, sizeof(pcache1));
+}
+
+/*
+** Implementation of the sqlite3_pcache.xCreate method.
+**
+** Allocate a new cache.
+*/
+static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
+ PCache1 *pCache; /* The newly created page cache */
+ PGroup *pGroup; /* The group the new page cache will belong to */
+ int sz; /* Bytes of memory required to allocate the new cache */
+
+ /*
+ ** The seperateCache variable is true if each PCache has its own private
+ ** PGroup. In other words, separateCache is true for mode (1) where no
+ ** mutexing is required.
+ **
+ ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
+ **
+ ** * Always use a unified cache in single-threaded applications
+ **
+ ** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off)
+ ** use separate caches (mode-1)
+ */
+#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
+ const int separateCache = 0;
+#else
+ int separateCache = sqlite3GlobalConfig.bCoreMutex>0;
+#endif
+
+ assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
+ assert( szExtra < 300 );
+
+ sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
+ pCache = (PCache1 *)sqlite3MallocZero(sz);
+ if( pCache ){
+ if( separateCache ){
+ pGroup = (PGroup*)&pCache[1];
+ pGroup->mxPinned = 10;
+ }else{
+ pGroup = &pcache1.grp;
+ }
+ pCache->pGroup = pGroup;
+ pCache->szPage = szPage;
+ pCache->szExtra = szExtra;
+ pCache->bPurgeable = (bPurgeable ? 1 : 0);
+ if( bPurgeable ){
+ pCache->nMin = 10;
+ pcache1EnterMutex(pGroup);
+ pGroup->nMinPage += pCache->nMin;
+ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+ pcache1LeaveMutex(pGroup);
+ }
+ }
+ return (sqlite3_pcache *)pCache;
+}
+
+/*
+** Implementation of the sqlite3_pcache.xCachesize method.
+**
+** Configure the cache_size limit for a cache.
+*/
+static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
+ PCache1 *pCache = (PCache1 *)p;
+ if( pCache->bPurgeable ){
+ PGroup *pGroup = pCache->pGroup;
+ pcache1EnterMutex(pGroup);
+ pGroup->nMaxPage += (nMax - pCache->nMax);
+ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+ pCache->nMax = nMax;
+ pCache->n90pct = pCache->nMax*9/10;
+ pcache1EnforceMaxPage(pGroup);
+ pcache1LeaveMutex(pGroup);
+ }
+}
+
+/*
+** Implementation of the sqlite3_pcache.xShrink method.
+**
+** Free up as much memory as possible.
+*/
+static void pcache1Shrink(sqlite3_pcache *p){
+ PCache1 *pCache = (PCache1*)p;
+ if( pCache->bPurgeable ){
+ PGroup *pGroup = pCache->pGroup;
+ int savedMaxPage;
+ pcache1EnterMutex(pGroup);
+ savedMaxPage = pGroup->nMaxPage;
+ pGroup->nMaxPage = 0;
+ pcache1EnforceMaxPage(pGroup);
+ pGroup->nMaxPage = savedMaxPage;
+ pcache1LeaveMutex(pGroup);
+ }
+}
+
+/*
+** Implementation of the sqlite3_pcache.xPagecount method.
+*/
+static int pcache1Pagecount(sqlite3_pcache *p){
+ int n;
+ PCache1 *pCache = (PCache1*)p;
+ pcache1EnterMutex(pCache->pGroup);
+ n = pCache->nPage;
+ pcache1LeaveMutex(pCache->pGroup);
+ return n;
+}
+
+/*
+** Implementation of the sqlite3_pcache.xFetch method.
+**
+** Fetch a page by key value.
+**
+** Whether or not a new page may be allocated by this function depends on
+** the value of the createFlag argument. 0 means do not allocate a new
+** page. 1 means allocate a new page if space is easily available. 2
+** means to try really hard to allocate a new page.
+**
+** For a non-purgeable cache (a cache used as the storage for an in-memory
+** database) there is really no difference between createFlag 1 and 2. So
+** the calling function (pcache.c) will never have a createFlag of 1 on
+** a non-purgeable cache.
+**
+** There are three different approaches to obtaining space for a page,
+** depending on the value of parameter createFlag (which may be 0, 1 or 2).
+**
+** 1. Regardless of the value of createFlag, the cache is searched for a
+** copy of the requested page. If one is found, it is returned.
+**
+** 2. If createFlag==0 and the page is not already in the cache, NULL is
+** returned.
+**
+** 3. If createFlag is 1, and the page is not already in the cache, then
+** return NULL (do not allocate a new page) if any of the following
+** conditions are true:
+**
+** (a) the number of pages pinned by the cache is greater than
+** PCache1.nMax, or
+**
+** (b) the number of pages pinned by the cache is greater than
+** the sum of nMax for all purgeable caches, less the sum of
+** nMin for all other purgeable caches, or
+**
+** 4. If none of the first three conditions apply and the cache is marked
+** as purgeable, and if one of the following is true:
+**
+** (a) The number of pages allocated for the cache is already
+** PCache1.nMax, or
+**
+** (b) The number of pages allocated for all purgeable caches is
+** already equal to or greater than the sum of nMax for all
+** purgeable caches,
+**
+** (c) The system is under memory pressure and wants to avoid
+** unnecessary pages cache entry allocations
+**
+** then attempt to recycle a page from the LRU list. If it is the right
+** size, return the recycled buffer. Otherwise, free the buffer and
+** proceed to step 5.
+**
+** 5. Otherwise, allocate and return a new page buffer.
+*/
+static sqlite3_pcache_page *pcache1Fetch(
+ sqlite3_pcache *p,
+ unsigned int iKey,
+ int createFlag
+){
+ unsigned int nPinned;
+ PCache1 *pCache = (PCache1 *)p;
+ PGroup *pGroup;
+ PgHdr1 *pPage = 0;
+
+ assert( pCache->bPurgeable || createFlag!=1 );
+ assert( pCache->bPurgeable || pCache->nMin==0 );
+ assert( pCache->bPurgeable==0 || pCache->nMin==10 );
+ assert( pCache->nMin==0 || pCache->bPurgeable );
+ pcache1EnterMutex(pGroup = pCache->pGroup);
+
+ /* Step 1: Search the hash table for an existing entry. */
+ if( pCache->nHash>0 ){
+ unsigned int h = iKey % pCache->nHash;
+ for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
+ }
+
+ /* Step 2: Abort if no existing page is found and createFlag is 0 */
+ if( pPage || createFlag==0 ){
+ pcache1PinPage(pPage);
+ goto fetch_out;
+ }
+
+ /* The pGroup local variable will normally be initialized by the
+ ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined,
+ ** then pcache1EnterMutex() is a no-op, so we have to initialize the
+ ** local variable here. Delaying the initialization of pGroup is an
+ ** optimization: The common case is to exit the module before reaching
+ ** this point.
+ */
+#ifdef SQLITE_MUTEX_OMIT
+ pGroup = pCache->pGroup;
+#endif
+
+ /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
+ assert( pCache->nPage >= pCache->nRecyclable );
+ nPinned = pCache->nPage - pCache->nRecyclable;
+ assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
+ assert( pCache->n90pct == pCache->nMax*9/10 );
+ if( createFlag==1 && (
+ nPinned>=pGroup->mxPinned
+ || nPinned>=pCache->n90pct
+ || pcache1UnderMemoryPressure(pCache)
+ )){
+ goto fetch_out;
+ }
+
+ if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
+ goto fetch_out;
+ }
+
+ /* Step 4. Try to recycle a page. */
+ if( pCache->bPurgeable && pGroup->pLruTail && (
+ (pCache->nPage+1>=pCache->nMax)
+ || pGroup->nCurrentPage>=pGroup->nMaxPage
+ || pcache1UnderMemoryPressure(pCache)
+ )){
+ PCache1 *pOther;
+ pPage = pGroup->pLruTail;
+ pcache1RemoveFromHash(pPage);
+ pcache1PinPage(pPage);
+ pOther = pPage->pCache;
+
+ /* We want to verify that szPage and szExtra are the same for pOther
+ ** and pCache. Assert that we can verify this by comparing sums. */
+ assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
+ assert( pCache->szExtra<512 );
+ assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
+ assert( pOther->szExtra<512 );
+
+ if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
+ pcache1FreePage(pPage);
+ pPage = 0;
+ }else{
+ pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
+ }
+ }
+
+ /* Step 5. If a usable page buffer has still not been found,
+ ** attempt to allocate a new one.
+ */
+ if( !pPage ){
+ if( createFlag==1 ) sqlite3BeginBenignMalloc();
+ pPage = pcache1AllocPage(pCache);
+ if( createFlag==1 ) sqlite3EndBenignMalloc();
+ }
+
+ if( pPage ){
+ unsigned int h = iKey % pCache->nHash;
+ pCache->nPage++;
+ pPage->iKey = iKey;
+ pPage->pNext = pCache->apHash[h];
+ pPage->pCache = pCache;
+ pPage->pLruPrev = 0;
+ pPage->pLruNext = 0;
+ *(void **)pPage->page.pExtra = 0;
+ pCache->apHash[h] = pPage;
+ }
+
+fetch_out:
+ if( pPage && iKey>pCache->iMaxKey ){
+ pCache->iMaxKey = iKey;
+ }
+ pcache1LeaveMutex(pGroup);
+ return &pPage->page;
+}
+
+
+/*
+** Implementation of the sqlite3_pcache.xUnpin method.
+**
+** Mark a page as unpinned (eligible for asynchronous recycling).
+*/
+static void pcache1Unpin(
+ sqlite3_pcache *p,
+ sqlite3_pcache_page *pPg,
+ int reuseUnlikely
+){
+ PCache1 *pCache = (PCache1 *)p;
+ PgHdr1 *pPage = (PgHdr1 *)pPg;
+ PGroup *pGroup = pCache->pGroup;
+
+ assert( pPage->pCache==pCache );
+ pcache1EnterMutex(pGroup);
+
+ /* It is an error to call this function if the page is already
+ ** part of the PGroup LRU list.
+ */
+ assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
+ assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
+
+ if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
+ pcache1RemoveFromHash(pPage);
+ pcache1FreePage(pPage);
+ }else{
+ /* Add the page to the PGroup LRU list. */
+ if( pGroup->pLruHead ){
+ pGroup->pLruHead->pLruPrev = pPage;
+ pPage->pLruNext = pGroup->pLruHead;
+ pGroup->pLruHead = pPage;
+ }else{
+ pGroup->pLruTail = pPage;
+ pGroup->pLruHead = pPage;
+ }
+ pCache->nRecyclable++;
+ }
+
+ pcache1LeaveMutex(pCache->pGroup);
+}
+
+/*
+** Implementation of the sqlite3_pcache.xRekey method.
+*/
+static void pcache1Rekey(
+ sqlite3_pcache *p,
+ sqlite3_pcache_page *pPg,
+ unsigned int iOld,
+ unsigned int iNew
+){
+ PCache1 *pCache = (PCache1 *)p;
+ PgHdr1 *pPage = (PgHdr1 *)pPg;
+ PgHdr1 **pp;
+ unsigned int h;
+ assert( pPage->iKey==iOld );
+ assert( pPage->pCache==pCache );
+
+ pcache1EnterMutex(pCache->pGroup);
+
+ h = iOld%pCache->nHash;
+ pp = &pCache->apHash[h];
+ while( (*pp)!=pPage ){
+ pp = &(*pp)->pNext;
+ }
+ *pp = pPage->pNext;
+
+ h = iNew%pCache->nHash;
+ pPage->iKey = iNew;
+ pPage->pNext = pCache->apHash[h];
+ pCache->apHash[h] = pPage;
+ if( iNew>pCache->iMaxKey ){
+ pCache->iMaxKey = iNew;
+ }
+
+ pcache1LeaveMutex(pCache->pGroup);
+}
+
+/*
+** Implementation of the sqlite3_pcache.xTruncate method.
+**
+** Discard all unpinned pages in the cache with a page number equal to
+** or greater than parameter iLimit. Any pinned pages with a page number
+** equal to or greater than iLimit are implicitly unpinned.
+*/
+static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
+ PCache1 *pCache = (PCache1 *)p;
+ pcache1EnterMutex(pCache->pGroup);
+ if( iLimit<=pCache->iMaxKey ){
+ pcache1TruncateUnsafe(pCache, iLimit);
+ pCache->iMaxKey = iLimit-1;
+ }
+ pcache1LeaveMutex(pCache->pGroup);
+}
+
+/*
+** Implementation of the sqlite3_pcache.xDestroy method.
+**
+** Destroy a cache allocated using pcache1Create().
+*/
+static void pcache1Destroy(sqlite3_pcache *p){
+ PCache1 *pCache = (PCache1 *)p;
+ PGroup *pGroup = pCache->pGroup;
+ assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
+ pcache1EnterMutex(pGroup);
+ pcache1TruncateUnsafe(pCache, 0);
+ assert( pGroup->nMaxPage >= pCache->nMax );
+ pGroup->nMaxPage -= pCache->nMax;
+ assert( pGroup->nMinPage >= pCache->nMin );
+ pGroup->nMinPage -= pCache->nMin;
+ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+ pcache1EnforceMaxPage(pGroup);
+ pcache1LeaveMutex(pGroup);
+ sqlite3_free(pCache->apHash);
+ sqlite3_free(pCache);
+}
+
+/*
+** This function is called during initialization (sqlite3_initialize()) to
+** install the default pluggable cache module, assuming the user has not
+** already provided an alternative.
+*/
+SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
+ static const sqlite3_pcache_methods2 defaultMethods = {
+ 1, /* iVersion */
+ 0, /* pArg */
+ pcache1Init, /* xInit */
+ pcache1Shutdown, /* xShutdown */
+ pcache1Create, /* xCreate */
+ pcache1Cachesize, /* xCachesize */
+ pcache1Pagecount, /* xPagecount */
+ pcache1Fetch, /* xFetch */
+ pcache1Unpin, /* xUnpin */
+ pcache1Rekey, /* xRekey */
+ pcache1Truncate, /* xTruncate */
+ pcache1Destroy, /* xDestroy */
+ pcache1Shrink /* xShrink */
+ };
+ sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
+}
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/*
+** This function is called to free superfluous dynamically allocated memory
+** held by the pager system. Memory in use by any SQLite pager allocated
+** by the current thread may be sqlite3_free()ed.
+**
+** nReq is the number of bytes of memory required. Once this much has
+** been released, the function returns. The return value is the total number
+** of bytes of memory released.
+*/
+SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
+ int nFree = 0;
+ assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
+ assert( sqlite3_mutex_notheld(pcache1.mutex) );
+ if( pcache1.pStart==0 ){
+ PgHdr1 *p;
+ pcache1EnterMutex(&pcache1.grp);
+ while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
+ nFree += pcache1MemSize(p->page.pBuf);
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+ nFree += sqlite3MemSize(p);
+#endif
+ pcache1PinPage(p);
+ pcache1RemoveFromHash(p);
+ pcache1FreePage(p);
+ }
+ pcache1LeaveMutex(&pcache1.grp);
+ }
+ return nFree;
+}
+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+
+#ifdef SQLITE_TEST
+/*
+** This function is used by test procedures to inspect the internal state
+** of the global cache.
+*/
+SQLITE_PRIVATE void sqlite3PcacheStats(
+ int *pnCurrent, /* OUT: Total number of pages cached */
+ int *pnMax, /* OUT: Global maximum cache size */
+ int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
+ int *pnRecyclable /* OUT: Total number of pages available for recycling */
+){
+ PgHdr1 *p;
+ int nRecyclable = 0;
+ for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
+ nRecyclable++;
+ }
+ *pnCurrent = pcache1.grp.nCurrentPage;
+ *pnMax = (int)pcache1.grp.nMaxPage;
+ *pnMin = (int)pcache1.grp.nMinPage;
+ *pnRecyclable = nRecyclable;
+}
+#endif
+
+/************** End of pcache1.c *********************************************/
+/************** Begin file rowset.c ******************************************/
+/*
+** 2008 December 3
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This module implements an object we call a "RowSet".
+**
+** The RowSet object is a collection of rowids. Rowids
+** are inserted into the RowSet in an arbitrary order. Inserts
+** can be intermixed with tests to see if a given rowid has been
+** previously inserted into the RowSet.
+**
+** After all inserts are finished, it is possible to extract the
+** elements of the RowSet in sorted order. Once this extraction
+** process has started, no new elements may be inserted.
+**
+** Hence, the primitive operations for a RowSet are:
+**
+** CREATE
+** INSERT
+** TEST
+** SMALLEST
+** DESTROY
+**
+** The CREATE and DESTROY primitives are the constructor and destructor,
+** obviously. The INSERT primitive adds a new element to the RowSet.
+** TEST checks to see if an element is already in the RowSet. SMALLEST
+** extracts the least value from the RowSet.
+**
+** The INSERT primitive might allocate additional memory. Memory is
+** allocated in chunks so most INSERTs do no allocation. There is an
+** upper bound on the size of allocated memory. No memory is freed
+** until DESTROY.
+**
+** The TEST primitive includes a "batch" number. The TEST primitive
+** will only see elements that were inserted before the last change
+** in the batch number. In other words, if an INSERT occurs between
+** two TESTs where the TESTs have the same batch nubmer, then the
+** value added by the INSERT will not be visible to the second TEST.
+** The initial batch number is zero, so if the very first TEST contains
+** a non-zero batch number, it will see all prior INSERTs.
+**
+** No INSERTs may occurs after a SMALLEST. An assertion will fail if
+** that is attempted.
+**
+** The cost of an INSERT is roughly constant. (Sometime new memory
+** has to be allocated on an INSERT.) The cost of a TEST with a new
+** batch number is O(NlogN) where N is the number of elements in the RowSet.
+** The cost of a TEST using the same batch number is O(logN). The cost
+** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
+** primitives are constant time. The cost of DESTROY is O(N).
+**
+** There is an added cost of O(N) when switching between TEST and
+** SMALLEST primitives.
+*/
+
+
+/*
+** Target size for allocation chunks.
+*/
+#define ROWSET_ALLOCATION_SIZE 1024
+
+/*
+** The number of rowset entries per allocation chunk.
+*/
+#define ROWSET_ENTRY_PER_CHUNK \
+ ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
+
+/*
+** Each entry in a RowSet is an instance of the following object.
+**
+** This same object is reused to store a linked list of trees of RowSetEntry
+** objects. In that alternative use, pRight points to the next entry
+** in the list, pLeft points to the tree, and v is unused. The
+** RowSet.pForest value points to the head of this forest list.
+*/
+struct RowSetEntry {
+ i64 v; /* ROWID value for this entry */
+ struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */
+ struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */
+};
+
+/*
+** RowSetEntry objects are allocated in large chunks (instances of the
+** following structure) to reduce memory allocation overhead. The
+** chunks are kept on a linked list so that they can be deallocated
+** when the RowSet is destroyed.
+*/
+struct RowSetChunk {
+ struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */
+ struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
+};
+
+/*
+** A RowSet in an instance of the following structure.
+**
+** A typedef of this structure if found in sqliteInt.h.
+*/
+struct RowSet {
+ struct RowSetChunk *pChunk; /* List of all chunk allocations */
+ sqlite3 *db; /* The database connection */
+ struct RowSetEntry *pEntry; /* List of entries using pRight */
+ struct RowSetEntry *pLast; /* Last entry on the pEntry list */
+ struct RowSetEntry *pFresh; /* Source of new entry objects */
+ struct RowSetEntry *pForest; /* List of binary trees of entries */
+ u16 nFresh; /* Number of objects on pFresh */
+ u8 rsFlags; /* Various flags */
+ u8 iBatch; /* Current insert batch */
+};
+
+/*
+** Allowed values for RowSet.rsFlags
+*/
+#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */
+#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */
+
+/*
+** Turn bulk memory into a RowSet object. N bytes of memory
+** are available at pSpace. The db pointer is used as a memory context
+** for any subsequent allocations that need to occur.
+** Return a pointer to the new RowSet object.
+**
+** It must be the case that N is sufficient to make a Rowset. If not
+** an assertion fault occurs.
+**
+** If N is larger than the minimum, use the surplus as an initial
+** allocation of entries available to be filled.
+*/
+SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
+ RowSet *p;
+ assert( N >= ROUND8(sizeof(*p)) );
+ p = pSpace;
+ p->pChunk = 0;
+ p->db = db;
+ p->pEntry = 0;
+ p->pLast = 0;
+ p->pForest = 0;
+ p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
+ p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
+ p->rsFlags = ROWSET_SORTED;
+ p->iBatch = 0;
+ return p;
+}
+
+/*
+** Deallocate all chunks from a RowSet. This frees all memory that
+** the RowSet has allocated over its lifetime. This routine is
+** the destructor for the RowSet.
+*/
+SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
+ struct RowSetChunk *pChunk, *pNextChunk;
+ for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
+ pNextChunk = pChunk->pNextChunk;
+ sqlite3DbFree(p->db, pChunk);
+ }
+ p->pChunk = 0;
+ p->nFresh = 0;
+ p->pEntry = 0;
+ p->pLast = 0;
+ p->pForest = 0;
+ p->rsFlags = ROWSET_SORTED;
+}
+
+/*
+** Allocate a new RowSetEntry object that is associated with the
+** given RowSet. Return a pointer to the new and completely uninitialized
+** objected.
+**
+** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
+** routine returns NULL.
+*/
+static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
+ assert( p!=0 );
+ if( p->nFresh==0 ){
+ struct RowSetChunk *pNew;
+ pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
+ if( pNew==0 ){
+ return 0;
+ }
+ pNew->pNextChunk = p->pChunk;
+ p->pChunk = pNew;
+ p->pFresh = pNew->aEntry;
+ p->nFresh = ROWSET_ENTRY_PER_CHUNK;
+ }
+ p->nFresh--;
+ return p->pFresh++;
+}
+
+/*
+** Insert a new value into a RowSet.
+**
+** The mallocFailed flag of the database connection is set if a
+** memory allocation fails.
+*/
+SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
+ struct RowSetEntry *pEntry; /* The new entry */
+ struct RowSetEntry *pLast; /* The last prior entry */
+
+ /* This routine is never called after sqlite3RowSetNext() */
+ assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
+
+ pEntry = rowSetEntryAlloc(p);
+ if( pEntry==0 ) return;
+ pEntry->v = rowid;
+ pEntry->pRight = 0;
+ pLast = p->pLast;
+ if( pLast ){
+ if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){
+ p->rsFlags &= ~ROWSET_SORTED;
+ }
+ pLast->pRight = pEntry;
+ }else{
+ p->pEntry = pEntry;
+ }
+ p->pLast = pEntry;
+}
+
+/*
+** Merge two lists of RowSetEntry objects. Remove duplicates.
+**
+** The input lists are connected via pRight pointers and are
+** assumed to each already be in sorted order.
+*/
+static struct RowSetEntry *rowSetEntryMerge(
+ struct RowSetEntry *pA, /* First sorted list to be merged */
+ struct RowSetEntry *pB /* Second sorted list to be merged */
+){
+ struct RowSetEntry head;
+ struct RowSetEntry *pTail;
+
+ pTail = &head;
+ while( pA && pB ){
+ assert( pA->pRight==0 || pA->v<=pA->pRight->v );
+ assert( pB->pRight==0 || pB->v<=pB->pRight->v );
+ if( pA->v<pB->v ){
+ pTail->pRight = pA;
+ pA = pA->pRight;
+ pTail = pTail->pRight;
+ }else if( pB->v<pA->v ){
+ pTail->pRight = pB;
+ pB = pB->pRight;
+ pTail = pTail->pRight;
+ }else{
+ pA = pA->pRight;
+ }
+ }
+ if( pA ){
+ assert( pA->pRight==0 || pA->v<=pA->pRight->v );
+ pTail->pRight = pA;
+ }else{
+ assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v );
+ pTail->pRight = pB;
+ }
+ return head.pRight;
+}
+
+/*
+** Sort all elements on the list of RowSetEntry objects into order of
+** increasing v.
+*/
+static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
+ unsigned int i;
+ struct RowSetEntry *pNext, *aBucket[40];
+
+ memset(aBucket, 0, sizeof(aBucket));
+ while( pIn ){
+ pNext = pIn->pRight;
+ pIn->pRight = 0;
+ for(i=0; aBucket[i]; i++){
+ pIn = rowSetEntryMerge(aBucket[i], pIn);
+ aBucket[i] = 0;
+ }
+ aBucket[i] = pIn;
+ pIn = pNext;
+ }
+ pIn = 0;
+ for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
+ pIn = rowSetEntryMerge(pIn, aBucket[i]);
+ }
+ return pIn;
+}
+
+
+/*
+** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
+** Convert this tree into a linked list connected by the pRight pointers
+** and return pointers to the first and last elements of the new list.
+*/
+static void rowSetTreeToList(
+ struct RowSetEntry *pIn, /* Root of the input tree */
+ struct RowSetEntry **ppFirst, /* Write head of the output list here */
+ struct RowSetEntry **ppLast /* Write tail of the output list here */
+){
+ assert( pIn!=0 );
+ if( pIn->pLeft ){
+ struct RowSetEntry *p;
+ rowSetTreeToList(pIn->pLeft, ppFirst, &p);
+ p->pRight = pIn;
+ }else{
+ *ppFirst = pIn;
+ }
+ if( pIn->pRight ){
+ rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
+ }else{
+ *ppLast = pIn;
+ }
+ assert( (*ppLast)->pRight==0 );
+}
+
+
+/*
+** Convert a sorted list of elements (connected by pRight) into a binary
+** tree with depth of iDepth. A depth of 1 means the tree contains a single
+** node taken from the head of *ppList. A depth of 2 means a tree with
+** three nodes. And so forth.
+**
+** Use as many entries from the input list as required and update the
+** *ppList to point to the unused elements of the list. If the input
+** list contains too few elements, then construct an incomplete tree
+** and leave *ppList set to NULL.
+**
+** Return a pointer to the root of the constructed binary tree.
+*/
+static struct RowSetEntry *rowSetNDeepTree(
+ struct RowSetEntry **ppList,
+ int iDepth
+){
+ struct RowSetEntry *p; /* Root of the new tree */
+ struct RowSetEntry *pLeft; /* Left subtree */
+ if( *ppList==0 ){
+ return 0;
+ }
+ if( iDepth==1 ){
+ p = *ppList;
+ *ppList = p->pRight;
+ p->pLeft = p->pRight = 0;
+ return p;
+ }
+ pLeft = rowSetNDeepTree(ppList, iDepth-1);
+ p = *ppList;
+ if( p==0 ){
+ return pLeft;
+ }
+ p->pLeft = pLeft;
+ *ppList = p->pRight;
+ p->pRight = rowSetNDeepTree(ppList, iDepth-1);
+ return p;
+}
+
+/*
+** Convert a sorted list of elements into a binary tree. Make the tree
+** as deep as it needs to be in order to contain the entire list.
+*/
+static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
+ int iDepth; /* Depth of the tree so far */
+ struct RowSetEntry *p; /* Current tree root */
+ struct RowSetEntry *pLeft; /* Left subtree */
+
+ assert( pList!=0 );
+ p = pList;
+ pList = p->pRight;
+ p->pLeft = p->pRight = 0;
+ for(iDepth=1; pList; iDepth++){
+ pLeft = p;
+ p = pList;
+ pList = p->pRight;
+ p->pLeft = pLeft;
+ p->pRight = rowSetNDeepTree(&pList, iDepth);
+ }
+ return p;
+}
+
+/*
+** Take all the entries on p->pEntry and on the trees in p->pForest and
+** sort them all together into one big ordered list on p->pEntry.
+**
+** This routine should only be called once in the life of a RowSet.
+*/
+static void rowSetToList(RowSet *p){
+
+ /* This routine is called only once */
+ assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
+
+ if( (p->rsFlags & ROWSET_SORTED)==0 ){
+ p->pEntry = rowSetEntrySort(p->pEntry);
+ }
+
+ /* While this module could theoretically support it, sqlite3RowSetNext()
+ ** is never called after sqlite3RowSetText() for the same RowSet. So
+ ** there is never a forest to deal with. Should this change, simply
+ ** remove the assert() and the #if 0. */
+ assert( p->pForest==0 );
+#if 0
+ while( p->pForest ){
+ struct RowSetEntry *pTree = p->pForest->pLeft;
+ if( pTree ){
+ struct RowSetEntry *pHead, *pTail;
+ rowSetTreeToList(pTree, &pHead, &pTail);
+ p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
+ }
+ p->pForest = p->pForest->pRight;
+ }
+#endif
+ p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */
+}
+
+/*
+** Extract the smallest element from the RowSet.
+** Write the element into *pRowid. Return 1 on success. Return
+** 0 if the RowSet is already empty.
+**
+** After this routine has been called, the sqlite3RowSetInsert()
+** routine may not be called again.
+*/
+SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
+ assert( p!=0 );
+
+ /* Merge the forest into a single sorted list on first call */
+ if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p);
+
+ /* Return the next entry on the list */
+ if( p->pEntry ){
+ *pRowid = p->pEntry->v;
+ p->pEntry = p->pEntry->pRight;
+ if( p->pEntry==0 ){
+ sqlite3RowSetClear(p);
+ }
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
+/*
+** Check to see if element iRowid was inserted into the rowset as
+** part of any insert batch prior to iBatch. Return 1 or 0.
+**
+** If this is the first test of a new batch and if there exist entires
+** on pRowSet->pEntry, then sort those entires into the forest at
+** pRowSet->pForest so that they can be tested.
+*/
+SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
+ struct RowSetEntry *p, *pTree;
+
+ /* This routine is never called after sqlite3RowSetNext() */
+ assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
+
+ /* Sort entries into the forest on the first test of a new batch
+ */
+ if( iBatch!=pRowSet->iBatch ){
+ p = pRowSet->pEntry;
+ if( p ){
+ struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
+ if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){
+ p = rowSetEntrySort(p);
+ }
+ for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
+ ppPrevTree = &pTree->pRight;
+ if( pTree->pLeft==0 ){
+ pTree->pLeft = rowSetListToTree(p);
+ break;
+ }else{
+ struct RowSetEntry *pAux, *pTail;
+ rowSetTreeToList(pTree->pLeft, &pAux, &pTail);
+ pTree->pLeft = 0;
+ p = rowSetEntryMerge(pAux, p);
+ }
+ }
+ if( pTree==0 ){
+ *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet);
+ if( pTree ){
+ pTree->v = 0;
+ pTree->pRight = 0;
+ pTree->pLeft = rowSetListToTree(p);
+ }
+ }
+ pRowSet->pEntry = 0;
+ pRowSet->pLast = 0;
+ pRowSet->rsFlags |= ROWSET_SORTED;
+ }
+ pRowSet->iBatch = iBatch;
+ }
+
+ /* Test to see if the iRowid value appears anywhere in the forest.
+ ** Return 1 if it does and 0 if not.
+ */
+ for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
+ p = pTree->pLeft;
+ while( p ){
+ if( p->v<iRowid ){
+ p = p->pRight;
+ }else if( p->v>iRowid ){
+ p = p->pLeft;
+ }else{
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/************** End of rowset.c **********************************************/
+/************** Begin file pager.c *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This is the implementation of the page cache subsystem or "pager".
+**
+** The pager is used to access a database disk file. It implements
+** atomic commit and rollback through the use of a journal file that
+** is separate from the database file. The pager also implements file
+** locking to prevent two processes from writing the same database
+** file simultaneously, or one process from reading the database while
+** another is writing.
+*/
+#ifndef SQLITE_OMIT_DISKIO
+/************** Include wal.h in the middle of pager.c ***********************/
+/************** Begin file wal.h *********************************************/
+/*
+** 2010 February 1
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface to the write-ahead logging
+** system. Refer to the comments below and the header comment attached to
+** the implementation of each function in log.c for further details.
+*/
+
+#ifndef _WAL_H_
+#define _WAL_H_
+
+
+/* Additional values that can be added to the sync_flags argument of
+** sqlite3WalFrames():
+*/
+#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */
+#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
+
+#ifdef SQLITE_OMIT_WAL
+# define sqlite3WalOpen(x,y,z) 0
+# define sqlite3WalLimit(x,y)
+# define sqlite3WalClose(w,x,y,z) 0
+# define sqlite3WalBeginReadTransaction(y,z) 0
+# define sqlite3WalEndReadTransaction(z)
+# define sqlite3WalRead(v,w,x,y,z) 0
+# define sqlite3WalDbsize(y) 0
+# define sqlite3WalBeginWriteTransaction(y) 0
+# define sqlite3WalEndWriteTransaction(x) 0
+# define sqlite3WalUndo(x,y,z) 0
+# define sqlite3WalSavepoint(y,z)
+# define sqlite3WalSavepointUndo(y,z) 0
+# define sqlite3WalFrames(u,v,w,x,y,z) 0
+# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
+# define sqlite3WalCallback(z) 0
+# define sqlite3WalExclusiveMode(y,z) 0
+# define sqlite3WalHeapMemory(z) 0
+# define sqlite3WalFramesize(z) 0
+#else
+
+#define WAL_SAVEPOINT_NDATA 4
+
+/* Connection to a write-ahead log (WAL) file.
+** There is one object of this type for each pager.
+*/
+typedef struct Wal Wal;
+
+/* Open and close a connection to a write-ahead log. */
+SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
+SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
+
+/* Set the limiting size of a WAL file. */
+SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
+
+/* Used by readers to open (lock) and close (unlock) a snapshot. A
+** snapshot is like a read-transaction. It is the state of the database
+** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
+** preserves the current state even if the other threads or processes
+** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
+** transaction and releases the lock.
+*/
+SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
+SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal);
+
+/* Read a page from the write-ahead log, if it is present. */
+SQLITE_PRIVATE int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
+
+/* If the WAL is not empty, return the size of the database. */
+SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal);
+
+/* Obtain or release the WRITER lock. */
+SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal);
+SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal);
+
+/* Undo any frames written (but not committed) to the log */
+SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
+
+/* Return an integer that records the current (uncommitted) write
+** position in the WAL */
+SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);
+
+/* Move the write position of the WAL back to iFrame. Called in
+** response to a ROLLBACK TO command. */
+SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
+
+/* Write a frame or frames to the log. */
+SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
+
+/* Copy pages from the log to the database file */
+SQLITE_PRIVATE int sqlite3WalCheckpoint(
+ Wal *pWal, /* Write-ahead log connection */
+ int eMode, /* One of PASSIVE, FULL and RESTART */
+ int (*xBusy)(void*), /* Function to call when busy */
+ void *pBusyArg, /* Context argument for xBusyHandler */
+ int sync_flags, /* Flags to sync db file with (or 0) */
+ int nBuf, /* Size of buffer nBuf */
+ u8 *zBuf, /* Temporary buffer to use */
+ int *pnLog, /* OUT: Number of frames in WAL */
+ int *pnCkpt /* OUT: Number of backfilled frames in WAL */
+);
+
+/* Return the value to pass to a sqlite3_wal_hook callback, the
+** number of frames in the WAL at the point of the last commit since
+** sqlite3WalCallback() was called. If no commits have occurred since
+** the last call, then return 0.
+*/
+SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal);
+
+/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
+** by the pager layer on the database file.
+*/
+SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
+
+/* Return true if the argument is non-NULL and the WAL module is using
+** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
+** WAL module is using shared-memory, return false.
+*/
+SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
+
+#ifdef SQLITE_ENABLE_ZIPVFS
+/* If the WAL file is not empty, return the number of bytes of content
+** stored in each frame (i.e. the db page-size when the WAL was created).
+*/
+SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
+#endif
+
+#endif /* ifndef SQLITE_OMIT_WAL */
+#endif /* _WAL_H_ */
+
+/************** End of wal.h *************************************************/
+/************** Continuing where we left off in pager.c **********************/
+
+
+/******************* NOTES ON THE DESIGN OF THE PAGER ************************
+**
+** This comment block describes invariants that hold when using a rollback
+** journal. These invariants do not apply for journal_mode=WAL,
+** journal_mode=MEMORY, or journal_mode=OFF.
+**
+** Within this comment block, a page is deemed to have been synced
+** automatically as soon as it is written when PRAGMA synchronous=OFF.
+** Otherwise, the page is not synced until the xSync method of the VFS
+** is called successfully on the file containing the page.
+**
+** Definition: A page of the database file is said to be "overwriteable" if
+** one or more of the following are true about the page:
+**
+** (a) The original content of the page as it was at the beginning of
+** the transaction has been written into the rollback journal and
+** synced.
+**
+** (b) The page was a freelist leaf page at the start of the transaction.
+**
+** (c) The page number is greater than the largest page that existed in
+** the database file at the start of the transaction.
+**
+** (1) A page of the database file is never overwritten unless one of the
+** following are true:
+**
+** (a) The page and all other pages on the same sector are overwriteable.
+**
+** (b) The atomic page write optimization is enabled, and the entire
+** transaction other than the update of the transaction sequence
+** number consists of a single page change.
+**
+** (2) The content of a page written into the rollback journal exactly matches
+** both the content in the database when the rollback journal was written
+** and the content in the database at the beginning of the current
+** transaction.
+**
+** (3) Writes to the database file are an integer multiple of the page size
+** in length and are aligned on a page boundary.
+**
+** (4) Reads from the database file are either aligned on a page boundary and
+** an integer multiple of the page size in length or are taken from the
+** first 100 bytes of the database file.
+**
+** (5) All writes to the database file are synced prior to the rollback journal
+** being deleted, truncated, or zeroed.
+**
+** (6) If a master journal file is used, then all writes to the database file
+** are synced prior to the master journal being deleted.
+**
+** Definition: Two databases (or the same database at two points it time)
+** are said to be "logically equivalent" if they give the same answer to
+** all queries. Note in particular the content of freelist leaf
+** pages can be changed arbitarily without effecting the logical equivalence
+** of the database.
+**
+** (7) At any time, if any subset, including the empty set and the total set,
+** of the unsynced changes to a rollback journal are removed and the
+** journal is rolled back, the resulting database file will be logical
+** equivalent to the database file at the beginning of the transaction.
+**
+** (8) When a transaction is rolled back, the xTruncate method of the VFS
+** is called to restore the database file to the same size it was at
+** the beginning of the transaction. (In some VFSes, the xTruncate
+** method is a no-op, but that does not change the fact the SQLite will
+** invoke it.)
+**
+** (9) Whenever the database file is modified, at least one bit in the range
+** of bytes from 24 through 39 inclusive will be changed prior to releasing
+** the EXCLUSIVE lock, thus signaling other connections on the same
+** database to flush their caches.
+**
+** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less
+** than one billion transactions.
+**
+** (11) A database file is well-formed at the beginning and at the conclusion
+** of every transaction.
+**
+** (12) An EXCLUSIVE lock is held on the database file when writing to
+** the database file.
+**
+** (13) A SHARED lock is held on the database file while reading any
+** content out of the database file.
+**
+******************************************************************************/
+
+/*
+** Macros for troubleshooting. Normally turned off
+*/
+#if 0
+int sqlite3PagerTrace=1; /* True to enable tracing */
+#define sqlite3DebugPrintf printf
+#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
+#else
+#define PAGERTRACE(X)
+#endif
+
+/*
+** The following two macros are used within the PAGERTRACE() macros above
+** to print out file-descriptors.
+**
+** PAGERID() takes a pointer to a Pager struct as its argument. The
+** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
+** struct as its argument.
+*/
+#define PAGERID(p) ((int)(p->fd))
+#define FILEHANDLEID(fd) ((int)fd)
+
+/*
+** The Pager.eState variable stores the current 'state' of a pager. A
+** pager may be in any one of the seven states shown in the following
+** state diagram.
+**
+** OPEN <------+------+
+** | | |
+** V | |
+** +---------> READER-------+ |
+** | | |
+** | V |
+** |<-------WRITER_LOCKED------> ERROR
+** | | ^
+** | V |
+** |<------WRITER_CACHEMOD-------->|
+** | | |
+** | V |
+** |<-------WRITER_DBMOD---------->|
+** | | |
+** | V |
+** +<------WRITER_FINISHED-------->+
+**
+**
+** List of state transitions and the C [function] that performs each:
+**
+** OPEN -> READER [sqlite3PagerSharedLock]
+** READER -> OPEN [pager_unlock]
+**
+** READER -> WRITER_LOCKED [sqlite3PagerBegin]
+** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal]
+** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal]
+** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne]
+** WRITER_*** -> READER [pager_end_transaction]
+**
+** WRITER_*** -> ERROR [pager_error]
+** ERROR -> OPEN [pager_unlock]
+**
+**
+** OPEN:
+**
+** The pager starts up in this state. Nothing is guaranteed in this
+** state - the file may or may not be locked and the database size is
+** unknown. The database may not be read or written.
+**
+** * No read or write transaction is active.
+** * Any lock, or no lock at all, may be held on the database file.
+** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
+**
+** READER:
+**
+** In this state all the requirements for reading the database in
+** rollback (non-WAL) mode are met. Unless the pager is (or recently
+** was) in exclusive-locking mode, a user-level read transaction is
+** open. The database size is known in this state.
+**
+** A connection running with locking_mode=normal enters this state when
+** it opens a read-transaction on the database and returns to state
+** OPEN after the read-transaction is completed. However a connection
+** running in locking_mode=exclusive (including temp databases) remains in
+** this state even after the read-transaction is closed. The only way
+** a locking_mode=exclusive connection can transition from READER to OPEN
+** is via the ERROR state (see below).
+**
+** * A read transaction may be active (but a write-transaction cannot).
+** * A SHARED or greater lock is held on the database file.
+** * The dbSize variable may be trusted (even if a user-level read
+** transaction is not active). The dbOrigSize and dbFileSize variables
+** may not be trusted at this point.
+** * If the database is a WAL database, then the WAL connection is open.
+** * Even if a read-transaction is not open, it is guaranteed that
+** there is no hot-journal in the file-system.
+**
+** WRITER_LOCKED:
+**
+** The pager moves to this state from READER when a write-transaction
+** is first opened on the database. In WRITER_LOCKED state, all locks
+** required to start a write-transaction are held, but no actual
+** modifications to the cache or database have taken place.
+**
+** In rollback mode, a RESERVED or (if the transaction was opened with
+** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
+** moving to this state, but the journal file is not written to or opened
+** to in this state. If the transaction is committed or rolled back while
+** in WRITER_LOCKED state, all that is required is to unlock the database
+** file.
+**
+** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
+** If the connection is running with locking_mode=exclusive, an attempt
+** is made to obtain an EXCLUSIVE lock on the database file.
+**
+** * A write transaction is active.
+** * If the connection is open in rollback-mode, a RESERVED or greater
+** lock is held on the database file.
+** * If the connection is open in WAL-mode, a WAL write transaction
+** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
+** called).
+** * The dbSize, dbOrigSize and dbFileSize variables are all valid.
+** * The contents of the pager cache have not been modified.
+** * The journal file may or may not be open.
+** * Nothing (not even the first header) has been written to the journal.
+**
+** WRITER_CACHEMOD:
+**
+** A pager moves from WRITER_LOCKED state to this state when a page is
+** first modified by the upper layer. In rollback mode the journal file
+** is opened (if it is not already open) and a header written to the
+** start of it. The database file on disk has not been modified.
+**
+** * A write transaction is active.
+** * A RESERVED or greater lock is held on the database file.
+** * The journal file is open and the first header has been written
+** to it, but the header has not been synced to disk.
+** * The contents of the page cache have been modified.
+**
+** WRITER_DBMOD:
+**
+** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state
+** when it modifies the contents of the database file. WAL connections
+** never enter this state (since they do not modify the database file,
+** just the log file).
+**
+** * A write transaction is active.
+** * An EXCLUSIVE or greater lock is held on the database file.
+** * The journal file is open and the first header has been written
+** and synced to disk.
+** * The contents of the page cache have been modified (and possibly
+** written to disk).
+**
+** WRITER_FINISHED:
+**
+** It is not possible for a WAL connection to enter this state.
+**
+** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
+** state after the entire transaction has been successfully written into the
+** database file. In this state the transaction may be committed simply
+** by finalizing the journal file. Once in WRITER_FINISHED state, it is
+** not possible to modify the database further. At this point, the upper
+** layer must either commit or rollback the transaction.
+**
+** * A write transaction is active.
+** * An EXCLUSIVE or greater lock is held on the database file.
+** * All writing and syncing of journal and database data has finished.
+** If no error occurred, all that remains is to finalize the journal to
+** commit the transaction. If an error did occur, the caller will need
+** to rollback the transaction.
+**
+** ERROR:
+**
+** The ERROR state is entered when an IO or disk-full error (including
+** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
+** difficult to be sure that the in-memory pager state (cache contents,
+** db size etc.) are consistent with the contents of the file-system.
+**
+** Temporary pager files may enter the ERROR state, but in-memory pagers
+** cannot.
+**
+** For example, if an IO error occurs while performing a rollback,
+** the contents of the page-cache may be left in an inconsistent state.
+** At this point it would be dangerous to change back to READER state
+** (as usually happens after a rollback). Any subsequent readers might
+** report database corruption (due to the inconsistent cache), and if
+** they upgrade to writers, they may inadvertently corrupt the database
+** file. To avoid this hazard, the pager switches into the ERROR state
+** instead of READER following such an error.
+**
+** Once it has entered the ERROR state, any attempt to use the pager
+** to read or write data returns an error. Eventually, once all
+** outstanding transactions have been abandoned, the pager is able to
+** transition back to OPEN state, discarding the contents of the
+** page-cache and any other in-memory state at the same time. Everything
+** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
+** when a read-transaction is next opened on the pager (transitioning
+** the pager into READER state). At that point the system has recovered
+** from the error.
+**
+** Specifically, the pager jumps into the ERROR state if:
+**
+** 1. An error occurs while attempting a rollback. This happens in
+** function sqlite3PagerRollback().
+**
+** 2. An error occurs while attempting to finalize a journal file
+** following a commit in function sqlite3PagerCommitPhaseTwo().
+**
+** 3. An error occurs while attempting to write to the journal or
+** database file in function pagerStress() in order to free up
+** memory.
+**
+** In other cases, the error is returned to the b-tree layer. The b-tree
+** layer then attempts a rollback operation. If the error condition
+** persists, the pager enters the ERROR state via condition (1) above.
+**
+** Condition (3) is necessary because it can be triggered by a read-only
+** statement executed within a transaction. In this case, if the error
+** code were simply returned to the user, the b-tree layer would not
+** automatically attempt a rollback, as it assumes that an error in a
+** read-only statement cannot leave the pager in an internally inconsistent
+** state.
+**
+** * The Pager.errCode variable is set to something other than SQLITE_OK.
+** * There are one or more outstanding references to pages (after the
+** last reference is dropped the pager should move back to OPEN state).
+** * The pager is not an in-memory pager.
+**
+**
+** Notes:
+**
+** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
+** connection is open in WAL mode. A WAL connection is always in one
+** of the first four states.
+**
+** * Normally, a connection open in exclusive mode is never in PAGER_OPEN
+** state. There are two exceptions: immediately after exclusive-mode has
+** been turned on (and before any read or write transactions are
+** executed), and when the pager is leaving the "error state".
+**
+** * See also: assert_pager_state().
+*/
+#define PAGER_OPEN 0
+#define PAGER_READER 1
+#define PAGER_WRITER_LOCKED 2
+#define PAGER_WRITER_CACHEMOD 3
+#define PAGER_WRITER_DBMOD 4
+#define PAGER_WRITER_FINISHED 5
+#define PAGER_ERROR 6
+
+/*
+** The Pager.eLock variable is almost always set to one of the
+** following locking-states, according to the lock currently held on
+** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
+** This variable is kept up to date as locks are taken and released by
+** the pagerLockDb() and pagerUnlockDb() wrappers.
+**
+** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
+** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
+** the operation was successful. In these circumstances pagerLockDb() and
+** pagerUnlockDb() take a conservative approach - eLock is always updated
+** when unlocking the file, and only updated when locking the file if the
+** VFS call is successful. This way, the Pager.eLock variable may be set
+** to a less exclusive (lower) value than the lock that is actually held
+** at the system level, but it is never set to a more exclusive value.
+**
+** This is usually safe. If an xUnlock fails or appears to fail, there may
+** be a few redundant xLock() calls or a lock may be held for longer than
+** required, but nothing really goes wrong.
+**
+** The exception is when the database file is unlocked as the pager moves
+** from ERROR to OPEN state. At this point there may be a hot-journal file
+** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
+** transition, by the same pager or any other). If the call to xUnlock()
+** fails at this point and the pager is left holding an EXCLUSIVE lock, this
+** can confuse the call to xCheckReservedLock() call made later as part
+** of hot-journal detection.
+**
+** xCheckReservedLock() is defined as returning true "if there is a RESERVED
+** lock held by this process or any others". So xCheckReservedLock may
+** return true because the caller itself is holding an EXCLUSIVE lock (but
+** doesn't know it because of a previous error in xUnlock). If this happens
+** a hot-journal may be mistaken for a journal being created by an active
+** transaction in another process, causing SQLite to read from the database
+** without rolling it back.
+**
+** To work around this, if a call to xUnlock() fails when unlocking the
+** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
+** is only changed back to a real locking state after a successful call
+** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
+** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
+** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
+** lock on the database file before attempting to roll it back. See function
+** PagerSharedLock() for more detail.
+**
+** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
+** PAGER_OPEN state.
+*/
+#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
+
+/*
+** A macro used for invoking the codec if there is one
+*/
+#ifdef SQLITE_HAS_CODEC
+# define CODEC1(P,D,N,X,E) \
+ if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
+# define CODEC2(P,D,N,X,E,O) \
+ if( P->xCodec==0 ){ O=(char*)D; }else \
+ if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
+#else
+# define CODEC1(P,D,N,X,E) /* NO-OP */
+# define CODEC2(P,D,N,X,E,O) O=(char*)D
+#endif
+
+/*
+** The maximum allowed sector size. 64KiB. If the xSectorsize() method
+** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
+** This could conceivably cause corruption following a power failure on
+** such a system. This is currently an undocumented limit.
+*/
+#define MAX_SECTOR_SIZE 0x10000
+
+/*
+** An instance of the following structure is allocated for each active
+** savepoint and statement transaction in the system. All such structures
+** are stored in the Pager.aSavepoint[] array, which is allocated and
+** resized using sqlite3Realloc().
+**
+** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
+** set to 0. If a journal-header is written into the main journal while
+** the savepoint is active, then iHdrOffset is set to the byte offset
+** immediately following the last journal record written into the main
+** journal before the journal-header. This is required during savepoint
+** rollback (see pagerPlaybackSavepoint()).
+*/
+typedef struct PagerSavepoint PagerSavepoint;
+struct PagerSavepoint {
+ i64 iOffset; /* Starting offset in main journal */
+ i64 iHdrOffset; /* See above */
+ Bitvec *pInSavepoint; /* Set of pages in this savepoint */
+ Pgno nOrig; /* Original number of pages in file */
+ Pgno iSubRec; /* Index of first record in sub-journal */
+#ifndef SQLITE_OMIT_WAL
+ u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
+#endif
+};
+
+/*
+** A open page cache is an instance of struct Pager. A description of
+** some of the more important member variables follows:
+**
+** eState
+**
+** The current 'state' of the pager object. See the comment and state
+** diagram above for a description of the pager state.
+**
+** eLock
+**
+** For a real on-disk database, the current lock held on the database file -
+** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
+**
+** For a temporary or in-memory database (neither of which require any
+** locks), this variable is always set to EXCLUSIVE_LOCK. Since such
+** databases always have Pager.exclusiveMode==1, this tricks the pager
+** logic into thinking that it already has all the locks it will ever
+** need (and no reason to release them).
+**
+** In some (obscure) circumstances, this variable may also be set to
+** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for
+** details.
+**
+** changeCountDone
+**
+** This boolean variable is used to make sure that the change-counter
+** (the 4-byte header field at byte offset 24 of the database file) is
+** not updated more often than necessary.
+**
+** It is set to true when the change-counter field is updated, which
+** can only happen if an exclusive lock is held on the database file.
+** It is cleared (set to false) whenever an exclusive lock is
+** relinquished on the database file. Each time a transaction is committed,
+** The changeCountDone flag is inspected. If it is true, the work of
+** updating the change-counter is omitted for the current transaction.
+**
+** This mechanism means that when running in exclusive mode, a connection
+** need only update the change-counter once, for the first transaction
+** committed.
+**
+** setMaster
+**
+** When PagerCommitPhaseOne() is called to commit a transaction, it may
+** (or may not) specify a master-journal name to be written into the
+** journal file before it is synced to disk.
+**
+** Whether or not a journal file contains a master-journal pointer affects
+** the way in which the journal file is finalized after the transaction is
+** committed or rolled back when running in "journal_mode=PERSIST" mode.
+** If a journal file does not contain a master-journal pointer, it is
+** finalized by overwriting the first journal header with zeroes. If
+** it does contain a master-journal pointer the journal file is finalized
+** by truncating it to zero bytes, just as if the connection were
+** running in "journal_mode=truncate" mode.
+**
+** Journal files that contain master journal pointers cannot be finalized
+** simply by overwriting the first journal-header with zeroes, as the
+** master journal pointer could interfere with hot-journal rollback of any
+** subsequently interrupted transaction that reuses the journal file.
+**
+** The flag is cleared as soon as the journal file is finalized (either
+** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
+** journal file from being successfully finalized, the setMaster flag
+** is cleared anyway (and the pager will move to ERROR state).
+**
+** doNotSpill, doNotSyncSpill
+**
+** These two boolean variables control the behavior of cache-spills
+** (calls made by the pcache module to the pagerStress() routine to
+** write cached data to the file-system in order to free up memory).
+**
+** When doNotSpill is non-zero, writing to the database from pagerStress()
+** is disabled altogether. This is done in a very obscure case that
+** comes up during savepoint rollback that requires the pcache module
+** to allocate a new page to prevent the journal file from being written
+** while it is being traversed by code in pager_playback().
+**
+** If doNotSyncSpill is non-zero, writing to the database from pagerStress()
+** is permitted, but syncing the journal file is not. This flag is set
+** by sqlite3PagerWrite() when the file-system sector-size is larger than
+** the database page-size in order to prevent a journal sync from happening
+** in between the journalling of two pages on the same sector.
+**
+** subjInMemory
+**
+** This is a boolean variable. If true, then any required sub-journal
+** is opened as an in-memory journal file. If false, then in-memory
+** sub-journals are only used for in-memory pager files.
+**
+** This variable is updated by the upper layer each time a new
+** write-transaction is opened.
+**
+** dbSize, dbOrigSize, dbFileSize
+**
+** Variable dbSize is set to the number of pages in the database file.
+** It is valid in PAGER_READER and higher states (all states except for
+** OPEN and ERROR).
+**
+** dbSize is set based on the size of the database file, which may be
+** larger than the size of the database (the value stored at offset
+** 28 of the database header by the btree). If the size of the file
+** is not an integer multiple of the page-size, the value stored in
+** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2).
+** Except, any file that is greater than 0 bytes in size is considered
+** to have at least one page. (i.e. a 1KB file with 2K page-size leads
+** to dbSize==1).
+**
+** During a write-transaction, if pages with page-numbers greater than
+** dbSize are modified in the cache, dbSize is updated accordingly.
+** Similarly, if the database is truncated using PagerTruncateImage(),
+** dbSize is updated.
+**
+** Variables dbOrigSize and dbFileSize are valid in states
+** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
+** variable at the start of the transaction. It is used during rollback,
+** and to determine whether or not pages need to be journalled before
+** being modified.
+**
+** Throughout a write-transaction, dbFileSize contains the size of
+** the file on disk in pages. It is set to a copy of dbSize when the
+** write-transaction is first opened, and updated when VFS calls are made
+** to write or truncate the database file on disk.
+**
+** The only reason the dbFileSize variable is required is to suppress
+** unnecessary calls to xTruncate() after committing a transaction. If,
+** when a transaction is committed, the dbFileSize variable indicates
+** that the database file is larger than the database image (Pager.dbSize),
+** pager_truncate() is called. The pager_truncate() call uses xFilesize()
+** to measure the database file on disk, and then truncates it if required.
+** dbFileSize is not used when rolling back a transaction. In this case
+** pager_truncate() is called unconditionally (which means there may be
+** a call to xFilesize() that is not strictly required). In either case,
+** pager_truncate() may cause the file to become smaller or larger.
+**
+** dbHintSize
+**
+** The dbHintSize variable is used to limit the number of calls made to
+** the VFS xFileControl(FCNTL_SIZE_HINT) method.
+**
+** dbHintSize is set to a copy of the dbSize variable when a
+** write-transaction is opened (at the same time as dbFileSize and
+** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
+** dbHintSize is increased to the number of pages that correspond to the
+** size-hint passed to the method call. See pager_write_pagelist() for
+** details.
+**
+** errCode
+**
+** The Pager.errCode variable is only ever used in PAGER_ERROR state. It
+** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
+** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
+** sub-codes.
+*/
+struct Pager {
+ sqlite3_vfs *pVfs; /* OS functions to use for IO */
+ u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
+ u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */
+ u8 useJournal; /* Use a rollback journal on this file */
+ u8 noSync; /* Do not sync the journal if true */
+ u8 fullSync; /* Do extra syncs of the journal for robustness */
+ u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
+ u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
+ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
+ u8 tempFile; /* zFilename is a temporary file */
+ u8 readOnly; /* True for a read-only database */
+ u8 memDb; /* True to inhibit all file I/O */
+
+ /**************************************************************************
+ ** The following block contains those class members that change during
+ ** routine opertion. Class members not in this block are either fixed
+ ** when the pager is first created or else only change when there is a
+ ** significant mode change (such as changing the page_size, locking_mode,
+ ** or the journal_mode). From another view, these class members describe
+ ** the "state" of the pager, while other class members describe the
+ ** "configuration" of the pager.
+ */
+ u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
+ u8 eLock; /* Current lock held on database file */
+ u8 changeCountDone; /* Set after incrementing the change-counter */
+ u8 setMaster; /* True if a m-j name has been written to jrnl */
+ u8 doNotSpill; /* Do not spill the cache when non-zero */
+ u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */
+ u8 subjInMemory; /* True to use in-memory sub-journals */
+ Pgno dbSize; /* Number of pages in the database */
+ Pgno dbOrigSize; /* dbSize before the current transaction */
+ Pgno dbFileSize; /* Number of pages in the database file */
+ Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
+ int errCode; /* One of several kinds of errors */
+ int nRec; /* Pages journalled since last j-header written */
+ u32 cksumInit; /* Quasi-random value added to every checksum */
+ u32 nSubRec; /* Number of records written to sub-journal */
+ Bitvec *pInJournal; /* One bit for each page in the database file */
+ sqlite3_file *fd; /* File descriptor for database */
+ sqlite3_file *jfd; /* File descriptor for main journal */
+ sqlite3_file *sjfd; /* File descriptor for sub-journal */
+ i64 journalOff; /* Current write offset in the journal file */
+ i64 journalHdr; /* Byte offset to previous journal header */
+ sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
+ PagerSavepoint *aSavepoint; /* Array of active savepoints */
+ int nSavepoint; /* Number of elements in aSavepoint[] */
+ char dbFileVers[16]; /* Changes whenever database file changes */
+ /*
+ ** End of the routinely-changing class members
+ ***************************************************************************/
+
+ u16 nExtra; /* Add this many bytes to each in-memory page */
+ i16 nReserve; /* Number of unused bytes at end of each page */
+ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
+ u32 sectorSize; /* Assumed sector size during rollback */
+ int pageSize; /* Number of bytes in a page */
+ Pgno mxPgno; /* Maximum allowed size of the database */
+ i64 journalSizeLimit; /* Size limit for persistent journal files */
+ char *zFilename; /* Name of the database file */
+ char *zJournal; /* Name of the journal file */
+ int (*xBusyHandler)(void*); /* Function to call when busy */
+ void *pBusyHandlerArg; /* Context argument for xBusyHandler */
+ int aStat[3]; /* Total cache hits, misses and writes */
+#ifdef SQLITE_TEST
+ int nRead; /* Database pages read */
+#endif
+ void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
+#ifdef SQLITE_HAS_CODEC
+ void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
+ void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
+ void (*xCodecFree)(void*); /* Destructor for the codec */
+ void *pCodec; /* First argument to xCodec... methods */
+#endif
+ char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
+ PCache *pPCache; /* Pointer to page cache object */
+#ifndef SQLITE_OMIT_WAL
+ Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
+ char *zWal; /* File name for write-ahead log */
+#endif
+};
+
+/*
+** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
+** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
+** or CACHE_WRITE to sqlite3_db_status().
+*/
+#define PAGER_STAT_HIT 0
+#define PAGER_STAT_MISS 1
+#define PAGER_STAT_WRITE 2
+
+/*
+** The following global variables hold counters used for
+** testing purposes only. These variables do not exist in
+** a non-testing build. These variables are not thread-safe.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
+SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
+SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
+# define PAGER_INCR(v) v++
+#else
+# define PAGER_INCR(v)
+#endif
+
+
+
+/*
+** Journal files begin with the following magic string. The data
+** was obtained from /dev/random. It is used only as a sanity check.
+**
+** Since version 2.8.0, the journal format contains additional sanity
+** checking information. If the power fails while the journal is being
+** written, semi-random garbage data might appear in the journal
+** file after power is restored. If an attempt is then made
+** to roll the journal back, the database could be corrupted. The additional
+** sanity checking data is an attempt to discover the garbage in the
+** journal and ignore it.
+**
+** The sanity checking information for the new journal format consists
+** of a 32-bit checksum on each page of data. The checksum covers both
+** the page number and the pPager->pageSize bytes of data for the page.
+** This cksum is initialized to a 32-bit random value that appears in the
+** journal file right after the header. The random initializer is important,
+** because garbage data that appears at the end of a journal is likely
+** data that was once in other files that have now been deleted. If the
+** garbage data came from an obsolete journal file, the checksums might
+** be correct. But by initializing the checksum to random value which
+** is different for every journal, we minimize that risk.
+*/
+static const unsigned char aJournalMagic[] = {
+ 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
+};
+
+/*
+** The size of the of each page record in the journal is given by
+** the following macro.
+*/
+#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)
+
+/*
+** The journal header size for this pager. This is usually the same
+** size as a single disk sector. See also setSectorSize().
+*/
+#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
+
+/*
+** The macro MEMDB is true if we are dealing with an in-memory database.
+** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
+** the value of MEMDB will be a constant and the compiler will optimize
+** out code that would never execute.
+*/
+#ifdef SQLITE_OMIT_MEMORYDB
+# define MEMDB 0
+#else
+# define MEMDB pPager->memDb
+#endif
+
+/*
+** The maximum legal page number is (2^31 - 1).
+*/
+#define PAGER_MAX_PGNO 2147483647
+
+/*
+** The argument to this macro is a file descriptor (type sqlite3_file*).
+** Return 0 if it is not open, or non-zero (but not 1) if it is.
+**
+** This is so that expressions can be written as:
+**
+** if( isOpen(pPager->jfd) ){ ...
+**
+** instead of
+**
+** if( pPager->jfd->pMethods ){ ...
+*/
+#define isOpen(pFd) ((pFd)->pMethods)
+
+/*
+** Return true if this pager uses a write-ahead log instead of the usual
+** rollback journal. Otherwise false.
+*/
+#ifndef SQLITE_OMIT_WAL
+static int pagerUseWal(Pager *pPager){
+ return (pPager->pWal!=0);
+}
+#else
+# define pagerUseWal(x) 0
+# define pagerRollbackWal(x) 0
+# define pagerWalFrames(v,w,x,y) 0
+# define pagerOpenWalIfPresent(z) SQLITE_OK
+# define pagerBeginReadTransaction(z) SQLITE_OK
+#endif
+
+#ifndef NDEBUG
+/*
+** Usage:
+**
+** assert( assert_pager_state(pPager) );
+**
+** This function runs many asserts to try to find inconsistencies in
+** the internal state of the Pager object.
+*/
+static int assert_pager_state(Pager *p){
+ Pager *pPager = p;
+
+ /* State must be valid. */
+ assert( p->eState==PAGER_OPEN
+ || p->eState==PAGER_READER
+ || p->eState==PAGER_WRITER_LOCKED
+ || p->eState==PAGER_WRITER_CACHEMOD
+ || p->eState==PAGER_WRITER_DBMOD
+ || p->eState==PAGER_WRITER_FINISHED
+ || p->eState==PAGER_ERROR
+ );
+
+ /* Regardless of the current state, a temp-file connection always behaves
+ ** as if it has an exclusive lock on the database file. It never updates
+ ** the change-counter field, so the changeCountDone flag is always set.
+ */
+ assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
+ assert( p->tempFile==0 || pPager->changeCountDone );
+
+ /* If the useJournal flag is clear, the journal-mode must be "OFF".
+ ** And if the journal-mode is "OFF", the journal file must not be open.
+ */
+ assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
+ assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
+
+ /* Check that MEMDB implies noSync. And an in-memory journal. Since
+ ** this means an in-memory pager performs no IO at all, it cannot encounter
+ ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
+ ** a journal file. (although the in-memory journal implementation may
+ ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
+ ** is therefore not possible for an in-memory pager to enter the ERROR
+ ** state.
+ */
+ if( MEMDB ){
+ assert( p->noSync );
+ assert( p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_MEMORY
+ );
+ assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
+ assert( pagerUseWal(p)==0 );
+ }
+
+ /* If changeCountDone is set, a RESERVED lock or greater must be held
+ ** on the file.
+ */
+ assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
+ assert( p->eLock!=PENDING_LOCK );
+
+ switch( p->eState ){
+ case PAGER_OPEN:
+ assert( !MEMDB );
+ assert( pPager->errCode==SQLITE_OK );
+ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
+ break;
+
+ case PAGER_READER:
+ assert( pPager->errCode==SQLITE_OK );
+ assert( p->eLock!=UNKNOWN_LOCK );
+ assert( p->eLock>=SHARED_LOCK );
+ break;
+
+ case PAGER_WRITER_LOCKED:
+ assert( p->eLock!=UNKNOWN_LOCK );
+ assert( pPager->errCode==SQLITE_OK );
+ if( !pagerUseWal(pPager) ){
+ assert( p->eLock>=RESERVED_LOCK );
+ }
+ assert( pPager->dbSize==pPager->dbOrigSize );
+ assert( pPager->dbOrigSize==pPager->dbFileSize );
+ assert( pPager->dbOrigSize==pPager->dbHintSize );
+ assert( pPager->setMaster==0 );
+ break;
+
+ case PAGER_WRITER_CACHEMOD:
+ assert( p->eLock!=UNKNOWN_LOCK );
+ assert( pPager->errCode==SQLITE_OK );
+ if( !pagerUseWal(pPager) ){
+ /* It is possible that if journal_mode=wal here that neither the
+ ** journal file nor the WAL file are open. This happens during
+ ** a rollback transaction that switches from journal_mode=off
+ ** to journal_mode=wal.
+ */
+ assert( p->eLock>=RESERVED_LOCK );
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
+ );
+ }
+ assert( pPager->dbOrigSize==pPager->dbFileSize );
+ assert( pPager->dbOrigSize==pPager->dbHintSize );
+ break;
+
+ case PAGER_WRITER_DBMOD:
+ assert( p->eLock==EXCLUSIVE_LOCK );
+ assert( pPager->errCode==SQLITE_OK );
+ assert( !pagerUseWal(pPager) );
+ assert( p->eLock>=EXCLUSIVE_LOCK );
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
+ );
+ assert( pPager->dbOrigSize<=pPager->dbHintSize );
+ break;
+
+ case PAGER_WRITER_FINISHED:
+ assert( p->eLock==EXCLUSIVE_LOCK );
+ assert( pPager->errCode==SQLITE_OK );
+ assert( !pagerUseWal(pPager) );
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
+ );
+ break;
+
+ case PAGER_ERROR:
+ /* There must be at least one outstanding reference to the pager if
+ ** in ERROR state. Otherwise the pager should have already dropped
+ ** back to OPEN state.
+ */
+ assert( pPager->errCode!=SQLITE_OK );
+ assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
+ break;
+ }
+
+ return 1;
+}
+#endif /* ifndef NDEBUG */
+
+#ifdef SQLITE_DEBUG
+/*
+** Return a pointer to a human readable string in a static buffer
+** containing the state of the Pager object passed as an argument. This
+** is intended to be used within debuggers. For example, as an alternative
+** to "print *pPager" in gdb:
+**
+** (gdb) printf "%s", print_pager_state(pPager)
+*/
+static char *print_pager_state(Pager *p){
+ static char zRet[1024];
+
+ sqlite3_snprintf(1024, zRet,
+ "Filename: %s\n"
+ "State: %s errCode=%d\n"
+ "Lock: %s\n"
+ "Locking mode: locking_mode=%s\n"
+ "Journal mode: journal_mode=%s\n"
+ "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
+ "Journal: journalOff=%lld journalHdr=%lld\n"
+ "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
+ , p->zFilename
+ , p->eState==PAGER_OPEN ? "OPEN" :
+ p->eState==PAGER_READER ? "READER" :
+ p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" :
+ p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
+ p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" :
+ p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
+ p->eState==PAGER_ERROR ? "ERROR" : "?error?"
+ , (int)p->errCode
+ , p->eLock==NO_LOCK ? "NO_LOCK" :
+ p->eLock==RESERVED_LOCK ? "RESERVED" :
+ p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" :
+ p->eLock==SHARED_LOCK ? "SHARED" :
+ p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?"
+ , p->exclusiveMode ? "exclusive" : "normal"
+ , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" :
+ p->journalMode==PAGER_JOURNALMODE_OFF ? "off" :
+ p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" :
+ p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" :
+ p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
+ p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?"
+ , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
+ , p->journalOff, p->journalHdr
+ , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
+ );
+
+ return zRet;
+}
+#endif
+
+/*
+** Return true if it is necessary to write page *pPg into the sub-journal.
+** A page needs to be written into the sub-journal if there exists one
+** or more open savepoints for which:
+**
+** * The page-number is less than or equal to PagerSavepoint.nOrig, and
+** * The bit corresponding to the page-number is not set in
+** PagerSavepoint.pInSavepoint.
+*/
+static int subjRequiresPage(PgHdr *pPg){
+ Pgno pgno = pPg->pgno;
+ Pager *pPager = pPg->pPager;
+ int i;
+ for(i=0; i<pPager->nSavepoint; i++){
+ PagerSavepoint *p = &pPager->aSavepoint[i];
+ if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+** Return true if the page is already in the journal file.
+*/
+static int pageInJournal(PgHdr *pPg){
+ return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
+}
+
+/*
+** Read a 32-bit integer from the given file descriptor. Store the integer
+** that is read in *pRes. Return SQLITE_OK if everything worked, or an
+** error code is something goes wrong.
+**
+** All values are stored on disk as big-endian.
+*/
+static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
+ unsigned char ac[4];
+ int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
+ if( rc==SQLITE_OK ){
+ *pRes = sqlite3Get4byte(ac);
+ }
+ return rc;
+}
+
+/*
+** Write a 32-bit integer into a string buffer in big-endian byte order.
+*/
+#define put32bits(A,B) sqlite3Put4byte((u8*)A,B)
+
+
+/*
+** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK
+** on success or an error code is something goes wrong.
+*/
+static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
+ char ac[4];
+ put32bits(ac, val);
+ return sqlite3OsWrite(fd, ac, 4, offset);
+}
+
+/*
+** Unlock the database file to level eLock, which must be either NO_LOCK
+** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
+** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
+**
+** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
+** called, do not modify it. See the comment above the #define of
+** UNKNOWN_LOCK for an explanation of this.
+*/
+static int pagerUnlockDb(Pager *pPager, int eLock){
+ int rc = SQLITE_OK;
+
+ assert( !pPager->exclusiveMode || pPager->eLock==eLock );
+ assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
+ assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
+ if( isOpen(pPager->fd) ){
+ assert( pPager->eLock>=eLock );
+ rc = sqlite3OsUnlock(pPager->fd, eLock);
+ if( pPager->eLock!=UNKNOWN_LOCK ){
+ pPager->eLock = (u8)eLock;
+ }
+ IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
+ }
+ return rc;
+}
+
+/*
+** Lock the database file to level eLock, which must be either SHARED_LOCK,
+** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
+** Pager.eLock variable to the new locking state.
+**
+** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
+** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
+** See the comment above the #define of UNKNOWN_LOCK for an explanation
+** of this.
+*/
+static int pagerLockDb(Pager *pPager, int eLock){
+ int rc = SQLITE_OK;
+
+ assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
+ if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
+ rc = sqlite3OsLock(pPager->fd, eLock);
+ if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
+ pPager->eLock = (u8)eLock;
+ IOTRACE(("LOCK %p %d\n", pPager, eLock))
+ }
+ }
+ return rc;
+}
+
+/*
+** This function determines whether or not the atomic-write optimization
+** can be used with this pager. The optimization can be used if:
+**
+** (a) the value returned by OsDeviceCharacteristics() indicates that
+** a database page may be written atomically, and
+** (b) the value returned by OsSectorSize() is less than or equal
+** to the page size.
+**
+** The optimization is also always enabled for temporary files. It is
+** an error to call this function if pPager is opened on an in-memory
+** database.
+**
+** If the optimization cannot be used, 0 is returned. If it can be used,
+** then the value returned is the size of the journal file when it
+** contains rollback data for exactly one page.
+*/
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+static int jrnlBufferSize(Pager *pPager){
+ assert( !MEMDB );
+ if( !pPager->tempFile ){
+ int dc; /* Device characteristics */
+ int nSector; /* Sector size */
+ int szPage; /* Page size */
+
+ assert( isOpen(pPager->fd) );
+ dc = sqlite3OsDeviceCharacteristics(pPager->fd);
+ nSector = pPager->sectorSize;
+ szPage = pPager->pageSize;
+
+ assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
+ assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
+ if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
+ return 0;
+ }
+ }
+
+ return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
+}
+#endif
+
+/*
+** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
+** on the cache using a hash function. This is used for testing
+** and debugging only.
+*/
+#ifdef SQLITE_CHECK_PAGES
+/*
+** Return a 32-bit hash of the page data for pPage.
+*/
+static u32 pager_datahash(int nByte, unsigned char *pData){
+ u32 hash = 0;
+ int i;
+ for(i=0; i<nByte; i++){
+ hash = (hash*1039) + pData[i];
+ }
+ return hash;
+}
+static u32 pager_pagehash(PgHdr *pPage){
+ return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
+}
+static void pager_set_pagehash(PgHdr *pPage){
+ pPage->pageHash = pager_pagehash(pPage);
+}
+
+/*
+** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
+** is defined, and NDEBUG is not defined, an assert() statement checks
+** that the page is either dirty or still matches the calculated page-hash.
+*/
+#define CHECK_PAGE(x) checkPage(x)
+static void checkPage(PgHdr *pPg){
+ Pager *pPager = pPg->pPager;
+ assert( pPager->eState!=PAGER_ERROR );
+ assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
+}
+
+#else
+#define pager_datahash(X,Y) 0
+#define pager_pagehash(X) 0
+#define pager_set_pagehash(X)
+#define CHECK_PAGE(x)
+#endif /* SQLITE_CHECK_PAGES */
+
+/*
+** When this is called the journal file for pager pPager must be open.
+** This function attempts to read a master journal file name from the
+** end of the file and, if successful, copies it into memory supplied
+** by the caller. See comments above writeMasterJournal() for the format
+** used to store a master journal file name at the end of a journal file.
+**
+** zMaster must point to a buffer of at least nMaster bytes allocated by
+** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
+** enough space to write the master journal name). If the master journal
+** name in the journal is longer than nMaster bytes (including a
+** nul-terminator), then this is handled as if no master journal name
+** were present in the journal.
+**
+** If a master journal file name is present at the end of the journal
+** file, then it is copied into the buffer pointed to by zMaster. A
+** nul-terminator byte is appended to the buffer following the master
+** journal file name.
+**
+** If it is determined that no master journal file name is present
+** zMaster[0] is set to 0 and SQLITE_OK returned.
+**
+** If an error occurs while reading from the journal file, an SQLite
+** error code is returned.
+*/
+static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
+ int rc; /* Return code */
+ u32 len; /* Length in bytes of master journal name */
+ i64 szJ; /* Total size in bytes of journal file pJrnl */
+ u32 cksum; /* MJ checksum value read from journal */
+ u32 u; /* Unsigned loop counter */
+ unsigned char aMagic[8]; /* A buffer to hold the magic header */
+ zMaster[0] = '\0';
+
+ if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
+ || szJ<16
+ || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
+ || len>=nMaster
+ || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
+ || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
+ || memcmp(aMagic, aJournalMagic, 8)
+ || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
+ ){
+ return rc;
+ }
+
+ /* See if the checksum matches the master journal name */
+ for(u=0; u<len; u++){
+ cksum -= zMaster[u];
+ }
+ if( cksum ){
+ /* If the checksum doesn't add up, then one or more of the disk sectors
+ ** containing the master journal filename is corrupted. This means
+ ** definitely roll back, so just return SQLITE_OK and report a (nul)
+ ** master-journal filename.
+ */
+ len = 0;
+ }
+ zMaster[len] = '\0';
+
+ return SQLITE_OK;
+}
+
+/*
+** Return the offset of the sector boundary at or immediately
+** following the value in pPager->journalOff, assuming a sector
+** size of pPager->sectorSize bytes.
+**
+** i.e for a sector size of 512:
+**
+** Pager.journalOff Return value
+** ---------------------------------------
+** 0 0
+** 512 512
+** 100 512
+** 2000 2048
+**
+*/
+static i64 journalHdrOffset(Pager *pPager){
+ i64 offset = 0;
+ i64 c = pPager->journalOff;
+ if( c ){
+ offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
+ }
+ assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
+ assert( offset>=c );
+ assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
+ return offset;
+}
+
+/*
+** The journal file must be open when this function is called.
+**
+** This function is a no-op if the journal file has not been written to
+** within the current transaction (i.e. if Pager.journalOff==0).
+**
+** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
+** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
+** zero the 28-byte header at the start of the journal file. In either case,
+** if the pager is not in no-sync mode, sync the journal file immediately
+** after writing or truncating it.
+**
+** If Pager.journalSizeLimit is set to a positive, non-zero value, and
+** following the truncation or zeroing described above the size of the
+** journal file in bytes is larger than this value, then truncate the
+** journal file to Pager.journalSizeLimit bytes. The journal file does
+** not need to be synced following this operation.
+**
+** If an IO error occurs, abandon processing and return the IO error code.
+** Otherwise, return SQLITE_OK.
+*/
+static int zeroJournalHdr(Pager *pPager, int doTruncate){
+ int rc = SQLITE_OK; /* Return code */
+ assert( isOpen(pPager->jfd) );
+ if( pPager->journalOff ){
+ const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */
+
+ IOTRACE(("JZEROHDR %p\n", pPager))
+ if( doTruncate || iLimit==0 ){
+ rc = sqlite3OsTruncate(pPager->jfd, 0);
+ }else{
+ static const char zeroHdr[28] = {0};
+ rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
+ }
+ if( rc==SQLITE_OK && !pPager->noSync ){
+ rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
+ }
+
+ /* At this point the transaction is committed but the write lock
+ ** is still held on the file. If there is a size limit configured for
+ ** the persistent journal and the journal file currently consumes more
+ ** space than that limit allows for, truncate it now. There is no need
+ ** to sync the file following this operation.
+ */
+ if( rc==SQLITE_OK && iLimit>0 ){
+ i64 sz;
+ rc = sqlite3OsFileSize(pPager->jfd, &sz);
+ if( rc==SQLITE_OK && sz>iLimit ){
+ rc = sqlite3OsTruncate(pPager->jfd, iLimit);
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** The journal file must be open when this routine is called. A journal
+** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
+** current location.
+**
+** The format for the journal header is as follows:
+** - 8 bytes: Magic identifying journal format.
+** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
+** - 4 bytes: Random number used for page hash.
+** - 4 bytes: Initial database page count.
+** - 4 bytes: Sector size used by the process that wrote this journal.
+** - 4 bytes: Database page size.
+**
+** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
+*/
+static int writeJournalHdr(Pager *pPager){
+ int rc = SQLITE_OK; /* Return code */
+ char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */
+ u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
+ u32 nWrite; /* Bytes of header sector written */
+ int ii; /* Loop counter */
+
+ assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
+
+ if( nHeader>JOURNAL_HDR_SZ(pPager) ){
+ nHeader = JOURNAL_HDR_SZ(pPager);
+ }
+
+ /* If there are active savepoints and any of them were created
+ ** since the most recent journal header was written, update the
+ ** PagerSavepoint.iHdrOffset fields now.
+ */
+ for(ii=0; ii<pPager->nSavepoint; ii++){
+ if( pPager->aSavepoint[ii].iHdrOffset==0 ){
+ pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
+ }
+ }
+
+ pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
+
+ /*
+ ** Write the nRec Field - the number of page records that follow this
+ ** journal header. Normally, zero is written to this value at this time.
+ ** After the records are added to the journal (and the journal synced,
+ ** if in full-sync mode), the zero is overwritten with the true number
+ ** of records (see syncJournal()).
+ **
+ ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
+ ** reading the journal this value tells SQLite to assume that the
+ ** rest of the journal file contains valid page records. This assumption
+ ** is dangerous, as if a failure occurred whilst writing to the journal
+ ** file it may contain some garbage data. There are two scenarios
+ ** where this risk can be ignored:
+ **
+ ** * When the pager is in no-sync mode. Corruption can follow a
+ ** power failure in this case anyway.
+ **
+ ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
+ ** that garbage data is never appended to the journal file.
+ */
+ assert( isOpen(pPager->fd) || pPager->noSync );
+ if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
+ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
+ ){
+ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
+ put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
+ }else{
+ memset(zHeader, 0, sizeof(aJournalMagic)+4);
+ }
+
+ /* The random check-hash initializer */
+ sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
+ put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
+ /* The initial database size */
+ put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
+ /* The assumed sector size for this process */
+ put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
+
+ /* The page size */
+ put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
+
+ /* Initializing the tail of the buffer is not necessary. Everything
+ ** works find if the following memset() is omitted. But initializing
+ ** the memory prevents valgrind from complaining, so we are willing to
+ ** take the performance hit.
+ */
+ memset(&zHeader[sizeof(aJournalMagic)+20], 0,
+ nHeader-(sizeof(aJournalMagic)+20));
+
+ /* In theory, it is only necessary to write the 28 bytes that the
+ ** journal header consumes to the journal file here. Then increment the
+ ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
+ ** record is written to the following sector (leaving a gap in the file
+ ** that will be implicitly filled in by the OS).
+ **
+ ** However it has been discovered that on some systems this pattern can
+ ** be significantly slower than contiguously writing data to the file,
+ ** even if that means explicitly writing data to the block of
+ ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
+ ** is done.
+ **
+ ** The loop is required here in case the sector-size is larger than the
+ ** database page size. Since the zHeader buffer is only Pager.pageSize
+ ** bytes in size, more than one call to sqlite3OsWrite() may be required
+ ** to populate the entire journal header sector.
+ */
+ for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
+ IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
+ rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
+ assert( pPager->journalHdr <= pPager->journalOff );
+ pPager->journalOff += nHeader;
+ }
+
+ return rc;
+}
+
+/*
+** The journal file must be open when this is called. A journal header file
+** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
+** file. The current location in the journal file is given by
+** pPager->journalOff. See comments above function writeJournalHdr() for
+** a description of the journal header format.
+**
+** If the header is read successfully, *pNRec is set to the number of
+** page records following this header and *pDbSize is set to the size of the
+** database before the transaction began, in pages. Also, pPager->cksumInit
+** is set to the value read from the journal header. SQLITE_OK is returned
+** in this case.
+**
+** If the journal header file appears to be corrupted, SQLITE_DONE is
+** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes
+** cannot be read from the journal file an error code is returned.
+*/
+static int readJournalHdr(
+ Pager *pPager, /* Pager object */
+ int isHot,
+ i64 journalSize, /* Size of the open journal file in bytes */
+ u32 *pNRec, /* OUT: Value read from the nRec field */
+ u32 *pDbSize /* OUT: Value of original database size field */
+){
+ int rc; /* Return code */
+ unsigned char aMagic[8]; /* A buffer to hold the magic header */
+ i64 iHdrOff; /* Offset of journal header being read */
+
+ assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
+
+ /* Advance Pager.journalOff to the start of the next sector. If the
+ ** journal file is too small for there to be a header stored at this
+ ** point, return SQLITE_DONE.
+ */
+ pPager->journalOff = journalHdrOffset(pPager);
+ if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
+ return SQLITE_DONE;
+ }
+ iHdrOff = pPager->journalOff;
+
+ /* Read in the first 8 bytes of the journal header. If they do not match
+ ** the magic string found at the start of each journal header, return
+ ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
+ ** proceed.
+ */
+ if( isHot || iHdrOff!=pPager->journalHdr ){
+ rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
+ if( rc ){
+ return rc;
+ }
+ if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
+ return SQLITE_DONE;
+ }
+ }
+
+ /* Read the first three 32-bit fields of the journal header: The nRec
+ ** field, the checksum-initializer and the database size at the start
+ ** of the transaction. Return an error code if anything goes wrong.
+ */
+ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
+ || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
+ || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
+ ){
+ return rc;
+ }
+
+ if( pPager->journalOff==0 ){
+ u32 iPageSize; /* Page-size field of journal header */
+ u32 iSectorSize; /* Sector-size field of journal header */
+
+ /* Read the page-size and sector-size journal header fields. */
+ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
+ || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
+ ){
+ return rc;
+ }
+
+ /* Versions of SQLite prior to 3.5.8 set the page-size field of the
+ ** journal header to zero. In this case, assume that the Pager.pageSize
+ ** variable is already set to the correct page size.
+ */
+ if( iPageSize==0 ){
+ iPageSize = pPager->pageSize;
+ }
+
+ /* Check that the values read from the page-size and sector-size fields
+ ** are within range. To be 'in range', both values need to be a power
+ ** of two greater than or equal to 512 or 32, and not greater than their
+ ** respective compile time maximum limits.
+ */
+ if( iPageSize<512 || iSectorSize<32
+ || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
+ || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
+ ){
+ /* If the either the page-size or sector-size in the journal-header is
+ ** invalid, then the process that wrote the journal-header must have
+ ** crashed before the header was synced. In this case stop reading
+ ** the journal file here.
+ */
+ return SQLITE_DONE;
+ }
+
+ /* Update the page-size to match the value read from the journal.
+ ** Use a testcase() macro to make sure that malloc failure within
+ ** PagerSetPagesize() is tested.
+ */
+ rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
+ testcase( rc!=SQLITE_OK );
+
+ /* Update the assumed sector-size to match the value used by
+ ** the process that created this journal. If this journal was
+ ** created by a process other than this one, then this routine
+ ** is being called from within pager_playback(). The local value
+ ** of Pager.sectorSize is restored at the end of that routine.
+ */
+ pPager->sectorSize = iSectorSize;
+ }
+
+ pPager->journalOff += JOURNAL_HDR_SZ(pPager);
+ return rc;
+}
+
+
+/*
+** Write the supplied master journal name into the journal file for pager
+** pPager at the current location. The master journal name must be the last
+** thing written to a journal file. If the pager is in full-sync mode, the
+** journal file descriptor is advanced to the next sector boundary before
+** anything is written. The format is:
+**
+** + 4 bytes: PAGER_MJ_PGNO.
+** + N bytes: Master journal filename in utf-8.
+** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
+** + 4 bytes: Master journal name checksum.
+** + 8 bytes: aJournalMagic[].
+**
+** The master journal page checksum is the sum of the bytes in the master
+** journal name, where each byte is interpreted as a signed 8-bit integer.
+**
+** If zMaster is a NULL pointer (occurs for a single database transaction),
+** this call is a no-op.
+*/
+static int writeMasterJournal(Pager *pPager, const char *zMaster){
+ int rc; /* Return code */
+ int nMaster; /* Length of string zMaster */
+ i64 iHdrOff; /* Offset of header in journal file */
+ i64 jrnlSize; /* Size of journal file on disk */
+ u32 cksum = 0; /* Checksum of string zMaster */
+
+ assert( pPager->setMaster==0 );
+ assert( !pagerUseWal(pPager) );
+
+ if( !zMaster
+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ ){
+ return SQLITE_OK;
+ }
+ pPager->setMaster = 1;
+ assert( isOpen(pPager->jfd) );
+ assert( pPager->journalHdr <= pPager->journalOff );
+
+ /* Calculate the length in bytes and the checksum of zMaster */
+ for(nMaster=0; zMaster[nMaster]; nMaster++){
+ cksum += zMaster[nMaster];
+ }
+
+ /* If in full-sync mode, advance to the next disk sector before writing
+ ** the master journal name. This is in case the previous page written to
+ ** the journal has already been synced.
+ */
+ if( pPager->fullSync ){
+ pPager->journalOff = journalHdrOffset(pPager);
+ }
+ iHdrOff = pPager->journalOff;
+
+ /* Write the master journal data to the end of the journal file. If
+ ** an error occurs, return the error code to the caller.
+ */
+ if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
+ || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
+ || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
+ || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
+ || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8)))
+ ){
+ return rc;
+ }
+ pPager->journalOff += (nMaster+20);
+
+ /* If the pager is in peristent-journal mode, then the physical
+ ** journal-file may extend past the end of the master-journal name
+ ** and 8 bytes of magic data just written to the file. This is
+ ** dangerous because the code to rollback a hot-journal file
+ ** will not be able to find the master-journal name to determine
+ ** whether or not the journal is hot.
+ **
+ ** Easiest thing to do in this scenario is to truncate the journal
+ ** file to the required size.
+ */
+ if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
+ && jrnlSize>pPager->journalOff
+ ){
+ rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
+ }
+ return rc;
+}
+
+/*
+** Find a page in the hash table given its page number. Return
+** a pointer to the page or NULL if the requested page is not
+** already in memory.
+*/
+static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
+ PgHdr *p; /* Return value */
+
+ /* It is not possible for a call to PcacheFetch() with createFlag==0 to
+ ** fail, since no attempt to allocate dynamic memory will be made.
+ */
+ (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
+ return p;
+}
+
+/*
+** Discard the entire contents of the in-memory page-cache.
+*/
+static void pager_reset(Pager *pPager){
+ sqlite3BackupRestart(pPager->pBackup);
+ sqlite3PcacheClear(pPager->pPCache);
+}
+
+/*
+** Free all structures in the Pager.aSavepoint[] array and set both
+** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
+** if it is open and the pager is not in exclusive mode.
+*/
+static void releaseAllSavepoints(Pager *pPager){
+ int ii; /* Iterator for looping through Pager.aSavepoint */
+ for(ii=0; ii<pPager->nSavepoint; ii++){
+ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
+ }
+ if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){
+ sqlite3OsClose(pPager->sjfd);
+ }
+ sqlite3_free(pPager->aSavepoint);
+ pPager->aSavepoint = 0;
+ pPager->nSavepoint = 0;
+ pPager->nSubRec = 0;
+}
+
+/*
+** Set the bit number pgno in the PagerSavepoint.pInSavepoint
+** bitvecs of all open savepoints. Return SQLITE_OK if successful
+** or SQLITE_NOMEM if a malloc failure occurs.
+*/
+static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
+ int ii; /* Loop counter */
+ int rc = SQLITE_OK; /* Result code */
+
+ for(ii=0; ii<pPager->nSavepoint; ii++){
+ PagerSavepoint *p = &pPager->aSavepoint[ii];
+ if( pgno<=p->nOrig ){
+ rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
+ testcase( rc==SQLITE_NOMEM );
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ }
+ }
+ return rc;
+}
+
+/*
+** This function is a no-op if the pager is in exclusive mode and not
+** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
+** state.
+**
+** If the pager is not in exclusive-access mode, the database file is
+** completely unlocked. If the file is unlocked and the file-system does
+** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
+** closed (if it is open).
+**
+** If the pager is in ERROR state when this function is called, the
+** contents of the pager cache are discarded before switching back to
+** the OPEN state. Regardless of whether the pager is in exclusive-mode
+** or not, any journal file left in the file-system will be treated
+** as a hot-journal and rolled back the next time a read-transaction
+** is opened (by this or by any other connection).
+*/
+static void pager_unlock(Pager *pPager){
+
+ assert( pPager->eState==PAGER_READER
+ || pPager->eState==PAGER_OPEN
+ || pPager->eState==PAGER_ERROR
+ );
+
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
+ releaseAllSavepoints(pPager);
+
+ if( pagerUseWal(pPager) ){
+ assert( !isOpen(pPager->jfd) );
+ sqlite3WalEndReadTransaction(pPager->pWal);
+ pPager->eState = PAGER_OPEN;
+ }else if( !pPager->exclusiveMode ){
+ int rc; /* Error code returned by pagerUnlockDb() */
+ int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
+
+ /* If the operating system support deletion of open files, then
+ ** close the journal file when dropping the database lock. Otherwise
+ ** another connection with journal_mode=delete might delete the file
+ ** out from under us.
+ */
+ assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 );
+ assert( (PAGER_JOURNALMODE_OFF & 5)!=1 );
+ assert( (PAGER_JOURNALMODE_WAL & 5)!=1 );
+ assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 );
+ assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
+ assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
+ if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
+ || 1!=(pPager->journalMode & 5)
+ ){
+ sqlite3OsClose(pPager->jfd);
+ }
+
+ /* If the pager is in the ERROR state and the call to unlock the database
+ ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
+ ** above the #define for UNKNOWN_LOCK for an explanation of why this
+ ** is necessary.
+ */
+ rc = pagerUnlockDb(pPager, NO_LOCK);
+ if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
+ pPager->eLock = UNKNOWN_LOCK;
+ }
+
+ /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
+ ** without clearing the error code. This is intentional - the error
+ ** code is cleared and the cache reset in the block below.
+ */
+ assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
+ pPager->changeCountDone = 0;
+ pPager->eState = PAGER_OPEN;
+ }
+
+ /* If Pager.errCode is set, the contents of the pager cache cannot be
+ ** trusted. Now that there are no outstanding references to the pager,
+ ** it can safely move back to PAGER_OPEN state. This happens in both
+ ** normal and exclusive-locking mode.
+ */
+ if( pPager->errCode ){
+ assert( !MEMDB );
+ pager_reset(pPager);
+ pPager->changeCountDone = pPager->tempFile;
+ pPager->eState = PAGER_OPEN;
+ pPager->errCode = SQLITE_OK;
+ }
+
+ pPager->journalOff = 0;
+ pPager->journalHdr = 0;
+ pPager->setMaster = 0;
+}
+
+/*
+** This function is called whenever an IOERR or FULL error that requires
+** the pager to transition into the ERROR state may ahve occurred.
+** The first argument is a pointer to the pager structure, the second
+** the error-code about to be returned by a pager API function. The
+** value returned is a copy of the second argument to this function.
+**
+** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
+** IOERR sub-codes, the pager enters the ERROR state and the error code
+** is stored in Pager.errCode. While the pager remains in the ERROR state,
+** all major API calls on the Pager will immediately return Pager.errCode.
+**
+** The ERROR state indicates that the contents of the pager-cache
+** cannot be trusted. This state can be cleared by completely discarding
+** the contents of the pager-cache. If a transaction was active when
+** the persistent error occurred, then the rollback journal may need
+** to be replayed to restore the contents of the database file (as if
+** it were a hot-journal).
+*/
+static int pager_error(Pager *pPager, int rc){
+ int rc2 = rc & 0xff;
+ assert( rc==SQLITE_OK || !MEMDB );
+ assert(
+ pPager->errCode==SQLITE_FULL ||
+ pPager->errCode==SQLITE_OK ||
+ (pPager->errCode & 0xff)==SQLITE_IOERR
+ );
+ if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
+ pPager->errCode = rc;
+ pPager->eState = PAGER_ERROR;
+ }
+ return rc;
+}
+
+static int pager_truncate(Pager *pPager, Pgno nPage);
+
+/*
+** This routine ends a transaction. A transaction is usually ended by
+** either a COMMIT or a ROLLBACK operation. This routine may be called
+** after rollback of a hot-journal, or if an error occurs while opening
+** the journal file or writing the very first journal-header of a
+** database transaction.
+**
+** This routine is never called in PAGER_ERROR state. If it is called
+** in PAGER_NONE or PAGER_SHARED state and the lock held is less
+** exclusive than a RESERVED lock, it is a no-op.
+**
+** Otherwise, any active savepoints are released.
+**
+** If the journal file is open, then it is "finalized". Once a journal
+** file has been finalized it is not possible to use it to roll back a
+** transaction. Nor will it be considered to be a hot-journal by this
+** or any other database connection. Exactly how a journal is finalized
+** depends on whether or not the pager is running in exclusive mode and
+** the current journal-mode (Pager.journalMode value), as follows:
+**
+** journalMode==MEMORY
+** Journal file descriptor is simply closed. This destroys an
+** in-memory journal.
+**
+** journalMode==TRUNCATE
+** Journal file is truncated to zero bytes in size.
+**
+** journalMode==PERSIST
+** The first 28 bytes of the journal file are zeroed. This invalidates
+** the first journal header in the file, and hence the entire journal
+** file. An invalid journal file cannot be rolled back.
+**
+** journalMode==DELETE
+** The journal file is closed and deleted using sqlite3OsDelete().
+**
+** If the pager is running in exclusive mode, this method of finalizing
+** the journal file is never used. Instead, if the journalMode is
+** DELETE and the pager is in exclusive mode, the method described under
+** journalMode==PERSIST is used instead.
+**
+** After the journal is finalized, the pager moves to PAGER_READER state.
+** If running in non-exclusive rollback mode, the lock on the file is
+** downgraded to a SHARED_LOCK.
+**
+** SQLITE_OK is returned if no error occurs. If an error occurs during
+** any of the IO operations to finalize the journal file or unlock the
+** database then the IO error code is returned to the user. If the
+** operation to finalize the journal file fails, then the code still
+** tries to unlock the database file if not in exclusive mode. If the
+** unlock operation fails as well, then the first error code related
+** to the first error encountered (the journal finalization one) is
+** returned.
+*/
+static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
+ int rc = SQLITE_OK; /* Error code from journal finalization operation */
+ int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
+
+ /* Do nothing if the pager does not have an open write transaction
+ ** or at least a RESERVED lock. This function may be called when there
+ ** is no write-transaction active but a RESERVED or greater lock is
+ ** held under two circumstances:
+ **
+ ** 1. After a successful hot-journal rollback, it is called with
+ ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
+ **
+ ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
+ ** lock switches back to locking_mode=normal and then executes a
+ ** read-transaction, this function is called with eState==PAGER_READER
+ ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
+ */
+ assert( assert_pager_state(pPager) );
+ assert( pPager->eState!=PAGER_ERROR );
+ if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
+ return SQLITE_OK;
+ }
+
+ releaseAllSavepoints(pPager);
+ assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
+ if( isOpen(pPager->jfd) ){
+ assert( !pagerUseWal(pPager) );
+
+ /* Finalize the journal file. */
+ if( sqlite3IsMemJournal(pPager->jfd) ){
+ assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY );
+ sqlite3OsClose(pPager->jfd);
+ }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
+ if( pPager->journalOff==0 ){
+ rc = SQLITE_OK;
+ }else{
+ rc = sqlite3OsTruncate(pPager->jfd, 0);
+ }
+ pPager->journalOff = 0;
+ }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
+ || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
+ ){
+ rc = zeroJournalHdr(pPager, hasMaster);
+ pPager->journalOff = 0;
+ }else{
+ /* This branch may be executed with Pager.journalMode==MEMORY if
+ ** a hot-journal was just rolled back. In this case the journal
+ ** file should be closed and deleted. If this connection writes to
+ ** the database file, it will do so using an in-memory journal.
+ */
+ int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
+ assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ );
+ sqlite3OsClose(pPager->jfd);
+ if( bDelete ){
+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+ }
+ }
+ }
+
+#ifdef SQLITE_CHECK_PAGES
+ sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
+ if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
+ PgHdr *p = pager_lookup(pPager, 1);
+ if( p ){
+ p->pageHash = 0;
+ sqlite3PagerUnref(p);
+ }
+ }
+#endif
+
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
+ pPager->nRec = 0;
+ sqlite3PcacheCleanAll(pPager->pPCache);
+ sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
+
+ if( pagerUseWal(pPager) ){
+ /* Drop the WAL write-lock, if any. Also, if the connection was in
+ ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
+ ** lock held on the database file.
+ */
+ rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
+ assert( rc2==SQLITE_OK );
+ }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
+ /* This branch is taken when committing a transaction in rollback-journal
+ ** mode if the database file on disk is larger than the database image.
+ ** At this point the journal has been finalized and the transaction
+ ** successfully committed, but the EXCLUSIVE lock is still held on the
+ ** file. So it is safe to truncate the database file to its minimum
+ ** required size. */
+ assert( pPager->eLock==EXCLUSIVE_LOCK );
+ rc = pager_truncate(pPager, pPager->dbSize);
+ }
+
+ if( !pPager->exclusiveMode
+ && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
+ ){
+ rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
+ pPager->changeCountDone = 0;
+ }
+ pPager->eState = PAGER_READER;
+ pPager->setMaster = 0;
+
+ return (rc==SQLITE_OK?rc2:rc);
+}
+
+/*
+** Execute a rollback if a transaction is active and unlock the
+** database file.
+**
+** If the pager has already entered the ERROR state, do not attempt
+** the rollback at this time. Instead, pager_unlock() is called. The
+** call to pager_unlock() will discard all in-memory pages, unlock
+** the database file and move the pager back to OPEN state. If this
+** means that there is a hot-journal left in the file-system, the next
+** connection to obtain a shared lock on the pager (which may be this one)
+** will roll it back.
+**
+** If the pager has not already entered the ERROR state, but an IO or
+** malloc error occurs during a rollback, then this will itself cause
+** the pager to enter the ERROR state. Which will be cleared by the
+** call to pager_unlock(), as described above.
+*/
+static void pagerUnlockAndRollback(Pager *pPager){
+ if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
+ assert( assert_pager_state(pPager) );
+ if( pPager->eState>=PAGER_WRITER_LOCKED ){
+ sqlite3BeginBenignMalloc();
+ sqlite3PagerRollback(pPager);
+ sqlite3EndBenignMalloc();
+ }else if( !pPager->exclusiveMode ){
+ assert( pPager->eState==PAGER_READER );
+ pager_end_transaction(pPager, 0, 0);
+ }
+ }
+ pager_unlock(pPager);
+}
+
+/*
+** Parameter aData must point to a buffer of pPager->pageSize bytes
+** of data. Compute and return a checksum based ont the contents of the
+** page of data and the current value of pPager->cksumInit.
+**
+** This is not a real checksum. It is really just the sum of the
+** random initial value (pPager->cksumInit) and every 200th byte
+** of the page data, starting with byte offset (pPager->pageSize%200).
+** Each byte is interpreted as an 8-bit unsigned integer.
+**
+** Changing the formula used to compute this checksum results in an
+** incompatible journal file format.
+**
+** If journal corruption occurs due to a power failure, the most likely
+** scenario is that one end or the other of the record will be changed.
+** It is much less likely that the two ends of the journal record will be
+** correct and the middle be corrupt. Thus, this "checksum" scheme,
+** though fast and simple, catches the mostly likely kind of corruption.
+*/
+static u32 pager_cksum(Pager *pPager, const u8 *aData){
+ u32 cksum = pPager->cksumInit; /* Checksum value to return */
+ int i = pPager->pageSize-200; /* Loop counter */
+ while( i>0 ){
+ cksum += aData[i];
+ i -= 200;
+ }
+ return cksum;
+}
+
+/*
+** Report the current page size and number of reserved bytes back
+** to the codec.
+*/
+#ifdef SQLITE_HAS_CODEC
+static void pagerReportSize(Pager *pPager){
+ if( pPager->xCodecSizeChng ){
+ pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
+ (int)pPager->nReserve);
+ }
+}
+#else
+# define pagerReportSize(X) /* No-op if we do not support a codec */
+#endif
+
+/*
+** Read a single page from either the journal file (if isMainJrnl==1) or
+** from the sub-journal (if isMainJrnl==0) and playback that page.
+** The page begins at offset *pOffset into the file. The *pOffset
+** value is increased to the start of the next page in the journal.
+**
+** The main rollback journal uses checksums - the statement journal does
+** not.
+**
+** If the page number of the page record read from the (sub-)journal file
+** is greater than the current value of Pager.dbSize, then playback is
+** skipped and SQLITE_OK is returned.
+**
+** If pDone is not NULL, then it is a record of pages that have already
+** been played back. If the page at *pOffset has already been played back
+** (if the corresponding pDone bit is set) then skip the playback.
+** Make sure the pDone bit corresponding to the *pOffset page is set
+** prior to returning.
+**
+** If the page record is successfully read from the (sub-)journal file
+** and played back, then SQLITE_OK is returned. If an IO error occurs
+** while reading the record from the (sub-)journal file or while writing
+** to the database file, then the IO error code is returned. If data
+** is successfully read from the (sub-)journal file but appears to be
+** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
+** two circumstances:
+**
+** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
+** * If the record is being rolled back from the main journal file
+** and the checksum field does not match the record content.
+**
+** Neither of these two scenarios are possible during a savepoint rollback.
+**
+** If this is a savepoint rollback, then memory may have to be dynamically
+** allocated by this function. If this is the case and an allocation fails,
+** SQLITE_NOMEM is returned.
+*/
+static int pager_playback_one_page(
+ Pager *pPager, /* The pager being played back */
+ i64 *pOffset, /* Offset of record to playback */
+ Bitvec *pDone, /* Bitvec of pages already played back */
+ int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */
+ int isSavepnt /* True for a savepoint rollback */
+){
+ int rc;
+ PgHdr *pPg; /* An existing page in the cache */
+ Pgno pgno; /* The page number of a page in journal */
+ u32 cksum; /* Checksum used for sanity checking */
+ char *aData; /* Temporary storage for the page */
+ sqlite3_file *jfd; /* The file descriptor for the journal file */
+ int isSynced; /* True if journal page is synced */
+
+ assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
+ assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
+ assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */
+ assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */
+
+ aData = pPager->pTmpSpace;
+ assert( aData ); /* Temp storage must have already been allocated */
+ assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
+
+ /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
+ ** or savepoint rollback done at the request of the caller) or this is
+ ** a hot-journal rollback. If it is a hot-journal rollback, the pager
+ ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
+ ** only reads from the main journal, not the sub-journal.
+ */
+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD
+ || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
+ );
+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );
+
+ /* Read the page number and page data from the journal or sub-journal
+ ** file. Return an error code to the caller if an IO error occurs.
+ */
+ jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
+ rc = read32bits(jfd, *pOffset, &pgno);
+ if( rc!=SQLITE_OK ) return rc;
+ rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
+ if( rc!=SQLITE_OK ) return rc;
+ *pOffset += pPager->pageSize + 4 + isMainJrnl*4;
+
+ /* Sanity checking on the page. This is more important that I originally
+ ** thought. If a power failure occurs while the journal is being written,
+ ** it could cause invalid data to be written into the journal. We need to
+ ** detect this invalid data (with high probability) and ignore it.
+ */
+ if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
+ assert( !isSavepnt );
+ return SQLITE_DONE;
+ }
+ if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
+ return SQLITE_OK;
+ }
+ if( isMainJrnl ){
+ rc = read32bits(jfd, (*pOffset)-4, &cksum);
+ if( rc ) return rc;
+ if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
+ return SQLITE_DONE;
+ }
+ }
+
+ /* If this page has already been played by before during the current
+ ** rollback, then don't bother to play it back again.
+ */
+ if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* When playing back page 1, restore the nReserve setting
+ */
+ if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
+ pPager->nReserve = ((u8*)aData)[20];
+ pagerReportSize(pPager);
+ }
+
+ /* If the pager is in CACHEMOD state, then there must be a copy of this
+ ** page in the pager cache. In this case just update the pager cache,
+ ** not the database file. The page is left marked dirty in this case.
+ **
+ ** An exception to the above rule: If the database is in no-sync mode
+ ** and a page is moved during an incremental vacuum then the page may
+ ** not be in the pager cache. Later: if a malloc() or IO error occurs
+ ** during a Movepage() call, then the page may not be in the cache
+ ** either. So the condition described in the above paragraph is not
+ ** assert()able.
+ **
+ ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
+ ** pager cache if it exists and the main file. The page is then marked
+ ** not dirty. Since this code is only executed in PAGER_OPEN state for
+ ** a hot-journal rollback, it is guaranteed that the page-cache is empty
+ ** if the pager is in OPEN state.
+ **
+ ** Ticket #1171: The statement journal might contain page content that is
+ ** different from the page content at the start of the transaction.
+ ** This occurs when a page is changed prior to the start of a statement
+ ** then changed again within the statement. When rolling back such a
+ ** statement we must not write to the original database unless we know
+ ** for certain that original page contents are synced into the main rollback
+ ** journal. Otherwise, a power loss might leave modified data in the
+ ** database file without an entry in the rollback journal that can
+ ** restore the database to its original form. Two conditions must be
+ ** met before writing to the database files. (1) the database must be
+ ** locked. (2) we know that the original page content is fully synced
+ ** in the main journal either because the page is not in cache or else
+ ** the page is marked as needSync==0.
+ **
+ ** 2008-04-14: When attempting to vacuum a corrupt database file, it
+ ** is possible to fail a statement on a database that does not yet exist.
+ ** Do not attempt to write if database file has never been opened.
+ */
+ if( pagerUseWal(pPager) ){
+ pPg = 0;
+ }else{
+ pPg = pager_lookup(pPager, pgno);
+ }
+ assert( pPg || !MEMDB );
+ assert( pPager->eState!=PAGER_OPEN || pPg==0 );
+ PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
+ PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
+ (isMainJrnl?"main-journal":"sub-journal")
+ ));
+ if( isMainJrnl ){
+ isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
+ }else{
+ isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
+ }
+ if( isOpen(pPager->fd)
+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
+ && isSynced
+ ){
+ i64 ofst = (pgno-1)*(i64)pPager->pageSize;
+ testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
+ assert( !pagerUseWal(pPager) );
+ rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst);
+ if( pgno>pPager->dbFileSize ){
+ pPager->dbFileSize = pgno;
+ }
+ if( pPager->pBackup ){
+ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
+ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
+ CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
+ }
+ }else if( !isMainJrnl && pPg==0 ){
+ /* If this is a rollback of a savepoint and data was not written to
+ ** the database and the page is not in-memory, there is a potential
+ ** problem. When the page is next fetched by the b-tree layer, it
+ ** will be read from the database file, which may or may not be
+ ** current.
+ **
+ ** There are a couple of different ways this can happen. All are quite
+ ** obscure. When running in synchronous mode, this can only happen
+ ** if the page is on the free-list at the start of the transaction, then
+ ** populated, then moved using sqlite3PagerMovepage().
+ **
+ ** The solution is to add an in-memory page to the cache containing
+ ** the data just read from the sub-journal. Mark the page as dirty
+ ** and if the pager requires a journal-sync, then mark the page as
+ ** requiring a journal-sync before it is written.
+ */
+ assert( isSavepnt );
+ assert( pPager->doNotSpill==0 );
+ pPager->doNotSpill++;
+ rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
+ assert( pPager->doNotSpill==1 );
+ pPager->doNotSpill--;
+ if( rc!=SQLITE_OK ) return rc;
+ pPg->flags &= ~PGHDR_NEED_READ;
+ sqlite3PcacheMakeDirty(pPg);
+ }
+ if( pPg ){
+ /* No page should ever be explicitly rolled back that is in use, except
+ ** for page 1 which is held in use in order to keep the lock on the
+ ** database active. However such a page may be rolled back as a result
+ ** of an internal error resulting in an automatic call to
+ ** sqlite3PagerRollback().
+ */
+ void *pData;
+ pData = pPg->pData;
+ memcpy(pData, (u8*)aData, pPager->pageSize);
+ pPager->xReiniter(pPg);
+ if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
+ /* If the contents of this page were just restored from the main
+ ** journal file, then its content must be as they were when the
+ ** transaction was first opened. In this case we can mark the page
+ ** as clean, since there will be no need to write it out to the
+ ** database.
+ **
+ ** There is one exception to this rule. If the page is being rolled
+ ** back as part of a savepoint (or statement) rollback from an
+ ** unsynced portion of the main journal file, then it is not safe
+ ** to mark the page as clean. This is because marking the page as
+ ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
+ ** already in the journal file (recorded in Pager.pInJournal) and
+ ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to
+ ** again within this transaction, it will be marked as dirty but
+ ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially
+ ** be written out into the database file before its journal file
+ ** segment is synced. If a crash occurs during or following this,
+ ** database corruption may ensue.
+ */
+ assert( !pagerUseWal(pPager) );
+ sqlite3PcacheMakeClean(pPg);
+ }
+ pager_set_pagehash(pPg);
+
+ /* If this was page 1, then restore the value of Pager.dbFileVers.
+ ** Do this before any decoding. */
+ if( pgno==1 ){
+ memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
+ }
+
+ /* Decode the page just read from disk */
+ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM);
+ sqlite3PcacheRelease(pPg);
+ }
+ return rc;
+}
+
+/*
+** Parameter zMaster is the name of a master journal file. A single journal
+** file that referred to the master journal file has just been rolled back.
+** This routine checks if it is possible to delete the master journal file,
+** and does so if it is.
+**
+** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
+** available for use within this function.
+**
+** When a master journal file is created, it is populated with the names
+** of all of its child journals, one after another, formatted as utf-8
+** encoded text. The end of each child journal file is marked with a
+** nul-terminator byte (0x00). i.e. the entire contents of a master journal
+** file for a transaction involving two databases might be:
+**
+** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
+**
+** A master journal file may only be deleted once all of its child
+** journals have been rolled back.
+**
+** This function reads the contents of the master-journal file into
+** memory and loops through each of the child journal names. For
+** each child journal, it checks if:
+**
+** * if the child journal exists, and if so
+** * if the child journal contains a reference to master journal
+** file zMaster
+**
+** If a child journal can be found that matches both of the criteria
+** above, this function returns without doing anything. Otherwise, if
+** no such child journal can be found, file zMaster is deleted from
+** the file-system using sqlite3OsDelete().
+**
+** If an IO error within this function, an error code is returned. This
+** function allocates memory by calling sqlite3Malloc(). If an allocation
+** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
+** occur, SQLITE_OK is returned.
+**
+** TODO: This function allocates a single block of memory to load
+** the entire contents of the master journal file. This could be
+** a couple of kilobytes or so - potentially larger than the page
+** size.
+*/
+static int pager_delmaster(Pager *pPager, const char *zMaster){
+ sqlite3_vfs *pVfs = pPager->pVfs;
+ int rc; /* Return code */
+ sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */
+ sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
+ char *zMasterJournal = 0; /* Contents of master journal file */
+ i64 nMasterJournal; /* Size of master journal file */
+ char *zJournal; /* Pointer to one journal within MJ file */
+ char *zMasterPtr; /* Space to hold MJ filename from a journal file */
+ int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */
+
+ /* Allocate space for both the pJournal and pMaster file descriptors.
+ ** If successful, open the master journal file for reading.
+ */
+ pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
+ pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
+ if( !pMaster ){
+ rc = SQLITE_NOMEM;
+ }else{
+ const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
+ rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
+ }
+ if( rc!=SQLITE_OK ) goto delmaster_out;
+
+ /* Load the entire master journal file into space obtained from
+ ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain
+ ** sufficient space (in zMasterPtr) to hold the names of master
+ ** journal files extracted from regular rollback-journals.
+ */
+ rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
+ if( rc!=SQLITE_OK ) goto delmaster_out;
+ nMasterPtr = pVfs->mxPathname+1;
+ zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
+ if( !zMasterJournal ){
+ rc = SQLITE_NOMEM;
+ goto delmaster_out;
+ }
+ zMasterPtr = &zMasterJournal[nMasterJournal+1];
+ rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
+ if( rc!=SQLITE_OK ) goto delmaster_out;
+ zMasterJournal[nMasterJournal] = 0;
+
+ zJournal = zMasterJournal;
+ while( (zJournal-zMasterJournal)<nMasterJournal ){
+ int exists;
+ rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
+ if( rc!=SQLITE_OK ){
+ goto delmaster_out;
+ }
+ if( exists ){
+ /* One of the journals pointed to by the master journal exists.
+ ** Open it and check if it points at the master journal. If
+ ** so, return without deleting the master journal file.
+ */
+ int c;
+ int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
+ rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
+ if( rc!=SQLITE_OK ){
+ goto delmaster_out;
+ }
+
+ rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
+ sqlite3OsClose(pJournal);
+ if( rc!=SQLITE_OK ){
+ goto delmaster_out;
+ }
+
+ c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
+ if( c ){
+ /* We have a match. Do not delete the master journal file. */
+ goto delmaster_out;
+ }
+ }
+ zJournal += (sqlite3Strlen30(zJournal)+1);
+ }
+
+ sqlite3OsClose(pMaster);
+ rc = sqlite3OsDelete(pVfs, zMaster, 0);
+
+delmaster_out:
+ sqlite3_free(zMasterJournal);
+ if( pMaster ){
+ sqlite3OsClose(pMaster);
+ assert( !isOpen(pJournal) );
+ sqlite3_free(pMaster);
+ }
+ return rc;
+}
+
+
+/*
+** This function is used to change the actual size of the database
+** file in the file-system. This only happens when committing a transaction,
+** or rolling back a transaction (including rolling back a hot-journal).
+**
+** If the main database file is not open, or the pager is not in either
+** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
+** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
+** If the file on disk is currently larger than nPage pages, then use the VFS
+** xTruncate() method to truncate it.
+**
+** Or, it might might be the case that the file on disk is smaller than
+** nPage pages. Some operating system implementations can get confused if
+** you try to truncate a file to some size that is larger than it
+** currently is, so detect this case and write a single zero byte to
+** the end of the new file instead.
+**
+** If successful, return SQLITE_OK. If an IO error occurs while modifying
+** the database file, return the error code to the caller.
+*/
+static int pager_truncate(Pager *pPager, Pgno nPage){
+ int rc = SQLITE_OK;
+ assert( pPager->eState!=PAGER_ERROR );
+ assert( pPager->eState!=PAGER_READER );
+
+ if( isOpen(pPager->fd)
+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
+ ){
+ i64 currentSize, newSize;
+ int szPage = pPager->pageSize;
+ assert( pPager->eLock==EXCLUSIVE_LOCK );
+ /* TODO: Is it safe to use Pager.dbFileSize here? */
+ rc = sqlite3OsFileSize(pPager->fd, &currentSize);
+ newSize = szPage*(i64)nPage;
+ if( rc==SQLITE_OK && currentSize!=newSize ){
+ if( currentSize>newSize ){
+ rc = sqlite3OsTruncate(pPager->fd, newSize);
+ }else if( (currentSize+szPage)<=newSize ){
+ char *pTmp = pPager->pTmpSpace;
+ memset(pTmp, 0, szPage);
+ testcase( (newSize-szPage) == currentSize );
+ testcase( (newSize-szPage) > currentSize );
+ rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
+ }
+ if( rc==SQLITE_OK ){
+ pPager->dbFileSize = nPage;
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Return a sanitized version of the sector-size of OS file pFile. The
+** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
+*/
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
+ int iRet = sqlite3OsSectorSize(pFile);
+ if( iRet<32 ){
+ iRet = 512;
+ }else if( iRet>MAX_SECTOR_SIZE ){
+ assert( MAX_SECTOR_SIZE>=512 );
+ iRet = MAX_SECTOR_SIZE;
+ }
+ return iRet;
+}
+
+/*
+** Set the value of the Pager.sectorSize variable for the given
+** pager based on the value returned by the xSectorSize method
+** of the open database file. The sector size will be used used
+** to determine the size and alignment of journal header and
+** master journal pointers within created journal files.
+**
+** For temporary files the effective sector size is always 512 bytes.
+**
+** Otherwise, for non-temporary files, the effective sector size is
+** the value returned by the xSectorSize() method rounded up to 32 if
+** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
+** is greater than MAX_SECTOR_SIZE.
+**
+** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
+** the effective sector size to its minimum value (512). The purpose of
+** pPager->sectorSize is to define the "blast radius" of bytes that
+** might change if a crash occurs while writing to a single byte in
+** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero
+** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
+** size. For backwards compatibility of the rollback journal file format,
+** we cannot reduce the effective sector size below 512.
+*/
+static void setSectorSize(Pager *pPager){
+ assert( isOpen(pPager->fd) || pPager->tempFile );
+
+ if( pPager->tempFile
+ || (sqlite3OsDeviceCharacteristics(pPager->fd) &
+ SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
+ ){
+ /* Sector size doesn't matter for temporary files. Also, the file
+ ** may not have been opened yet, in which case the OsSectorSize()
+ ** call will segfault. */
+ pPager->sectorSize = 512;
+ }else{
+ pPager->sectorSize = sqlite3SectorSize(pPager->fd);
+ }
+}
+
+/*
+** Playback the journal and thus restore the database file to
+** the state it was in before we started making changes.
+**
+** The journal file format is as follows:
+**
+** (1) 8 byte prefix. A copy of aJournalMagic[].
+** (2) 4 byte big-endian integer which is the number of valid page records
+** in the journal. If this value is 0xffffffff, then compute the
+** number of page records from the journal size.
+** (3) 4 byte big-endian integer which is the initial value for the
+** sanity checksum.
+** (4) 4 byte integer which is the number of pages to truncate the
+** database to during a rollback.
+** (5) 4 byte big-endian integer which is the sector size. The header
+** is this many bytes in size.
+** (6) 4 byte big-endian integer which is the page size.
+** (7) zero padding out to the next sector size.
+** (8) Zero or more pages instances, each as follows:
+** + 4 byte page number.
+** + pPager->pageSize bytes of data.
+** + 4 byte checksum
+**
+** When we speak of the journal header, we mean the first 7 items above.
+** Each entry in the journal is an instance of the 8th item.
+**
+** Call the value from the second bullet "nRec". nRec is the number of
+** valid page entries in the journal. In most cases, you can compute the
+** value of nRec from the size of the journal file. But if a power
+** failure occurred while the journal was being written, it could be the
+** case that the size of the journal file had already been increased but
+** the extra entries had not yet made it safely to disk. In such a case,
+** the value of nRec computed from the file size would be too large. For
+** that reason, we always use the nRec value in the header.
+**
+** If the nRec value is 0xffffffff it means that nRec should be computed
+** from the file size. This value is used when the user selects the
+** no-sync option for the journal. A power failure could lead to corruption
+** in this case. But for things like temporary table (which will be
+** deleted when the power is restored) we don't care.
+**
+** If the file opened as the journal file is not a well-formed
+** journal file then all pages up to the first corrupted page are rolled
+** back (or no pages if the journal header is corrupted). The journal file
+** is then deleted and SQLITE_OK returned, just as if no corruption had
+** been encountered.
+**
+** If an I/O or malloc() error occurs, the journal-file is not deleted
+** and an error code is returned.
+**
+** The isHot parameter indicates that we are trying to rollback a journal
+** that might be a hot journal. Or, it could be that the journal is
+** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
+** If the journal really is hot, reset the pager cache prior rolling
+** back any content. If the journal is merely persistent, no reset is
+** needed.
+*/
+static int pager_playback(Pager *pPager, int isHot){
+ sqlite3_vfs *pVfs = pPager->pVfs;
+ i64 szJ; /* Size of the journal file in bytes */
+ u32 nRec; /* Number of Records in the journal */
+ u32 u; /* Unsigned loop counter */
+ Pgno mxPg = 0; /* Size of the original file in pages */
+ int rc; /* Result code of a subroutine */
+ int res = 1; /* Value returned by sqlite3OsAccess() */
+ char *zMaster = 0; /* Name of master journal file if any */
+ int needPagerReset; /* True to reset page prior to first page rollback */
+
+ /* Figure out how many records are in the journal. Abort early if
+ ** the journal is empty.
+ */
+ assert( isOpen(pPager->jfd) );
+ rc = sqlite3OsFileSize(pPager->jfd, &szJ);
+ if( rc!=SQLITE_OK ){
+ goto end_playback;
+ }
+
+ /* Read the master journal name from the journal, if it is present.
+ ** If a master journal file name is specified, but the file is not
+ ** present on disk, then the journal is not hot and does not need to be
+ ** played back.
+ **
+ ** TODO: Technically the following is an error because it assumes that
+ ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
+ ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
+ ** mxPathname is 512, which is the same as the minimum allowable value
+ ** for pageSize.
+ */
+ zMaster = pPager->pTmpSpace;
+ rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
+ if( rc==SQLITE_OK && zMaster[0] ){
+ rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
+ }
+ zMaster = 0;
+ if( rc!=SQLITE_OK || !res ){
+ goto end_playback;
+ }
+ pPager->journalOff = 0;
+ needPagerReset = isHot;
+
+ /* This loop terminates either when a readJournalHdr() or
+ ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
+ ** occurs.
+ */
+ while( 1 ){
+ /* Read the next journal header from the journal file. If there are
+ ** not enough bytes left in the journal file for a complete header, or
+ ** it is corrupted, then a process must have failed while writing it.
+ ** This indicates nothing more needs to be rolled back.
+ */
+ rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ }
+ goto end_playback;
+ }
+
+ /* If nRec is 0xffffffff, then this journal was created by a process
+ ** working in no-sync mode. This means that the rest of the journal
+ ** file consists of pages, there are no more journal headers. Compute
+ ** the value of nRec based on this assumption.
+ */
+ if( nRec==0xffffffff ){
+ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
+ nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
+ }
+
+ /* If nRec is 0 and this rollback is of a transaction created by this
+ ** process and if this is the final header in the journal, then it means
+ ** that this part of the journal was being filled but has not yet been
+ ** synced to disk. Compute the number of pages based on the remaining
+ ** size of the file.
+ **
+ ** The third term of the test was added to fix ticket #2565.
+ ** When rolling back a hot journal, nRec==0 always means that the next
+ ** chunk of the journal contains zero pages to be rolled back. But
+ ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
+ ** the journal, it means that the journal might contain additional
+ ** pages that need to be rolled back and that the number of pages
+ ** should be computed based on the journal file size.
+ */
+ if( nRec==0 && !isHot &&
+ pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
+ nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
+ }
+
+ /* If this is the first header read from the journal, truncate the
+ ** database file back to its original size.
+ */
+ if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
+ rc = pager_truncate(pPager, mxPg);
+ if( rc!=SQLITE_OK ){
+ goto end_playback;
+ }
+ pPager->dbSize = mxPg;
+ }
+
+ /* Copy original pages out of the journal and back into the
+ ** database file and/or page cache.
+ */
+ for(u=0; u<nRec; u++){
+ if( needPagerReset ){
+ pager_reset(pPager);
+ needPagerReset = 0;
+ }
+ rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_DONE ){
+ pPager->journalOff = szJ;
+ break;
+ }else if( rc==SQLITE_IOERR_SHORT_READ ){
+ /* If the journal has been truncated, simply stop reading and
+ ** processing the journal. This might happen if the journal was
+ ** not completely written and synced prior to a crash. In that
+ ** case, the database should have never been written in the
+ ** first place so it is OK to simply abandon the rollback. */
+ rc = SQLITE_OK;
+ goto end_playback;
+ }else{
+ /* If we are unable to rollback, quit and return the error
+ ** code. This will cause the pager to enter the error state
+ ** so that no further harm will be done. Perhaps the next
+ ** process to come along will be able to rollback the database.
+ */
+ goto end_playback;
+ }
+ }
+ }
+ }
+ /*NOTREACHED*/
+ assert( 0 );
+
+end_playback:
+ /* Following a rollback, the database file should be back in its original
+ ** state prior to the start of the transaction, so invoke the
+ ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
+ ** assertion that the transaction counter was modified.
+ */
+#ifdef SQLITE_DEBUG
+ if( pPager->fd->pMethods ){
+ sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
+ }
+#endif
+
+ /* If this playback is happening automatically as a result of an IO or
+ ** malloc error that occurred after the change-counter was updated but
+ ** before the transaction was committed, then the change-counter
+ ** modification may just have been reverted. If this happens in exclusive
+ ** mode, then subsequent transactions performed by the connection will not
+ ** update the change-counter at all. This may lead to cache inconsistency
+ ** problems for other processes at some point in the future. So, just
+ ** in case this has happened, clear the changeCountDone flag now.
+ */
+ pPager->changeCountDone = pPager->tempFile;
+
+ if( rc==SQLITE_OK ){
+ zMaster = pPager->pTmpSpace;
+ rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
+ testcase( rc!=SQLITE_OK );
+ }
+ if( rc==SQLITE_OK
+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
+ ){
+ rc = sqlite3PagerSync(pPager);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
+ testcase( rc!=SQLITE_OK );
+ }
+ if( rc==SQLITE_OK && zMaster[0] && res ){
+ /* If there was a master journal and this routine will return success,
+ ** see if it is possible to delete the master journal.
+ */
+ rc = pager_delmaster(pPager, zMaster);
+ testcase( rc!=SQLITE_OK );
+ }
+
+ /* The Pager.sectorSize variable may have been updated while rolling
+ ** back a journal created by a process with a different sector size
+ ** value. Reset it to the correct value for this process.
+ */
+ setSectorSize(pPager);
+ return rc;
+}
+
+
+/*
+** Read the content for page pPg out of the database file and into
+** pPg->pData. A shared lock or greater must be held on the database
+** file before this function is called.
+**
+** If page 1 is read, then the value of Pager.dbFileVers[] is set to
+** the value read from the database file.
+**
+** If an IO error occurs, then the IO error is returned to the caller.
+** Otherwise, SQLITE_OK is returned.
+*/
+static int readDbPage(PgHdr *pPg){
+ Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
+ Pgno pgno = pPg->pgno; /* Page number to read */
+ int rc = SQLITE_OK; /* Return code */
+ int isInWal = 0; /* True if page is in log file */
+ int pgsz = pPager->pageSize; /* Number of bytes to read */
+
+ assert( pPager->eState>=PAGER_READER && !MEMDB );
+ assert( isOpen(pPager->fd) );
+
+ if( NEVER(!isOpen(pPager->fd)) ){
+ assert( pPager->tempFile );
+ memset(pPg->pData, 0, pPager->pageSize);
+ return SQLITE_OK;
+ }
+
+ if( pagerUseWal(pPager) ){
+ /* Try to pull the page from the write-ahead log. */
+ rc = sqlite3WalRead(pPager->pWal, pgno, &isInWal, pgsz, pPg->pData);
+ }
+ if( rc==SQLITE_OK && !isInWal ){
+ i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
+ rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
+ if( rc==SQLITE_IOERR_SHORT_READ ){
+ rc = SQLITE_OK;
+ }
+ }
+
+ if( pgno==1 ){
+ if( rc ){
+ /* If the read is unsuccessful, set the dbFileVers[] to something
+ ** that will never be a valid file version. dbFileVers[] is a copy
+ ** of bytes 24..39 of the database. Bytes 28..31 should always be
+ ** zero or the size of the database in page. Bytes 32..35 and 35..39
+ ** should be page numbers which are never 0xffffffff. So filling
+ ** pPager->dbFileVers[] with all 0xff bytes should suffice.
+ **
+ ** For an encrypted database, the situation is more complex: bytes
+ ** 24..39 of the database are white noise. But the probability of
+ ** white noising equaling 16 bytes of 0xff is vanishingly small so
+ ** we should still be ok.
+ */
+ memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
+ }else{
+ u8 *dbFileVers = &((u8*)pPg->pData)[24];
+ memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
+ }
+ }
+ CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
+
+ PAGER_INCR(sqlite3_pager_readdb_count);
+ PAGER_INCR(pPager->nRead);
+ IOTRACE(("PGIN %p %d\n", pPager, pgno));
+ PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
+ PAGERID(pPager), pgno, pager_pagehash(pPg)));
+
+ return rc;
+}
+
+/*
+** Update the value of the change-counter at offsets 24 and 92 in
+** the header and the sqlite version number at offset 96.
+**
+** This is an unconditional update. See also the pager_incr_changecounter()
+** routine which only updates the change-counter if the update is actually
+** needed, as determined by the pPager->changeCountDone state variable.
+*/
+static void pager_write_changecounter(PgHdr *pPg){
+ u32 change_counter;
+
+ /* Increment the value just read and write it back to byte 24. */
+ change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
+ put32bits(((char*)pPg->pData)+24, change_counter);
+
+ /* Also store the SQLite version number in bytes 96..99 and in
+ ** bytes 92..95 store the change counter for which the version number
+ ** is valid. */
+ put32bits(((char*)pPg->pData)+92, change_counter);
+ put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
+}
+
+#ifndef SQLITE_OMIT_WAL
+/*
+** This function is invoked once for each page that has already been
+** written into the log file when a WAL transaction is rolled back.
+** Parameter iPg is the page number of said page. The pCtx argument
+** is actually a pointer to the Pager structure.
+**
+** If page iPg is present in the cache, and has no outstanding references,
+** it is discarded. Otherwise, if there are one or more outstanding
+** references, the page content is reloaded from the database. If the
+** attempt to reload content from the database is required and fails,
+** return an SQLite error code. Otherwise, SQLITE_OK.
+*/
+static int pagerUndoCallback(void *pCtx, Pgno iPg){
+ int rc = SQLITE_OK;
+ Pager *pPager = (Pager *)pCtx;
+ PgHdr *pPg;
+
+ pPg = sqlite3PagerLookup(pPager, iPg);
+ if( pPg ){
+ if( sqlite3PcachePageRefcount(pPg)==1 ){
+ sqlite3PcacheDrop(pPg);
+ }else{
+ rc = readDbPage(pPg);
+ if( rc==SQLITE_OK ){
+ pPager->xReiniter(pPg);
+ }
+ sqlite3PagerUnref(pPg);
+ }
+ }
+
+ /* Normally, if a transaction is rolled back, any backup processes are
+ ** updated as data is copied out of the rollback journal and into the
+ ** database. This is not generally possible with a WAL database, as
+ ** rollback involves simply truncating the log file. Therefore, if one
+ ** or more frames have already been written to the log (and therefore
+ ** also copied into the backup databases) as part of this transaction,
+ ** the backups must be restarted.
+ */
+ sqlite3BackupRestart(pPager->pBackup);
+
+ return rc;
+}
+
+/*
+** This function is called to rollback a transaction on a WAL database.
+*/
+static int pagerRollbackWal(Pager *pPager){
+ int rc; /* Return Code */
+ PgHdr *pList; /* List of dirty pages to revert */
+
+ /* For all pages in the cache that are currently dirty or have already
+ ** been written (but not committed) to the log file, do one of the
+ ** following:
+ **
+ ** + Discard the cached page (if refcount==0), or
+ ** + Reload page content from the database (if refcount>0).
+ */
+ pPager->dbSize = pPager->dbOrigSize;
+ rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
+ pList = sqlite3PcacheDirtyList(pPager->pPCache);
+ while( pList && rc==SQLITE_OK ){
+ PgHdr *pNext = pList->pDirty;
+ rc = pagerUndoCallback((void *)pPager, pList->pgno);
+ pList = pNext;
+ }
+
+ return rc;
+}
+
+/*
+** This function is a wrapper around sqlite3WalFrames(). As well as logging
+** the contents of the list of pages headed by pList (connected by pDirty),
+** this function notifies any active backup processes that the pages have
+** changed.
+**
+** The list of pages passed into this routine is always sorted by page number.
+** Hence, if page 1 appears anywhere on the list, it will be the first page.
+*/
+static int pagerWalFrames(
+ Pager *pPager, /* Pager object */
+ PgHdr *pList, /* List of frames to log */
+ Pgno nTruncate, /* Database size after this commit */
+ int isCommit /* True if this is a commit */
+){
+ int rc; /* Return code */
+ int nList; /* Number of pages in pList */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
+ PgHdr *p; /* For looping over pages */
+#endif
+
+ assert( pPager->pWal );
+ assert( pList );
+#ifdef SQLITE_DEBUG
+ /* Verify that the page list is in accending order */
+ for(p=pList; p && p->pDirty; p=p->pDirty){
+ assert( p->pgno < p->pDirty->pgno );
+ }
+#endif
+
+ assert( pList->pDirty==0 || isCommit );
+ if( isCommit ){
+ /* If a WAL transaction is being committed, there is no point in writing
+ ** any pages with page numbers greater than nTruncate into the WAL file.
+ ** They will never be read by any client. So remove them from the pDirty
+ ** list here. */
+ PgHdr *p;
+ PgHdr **ppNext = &pList;
+ nList = 0;
+ for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
+ if( p->pgno<=nTruncate ){
+ ppNext = &p->pDirty;
+ nList++;
+ }
+ }
+ assert( pList );
+ }else{
+ nList = 1;
+ }
+ pPager->aStat[PAGER_STAT_WRITE] += nList;
+
+ if( pList->pgno==1 ) pager_write_changecounter(pList);
+ rc = sqlite3WalFrames(pPager->pWal,
+ pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
+ );
+ if( rc==SQLITE_OK && pPager->pBackup ){
+ PgHdr *p;
+ for(p=pList; p; p=p->pDirty){
+ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
+ }
+ }
+
+#ifdef SQLITE_CHECK_PAGES
+ pList = sqlite3PcacheDirtyList(pPager->pPCache);
+ for(p=pList; p; p=p->pDirty){
+ pager_set_pagehash(p);
+ }
+#endif
+
+ return rc;
+}
+
+/*
+** Begin a read transaction on the WAL.
+**
+** This routine used to be called "pagerOpenSnapshot()" because it essentially
+** makes a snapshot of the database at the current point in time and preserves
+** that snapshot for use by the reader in spite of concurrently changes by
+** other writers or checkpointers.
+*/
+static int pagerBeginReadTransaction(Pager *pPager){
+ int rc; /* Return code */
+ int changed = 0; /* True if cache must be reset */
+
+ assert( pagerUseWal(pPager) );
+ assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
+
+ /* sqlite3WalEndReadTransaction() was not called for the previous
+ ** transaction in locking_mode=EXCLUSIVE. So call it now. If we
+ ** are in locking_mode=NORMAL and EndRead() was previously called,
+ ** the duplicate call is harmless.
+ */
+ sqlite3WalEndReadTransaction(pPager->pWal);
+
+ rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
+ if( rc!=SQLITE_OK || changed ){
+ pager_reset(pPager);
+ }
+
+ return rc;
+}
+#endif
+
+/*
+** This function is called as part of the transition from PAGER_OPEN
+** to PAGER_READER state to determine the size of the database file
+** in pages (assuming the page size currently stored in Pager.pageSize).
+**
+** If no error occurs, SQLITE_OK is returned and the size of the database
+** in pages is stored in *pnPage. Otherwise, an error code (perhaps
+** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
+*/
+static int pagerPagecount(Pager *pPager, Pgno *pnPage){
+ Pgno nPage; /* Value to return via *pnPage */
+
+ /* Query the WAL sub-system for the database size. The WalDbsize()
+ ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
+ ** if the database size is not available. The database size is not
+ ** available from the WAL sub-system if the log file is empty or
+ ** contains no valid committed transactions.
+ */
+ assert( pPager->eState==PAGER_OPEN );
+ assert( pPager->eLock>=SHARED_LOCK );
+ nPage = sqlite3WalDbsize(pPager->pWal);
+
+ /* If the database size was not available from the WAL sub-system,
+ ** determine it based on the size of the database file. If the size
+ ** of the database file is not an integer multiple of the page-size,
+ ** round down to the nearest page. Except, any file larger than 0
+ ** bytes in size is considered to contain at least one page.
+ */
+ if( nPage==0 ){
+ i64 n = 0; /* Size of db file in bytes */
+ assert( isOpen(pPager->fd) || pPager->tempFile );
+ if( isOpen(pPager->fd) ){
+ int rc = sqlite3OsFileSize(pPager->fd, &n);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+ nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
+ }
+
+ /* If the current number of pages in the file is greater than the
+ ** configured maximum pager number, increase the allowed limit so
+ ** that the file can be read.
+ */
+ if( nPage>pPager->mxPgno ){
+ pPager->mxPgno = (Pgno)nPage;
+ }
+
+ *pnPage = nPage;
+ return SQLITE_OK;
+}
+
+#ifndef SQLITE_OMIT_WAL
+/*
+** Check if the *-wal file that corresponds to the database opened by pPager
+** exists if the database is not empy, or verify that the *-wal file does
+** not exist (by deleting it) if the database file is empty.
+**
+** If the database is not empty and the *-wal file exists, open the pager
+** in WAL mode. If the database is empty or if no *-wal file exists and
+** if no error occurs, make sure Pager.journalMode is not set to
+** PAGER_JOURNALMODE_WAL.
+**
+** Return SQLITE_OK or an error code.
+**
+** The caller must hold a SHARED lock on the database file to call this
+** function. Because an EXCLUSIVE lock on the db file is required to delete
+** a WAL on a none-empty database, this ensures there is no race condition
+** between the xAccess() below and an xDelete() being executed by some
+** other connection.
+*/
+static int pagerOpenWalIfPresent(Pager *pPager){
+ int rc = SQLITE_OK;
+ assert( pPager->eState==PAGER_OPEN );
+ assert( pPager->eLock>=SHARED_LOCK );
+
+ if( !pPager->tempFile ){
+ int isWal; /* True if WAL file exists */
+ Pgno nPage; /* Size of the database file */
+
+ rc = pagerPagecount(pPager, &nPage);
+ if( rc ) return rc;
+ if( nPage==0 ){
+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+ if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
+ isWal = 0;
+ }else{
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
+ );
+ }
+ if( rc==SQLITE_OK ){
+ if( isWal ){
+ testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
+ rc = sqlite3PagerOpenWal(pPager, 0);
+ }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
+ pPager->journalMode = PAGER_JOURNALMODE_DELETE;
+ }
+ }
+ }
+ return rc;
+}
+#endif
+
+/*
+** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
+** the entire master journal file. The case pSavepoint==NULL occurs when
+** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
+** savepoint.
+**
+** When pSavepoint is not NULL (meaning a non-transaction savepoint is
+** being rolled back), then the rollback consists of up to three stages,
+** performed in the order specified:
+**
+** * Pages are played back from the main journal starting at byte
+** offset PagerSavepoint.iOffset and continuing to
+** PagerSavepoint.iHdrOffset, or to the end of the main journal
+** file if PagerSavepoint.iHdrOffset is zero.
+**
+** * If PagerSavepoint.iHdrOffset is not zero, then pages are played
+** back starting from the journal header immediately following
+** PagerSavepoint.iHdrOffset to the end of the main journal file.
+**
+** * Pages are then played back from the sub-journal file, starting
+** with the PagerSavepoint.iSubRec and continuing to the end of
+** the journal file.
+**
+** Throughout the rollback process, each time a page is rolled back, the
+** corresponding bit is set in a bitvec structure (variable pDone in the
+** implementation below). This is used to ensure that a page is only
+** rolled back the first time it is encountered in either journal.
+**
+** If pSavepoint is NULL, then pages are only played back from the main
+** journal file. There is no need for a bitvec in this case.
+**
+** In either case, before playback commences the Pager.dbSize variable
+** is reset to the value that it held at the start of the savepoint
+** (or transaction). No page with a page-number greater than this value
+** is played back. If one is encountered it is simply skipped.
+*/
+static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
+ i64 szJ; /* Effective size of the main journal */
+ i64 iHdrOff; /* End of first segment of main-journal records */
+ int rc = SQLITE_OK; /* Return code */
+ Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */
+
+ assert( pPager->eState!=PAGER_ERROR );
+ assert( pPager->eState>=PAGER_WRITER_LOCKED );
+
+ /* Allocate a bitvec to use to store the set of pages rolled back */
+ if( pSavepoint ){
+ pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
+ if( !pDone ){
+ return SQLITE_NOMEM;
+ }
+ }
+
+ /* Set the database size back to the value it was before the savepoint
+ ** being reverted was opened.
+ */
+ pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
+ pPager->changeCountDone = pPager->tempFile;
+
+ if( !pSavepoint && pagerUseWal(pPager) ){
+ return pagerRollbackWal(pPager);
+ }
+
+ /* Use pPager->journalOff as the effective size of the main rollback
+ ** journal. The actual file might be larger than this in
+ ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything
+ ** past pPager->journalOff is off-limits to us.
+ */
+ szJ = pPager->journalOff;
+ assert( pagerUseWal(pPager)==0 || szJ==0 );
+
+ /* Begin by rolling back records from the main journal starting at
+ ** PagerSavepoint.iOffset and continuing to the next journal header.
+ ** There might be records in the main journal that have a page number
+ ** greater than the current database size (pPager->dbSize) but those
+ ** will be skipped automatically. Pages are added to pDone as they
+ ** are played back.
+ */
+ if( pSavepoint && !pagerUseWal(pPager) ){
+ iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
+ pPager->journalOff = pSavepoint->iOffset;
+ while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
+ rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
+ }
+ assert( rc!=SQLITE_DONE );
+ }else{
+ pPager->journalOff = 0;
+ }
+
+ /* Continue rolling back records out of the main journal starting at
+ ** the first journal header seen and continuing until the effective end
+ ** of the main journal file. Continue to skip out-of-range pages and
+ ** continue adding pages rolled back to pDone.
+ */
+ while( rc==SQLITE_OK && pPager->journalOff<szJ ){
+ u32 ii; /* Loop counter */
+ u32 nJRec = 0; /* Number of Journal Records */
+ u32 dummy;
+ rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
+ assert( rc!=SQLITE_DONE );
+
+ /*
+ ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
+ ** test is related to ticket #2565. See the discussion in the
+ ** pager_playback() function for additional information.
+ */
+ if( nJRec==0
+ && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
+ ){
+ nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
+ }
+ for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
+ rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
+ }
+ assert( rc!=SQLITE_DONE );
+ }
+ assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );
+
+ /* Finally, rollback pages from the sub-journal. Page that were
+ ** previously rolled back out of the main journal (and are hence in pDone)
+ ** will be skipped. Out-of-range pages are also skipped.
+ */
+ if( pSavepoint ){
+ u32 ii; /* Loop counter */
+ i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
+
+ if( pagerUseWal(pPager) ){
+ rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
+ }
+ for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
+ assert( offset==(i64)ii*(4+pPager->pageSize) );
+ rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
+ }
+ assert( rc!=SQLITE_DONE );
+ }
+
+ sqlite3BitvecDestroy(pDone);
+ if( rc==SQLITE_OK ){
+ pPager->journalOff = szJ;
+ }
+
+ return rc;
+}
+
+/*
+** Change the maximum number of in-memory pages that are allowed.
+*/
+SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
+ sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
+}
+
+/*
+** Free as much memory as possible from the pager.
+*/
+SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
+ sqlite3PcacheShrink(pPager->pPCache);
+}
+
+/*
+** Adjust the robustness of the database to damage due to OS crashes
+** or power failures by changing the number of syncs()s when writing
+** the rollback journal. There are three levels:
+**
+** OFF sqlite3OsSync() is never called. This is the default
+** for temporary and transient files.
+**
+** NORMAL The journal is synced once before writes begin on the
+** database. This is normally adequate protection, but
+** it is theoretically possible, though very unlikely,
+** that an inopertune power failure could leave the journal
+** in a state which would cause damage to the database
+** when it is rolled back.
+**
+** FULL The journal is synced twice before writes begin on the
+** database (with some additional information - the nRec field
+** of the journal header - being written in between the two
+** syncs). If we assume that writing a
+** single disk sector is atomic, then this mode provides
+** assurance that the journal will not be corrupted to the
+** point of causing damage to the database during rollback.
+**
+** The above is for a rollback-journal mode. For WAL mode, OFF continues
+** to mean that no syncs ever occur. NORMAL means that the WAL is synced
+** prior to the start of checkpoint and that the database file is synced
+** at the conclusion of the checkpoint if the entire content of the WAL
+** was written back into the database. But no sync operations occur for
+** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL
+** file is synced following each commit operation, in addition to the
+** syncs associated with NORMAL.
+**
+** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The
+** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
+** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an
+** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL
+** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the
+** synchronous=FULL versus synchronous=NORMAL setting determines when
+** the xSync primitive is called and is relevant to all platforms.
+**
+** Numeric values associated with these states are OFF==1, NORMAL=2,
+** and FULL=3.
+*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
+ Pager *pPager, /* The pager to set safety level for */
+ int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
+ int bFullFsync, /* PRAGMA fullfsync */
+ int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */
+){
+ assert( level>=1 && level<=3 );
+ pPager->noSync = (level==1 || pPager->tempFile) ?1:0;
+ pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
+ if( pPager->noSync ){
+ pPager->syncFlags = 0;
+ pPager->ckptSyncFlags = 0;
+ }else if( bFullFsync ){
+ pPager->syncFlags = SQLITE_SYNC_FULL;
+ pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
+ }else if( bCkptFullFsync ){
+ pPager->syncFlags = SQLITE_SYNC_NORMAL;
+ pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
+ }else{
+ pPager->syncFlags = SQLITE_SYNC_NORMAL;
+ pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
+ }
+ pPager->walSyncFlags = pPager->syncFlags;
+ if( pPager->fullSync ){
+ pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
+ }
+}
+#endif
+
+/*
+** The following global variable is incremented whenever the library
+** attempts to open a temporary file. This information is used for
+** testing and analysis only.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_opentemp_count = 0;
+#endif
+
+/*
+** Open a temporary file.
+**
+** Write the file descriptor into *pFile. Return SQLITE_OK on success
+** or some other error code if we fail. The OS will automatically
+** delete the temporary file when it is closed.
+**
+** The flags passed to the VFS layer xOpen() call are those specified
+** by parameter vfsFlags ORed with the following:
+**
+** SQLITE_OPEN_READWRITE
+** SQLITE_OPEN_CREATE
+** SQLITE_OPEN_EXCLUSIVE
+** SQLITE_OPEN_DELETEONCLOSE
+*/
+static int pagerOpentemp(
+ Pager *pPager, /* The pager object */
+ sqlite3_file *pFile, /* Write the file descriptor here */
+ int vfsFlags /* Flags passed through to the VFS */
+){
+ int rc; /* Return code */
+
+#ifdef SQLITE_TEST
+ sqlite3_opentemp_count++; /* Used for testing and analysis only */
+#endif
+
+ vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+ SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
+ rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
+ assert( rc!=SQLITE_OK || isOpen(pFile) );
+ return rc;
+}
+
+/*
+** Set the busy handler function.
+**
+** The pager invokes the busy-handler if sqlite3OsLock() returns
+** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
+** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
+** lock. It does *not* invoke the busy handler when upgrading from
+** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
+** (which occurs during hot-journal rollback). Summary:
+**
+** Transition | Invokes xBusyHandler
+** --------------------------------------------------------
+** NO_LOCK -> SHARED_LOCK | Yes
+** SHARED_LOCK -> RESERVED_LOCK | No
+** SHARED_LOCK -> EXCLUSIVE_LOCK | No
+** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
+**
+** If the busy-handler callback returns non-zero, the lock is
+** retried. If it returns zero, then the SQLITE_BUSY error is
+** returned to the caller of the pager API function.
+*/
+SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
+ Pager *pPager, /* Pager object */
+ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
+ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
+){
+ pPager->xBusyHandler = xBusyHandler;
+ pPager->pBusyHandlerArg = pBusyHandlerArg;
+
+ if( isOpen(pPager->fd) ){
+ void **ap = (void **)&pPager->xBusyHandler;
+ assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
+ assert( ap[1]==pBusyHandlerArg );
+ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
+ }
+}
+
+/*
+** Change the page size used by the Pager object. The new page size
+** is passed in *pPageSize.
+**
+** If the pager is in the error state when this function is called, it
+** is a no-op. The value returned is the error state error code (i.e.
+** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
+**
+** Otherwise, if all of the following are true:
+**
+** * the new page size (value of *pPageSize) is valid (a power
+** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
+**
+** * there are no outstanding page references, and
+**
+** * the database is either not an in-memory database or it is
+** an in-memory database that currently consists of zero pages.
+**
+** then the pager object page size is set to *pPageSize.
+**
+** If the page size is changed, then this function uses sqlite3PagerMalloc()
+** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
+** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
+** In all other cases, SQLITE_OK is returned.
+**
+** If the page size is not changed, either because one of the enumerated
+** conditions above is not true, the pager was in error state when this
+** function was called, or because the memory allocation attempt failed,
+** then *pPageSize is set to the old, retained page size before returning.
+*/
+SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
+ int rc = SQLITE_OK;
+
+ /* It is not possible to do a full assert_pager_state() here, as this
+ ** function may be called from within PagerOpen(), before the state
+ ** of the Pager object is internally consistent.
+ **
+ ** At one point this function returned an error if the pager was in
+ ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
+ ** there is at least one outstanding page reference, this function
+ ** is a no-op for that case anyhow.
+ */
+
+ u32 pageSize = *pPageSize;
+ assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
+ if( (pPager->memDb==0 || pPager->dbSize==0)
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
+ && pageSize && pageSize!=(u32)pPager->pageSize
+ ){
+ char *pNew = NULL; /* New temp space */
+ i64 nByte = 0;
+
+ if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
+ rc = sqlite3OsFileSize(pPager->fd, &nByte);
+ }
+ if( rc==SQLITE_OK ){
+ pNew = (char *)sqlite3PageMalloc(pageSize);
+ if( !pNew ) rc = SQLITE_NOMEM;
+ }
+
+ if( rc==SQLITE_OK ){
+ pager_reset(pPager);
+ pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
+ pPager->pageSize = pageSize;
+ sqlite3PageFree(pPager->pTmpSpace);
+ pPager->pTmpSpace = pNew;
+ sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
+ }
+ }
+
+ *pPageSize = pPager->pageSize;
+ if( rc==SQLITE_OK ){
+ if( nReserve<0 ) nReserve = pPager->nReserve;
+ assert( nReserve>=0 && nReserve<1000 );
+ pPager->nReserve = (i16)nReserve;
+ pagerReportSize(pPager);
+ }
+ return rc;
+}
+
+/*
+** Return a pointer to the "temporary page" buffer held internally
+** by the pager. This is a buffer that is big enough to hold the
+** entire content of a database page. This buffer is used internally
+** during rollback and will be overwritten whenever a rollback
+** occurs. But other modules are free to use it too, as long as
+** no rollbacks are happening.
+*/
+SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
+ return pPager->pTmpSpace;
+}
+
+/*
+** Attempt to set the maximum database page count if mxPage is positive.
+** Make no changes if mxPage is zero or negative. And never reduce the
+** maximum page count below the current size of the database.
+**
+** Regardless of mxPage, return the current maximum page count.
+*/
+SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
+ if( mxPage>0 ){
+ pPager->mxPgno = mxPage;
+ }
+ assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
+ assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */
+ return pPager->mxPgno;
+}
+
+/*
+** The following set of routines are used to disable the simulated
+** I/O error mechanism. These routines are used to avoid simulated
+** errors in places where we do not care about errors.
+**
+** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
+** and generate no code.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API extern int sqlite3_io_error_pending;
+SQLITE_API extern int sqlite3_io_error_hit;
+static int saved_cnt;
+void disable_simulated_io_errors(void){
+ saved_cnt = sqlite3_io_error_pending;
+ sqlite3_io_error_pending = -1;
+}
+void enable_simulated_io_errors(void){
+ sqlite3_io_error_pending = saved_cnt;
+}
+#else
+# define disable_simulated_io_errors()
+# define enable_simulated_io_errors()
+#endif
+
+/*
+** Read the first N bytes from the beginning of the file into memory
+** that pDest points to.
+**
+** If the pager was opened on a transient file (zFilename==""), or
+** opened on a file less than N bytes in size, the output buffer is
+** zeroed and SQLITE_OK returned. The rationale for this is that this
+** function is used to read database headers, and a new transient or
+** zero sized database has a header than consists entirely of zeroes.
+**
+** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
+** the error code is returned to the caller and the contents of the
+** output buffer undefined.
+*/
+SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
+ int rc = SQLITE_OK;
+ memset(pDest, 0, N);
+ assert( isOpen(pPager->fd) || pPager->tempFile );
+
+ /* This routine is only called by btree immediately after creating
+ ** the Pager object. There has not been an opportunity to transition
+ ** to WAL mode yet.
+ */
+ assert( !pagerUseWal(pPager) );
+
+ if( isOpen(pPager->fd) ){
+ IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
+ rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
+ if( rc==SQLITE_IOERR_SHORT_READ ){
+ rc = SQLITE_OK;
+ }
+ }
+ return rc;
+}
+
+/*
+** This function may only be called when a read-transaction is open on
+** the pager. It returns the total number of pages in the database.
+**
+** However, if the file is between 1 and <page-size> bytes in size, then
+** this is considered a 1 page file.
+*/
+SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
+ assert( pPager->eState>=PAGER_READER );
+ assert( pPager->eState!=PAGER_WRITER_FINISHED );
+ *pnPage = (int)pPager->dbSize;
+}
+
+
+/*
+** Try to obtain a lock of type locktype on the database file. If
+** a similar or greater lock is already held, this function is a no-op
+** (returning SQLITE_OK immediately).
+**
+** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
+** the busy callback if the lock is currently not available. Repeat
+** until the busy callback returns false or until the attempt to
+** obtain the lock succeeds.
+**
+** Return SQLITE_OK on success and an error code if we cannot obtain
+** the lock. If the lock is obtained successfully, set the Pager.state
+** variable to locktype before returning.
+*/
+static int pager_wait_on_lock(Pager *pPager, int locktype){
+ int rc; /* Return code */
+
+ /* Check that this is either a no-op (because the requested lock is
+ ** already held, or one of the transistions that the busy-handler
+ ** may be invoked during, according to the comment above
+ ** sqlite3PagerSetBusyhandler().
+ */
+ assert( (pPager->eLock>=locktype)
+ || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
+ || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
+ );
+
+ do {
+ rc = pagerLockDb(pPager, locktype);
+ }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
+ return rc;
+}
+
+/*
+** Function assertTruncateConstraint(pPager) checks that one of the
+** following is true for all dirty pages currently in the page-cache:
+**
+** a) The page number is less than or equal to the size of the
+** current database image, in pages, OR
+**
+** b) if the page content were written at this time, it would not
+** be necessary to write the current content out to the sub-journal
+** (as determined by function subjRequiresPage()).
+**
+** If the condition asserted by this function were not true, and the
+** dirty page were to be discarded from the cache via the pagerStress()
+** routine, pagerStress() would not write the current page content to
+** the database file. If a savepoint transaction were rolled back after
+** this happened, the correct behavior would be to restore the current
+** content of the page. However, since this content is not present in either
+** the database file or the portion of the rollback journal and
+** sub-journal rolled back the content could not be restored and the
+** database image would become corrupt. It is therefore fortunate that
+** this circumstance cannot arise.
+*/
+#if defined(SQLITE_DEBUG)
+static void assertTruncateConstraintCb(PgHdr *pPg){
+ assert( pPg->flags&PGHDR_DIRTY );
+ assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
+}
+static void assertTruncateConstraint(Pager *pPager){
+ sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
+}
+#else
+# define assertTruncateConstraint(pPager)
+#endif
+
+/*
+** Truncate the in-memory database file image to nPage pages. This
+** function does not actually modify the database file on disk. It
+** just sets the internal state of the pager object so that the
+** truncation will be done when the current transaction is committed.
+**
+** This function is only called right before committing a transaction.
+** Once this function has been called, the transaction must either be
+** rolled back or committed. It is not safe to call this function and
+** then continue writing to the database.
+*/
+SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
+ assert( pPager->dbSize>=nPage );
+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
+ pPager->dbSize = nPage;
+
+ /* At one point the code here called assertTruncateConstraint() to
+ ** ensure that all pages being truncated away by this operation are,
+ ** if one or more savepoints are open, present in the savepoint
+ ** journal so that they can be restored if the savepoint is rolled
+ ** back. This is no longer necessary as this function is now only
+ ** called right before committing a transaction. So although the
+ ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
+ ** they cannot be rolled back. So the assertTruncateConstraint() call
+ ** is no longer correct. */
+}
+
+
+/*
+** This function is called before attempting a hot-journal rollback. It
+** syncs the journal file to disk, then sets pPager->journalHdr to the
+** size of the journal file so that the pager_playback() routine knows
+** that the entire journal file has been synced.
+**
+** Syncing a hot-journal to disk before attempting to roll it back ensures
+** that if a power-failure occurs during the rollback, the process that
+** attempts rollback following system recovery sees the same journal
+** content as this process.
+**
+** If everything goes as planned, SQLITE_OK is returned. Otherwise,
+** an SQLite error code.
+*/
+static int pagerSyncHotJournal(Pager *pPager){
+ int rc = SQLITE_OK;
+ if( !pPager->noSync ){
+ rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
+ }
+ return rc;
+}
+
+/*
+** Shutdown the page cache. Free all memory and close all files.
+**
+** If a transaction was in progress when this routine is called, that
+** transaction is rolled back. All outstanding pages are invalidated
+** and their memory is freed. Any attempt to use a page associated
+** with this page cache after this function returns will likely
+** result in a coredump.
+**
+** This function always succeeds. If a transaction is active an attempt
+** is made to roll it back. If an error occurs during the rollback
+** a hot journal may be left in the filesystem but no error is returned
+** to the caller.
+*/
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
+ u8 *pTmp = (u8 *)pPager->pTmpSpace;
+
+ assert( assert_pager_state(pPager) );
+ disable_simulated_io_errors();
+ sqlite3BeginBenignMalloc();
+ /* pPager->errCode = 0; */
+ pPager->exclusiveMode = 0;
+#ifndef SQLITE_OMIT_WAL
+ sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
+ pPager->pWal = 0;
+#endif
+ pager_reset(pPager);
+ if( MEMDB ){
+ pager_unlock(pPager);
+ }else{
+ /* If it is open, sync the journal file before calling UnlockAndRollback.
+ ** If this is not done, then an unsynced portion of the open journal
+ ** file may be played back into the database. If a power failure occurs
+ ** while this is happening, the database could become corrupt.
+ **
+ ** If an error occurs while trying to sync the journal, shift the pager
+ ** into the ERROR state. This causes UnlockAndRollback to unlock the
+ ** database and close the journal file without attempting to roll it
+ ** back or finalize it. The next database user will have to do hot-journal
+ ** rollback before accessing the database file.
+ */
+ if( isOpen(pPager->jfd) ){
+ pager_error(pPager, pagerSyncHotJournal(pPager));
+ }
+ pagerUnlockAndRollback(pPager);
+ }
+ sqlite3EndBenignMalloc();
+ enable_simulated_io_errors();
+ PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
+ IOTRACE(("CLOSE %p\n", pPager))
+ sqlite3OsClose(pPager->jfd);
+ sqlite3OsClose(pPager->fd);
+ sqlite3PageFree(pTmp);
+ sqlite3PcacheClose(pPager->pPCache);
+
+#ifdef SQLITE_HAS_CODEC
+ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
+#endif
+
+ assert( !pPager->aSavepoint && !pPager->pInJournal );
+ assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
+
+ sqlite3_free(pPager);
+ return SQLITE_OK;
+}
+
+#if !defined(NDEBUG) || defined(SQLITE_TEST)
+/*
+** Return the page number for page pPg.
+*/
+SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){
+ return pPg->pgno;
+}
+#endif
+
+/*
+** Increment the reference count for page pPg.
+*/
+SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
+ sqlite3PcacheRef(pPg);
+}
+
+/*
+** Sync the journal. In other words, make sure all the pages that have
+** been written to the journal have actually reached the surface of the
+** disk and can be restored in the event of a hot-journal rollback.
+**
+** If the Pager.noSync flag is set, then this function is a no-op.
+** Otherwise, the actions required depend on the journal-mode and the
+** device characteristics of the file-system, as follows:
+**
+** * If the journal file is an in-memory journal file, no action need
+** be taken.
+**
+** * Otherwise, if the device does not support the SAFE_APPEND property,
+** then the nRec field of the most recently written journal header
+** is updated to contain the number of journal records that have
+** been written following it. If the pager is operating in full-sync
+** mode, then the journal file is synced before this field is updated.
+**
+** * If the device does not support the SEQUENTIAL property, then
+** journal file is synced.
+**
+** Or, in pseudo-code:
+**
+** if( NOT <in-memory journal> ){
+** if( NOT SAFE_APPEND ){
+** if( <full-sync mode> ) xSync(<journal file>);
+** <update nRec field>
+** }
+** if( NOT SEQUENTIAL ) xSync(<journal file>);
+** }
+**
+** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
+** page currently held in memory before returning SQLITE_OK. If an IO
+** error is encountered, then the IO error code is returned to the caller.
+*/
+static int syncJournal(Pager *pPager, int newHdr){
+ int rc; /* Return code */
+
+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ );
+ assert( assert_pager_state(pPager) );
+ assert( !pagerUseWal(pPager) );
+
+ rc = sqlite3PagerExclusiveLock(pPager);
+ if( rc!=SQLITE_OK ) return rc;
+
+ if( !pPager->noSync ){
+ assert( !pPager->tempFile );
+ if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
+ const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+ assert( isOpen(pPager->jfd) );
+
+ if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
+ /* This block deals with an obscure problem. If the last connection
+ ** that wrote to this database was operating in persistent-journal
+ ** mode, then the journal file may at this point actually be larger
+ ** than Pager.journalOff bytes. If the next thing in the journal
+ ** file happens to be a journal-header (written as part of the
+ ** previous connection's transaction), and a crash or power-failure
+ ** occurs after nRec is updated but before this connection writes
+ ** anything else to the journal file (or commits/rolls back its
+ ** transaction), then SQLite may become confused when doing the
+ ** hot-journal rollback following recovery. It may roll back all
+ ** of this connections data, then proceed to rolling back the old,
+ ** out-of-date data that follows it. Database corruption.
+ **
+ ** To work around this, if the journal file does appear to contain
+ ** a valid header following Pager.journalOff, then write a 0x00
+ ** byte to the start of it to prevent it from being recognized.
+ **
+ ** Variable iNextHdrOffset is set to the offset at which this
+ ** problematic header will occur, if it exists. aMagic is used
+ ** as a temporary buffer to inspect the first couple of bytes of
+ ** the potential journal header.
+ */
+ i64 iNextHdrOffset;
+ u8 aMagic[8];
+ u8 zHeader[sizeof(aJournalMagic)+4];
+
+ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
+ put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
+
+ iNextHdrOffset = journalHdrOffset(pPager);
+ rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
+ if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){
+ static const u8 zerobyte = 0;
+ rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset);
+ }
+ if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
+ return rc;
+ }
+
+ /* Write the nRec value into the journal file header. If in
+ ** full-synchronous mode, sync the journal first. This ensures that
+ ** all data has really hit the disk before nRec is updated to mark
+ ** it as a candidate for rollback.
+ **
+ ** This is not required if the persistent media supports the
+ ** SAFE_APPEND property. Because in this case it is not possible
+ ** for garbage data to be appended to the file, the nRec field
+ ** is populated with 0xFFFFFFFF when the journal header is written
+ ** and never needs to be updated.
+ */
+ if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
+ PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
+ IOTRACE(("JSYNC %p\n", pPager))
+ rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr));
+ rc = sqlite3OsWrite(
+ pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr
+ );
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
+ PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
+ IOTRACE(("JSYNC %p\n", pPager))
+ rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
+ (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
+ );
+ if( rc!=SQLITE_OK ) return rc;
+ }
+
+ pPager->journalHdr = pPager->journalOff;
+ if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
+ pPager->nRec = 0;
+ rc = writeJournalHdr(pPager);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ }else{
+ pPager->journalHdr = pPager->journalOff;
+ }
+ }
+
+ /* Unless the pager is in noSync mode, the journal file was just
+ ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
+ ** all pages.
+ */
+ sqlite3PcacheClearSyncFlags(pPager->pPCache);
+ pPager->eState = PAGER_WRITER_DBMOD;
+ assert( assert_pager_state(pPager) );
+ return SQLITE_OK;
+}
+
+/*
+** The argument is the first in a linked list of dirty pages connected
+** by the PgHdr.pDirty pointer. This function writes each one of the
+** in-memory pages in the list to the database file. The argument may
+** be NULL, representing an empty list. In this case this function is
+** a no-op.
+**
+** The pager must hold at least a RESERVED lock when this function
+** is called. Before writing anything to the database file, this lock
+** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
+** SQLITE_BUSY is returned and no data is written to the database file.
+**
+** If the pager is a temp-file pager and the actual file-system file
+** is not yet open, it is created and opened before any data is
+** written out.
+**
+** Once the lock has been upgraded and, if necessary, the file opened,
+** the pages are written out to the database file in list order. Writing
+** a page is skipped if it meets either of the following criteria:
+**
+** * The page number is greater than Pager.dbSize, or
+** * The PGHDR_DONT_WRITE flag is set on the page.
+**
+** If writing out a page causes the database file to grow, Pager.dbFileSize
+** is updated accordingly. If page 1 is written out, then the value cached
+** in Pager.dbFileVers[] is updated to match the new value stored in
+** the database file.
+**
+** If everything is successful, SQLITE_OK is returned. If an IO error
+** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
+** be obtained, SQLITE_BUSY is returned.
+*/
+static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
+ int rc = SQLITE_OK; /* Return code */
+
+ /* This function is only called for rollback pagers in WRITER_DBMOD state. */
+ assert( !pagerUseWal(pPager) );
+ assert( pPager->eState==PAGER_WRITER_DBMOD );
+ assert( pPager->eLock==EXCLUSIVE_LOCK );
+
+ /* If the file is a temp-file has not yet been opened, open it now. It
+ ** is not possible for rc to be other than SQLITE_OK if this branch
+ ** is taken, as pager_wait_on_lock() is a no-op for temp-files.
+ */
+ if( !isOpen(pPager->fd) ){
+ assert( pPager->tempFile && rc==SQLITE_OK );
+ rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
+ }
+
+ /* Before the first write, give the VFS a hint of what the final
+ ** file size will be.
+ */
+ assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
+ if( rc==SQLITE_OK && pPager->dbSize>pPager->dbHintSize ){
+ sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
+ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
+ pPager->dbHintSize = pPager->dbSize;
+ }
+
+ while( rc==SQLITE_OK && pList ){
+ Pgno pgno = pList->pgno;
+
+ /* If there are dirty pages in the page cache with page numbers greater
+ ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
+ ** make the file smaller (presumably by auto-vacuum code). Do not write
+ ** any such pages to the file.
+ **
+ ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
+ ** set (set by sqlite3PagerDontWrite()).
+ */
+ if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
+ i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
+ char *pData; /* Data to write */
+
+ assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
+ if( pList->pgno==1 ) pager_write_changecounter(pList);
+
+ /* Encode the database */
+ CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
+
+ /* Write out the page data. */
+ rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
+
+ /* If page 1 was just written, update Pager.dbFileVers to match
+ ** the value now stored in the database file. If writing this
+ ** page caused the database file to grow, update dbFileSize.
+ */
+ if( pgno==1 ){
+ memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
+ }
+ if( pgno>pPager->dbFileSize ){
+ pPager->dbFileSize = pgno;
+ }
+ pPager->aStat[PAGER_STAT_WRITE]++;
+
+ /* Update any backup objects copying the contents of this pager. */
+ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
+
+ PAGERTRACE(("STORE %d page %d hash(%08x)\n",
+ PAGERID(pPager), pgno, pager_pagehash(pList)));
+ IOTRACE(("PGOUT %p %d\n", pPager, pgno));
+ PAGER_INCR(sqlite3_pager_writedb_count);
+ }else{
+ PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
+ }
+ pager_set_pagehash(pList);
+ pList = pList->pDirty;
+ }
+
+ return rc;
+}
+
+/*
+** Ensure that the sub-journal file is open. If it is already open, this
+** function is a no-op.
+**
+** SQLITE_OK is returned if everything goes according to plan. An
+** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen()
+** fails.
+*/
+static int openSubJournal(Pager *pPager){
+ int rc = SQLITE_OK;
+ if( !isOpen(pPager->sjfd) ){
+ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
+ sqlite3MemJournalOpen(pPager->sjfd);
+ }else{
+ rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL);
+ }
+ }
+ return rc;
+}
+
+/*
+** Append a record of the current state of page pPg to the sub-journal.
+** It is the callers responsibility to use subjRequiresPage() to check
+** that it is really required before calling this function.
+**
+** If successful, set the bit corresponding to pPg->pgno in the bitvecs
+** for all open savepoints before returning.
+**
+** This function returns SQLITE_OK if everything is successful, an IO
+** error code if the attempt to write to the sub-journal fails, or
+** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
+** bitvec.
+*/
+static int subjournalPage(PgHdr *pPg){
+ int rc = SQLITE_OK;
+ Pager *pPager = pPg->pPager;
+ if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
+
+ /* Open the sub-journal, if it has not already been opened */
+ assert( pPager->useJournal );
+ assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
+ assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
+ assert( pagerUseWal(pPager)
+ || pageInJournal(pPg)
+ || pPg->pgno>pPager->dbOrigSize
+ );
+ rc = openSubJournal(pPager);
+
+ /* If the sub-journal was opened successfully (or was already open),
+ ** write the journal record into the file. */
+ if( rc==SQLITE_OK ){
+ void *pData = pPg->pData;
+ i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
+ char *pData2;
+
+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
+ PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
+ rc = write32bits(pPager->sjfd, offset, pPg->pgno);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ pPager->nSubRec++;
+ assert( pPager->nSavepoint>0 );
+ rc = addToSavepointBitvecs(pPager, pPg->pgno);
+ }
+ return rc;
+}
+
+/*
+** This function is called by the pcache layer when it has reached some
+** soft memory limit. The first argument is a pointer to a Pager object
+** (cast as a void*). The pager is always 'purgeable' (not an in-memory
+** database). The second argument is a reference to a page that is
+** currently dirty but has no outstanding references. The page
+** is always associated with the Pager object passed as the first
+** argument.
+**
+** The job of this function is to make pPg clean by writing its contents
+** out to the database file, if possible. This may involve syncing the
+** journal file.
+**
+** If successful, sqlite3PcacheMakeClean() is called on the page and
+** SQLITE_OK returned. If an IO error occurs while trying to make the
+** page clean, the IO error code is returned. If the page cannot be
+** made clean for some other reason, but no error occurs, then SQLITE_OK
+** is returned by sqlite3PcacheMakeClean() is not called.
+*/
+static int pagerStress(void *p, PgHdr *pPg){
+ Pager *pPager = (Pager *)p;
+ int rc = SQLITE_OK;
+
+ assert( pPg->pPager==pPager );
+ assert( pPg->flags&PGHDR_DIRTY );
+
+ /* The doNotSyncSpill flag is set during times when doing a sync of
+ ** journal (and adding a new header) is not allowed. This occurs
+ ** during calls to sqlite3PagerWrite() while trying to journal multiple
+ ** pages belonging to the same sector.
+ **
+ ** The doNotSpill flag inhibits all cache spilling regardless of whether
+ ** or not a sync is required. This is set during a rollback.
+ **
+ ** Spilling is also prohibited when in an error state since that could
+ ** lead to database corruption. In the current implementaton it
+ ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
+ ** while in the error state, hence it is impossible for this routine to
+ ** be called in the error state. Nevertheless, we include a NEVER()
+ ** test for the error state as a safeguard against future changes.
+ */
+ if( NEVER(pPager->errCode) ) return SQLITE_OK;
+ if( pPager->doNotSpill ) return SQLITE_OK;
+ if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
+ return SQLITE_OK;
+ }
+
+ pPg->pDirty = 0;
+ if( pagerUseWal(pPager) ){
+ /* Write a single frame for this page to the log. */
+ if( subjRequiresPage(pPg) ){
+ rc = subjournalPage(pPg);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pagerWalFrames(pPager, pPg, 0, 0);
+ }
+ }else{
+
+ /* Sync the journal file if required. */
+ if( pPg->flags&PGHDR_NEED_SYNC
+ || pPager->eState==PAGER_WRITER_CACHEMOD
+ ){
+ rc = syncJournal(pPager, 1);
+ }
+
+ /* If the page number of this page is larger than the current size of
+ ** the database image, it may need to be written to the sub-journal.
+ ** This is because the call to pager_write_pagelist() below will not
+ ** actually write data to the file in this case.
+ **
+ ** Consider the following sequence of events:
+ **
+ ** BEGIN;
+ ** <journal page X>
+ ** <modify page X>
+ ** SAVEPOINT sp;
+ ** <shrink database file to Y pages>
+ ** pagerStress(page X)
+ ** ROLLBACK TO sp;
+ **
+ ** If (X>Y), then when pagerStress is called page X will not be written
+ ** out to the database file, but will be dropped from the cache. Then,
+ ** following the "ROLLBACK TO sp" statement, reading page X will read
+ ** data from the database file. This will be the copy of page X as it
+ ** was when the transaction started, not as it was when "SAVEPOINT sp"
+ ** was executed.
+ **
+ ** The solution is to write the current data for page X into the
+ ** sub-journal file now (if it is not already there), so that it will
+ ** be restored to its current value when the "ROLLBACK TO sp" is
+ ** executed.
+ */
+ if( NEVER(
+ rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg)
+ ) ){
+ rc = subjournalPage(pPg);
+ }
+
+ /* Write the contents of the page out to the database file. */
+ if( rc==SQLITE_OK ){
+ assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
+ rc = pager_write_pagelist(pPager, pPg);
+ }
+ }
+
+ /* Mark the page as clean. */
+ if( rc==SQLITE_OK ){
+ PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
+ sqlite3PcacheMakeClean(pPg);
+ }
+
+ return pager_error(pPager, rc);
+}
+
+
+/*
+** Allocate and initialize a new Pager object and put a pointer to it
+** in *ppPager. The pager should eventually be freed by passing it
+** to sqlite3PagerClose().
+**
+** The zFilename argument is the path to the database file to open.
+** If zFilename is NULL then a randomly-named temporary file is created
+** and used as the file to be cached. Temporary files are be deleted
+** automatically when they are closed. If zFilename is ":memory:" then
+** all information is held in cache. It is never written to disk.
+** This can be used to implement an in-memory database.
+**
+** The nExtra parameter specifies the number of bytes of space allocated
+** along with each page reference. This space is available to the user
+** via the sqlite3PagerGetExtra() API.
+**
+** The flags argument is used to specify properties that affect the
+** operation of the pager. It should be passed some bitwise combination
+** of the PAGER_* flags.
+**
+** The vfsFlags parameter is a bitmask to pass to the flags parameter
+** of the xOpen() method of the supplied VFS when opening files.
+**
+** If the pager object is allocated and the specified file opened
+** successfully, SQLITE_OK is returned and *ppPager set to point to
+** the new pager object. If an error occurs, *ppPager is set to NULL
+** and error code returned. This function may return SQLITE_NOMEM
+** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
+** various SQLITE_IO_XXX errors.
+*/
+SQLITE_PRIVATE int sqlite3PagerOpen(
+ sqlite3_vfs *pVfs, /* The virtual file system to use */
+ Pager **ppPager, /* OUT: Return the Pager structure here */
+ const char *zFilename, /* Name of the database file to open */
+ int nExtra, /* Extra bytes append to each in-memory page */
+ int flags, /* flags controlling this file */
+ int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */
+ void (*xReinit)(DbPage*) /* Function to reinitialize pages */
+){
+ u8 *pPtr;
+ Pager *pPager = 0; /* Pager object to allocate and return */
+ int rc = SQLITE_OK; /* Return code */
+ int tempFile = 0; /* True for temp files (incl. in-memory files) */
+ int memDb = 0; /* True if this is an in-memory file */
+ int readOnly = 0; /* True if this is a read-only file */
+ int journalFileSize; /* Bytes to allocate for each journal fd */
+ char *zPathname = 0; /* Full path to database file */
+ int nPathname = 0; /* Number of bytes in zPathname */
+ int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
+ int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
+ u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
+ const char *zUri = 0; /* URI args to copy */
+ int nUri = 0; /* Number of bytes of URI args at *zUri */
+
+ /* Figure out how much space is required for each journal file-handle
+ ** (there are two of them, the main journal and the sub-journal). This
+ ** is the maximum space required for an in-memory journal file handle
+ ** and a regular journal file-handle. Note that a "regular journal-handle"
+ ** may be a wrapper capable of caching the first portion of the journal
+ ** file in memory to implement the atomic-write optimization (see
+ ** source file journal.c).
+ */
+ if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
+ journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
+ }else{
+ journalFileSize = ROUND8(sqlite3MemJournalSize());
+ }
+
+ /* Set the output variable to NULL in case an error occurs. */
+ *ppPager = 0;
+
+#ifndef SQLITE_OMIT_MEMORYDB
+ if( flags & PAGER_MEMORY ){
+ memDb = 1;
+ if( zFilename && zFilename[0] ){
+ zPathname = sqlite3DbStrDup(0, zFilename);
+ if( zPathname==0 ) return SQLITE_NOMEM;
+ nPathname = sqlite3Strlen30(zPathname);
+ zFilename = 0;
+ }
+ }
+#endif
+
+ /* Compute and store the full pathname in an allocated buffer pointed
+ ** to by zPathname, length nPathname. Or, if this is a temporary file,
+ ** leave both nPathname and zPathname set to 0.
+ */
+ if( zFilename && zFilename[0] ){
+ const char *z;
+ nPathname = pVfs->mxPathname+1;
+ zPathname = sqlite3DbMallocRaw(0, nPathname*2);
+ if( zPathname==0 ){
+ return SQLITE_NOMEM;
+ }
+ zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
+ rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
+ nPathname = sqlite3Strlen30(zPathname);
+ z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
+ while( *z ){
+ z += sqlite3Strlen30(z)+1;
+ z += sqlite3Strlen30(z)+1;
+ }
+ nUri = (int)(&z[1] - zUri);
+ assert( nUri>=0 );
+ if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
+ /* This branch is taken when the journal path required by
+ ** the database being opened will be more than pVfs->mxPathname
+ ** bytes in length. This means the database cannot be opened,
+ ** as it will not be possible to open the journal file or even
+ ** check for a hot-journal before reading.
+ */
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(0, zPathname);
+ return rc;
+ }
+ }
+
+ /* Allocate memory for the Pager structure, PCache object, the
+ ** three file descriptors, the database file name and the journal
+ ** file name. The layout in memory is as follows:
+ **
+ ** Pager object (sizeof(Pager) bytes)
+ ** PCache object (sqlite3PcacheSize() bytes)
+ ** Database file handle (pVfs->szOsFile bytes)
+ ** Sub-journal file handle (journalFileSize bytes)
+ ** Main journal file handle (journalFileSize bytes)
+ ** Database file name (nPathname+1 bytes)
+ ** Journal file name (nPathname+8+1 bytes)
+ */
+ pPtr = (u8 *)sqlite3MallocZero(
+ ROUND8(sizeof(*pPager)) + /* Pager structure */
+ ROUND8(pcacheSize) + /* PCache object */
+ ROUND8(pVfs->szOsFile) + /* The main db file */
+ journalFileSize * 2 + /* The two journal files */
+ nPathname + 1 + nUri + /* zFilename */
+ nPathname + 8 + 2 /* zJournal */
+#ifndef SQLITE_OMIT_WAL
+ + nPathname + 4 + 2 /* zWal */
+#endif
+ );
+ assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
+ if( !pPtr ){
+ sqlite3DbFree(0, zPathname);
+ return SQLITE_NOMEM;
+ }
+ pPager = (Pager*)(pPtr);
+ pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
+ pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
+ pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
+ pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
+ pPager->zFilename = (char*)(pPtr += journalFileSize);
+ assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
+
+ /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
+ if( zPathname ){
+ assert( nPathname>0 );
+ pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
+ memcpy(pPager->zFilename, zPathname, nPathname);
+ if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
+ memcpy(pPager->zJournal, zPathname, nPathname);
+ memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
+ sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
+#ifndef SQLITE_OMIT_WAL
+ pPager->zWal = &pPager->zJournal[nPathname+8+1];
+ memcpy(pPager->zWal, zPathname, nPathname);
+ memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
+ sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
+#endif
+ sqlite3DbFree(0, zPathname);
+ }
+ pPager->pVfs = pVfs;
+ pPager->vfsFlags = vfsFlags;
+
+ /* Open the pager file.
+ */
+ if( zFilename && zFilename[0] ){
+ int fout = 0; /* VFS flags returned by xOpen() */
+ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
+ assert( !memDb );
+ readOnly = (fout&SQLITE_OPEN_READONLY);
+
+ /* If the file was successfully opened for read/write access,
+ ** choose a default page size in case we have to create the
+ ** database file. The default page size is the maximum of:
+ **
+ ** + SQLITE_DEFAULT_PAGE_SIZE,
+ ** + The value returned by sqlite3OsSectorSize()
+ ** + The largest page size that can be written atomically.
+ */
+ if( rc==SQLITE_OK && !readOnly ){
+ setSectorSize(pPager);
+ assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
+ if( szPageDflt<pPager->sectorSize ){
+ if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
+ szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
+ }else{
+ szPageDflt = (u32)pPager->sectorSize;
+ }
+ }
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ {
+ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+ int ii;
+ assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
+ assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
+ assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
+ for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
+ if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
+ szPageDflt = ii;
+ }
+ }
+ }
+#endif
+ }
+ }else{
+ /* If a temporary file is requested, it is not opened immediately.
+ ** In this case we accept the default page size and delay actually
+ ** opening the file until the first call to OsWrite().
+ **
+ ** This branch is also run for an in-memory database. An in-memory
+ ** database is the same as a temp-file that is never written out to
+ ** disk and uses an in-memory rollback journal.
+ */
+ tempFile = 1;
+ pPager->eState = PAGER_READER;
+ pPager->eLock = EXCLUSIVE_LOCK;
+ readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
+ }
+
+ /* The following call to PagerSetPagesize() serves to set the value of
+ ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
+ */
+ if( rc==SQLITE_OK ){
+ assert( pPager->memDb==0 );
+ rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
+ testcase( rc!=SQLITE_OK );
+ }
+
+ /* If an error occurred in either of the blocks above, free the
+ ** Pager structure and close the file.
+ */
+ if( rc!=SQLITE_OK ){
+ assert( !pPager->pTmpSpace );
+ sqlite3OsClose(pPager->fd);
+ sqlite3_free(pPager);
+ return rc;
+ }
+
+ /* Initialize the PCache object. */
+ assert( nExtra<1000 );
+ nExtra = ROUND8(nExtra);
+ sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
+ !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
+
+ PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
+ IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
+
+ pPager->useJournal = (u8)useJournal;
+ /* pPager->stmtOpen = 0; */
+ /* pPager->stmtInUse = 0; */
+ /* pPager->nRef = 0; */
+ /* pPager->stmtSize = 0; */
+ /* pPager->stmtJSize = 0; */
+ /* pPager->nPage = 0; */
+ pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
+ /* pPager->state = PAGER_UNLOCK; */
+#if 0
+ assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
+#endif
+ /* pPager->errMask = 0; */
+ pPager->tempFile = (u8)tempFile;
+ assert( tempFile==PAGER_LOCKINGMODE_NORMAL
+ || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
+ assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
+ pPager->exclusiveMode = (u8)tempFile;
+ pPager->changeCountDone = pPager->tempFile;
+ pPager->memDb = (u8)memDb;
+ pPager->readOnly = (u8)readOnly;
+ assert( useJournal || pPager->tempFile );
+ pPager->noSync = pPager->tempFile;
+ if( pPager->noSync ){
+ assert( pPager->fullSync==0 );
+ assert( pPager->syncFlags==0 );
+ assert( pPager->walSyncFlags==0 );
+ assert( pPager->ckptSyncFlags==0 );
+ }else{
+ pPager->fullSync = 1;
+ pPager->syncFlags = SQLITE_SYNC_NORMAL;
+ pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
+ pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
+ }
+ /* pPager->pFirst = 0; */
+ /* pPager->pFirstSynced = 0; */
+ /* pPager->pLast = 0; */
+ pPager->nExtra = (u16)nExtra;
+ pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
+ assert( isOpen(pPager->fd) || tempFile );
+ setSectorSize(pPager);
+ if( !useJournal ){
+ pPager->journalMode = PAGER_JOURNALMODE_OFF;
+ }else if( memDb ){
+ pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
+ }
+ /* pPager->xBusyHandler = 0; */
+ /* pPager->pBusyHandlerArg = 0; */
+ pPager->xReiniter = xReinit;
+ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
+
+ *ppPager = pPager;
+ return SQLITE_OK;
+}
+
+
+
+/*
+** This function is called after transitioning from PAGER_UNLOCK to
+** PAGER_SHARED state. It tests if there is a hot journal present in
+** the file-system for the given pager. A hot journal is one that
+** needs to be played back. According to this function, a hot-journal
+** file exists if the following criteria are met:
+**
+** * The journal file exists in the file system, and
+** * No process holds a RESERVED or greater lock on the database file, and
+** * The database file itself is greater than 0 bytes in size, and
+** * The first byte of the journal file exists and is not 0x00.
+**
+** If the current size of the database file is 0 but a journal file
+** exists, that is probably an old journal left over from a prior
+** database with the same name. In this case the journal file is
+** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
+** is returned.
+**
+** This routine does not check if there is a master journal filename
+** at the end of the file. If there is, and that master journal file
+** does not exist, then the journal file is not really hot. In this
+** case this routine will return a false-positive. The pager_playback()
+** routine will discover that the journal file is not really hot and
+** will not roll it back.
+**
+** If a hot-journal file is found to exist, *pExists is set to 1 and
+** SQLITE_OK returned. If no hot-journal file is present, *pExists is
+** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
+** to determine whether or not a hot-journal file exists, the IO error
+** code is returned and the value of *pExists is undefined.
+*/
+static int hasHotJournal(Pager *pPager, int *pExists){
+ sqlite3_vfs * const pVfs = pPager->pVfs;
+ int rc = SQLITE_OK; /* Return code */
+ int exists = 1; /* True if a journal file is present */
+ int jrnlOpen = !!isOpen(pPager->jfd);
+
+ assert( pPager->useJournal );
+ assert( isOpen(pPager->fd) );
+ assert( pPager->eState==PAGER_OPEN );
+
+ assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
+ SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
+ ));
+
+ *pExists = 0;
+ if( !jrnlOpen ){
+ rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
+ }
+ if( rc==SQLITE_OK && exists ){
+ int locked = 0; /* True if some process holds a RESERVED lock */
+
+ /* Race condition here: Another process might have been holding the
+ ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
+ ** call above, but then delete the journal and drop the lock before
+ ** we get to the following sqlite3OsCheckReservedLock() call. If that
+ ** is the case, this routine might think there is a hot journal when
+ ** in fact there is none. This results in a false-positive which will
+ ** be dealt with by the playback routine. Ticket #3883.
+ */
+ rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
+ if( rc==SQLITE_OK && !locked ){
+ Pgno nPage; /* Number of pages in database file */
+
+ /* Check the size of the database file. If it consists of 0 pages,
+ ** then delete the journal file. See the header comment above for
+ ** the reasoning here. Delete the obsolete journal file under
+ ** a RESERVED lock to avoid race conditions and to avoid violating
+ ** [H33020].
+ */
+ rc = pagerPagecount(pPager, &nPage);
+ if( rc==SQLITE_OK ){
+ if( nPage==0 ){
+ sqlite3BeginBenignMalloc();
+ if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
+ sqlite3OsDelete(pVfs, pPager->zJournal, 0);
+ if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
+ }
+ sqlite3EndBenignMalloc();
+ }else{
+ /* The journal file exists and no other connection has a reserved
+ ** or greater lock on the database file. Now check that there is
+ ** at least one non-zero bytes at the start of the journal file.
+ ** If there is, then we consider this journal to be hot. If not,
+ ** it can be ignored.
+ */
+ if( !jrnlOpen ){
+ int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
+ }
+ if( rc==SQLITE_OK ){
+ u8 first = 0;
+ rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
+ if( rc==SQLITE_IOERR_SHORT_READ ){
+ rc = SQLITE_OK;
+ }
+ if( !jrnlOpen ){
+ sqlite3OsClose(pPager->jfd);
+ }
+ *pExists = (first!=0);
+ }else if( rc==SQLITE_CANTOPEN ){
+ /* If we cannot open the rollback journal file in order to see if
+ ** its has a zero header, that might be due to an I/O error, or
+ ** it might be due to the race condition described above and in
+ ** ticket #3883. Either way, assume that the journal is hot.
+ ** This might be a false positive. But if it is, then the
+ ** automatic journal playback and recovery mechanism will deal
+ ** with it under an EXCLUSIVE lock where we do not need to
+ ** worry so much with race conditions.
+ */
+ *pExists = 1;
+ rc = SQLITE_OK;
+ }
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+** This function is called to obtain a shared lock on the database file.
+** It is illegal to call sqlite3PagerAcquire() until after this function
+** has been successfully called. If a shared-lock is already held when
+** this function is called, it is a no-op.
+**
+** The following operations are also performed by this function.
+**
+** 1) If the pager is currently in PAGER_OPEN state (no lock held
+** on the database file), then an attempt is made to obtain a
+** SHARED lock on the database file. Immediately after obtaining
+** the SHARED lock, the file-system is checked for a hot-journal,
+** which is played back if present. Following any hot-journal
+** rollback, the contents of the cache are validated by checking
+** the 'change-counter' field of the database file header and
+** discarded if they are found to be invalid.
+**
+** 2) If the pager is running in exclusive-mode, and there are currently
+** no outstanding references to any pages, and is in the error state,
+** then an attempt is made to clear the error state by discarding
+** the contents of the page cache and rolling back any open journal
+** file.
+**
+** If everything is successful, SQLITE_OK is returned. If an IO error
+** occurs while locking the database, checking for a hot-journal file or
+** rolling back a journal file, the IO error code is returned.
+*/
+SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
+ int rc = SQLITE_OK; /* Return code */
+
+ /* This routine is only called from b-tree and only when there are no
+ ** outstanding pages. This implies that the pager state should either
+ ** be OPEN or READER. READER is only possible if the pager is or was in
+ ** exclusive access mode.
+ */
+ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
+ assert( assert_pager_state(pPager) );
+ assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
+ if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
+
+ if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
+ int bHotJournal = 1; /* True if there exists a hot journal-file */
+
+ assert( !MEMDB );
+
+ rc = pager_wait_on_lock(pPager, SHARED_LOCK);
+ if( rc!=SQLITE_OK ){
+ assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
+ goto failed;
+ }
+
+ /* If a journal file exists, and there is no RESERVED lock on the
+ ** database file, then it either needs to be played back or deleted.
+ */
+ if( pPager->eLock<=SHARED_LOCK ){
+ rc = hasHotJournal(pPager, &bHotJournal);
+ }
+ if( rc!=SQLITE_OK ){
+ goto failed;
+ }
+ if( bHotJournal ){
+ if( pPager->readOnly ){
+ rc = SQLITE_READONLY_ROLLBACK;
+ goto failed;
+ }
+
+ /* Get an EXCLUSIVE lock on the database file. At this point it is
+ ** important that a RESERVED lock is not obtained on the way to the
+ ** EXCLUSIVE lock. If it were, another process might open the
+ ** database file, detect the RESERVED lock, and conclude that the
+ ** database is safe to read while this process is still rolling the
+ ** hot-journal back.
+ **
+ ** Because the intermediate RESERVED lock is not requested, any
+ ** other process attempting to access the database file will get to
+ ** this point in the code and fail to obtain its own EXCLUSIVE lock
+ ** on the database file.
+ **
+ ** Unless the pager is in locking_mode=exclusive mode, the lock is
+ ** downgraded to SHARED_LOCK before this function returns.
+ */
+ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+ if( rc!=SQLITE_OK ){
+ goto failed;
+ }
+
+ /* If it is not already open and the file exists on disk, open the
+ ** journal for read/write access. Write access is required because
+ ** in exclusive-access mode the file descriptor will be kept open
+ ** and possibly used for a transaction later on. Also, write-access
+ ** is usually required to finalize the journal in journal_mode=persist
+ ** mode (and also for journal_mode=truncate on some systems).
+ **
+ ** If the journal does not exist, it usually means that some
+ ** other connection managed to get in and roll it back before
+ ** this connection obtained the exclusive lock above. Or, it
+ ** may mean that the pager was in the error-state when this
+ ** function was called and the journal file does not exist.
+ */
+ if( !isOpen(pPager->jfd) ){
+ sqlite3_vfs * const pVfs = pPager->pVfs;
+ int bExists; /* True if journal file exists */
+ rc = sqlite3OsAccess(
+ pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
+ if( rc==SQLITE_OK && bExists ){
+ int fout = 0;
+ int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
+ assert( !pPager->tempFile );
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
+ assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
+ if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ sqlite3OsClose(pPager->jfd);
+ }
+ }
+ }
+
+ /* Playback and delete the journal. Drop the database write
+ ** lock and reacquire the read lock. Purge the cache before
+ ** playing back the hot-journal so that we don't end up with
+ ** an inconsistent cache. Sync the hot journal before playing
+ ** it back since the process that crashed and left the hot journal
+ ** probably did not sync it and we are required to always sync
+ ** the journal before playing it back.
+ */
+ if( isOpen(pPager->jfd) ){
+ assert( rc==SQLITE_OK );
+ rc = pagerSyncHotJournal(pPager);
+ if( rc==SQLITE_OK ){
+ rc = pager_playback(pPager, 1);
+ pPager->eState = PAGER_OPEN;
+ }
+ }else if( !pPager->exclusiveMode ){
+ pagerUnlockDb(pPager, SHARED_LOCK);
+ }
+
+ if( rc!=SQLITE_OK ){
+ /* This branch is taken if an error occurs while trying to open
+ ** or roll back a hot-journal while holding an EXCLUSIVE lock. The
+ ** pager_unlock() routine will be called before returning to unlock
+ ** the file. If the unlock attempt fails, then Pager.eLock must be
+ ** set to UNKNOWN_LOCK (see the comment above the #define for
+ ** UNKNOWN_LOCK above for an explanation).
+ **
+ ** In order to get pager_unlock() to do this, set Pager.eState to
+ ** PAGER_ERROR now. This is not actually counted as a transition
+ ** to ERROR state in the state diagram at the top of this file,
+ ** since we know that the same call to pager_unlock() will very
+ ** shortly transition the pager object to the OPEN state. Calling
+ ** assert_pager_state() would fail now, as it should not be possible
+ ** to be in ERROR state when there are zero outstanding page
+ ** references.
+ */
+ pager_error(pPager, rc);
+ goto failed;
+ }
+
+ assert( pPager->eState==PAGER_OPEN );
+ assert( (pPager->eLock==SHARED_LOCK)
+ || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
+ );
+ }
+
+ if( !pPager->tempFile
+ && (pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0)
+ ){
+ /* The shared-lock has just been acquired on the database file
+ ** and there are already pages in the cache (from a previous
+ ** read or write transaction). Check to see if the database
+ ** has been modified. If the database has changed, flush the
+ ** cache.
+ **
+ ** Database changes is detected by looking at 15 bytes beginning
+ ** at offset 24 into the file. The first 4 of these 16 bytes are
+ ** a 32-bit counter that is incremented with each change. The
+ ** other bytes change randomly with each file change when
+ ** a codec is in use.
+ **
+ ** There is a vanishingly small chance that a change will not be
+ ** detected. The chance of an undetected change is so small that
+ ** it can be neglected.
+ */
+ Pgno nPage = 0;
+ char dbFileVers[sizeof(pPager->dbFileVers)];
+
+ rc = pagerPagecount(pPager, &nPage);
+ if( rc ) goto failed;
+
+ if( nPage>0 ){
+ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
+ rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
+ if( rc!=SQLITE_OK ){
+ goto failed;
+ }
+ }else{
+ memset(dbFileVers, 0, sizeof(dbFileVers));
+ }
+
+ if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
+ pager_reset(pPager);
+ }
+ }
+
+ /* If there is a WAL file in the file-system, open this database in WAL
+ ** mode. Otherwise, the following function call is a no-op.
+ */
+ rc = pagerOpenWalIfPresent(pPager);
+#ifndef SQLITE_OMIT_WAL
+ assert( pPager->pWal==0 || rc==SQLITE_OK );
+#endif
+ }
+
+ if( pagerUseWal(pPager) ){
+ assert( rc==SQLITE_OK );
+ rc = pagerBeginReadTransaction(pPager);
+ }
+
+ if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
+ rc = pagerPagecount(pPager, &pPager->dbSize);
+ }
+
+ failed:
+ if( rc!=SQLITE_OK ){
+ assert( !MEMDB );
+ pager_unlock(pPager);
+ assert( pPager->eState==PAGER_OPEN );
+ }else{
+ pPager->eState = PAGER_READER;
+ }
+ return rc;
+}
+
+/*
+** If the reference count has reached zero, rollback any active
+** transaction and unlock the pager.
+**
+** Except, in locking_mode=EXCLUSIVE when there is nothing to in
+** the rollback journal, the unlock is not performed and there is
+** nothing to rollback, so this routine is a no-op.
+*/
+static void pagerUnlockIfUnused(Pager *pPager){
+ if( (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
+ pagerUnlockAndRollback(pPager);
+ }
+}
+
+/*
+** Acquire a reference to page number pgno in pager pPager (a page
+** reference has type DbPage*). If the requested reference is
+** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
+**
+** If the requested page is already in the cache, it is returned.
+** Otherwise, a new page object is allocated and populated with data
+** read from the database file. In some cases, the pcache module may
+** choose not to allocate a new page object and may reuse an existing
+** object with no outstanding references.
+**
+** The extra data appended to a page is always initialized to zeros the
+** first time a page is loaded into memory. If the page requested is
+** already in the cache when this function is called, then the extra
+** data is left as it was when the page object was last used.
+**
+** If the database image is smaller than the requested page or if a
+** non-zero value is passed as the noContent parameter and the
+** requested page is not already stored in the cache, then no
+** actual disk read occurs. In this case the memory image of the
+** page is initialized to all zeros.
+**
+** If noContent is true, it means that we do not care about the contents
+** of the page. This occurs in two seperate scenarios:
+**
+** a) When reading a free-list leaf page from the database, and
+**
+** b) When a savepoint is being rolled back and we need to load
+** a new page into the cache to be filled with the data read
+** from the savepoint journal.
+**
+** If noContent is true, then the data returned is zeroed instead of
+** being read from the database. Additionally, the bits corresponding
+** to pgno in Pager.pInJournal (bitvec of pages already written to the
+** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
+** savepoints are set. This means if the page is made writable at any
+** point in the future, using a call to sqlite3PagerWrite(), its contents
+** will not be journaled. This saves IO.
+**
+** The acquisition might fail for several reasons. In all cases,
+** an appropriate error code is returned and *ppPage is set to NULL.
+**
+** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt
+** to find a page in the in-memory cache first. If the page is not already
+** in memory, this routine goes to disk to read it in whereas Lookup()
+** just returns 0. This routine acquires a read-lock the first time it
+** has to go to disk, and could also playback an old journal if necessary.
+** Since Lookup() never goes to disk, it never has to deal with locks
+** or journal files.
+*/
+SQLITE_PRIVATE int sqlite3PagerAcquire(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int noContent /* Do not bother reading content from disk if true */
+){
+ int rc;
+ PgHdr *pPg;
+
+ assert( pPager->eState>=PAGER_READER );
+ assert( assert_pager_state(pPager) );
+
+ if( pgno==0 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ /* If the pager is in the error state, return an error immediately.
+ ** Otherwise, request the page from the PCache layer. */
+ if( pPager->errCode!=SQLITE_OK ){
+ rc = pPager->errCode;
+ }else{
+ rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
+ }
+
+ if( rc!=SQLITE_OK ){
+ /* Either the call to sqlite3PcacheFetch() returned an error or the
+ ** pager was already in the error-state when this function was called.
+ ** Set pPg to 0 and jump to the exception handler. */
+ pPg = 0;
+ goto pager_acquire_err;
+ }
+ assert( (*ppPage)->pgno==pgno );
+ assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );
+
+ if( (*ppPage)->pPager && !noContent ){
+ /* In this case the pcache already contains an initialized copy of
+ ** the page. Return without further ado. */
+ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
+ pPager->aStat[PAGER_STAT_HIT]++;
+ return SQLITE_OK;
+
+ }else{
+ /* The pager cache has created a new page. Its content needs to
+ ** be initialized. */
+
+ pPg = *ppPage;
+ pPg->pPager = pPager;
+
+ /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
+ ** number greater than this, or the unused locking-page, is requested. */
+ if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto pager_acquire_err;
+ }
+
+ if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
+ if( pgno>pPager->mxPgno ){
+ rc = SQLITE_FULL;
+ goto pager_acquire_err;
+ }
+ if( noContent ){
+ /* Failure to set the bits in the InJournal bit-vectors is benign.
+ ** It merely means that we might do some extra work to journal a
+ ** page that does not need to be journaled. Nevertheless, be sure
+ ** to test the case where a malloc error occurs while trying to set
+ ** a bit in a bit vector.
+ */
+ sqlite3BeginBenignMalloc();
+ if( pgno<=pPager->dbOrigSize ){
+ TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
+ testcase( rc==SQLITE_NOMEM );
+ }
+ TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
+ testcase( rc==SQLITE_NOMEM );
+ sqlite3EndBenignMalloc();
+ }
+ memset(pPg->pData, 0, pPager->pageSize);
+ IOTRACE(("ZERO %p %d\n", pPager, pgno));
+ }else{
+ assert( pPg->pPager==pPager );
+ pPager->aStat[PAGER_STAT_MISS]++;
+ rc = readDbPage(pPg);
+ if( rc!=SQLITE_OK ){
+ goto pager_acquire_err;
+ }
+ }
+ pager_set_pagehash(pPg);
+ }
+
+ return SQLITE_OK;
+
+pager_acquire_err:
+ assert( rc!=SQLITE_OK );
+ if( pPg ){
+ sqlite3PcacheDrop(pPg);
+ }
+ pagerUnlockIfUnused(pPager);
+
+ *ppPage = 0;
+ return rc;
+}
+
+/*
+** Acquire a page if it is already in the in-memory cache. Do
+** not read the page from disk. Return a pointer to the page,
+** or 0 if the page is not in cache.
+**
+** See also sqlite3PagerGet(). The difference between this routine
+** and sqlite3PagerGet() is that _get() will go to the disk and read
+** in the page if the page is not already in cache. This routine
+** returns NULL if the page is not in cache or if a disk I/O error
+** has ever happened.
+*/
+SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
+ PgHdr *pPg = 0;
+ assert( pPager!=0 );
+ assert( pgno!=0 );
+ assert( pPager->pPCache!=0 );
+ assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR );
+ sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
+ return pPg;
+}
+
+/*
+** Release a page reference.
+**
+** If the number of references to the page drop to zero, then the
+** page is added to the LRU list. When all references to all pages
+** are released, a rollback occurs and the lock on the database is
+** removed.
+*/
+SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
+ if( pPg ){
+ Pager *pPager = pPg->pPager;
+ sqlite3PcacheRelease(pPg);
+ pagerUnlockIfUnused(pPager);
+ }
+}
+
+/*
+** This function is called at the start of every write transaction.
+** There must already be a RESERVED or EXCLUSIVE lock on the database
+** file when this routine is called.
+**
+** Open the journal file for pager pPager and write a journal header
+** to the start of it. If there are active savepoints, open the sub-journal
+** as well. This function is only used when the journal file is being
+** opened to write a rollback log for a transaction. It is not used
+** when opening a hot journal file to roll it back.
+**
+** If the journal file is already open (as it may be in exclusive mode),
+** then this function just writes a journal header to the start of the
+** already open file.
+**
+** Whether or not the journal file is opened by this function, the
+** Pager.pInJournal bitvec structure is allocated.
+**
+** Return SQLITE_OK if everything is successful. Otherwise, return
+** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
+** an IO error code if opening or writing the journal file fails.
+*/
+static int pager_open_journal(Pager *pPager){
+ int rc = SQLITE_OK; /* Return code */
+ sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */
+
+ assert( pPager->eState==PAGER_WRITER_LOCKED );
+ assert( assert_pager_state(pPager) );
+ assert( pPager->pInJournal==0 );
+
+ /* If already in the error state, this function is a no-op. But on
+ ** the other hand, this routine is never called if we are already in
+ ** an error state. */
+ if( NEVER(pPager->errCode) ) return pPager->errCode;
+
+ if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
+ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
+ if( pPager->pInJournal==0 ){
+ return SQLITE_NOMEM;
+ }
+
+ /* Open the journal file if it is not already open. */
+ if( !isOpen(pPager->jfd) ){
+ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
+ sqlite3MemJournalOpen(pPager->jfd);
+ }else{
+ const int flags = /* VFS flags to open journal file */
+ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
+ (pPager->tempFile ?
+ (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
+ (SQLITE_OPEN_MAIN_JOURNAL)
+ );
+ #ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ rc = sqlite3JournalOpen(
+ pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+ );
+ #else
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+ #endif
+ }
+ assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
+ }
+
+
+ /* Write the first journal header to the journal file and open
+ ** the sub-journal if necessary.
+ */
+ if( rc==SQLITE_OK ){
+ /* TODO: Check if all of these are really required. */
+ pPager->nRec = 0;
+ pPager->journalOff = 0;
+ pPager->setMaster = 0;
+ pPager->journalHdr = 0;
+ rc = writeJournalHdr(pPager);
+ }
+ }
+
+ if( rc!=SQLITE_OK ){
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
+ }else{
+ assert( pPager->eState==PAGER_WRITER_LOCKED );
+ pPager->eState = PAGER_WRITER_CACHEMOD;
+ }
+
+ return rc;
+}
+
+/*
+** Begin a write-transaction on the specified pager object. If a
+** write-transaction has already been opened, this function is a no-op.
+**
+** If the exFlag argument is false, then acquire at least a RESERVED
+** lock on the database file. If exFlag is true, then acquire at least
+** an EXCLUSIVE lock. If such a lock is already held, no locking
+** functions need be called.
+**
+** If the subjInMemory argument is non-zero, then any sub-journal opened
+** within this transaction will be opened as an in-memory file. This
+** has no effect if the sub-journal is already opened (as it may be when
+** running in exclusive mode) or if the transaction does not require a
+** sub-journal. If the subjInMemory argument is zero, then any required
+** sub-journal is implemented in-memory if pPager is an in-memory database,
+** or using a temporary file otherwise.
+*/
+SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
+ int rc = SQLITE_OK;
+
+ if( pPager->errCode ) return pPager->errCode;
+ assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
+ pPager->subjInMemory = (u8)subjInMemory;
+
+ if( ALWAYS(pPager->eState==PAGER_READER) ){
+ assert( pPager->pInJournal==0 );
+
+ if( pagerUseWal(pPager) ){
+ /* If the pager is configured to use locking_mode=exclusive, and an
+ ** exclusive lock on the database is not already held, obtain it now.
+ */
+ if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
+ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ sqlite3WalExclusiveMode(pPager->pWal, 1);
+ }
+
+ /* Grab the write lock on the log file. If successful, upgrade to
+ ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
+ ** The busy-handler is not invoked if another connection already
+ ** holds the write-lock. If possible, the upper layer will call it.
+ */
+ rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
+ }else{
+ /* Obtain a RESERVED lock on the database file. If the exFlag parameter
+ ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
+ ** busy-handler callback can be used when upgrading to the EXCLUSIVE
+ ** lock, but not when obtaining the RESERVED lock.
+ */
+ rc = pagerLockDb(pPager, RESERVED_LOCK);
+ if( rc==SQLITE_OK && exFlag ){
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ /* Change to WRITER_LOCKED state.
+ **
+ ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
+ ** when it has an open transaction, but never to DBMOD or FINISHED.
+ ** This is because in those states the code to roll back savepoint
+ ** transactions may copy data from the sub-journal into the database
+ ** file as well as into the page cache. Which would be incorrect in
+ ** WAL mode.
+ */
+ pPager->eState = PAGER_WRITER_LOCKED;
+ pPager->dbHintSize = pPager->dbSize;
+ pPager->dbFileSize = pPager->dbSize;
+ pPager->dbOrigSize = pPager->dbSize;
+ pPager->journalOff = 0;
+ }
+
+ assert( rc==SQLITE_OK || pPager->eState==PAGER_READER );
+ assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED );
+ assert( assert_pager_state(pPager) );
+ }
+
+ PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
+ return rc;
+}
+
+/*
+** Mark a single data page as writeable. The page is written into the
+** main journal or sub-journal as required. If the page is written into
+** one of the journals, the corresponding bit is set in the
+** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
+** of any open savepoints as appropriate.
+*/
+static int pager_write(PgHdr *pPg){
+ void *pData = pPg->pData;
+ Pager *pPager = pPg->pPager;
+ int rc = SQLITE_OK;
+
+ /* This routine is not called unless a write-transaction has already
+ ** been started. The journal file may or may not be open at this point.
+ ** It is never called in the ERROR state.
+ */
+ assert( pPager->eState==PAGER_WRITER_LOCKED
+ || pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ );
+ assert( assert_pager_state(pPager) );
+
+ /* If an error has been previously detected, report the same error
+ ** again. This should not happen, but the check provides robustness. */
+ if( NEVER(pPager->errCode) ) return pPager->errCode;
+
+ /* Higher-level routines never call this function if database is not
+ ** writable. But check anyway, just for robustness. */
+ if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
+
+ CHECK_PAGE(pPg);
+
+ /* The journal file needs to be opened. Higher level routines have already
+ ** obtained the necessary locks to begin the write-transaction, but the
+ ** rollback journal might not yet be open. Open it now if this is the case.
+ **
+ ** This is done before calling sqlite3PcacheMakeDirty() on the page.
+ ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
+ ** an error might occur and the pager would end up in WRITER_LOCKED state
+ ** with pages marked as dirty in the cache.
+ */
+ if( pPager->eState==PAGER_WRITER_LOCKED ){
+ rc = pager_open_journal(pPager);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
+ assert( assert_pager_state(pPager) );
+
+ /* Mark the page as dirty. If the page has already been written
+ ** to the journal then we can return right away.
+ */
+ sqlite3PcacheMakeDirty(pPg);
+ if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
+ assert( !pagerUseWal(pPager) );
+ }else{
+
+ /* The transaction journal now exists and we have a RESERVED or an
+ ** EXCLUSIVE lock on the main database file. Write the current page to
+ ** the transaction journal if it is not there already.
+ */
+ if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
+ assert( pagerUseWal(pPager)==0 );
+ if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
+ u32 cksum;
+ char *pData2;
+ i64 iOff = pPager->journalOff;
+
+ /* We should never write to the journal file the page that
+ ** contains the database locks. The following assert verifies
+ ** that we do not. */
+ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
+
+ assert( pPager->journalHdr<=pPager->journalOff );
+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
+ cksum = pager_cksum(pPager, (u8*)pData2);
+
+ /* Even if an IO or diskfull error occurs while journalling the
+ ** page in the block above, set the need-sync flag for the page.
+ ** Otherwise, when the transaction is rolled back, the logic in
+ ** playback_one_page() will think that the page needs to be restored
+ ** in the database file. And if an IO error occurs while doing so,
+ ** then corruption may follow.
+ */
+ pPg->flags |= PGHDR_NEED_SYNC;
+
+ rc = write32bits(pPager->jfd, iOff, pPg->pgno);
+ if( rc!=SQLITE_OK ) return rc;
+ rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
+ if( rc!=SQLITE_OK ) return rc;
+ rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
+ if( rc!=SQLITE_OK ) return rc;
+
+ IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
+ pPager->journalOff, pPager->pageSize));
+ PAGER_INCR(sqlite3_pager_writej_count);
+ PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
+ PAGERID(pPager), pPg->pgno,
+ ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
+
+ pPager->journalOff += 8 + pPager->pageSize;
+ pPager->nRec++;
+ assert( pPager->pInJournal!=0 );
+ rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
+ testcase( rc==SQLITE_NOMEM );
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ rc |= addToSavepointBitvecs(pPager, pPg->pgno);
+ if( rc!=SQLITE_OK ){
+ assert( rc==SQLITE_NOMEM );
+ return rc;
+ }
+ }else{
+ if( pPager->eState!=PAGER_WRITER_DBMOD ){
+ pPg->flags |= PGHDR_NEED_SYNC;
+ }
+ PAGERTRACE(("APPEND %d page %d needSync=%d\n",
+ PAGERID(pPager), pPg->pgno,
+ ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
+ }
+ }
+
+ /* If the statement journal is open and the page is not in it,
+ ** then write the current page to the statement journal. Note that
+ ** the statement journal format differs from the standard journal format
+ ** in that it omits the checksums and the header.
+ */
+ if( subjRequiresPage(pPg) ){
+ rc = subjournalPage(pPg);
+ }
+ }
+
+ /* Update the database size and return.
+ */
+ if( pPager->dbSize<pPg->pgno ){
+ pPager->dbSize = pPg->pgno;
+ }
+ return rc;
+}
+
+/*
+** Mark a data page as writeable. This routine must be called before
+** making changes to a page. The caller must check the return value
+** of this function and be careful not to change any page data unless
+** this routine returns SQLITE_OK.
+**
+** The difference between this function and pager_write() is that this
+** function also deals with the special case where 2 or more pages
+** fit on a single disk sector. In this case all co-resident pages
+** must have been written to the journal file before returning.
+**
+** If an error occurs, SQLITE_NOMEM or an IO error code is returned
+** as appropriate. Otherwise, SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
+ int rc = SQLITE_OK;
+
+ PgHdr *pPg = pDbPage;
+ Pager *pPager = pPg->pPager;
+ Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
+
+ assert( pPager->eState>=PAGER_WRITER_LOCKED );
+ assert( pPager->eState!=PAGER_ERROR );
+ assert( assert_pager_state(pPager) );
+
+ if( nPagePerSector>1 ){
+ Pgno nPageCount; /* Total number of pages in database file */
+ Pgno pg1; /* First page of the sector pPg is located on. */
+ int nPage = 0; /* Number of pages starting at pg1 to journal */
+ int ii; /* Loop counter */
+ int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
+
+ /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
+ ** a journal header to be written between the pages journaled by
+ ** this function.
+ */
+ assert( !MEMDB );
+ assert( pPager->doNotSyncSpill==0 );
+ pPager->doNotSyncSpill++;
+
+ /* This trick assumes that both the page-size and sector-size are
+ ** an integer power of 2. It sets variable pg1 to the identifier
+ ** of the first page of the sector pPg is located on.
+ */
+ pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
+
+ nPageCount = pPager->dbSize;
+ if( pPg->pgno>nPageCount ){
+ nPage = (pPg->pgno - pg1)+1;
+ }else if( (pg1+nPagePerSector-1)>nPageCount ){
+ nPage = nPageCount+1-pg1;
+ }else{
+ nPage = nPagePerSector;
+ }
+ assert(nPage>0);
+ assert(pg1<=pPg->pgno);
+ assert((pg1+nPage)>pPg->pgno);
+
+ for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
+ Pgno pg = pg1+ii;
+ PgHdr *pPage;
+ if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
+ if( pg!=PAGER_MJ_PGNO(pPager) ){
+ rc = sqlite3PagerGet(pPager, pg, &pPage);
+ if( rc==SQLITE_OK ){
+ rc = pager_write(pPage);
+ if( pPage->flags&PGHDR_NEED_SYNC ){
+ needSync = 1;
+ }
+ sqlite3PagerUnref(pPage);
+ }
+ }
+ }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
+ if( pPage->flags&PGHDR_NEED_SYNC ){
+ needSync = 1;
+ }
+ sqlite3PagerUnref(pPage);
+ }
+ }
+
+ /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
+ ** starting at pg1, then it needs to be set for all of them. Because
+ ** writing to any of these nPage pages may damage the others, the
+ ** journal file must contain sync()ed copies of all of them
+ ** before any of them can be written out to the database file.
+ */
+ if( rc==SQLITE_OK && needSync ){
+ assert( !MEMDB );
+ for(ii=0; ii<nPage; ii++){
+ PgHdr *pPage = pager_lookup(pPager, pg1+ii);
+ if( pPage ){
+ pPage->flags |= PGHDR_NEED_SYNC;
+ sqlite3PagerUnref(pPage);
+ }
+ }
+ }
+
+ assert( pPager->doNotSyncSpill==1 );
+ pPager->doNotSyncSpill--;
+ }else{
+ rc = pager_write(pDbPage);
+ }
+ return rc;
+}
+
+/*
+** Return TRUE if the page given in the argument was previously passed
+** to sqlite3PagerWrite(). In other words, return TRUE if it is ok
+** to change the content of the page.
+*/
+#ifndef NDEBUG
+SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
+ return pPg->flags&PGHDR_DIRTY;
+}
+#endif
+
+/*
+** A call to this routine tells the pager that it is not necessary to
+** write the information on page pPg back to the disk, even though
+** that page might be marked as dirty. This happens, for example, when
+** the page has been added as a leaf of the freelist and so its
+** content no longer matters.
+**
+** The overlying software layer calls this routine when all of the data
+** on the given page is unused. The pager marks the page as clean so
+** that it does not get written to disk.
+**
+** Tests show that this optimization can quadruple the speed of large
+** DELETE operations.
+*/
+SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
+ Pager *pPager = pPg->pPager;
+ if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
+ PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
+ IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
+ pPg->flags |= PGHDR_DONT_WRITE;
+ pager_set_pagehash(pPg);
+ }
+}
+
+/*
+** This routine is called to increment the value of the database file
+** change-counter, stored as a 4-byte big-endian integer starting at
+** byte offset 24 of the pager file. The secondary change counter at
+** 92 is also updated, as is the SQLite version number at offset 96.
+**
+** But this only happens if the pPager->changeCountDone flag is false.
+** To avoid excess churning of page 1, the update only happens once.
+** See also the pager_write_changecounter() routine that does an
+** unconditional update of the change counters.
+**
+** If the isDirectMode flag is zero, then this is done by calling
+** sqlite3PagerWrite() on page 1, then modifying the contents of the
+** page data. In this case the file will be updated when the current
+** transaction is committed.
+**
+** The isDirectMode flag may only be non-zero if the library was compiled
+** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
+** if isDirect is non-zero, then the database file is updated directly
+** by writing an updated version of page 1 using a call to the
+** sqlite3OsWrite() function.
+*/
+static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
+ int rc = SQLITE_OK;
+
+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ );
+ assert( assert_pager_state(pPager) );
+
+ /* Declare and initialize constant integer 'isDirect'. If the
+ ** atomic-write optimization is enabled in this build, then isDirect
+ ** is initialized to the value passed as the isDirectMode parameter
+ ** to this function. Otherwise, it is always set to zero.
+ **
+ ** The idea is that if the atomic-write optimization is not
+ ** enabled at compile time, the compiler can omit the tests of
+ ** 'isDirect' below, as well as the block enclosed in the
+ ** "if( isDirect )" condition.
+ */
+#ifndef SQLITE_ENABLE_ATOMIC_WRITE
+# define DIRECT_MODE 0
+ assert( isDirectMode==0 );
+ UNUSED_PARAMETER(isDirectMode);
+#else
+# define DIRECT_MODE isDirectMode
+#endif
+
+ if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
+ PgHdr *pPgHdr; /* Reference to page 1 */
+
+ assert( !pPager->tempFile && isOpen(pPager->fd) );
+
+ /* Open page 1 of the file for writing. */
+ rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
+ assert( pPgHdr==0 || rc==SQLITE_OK );
+
+ /* If page one was fetched successfully, and this function is not
+ ** operating in direct-mode, make page 1 writable. When not in
+ ** direct mode, page 1 is always held in cache and hence the PagerGet()
+ ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
+ */
+ if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
+ rc = sqlite3PagerWrite(pPgHdr);
+ }
+
+ if( rc==SQLITE_OK ){
+ /* Actually do the update of the change counter */
+ pager_write_changecounter(pPgHdr);
+
+ /* If running in direct mode, write the contents of page 1 to the file. */
+ if( DIRECT_MODE ){
+ const void *zBuf;
+ assert( pPager->dbFileSize>0 );
+ CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
+ pPager->aStat[PAGER_STAT_WRITE]++;
+ }
+ if( rc==SQLITE_OK ){
+ pPager->changeCountDone = 1;
+ }
+ }else{
+ pPager->changeCountDone = 1;
+ }
+ }
+
+ /* Release the page reference. */
+ sqlite3PagerUnref(pPgHdr);
+ }
+ return rc;
+}
+
+/*
+** Sync the database file to disk. This is a no-op for in-memory databases
+** or pages with the Pager.noSync flag set.
+**
+** If successful, or if called on a pager for which it is a no-op, this
+** function returns SQLITE_OK. Otherwise, an IO error code is returned.
+*/
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
+ int rc = SQLITE_OK;
+ if( !pPager->noSync ){
+ assert( !MEMDB );
+ rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
+ }else if( isOpen(pPager->fd) ){
+ assert( !MEMDB );
+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
+ if( rc==SQLITE_NOTFOUND ){
+ rc = SQLITE_OK;
+ }
+ }
+ return rc;
+}
+
+/*
+** This function may only be called while a write-transaction is active in
+** rollback. If the connection is in WAL mode, this call is a no-op.
+** Otherwise, if the connection does not already have an EXCLUSIVE lock on
+** the database file, an attempt is made to obtain one.
+**
+** If the EXCLUSIVE lock is already held or the attempt to obtain it is
+** successful, or the connection is in WAL mode, SQLITE_OK is returned.
+** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
+** returned.
+*/
+SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
+ int rc = SQLITE_OK;
+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ || pPager->eState==PAGER_WRITER_LOCKED
+ );
+ assert( assert_pager_state(pPager) );
+ if( 0==pagerUseWal(pPager) ){
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ }
+ return rc;
+}
+
+/*
+** Sync the database file for the pager pPager. zMaster points to the name
+** of a master journal file that should be written into the individual
+** journal file. zMaster may be NULL, which is interpreted as no master
+** journal (a single database transaction).
+**
+** This routine ensures that:
+**
+** * The database file change-counter is updated,
+** * the journal is synced (unless the atomic-write optimization is used),
+** * all dirty pages are written to the database file,
+** * the database file is truncated (if required), and
+** * the database file synced.
+**
+** The only thing that remains to commit the transaction is to finalize
+** (delete, truncate or zero the first part of) the journal file (or
+** delete the master journal file if specified).
+**
+** Note that if zMaster==NULL, this does not overwrite a previous value
+** passed to an sqlite3PagerCommitPhaseOne() call.
+**
+** If the final parameter - noSync - is true, then the database file itself
+** is not synced. The caller must call sqlite3PagerSync() directly to
+** sync the database file before calling CommitPhaseTwo() to delete the
+** journal file in this case.
+*/
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
+ Pager *pPager, /* Pager object */
+ const char *zMaster, /* If not NULL, the master journal name */
+ int noSync /* True to omit the xSync on the db file */
+){
+ int rc = SQLITE_OK; /* Return code */
+
+ assert( pPager->eState==PAGER_WRITER_LOCKED
+ || pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ || pPager->eState==PAGER_ERROR
+ );
+ assert( assert_pager_state(pPager) );
+
+ /* If a prior error occurred, report that error again. */
+ if( NEVER(pPager->errCode) ) return pPager->errCode;
+
+ PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
+ pPager->zFilename, zMaster, pPager->dbSize));
+
+ /* If no database changes have been made, return early. */
+ if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
+
+ if( MEMDB ){
+ /* If this is an in-memory db, or no pages have been written to, or this
+ ** function has already been called, it is mostly a no-op. However, any
+ ** backup in progress needs to be restarted.
+ */
+ sqlite3BackupRestart(pPager->pBackup);
+ }else{
+ if( pagerUseWal(pPager) ){
+ PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
+ PgHdr *pPageOne = 0;
+ if( pList==0 ){
+ /* Must have at least one page for the WAL commit flag.
+ ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
+ rc = sqlite3PagerGet(pPager, 1, &pPageOne);
+ pList = pPageOne;
+ pList->pDirty = 0;
+ }
+ assert( rc==SQLITE_OK );
+ if( ALWAYS(pList) ){
+ rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
+ }
+ sqlite3PagerUnref(pPageOne);
+ if( rc==SQLITE_OK ){
+ sqlite3PcacheCleanAll(pPager->pPCache);
+ }
+ }else{
+ /* The following block updates the change-counter. Exactly how it
+ ** does this depends on whether or not the atomic-update optimization
+ ** was enabled at compile time, and if this transaction meets the
+ ** runtime criteria to use the operation:
+ **
+ ** * The file-system supports the atomic-write property for
+ ** blocks of size page-size, and
+ ** * This commit is not part of a multi-file transaction, and
+ ** * Exactly one page has been modified and store in the journal file.
+ **
+ ** If the optimization was not enabled at compile time, then the
+ ** pager_incr_changecounter() function is called to update the change
+ ** counter in 'indirect-mode'. If the optimization is compiled in but
+ ** is not applicable to this transaction, call sqlite3JournalCreate()
+ ** to make sure the journal file has actually been created, then call
+ ** pager_incr_changecounter() to update the change-counter in indirect
+ ** mode.
+ **
+ ** Otherwise, if the optimization is both enabled and applicable,
+ ** then call pager_incr_changecounter() to update the change-counter
+ ** in 'direct' mode. In this case the journal file will never be
+ ** created for this transaction.
+ */
+ #ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ PgHdr *pPg;
+ assert( isOpen(pPager->jfd)
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ );
+ if( !zMaster && isOpen(pPager->jfd)
+ && pPager->journalOff==jrnlBufferSize(pPager)
+ && pPager->dbSize>=pPager->dbOrigSize
+ && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
+ ){
+ /* Update the db file change counter via the direct-write method. The
+ ** following call will modify the in-memory representation of page 1
+ ** to include the updated change counter and then write page 1
+ ** directly to the database file. Because of the atomic-write
+ ** property of the host file-system, this is safe.
+ */
+ rc = pager_incr_changecounter(pPager, 1);
+ }else{
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc==SQLITE_OK ){
+ rc = pager_incr_changecounter(pPager, 0);
+ }
+ }
+ #else
+ rc = pager_incr_changecounter(pPager, 0);
+ #endif
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+
+ /* Write the master journal name into the journal file. If a master
+ ** journal file name has already been written to the journal file,
+ ** or if zMaster is NULL (no master journal), then this call is a no-op.
+ */
+ rc = writeMasterJournal(pPager, zMaster);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+
+ /* Sync the journal file and write all dirty pages to the database.
+ ** If the atomic-update optimization is being used, this sync will not
+ ** create the journal file or perform any real IO.
+ **
+ ** Because the change-counter page was just modified, unless the
+ ** atomic-update optimization is used it is almost certain that the
+ ** journal requires a sync here. However, in locking_mode=exclusive
+ ** on a system under memory pressure it is just possible that this is
+ ** not the case. In this case it is likely enough that the redundant
+ ** xSync() call will be changed to a no-op by the OS anyhow.
+ */
+ rc = syncJournal(pPager, 0);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+
+ rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
+ if( rc!=SQLITE_OK ){
+ assert( rc!=SQLITE_IOERR_BLOCKED );
+ goto commit_phase_one_exit;
+ }
+ sqlite3PcacheCleanAll(pPager->pPCache);
+
+ /* If the file on disk is smaller than the database image, use
+ ** pager_truncate to grow the file here. This can happen if the database
+ ** image was extended as part of the current transaction and then the
+ ** last page in the db image moved to the free-list. In this case the
+ ** last page is never written out to disk, leaving the database file
+ ** undersized. Fix this now if it is the case. */
+ if( pPager->dbSize>pPager->dbFileSize ){
+ Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
+ assert( pPager->eState==PAGER_WRITER_DBMOD );
+ rc = pager_truncate(pPager, nNew);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ }
+
+ /* Finally, sync the database file. */
+ if( !noSync ){
+ rc = sqlite3PagerSync(pPager);
+ }
+ IOTRACE(("DBSYNC %p\n", pPager))
+ }
+ }
+
+commit_phase_one_exit:
+ if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
+ pPager->eState = PAGER_WRITER_FINISHED;
+ }
+ return rc;
+}
+
+
+/*
+** When this function is called, the database file has been completely
+** updated to reflect the changes made by the current transaction and
+** synced to disk. The journal file still exists in the file-system
+** though, and if a failure occurs at this point it will eventually
+** be used as a hot-journal and the current transaction rolled back.
+**
+** This function finalizes the journal file, either by deleting,
+** truncating or partially zeroing it, so that it cannot be used
+** for hot-journal rollback. Once this is done the transaction is
+** irrevocably committed.
+**
+** If an error occurs, an IO error code is returned and the pager
+** moves into the error state. Otherwise, SQLITE_OK is returned.
+*/
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
+ int rc = SQLITE_OK; /* Return code */
+
+ /* This routine should not be called if a prior error has occurred.
+ ** But if (due to a coding error elsewhere in the system) it does get
+ ** called, just return the same error code without doing anything. */
+ if( NEVER(pPager->errCode) ) return pPager->errCode;
+
+ assert( pPager->eState==PAGER_WRITER_LOCKED
+ || pPager->eState==PAGER_WRITER_FINISHED
+ || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
+ );
+ assert( assert_pager_state(pPager) );
+
+ /* An optimization. If the database was not actually modified during
+ ** this transaction, the pager is running in exclusive-mode and is
+ ** using persistent journals, then this function is a no-op.
+ **
+ ** The start of the journal file currently contains a single journal
+ ** header with the nRec field set to 0. If such a journal is used as
+ ** a hot-journal during hot-journal rollback, 0 changes will be made
+ ** to the database file. So there is no need to zero the journal
+ ** header. Since the pager is in exclusive mode, there is no need
+ ** to drop any locks either.
+ */
+ if( pPager->eState==PAGER_WRITER_LOCKED
+ && pPager->exclusiveMode
+ && pPager->journalMode==PAGER_JOURNALMODE_PERSIST
+ ){
+ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
+ pPager->eState = PAGER_READER;
+ return SQLITE_OK;
+ }
+
+ PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
+ rc = pager_end_transaction(pPager, pPager->setMaster, 1);
+ return pager_error(pPager, rc);
+}
+
+/*
+** If a write transaction is open, then all changes made within the
+** transaction are reverted and the current write-transaction is closed.
+** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
+** state if an error occurs.
+**
+** If the pager is already in PAGER_ERROR state when this function is called,
+** it returns Pager.errCode immediately. No work is performed in this case.
+**
+** Otherwise, in rollback mode, this function performs two functions:
+**
+** 1) It rolls back the journal file, restoring all database file and
+** in-memory cache pages to the state they were in when the transaction
+** was opened, and
+**
+** 2) It finalizes the journal file, so that it is not used for hot
+** rollback at any point in the future.
+**
+** Finalization of the journal file (task 2) is only performed if the
+** rollback is successful.
+**
+** In WAL mode, all cache-entries containing data modified within the
+** current transaction are either expelled from the cache or reverted to
+** their pre-transaction state by re-reading data from the database or
+** WAL files. The WAL transaction is then closed.
+*/
+SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
+ int rc = SQLITE_OK; /* Return code */
+ PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
+
+ /* PagerRollback() is a no-op if called in READER or OPEN state. If
+ ** the pager is already in the ERROR state, the rollback is not
+ ** attempted here. Instead, the error code is returned to the caller.
+ */
+ assert( assert_pager_state(pPager) );
+ if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
+ if( pPager->eState<=PAGER_READER ) return SQLITE_OK;
+
+ if( pagerUseWal(pPager) ){
+ int rc2;
+ rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
+ rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
+ int eState = pPager->eState;
+ rc = pager_end_transaction(pPager, 0, 0);
+ if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
+ /* This can happen using journal_mode=off. Move the pager to the error
+ ** state to indicate that the contents of the cache may not be trusted.
+ ** Any active readers will get SQLITE_ABORT.
+ */
+ pPager->errCode = SQLITE_ABORT;
+ pPager->eState = PAGER_ERROR;
+ return rc;
+ }
+ }else{
+ rc = pager_playback(pPager, 0);
+ }
+
+ assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
+ assert( rc==SQLITE_OK || rc==SQLITE_FULL
+ || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
+
+ /* If an error occurs during a ROLLBACK, we can no longer trust the pager
+ ** cache. So call pager_error() on the way out to make any error persistent.
+ */
+ return pager_error(pPager, rc);
+}
+
+/*
+** Return TRUE if the database file is opened read-only. Return FALSE
+** if the database is (in theory) writable.
+*/
+SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){
+ return pPager->readOnly;
+}
+
+/*
+** Return the number of references to the pager.
+*/
+SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
+ return sqlite3PcacheRefCount(pPager->pPCache);
+}
+
+/*
+** Return the approximate number of bytes of memory currently
+** used by the pager and its associated cache.
+*/
+SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){
+ int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
+ + 5*sizeof(void*);
+ return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
+ + sqlite3MallocSize(pPager)
+ + pPager->pageSize;
+}
+
+/*
+** Return the number of references to the specified page.
+*/
+SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
+ return sqlite3PcachePageRefcount(pPage);
+}
+
+#ifdef SQLITE_TEST
+/*
+** This routine is used for testing and analysis only.
+*/
+SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
+ static int a[11];
+ a[0] = sqlite3PcacheRefCount(pPager->pPCache);
+ a[1] = sqlite3PcachePagecount(pPager->pPCache);
+ a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
+ a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
+ a[4] = pPager->eState;
+ a[5] = pPager->errCode;
+ a[6] = pPager->aStat[PAGER_STAT_HIT];
+ a[7] = pPager->aStat[PAGER_STAT_MISS];
+ a[8] = 0; /* Used to be pPager->nOvfl */
+ a[9] = pPager->nRead;
+ a[10] = pPager->aStat[PAGER_STAT_WRITE];
+ return a;
+}
+#endif
+
+/*
+** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
+** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
+** current cache hit or miss count, according to the value of eStat. If the
+** reset parameter is non-zero, the cache hit or miss count is zeroed before
+** returning.
+*/
+SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
+
+ assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
+ || eStat==SQLITE_DBSTATUS_CACHE_MISS
+ || eStat==SQLITE_DBSTATUS_CACHE_WRITE
+ );
+
+ assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
+ assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
+ assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
+
+ *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
+ if( reset ){
+ pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
+ }
+}
+
+/*
+** Return true if this is an in-memory pager.
+*/
+SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
+ return MEMDB;
+}
+
+/*
+** Check that there are at least nSavepoint savepoints open. If there are
+** currently less than nSavepoints open, then open one or more savepoints
+** to make up the difference. If the number of savepoints is already
+** equal to nSavepoint, then this function is a no-op.
+**
+** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
+** occurs while opening the sub-journal file, then an IO error code is
+** returned. Otherwise, SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
+ int rc = SQLITE_OK; /* Return code */
+ int nCurrent = pPager->nSavepoint; /* Current number of savepoints */
+
+ assert( pPager->eState>=PAGER_WRITER_LOCKED );
+ assert( assert_pager_state(pPager) );
+
+ if( nSavepoint>nCurrent && pPager->useJournal ){
+ int ii; /* Iterator variable */
+ PagerSavepoint *aNew; /* New Pager.aSavepoint array */
+
+ /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
+ ** if the allocation fails. Otherwise, zero the new portion in case a
+ ** malloc failure occurs while populating it in the for(...) loop below.
+ */
+ aNew = (PagerSavepoint *)sqlite3Realloc(
+ pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
+ );
+ if( !aNew ){
+ return SQLITE_NOMEM;
+ }
+ memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
+ pPager->aSavepoint = aNew;
+
+ /* Populate the PagerSavepoint structures just allocated. */
+ for(ii=nCurrent; ii<nSavepoint; ii++){
+ aNew[ii].nOrig = pPager->dbSize;
+ if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
+ aNew[ii].iOffset = pPager->journalOff;
+ }else{
+ aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
+ }
+ aNew[ii].iSubRec = pPager->nSubRec;
+ aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
+ if( !aNew[ii].pInSavepoint ){
+ return SQLITE_NOMEM;
+ }
+ if( pagerUseWal(pPager) ){
+ sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
+ }
+ pPager->nSavepoint = ii+1;
+ }
+ assert( pPager->nSavepoint==nSavepoint );
+ assertTruncateConstraint(pPager);
+ }
+
+ return rc;
+}
+
+/*
+** This function is called to rollback or release (commit) a savepoint.
+** The savepoint to release or rollback need not be the most recently
+** created savepoint.
+**
+** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
+** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
+** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
+** that have occurred since the specified savepoint was created.
+**
+** The savepoint to rollback or release is identified by parameter
+** iSavepoint. A value of 0 means to operate on the outermost savepoint
+** (the first created). A value of (Pager.nSavepoint-1) means operate
+** on the most recently created savepoint. If iSavepoint is greater than
+** (Pager.nSavepoint-1), then this function is a no-op.
+**
+** If a negative value is passed to this function, then the current
+** transaction is rolled back. This is different to calling
+** sqlite3PagerRollback() because this function does not terminate
+** the transaction or unlock the database, it just restores the
+** contents of the database to its original state.
+**
+** In any case, all savepoints with an index greater than iSavepoint
+** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
+** then savepoint iSavepoint is also destroyed.
+**
+** This function may return SQLITE_NOMEM if a memory allocation fails,
+** or an IO error code if an IO error occurs while rolling back a
+** savepoint. If no errors occur, SQLITE_OK is returned.
+*/
+SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
+ int rc = pPager->errCode; /* Return code */
+
+ assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
+ assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
+
+ if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
+ int ii; /* Iterator variable */
+ int nNew; /* Number of remaining savepoints after this op. */
+
+ /* Figure out how many savepoints will still be active after this
+ ** operation. Store this value in nNew. Then free resources associated
+ ** with any savepoints that are destroyed by this operation.
+ */
+ nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
+ for(ii=nNew; ii<pPager->nSavepoint; ii++){
+ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
+ }
+ pPager->nSavepoint = nNew;
+
+ /* If this is a release of the outermost savepoint, truncate
+ ** the sub-journal to zero bytes in size. */
+ if( op==SAVEPOINT_RELEASE ){
+ if( nNew==0 && isOpen(pPager->sjfd) ){
+ /* Only truncate if it is an in-memory sub-journal. */
+ if( sqlite3IsMemJournal(pPager->sjfd) ){
+ rc = sqlite3OsTruncate(pPager->sjfd, 0);
+ assert( rc==SQLITE_OK );
+ }
+ pPager->nSubRec = 0;
+ }
+ }
+ /* Else this is a rollback operation, playback the specified savepoint.
+ ** If this is a temp-file, it is possible that the journal file has
+ ** not yet been opened. In this case there have been no changes to
+ ** the database file, so the playback operation can be skipped.
+ */
+ else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
+ PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
+ rc = pagerPlaybackSavepoint(pPager, pSavepoint);
+ assert(rc!=SQLITE_DONE);
+ }
+ }
+
+ return rc;
+}
+
+/*
+** Return the full pathname of the database file.
+**
+** Except, if the pager is in-memory only, then return an empty string if
+** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when
+** used to report the filename to the user, for compatibility with legacy
+** behavior. But when the Btree needs to know the filename for matching to
+** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
+** participate in shared-cache.
+*/
+SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
+ return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
+}
+
+/*
+** Return the VFS structure for the pager.
+*/
+SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
+ return pPager->pVfs;
+}
+
+/*
+** Return the file handle for the database file associated
+** with the pager. This might return NULL if the file has
+** not yet been opened.
+*/
+SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
+ return pPager->fd;
+}
+
+/*
+** Return the full pathname of the journal file.
+*/
+SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
+ return pPager->zJournal;
+}
+
+/*
+** Return true if fsync() calls are disabled for this pager. Return FALSE
+** if fsync()s are executed normally.
+*/
+SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){
+ return pPager->noSync;
+}
+
+#ifdef SQLITE_HAS_CODEC
+/*
+** Set or retrieve the codec for this pager
+*/
+SQLITE_PRIVATE void sqlite3PagerSetCodec(
+ Pager *pPager,
+ void *(*xCodec)(void*,void*,Pgno,int),
+ void (*xCodecSizeChng)(void*,int,int),
+ void (*xCodecFree)(void*),
+ void *pCodec
+){
+ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
+ pPager->xCodec = pPager->memDb ? 0 : xCodec;
+ pPager->xCodecSizeChng = xCodecSizeChng;
+ pPager->xCodecFree = xCodecFree;
+ pPager->pCodec = pCodec;
+ pagerReportSize(pPager);
+}
+SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
+ return pPager->pCodec;
+}
+#endif
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Move the page pPg to location pgno in the file.
+**
+** There must be no references to the page previously located at
+** pgno (which we call pPgOld) though that page is allowed to be
+** in cache. If the page previously located at pgno is not already
+** in the rollback journal, it is not put there by by this routine.
+**
+** References to the page pPg remain valid. Updating any
+** meta-data associated with pPg (i.e. data stored in the nExtra bytes
+** allocated along with the page) is the responsibility of the caller.
+**
+** A transaction must be active when this routine is called. It used to be
+** required that a statement transaction was not active, but this restriction
+** has been removed (CREATE INDEX needs to move a page when a statement
+** transaction is active).
+**
+** If the fourth argument, isCommit, is non-zero, then this page is being
+** moved as part of a database reorganization just before the transaction
+** is being committed. In this case, it is guaranteed that the database page
+** pPg refers to will not be written to again within this transaction.
+**
+** This function may return SQLITE_NOMEM or an IO error code if an error
+** occurs. Otherwise, it returns SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
+ PgHdr *pPgOld; /* The page being overwritten. */
+ Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */
+ int rc; /* Return code */
+ Pgno origPgno; /* The original page number */
+
+ assert( pPg->nRef>0 );
+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ );
+ assert( assert_pager_state(pPager) );
+
+ /* In order to be able to rollback, an in-memory database must journal
+ ** the page we are moving from.
+ */
+ if( MEMDB ){
+ rc = sqlite3PagerWrite(pPg);
+ if( rc ) return rc;
+ }
+
+ /* If the page being moved is dirty and has not been saved by the latest
+ ** savepoint, then save the current contents of the page into the
+ ** sub-journal now. This is required to handle the following scenario:
+ **
+ ** BEGIN;
+ ** <journal page X, then modify it in memory>
+ ** SAVEPOINT one;
+ ** <Move page X to location Y>
+ ** ROLLBACK TO one;
+ **
+ ** If page X were not written to the sub-journal here, it would not
+ ** be possible to restore its contents when the "ROLLBACK TO one"
+ ** statement were is processed.
+ **
+ ** subjournalPage() may need to allocate space to store pPg->pgno into
+ ** one or more savepoint bitvecs. This is the reason this function
+ ** may return SQLITE_NOMEM.
+ */
+ if( pPg->flags&PGHDR_DIRTY
+ && subjRequiresPage(pPg)
+ && SQLITE_OK!=(rc = subjournalPage(pPg))
+ ){
+ return rc;
+ }
+
+ PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
+ PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
+ IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
+
+ /* If the journal needs to be sync()ed before page pPg->pgno can
+ ** be written to, store pPg->pgno in local variable needSyncPgno.
+ **
+ ** If the isCommit flag is set, there is no need to remember that
+ ** the journal needs to be sync()ed before database page pPg->pgno
+ ** can be written to. The caller has already promised not to write to it.
+ */
+ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
+ needSyncPgno = pPg->pgno;
+ assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
+ pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
+ assert( pPg->flags&PGHDR_DIRTY );
+ }
+
+ /* If the cache contains a page with page-number pgno, remove it
+ ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
+ ** page pgno before the 'move' operation, it needs to be retained
+ ** for the page moved there.
+ */
+ pPg->flags &= ~PGHDR_NEED_SYNC;
+ pPgOld = pager_lookup(pPager, pgno);
+ assert( !pPgOld || pPgOld->nRef==1 );
+ if( pPgOld ){
+ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
+ if( MEMDB ){
+ /* Do not discard pages from an in-memory database since we might
+ ** need to rollback later. Just move the page out of the way. */
+ sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
+ }else{
+ sqlite3PcacheDrop(pPgOld);
+ }
+ }
+
+ origPgno = pPg->pgno;
+ sqlite3PcacheMove(pPg, pgno);
+ sqlite3PcacheMakeDirty(pPg);
+
+ /* For an in-memory database, make sure the original page continues
+ ** to exist, in case the transaction needs to roll back. Use pPgOld
+ ** as the original page since it has already been allocated.
+ */
+ if( MEMDB ){
+ assert( pPgOld );
+ sqlite3PcacheMove(pPgOld, origPgno);
+ sqlite3PagerUnref(pPgOld);
+ }
+
+ if( needSyncPgno ){
+ /* If needSyncPgno is non-zero, then the journal file needs to be
+ ** sync()ed before any data is written to database file page needSyncPgno.
+ ** Currently, no such page exists in the page-cache and the
+ ** "is journaled" bitvec flag has been set. This needs to be remedied by
+ ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
+ ** flag.
+ **
+ ** If the attempt to load the page into the page-cache fails, (due
+ ** to a malloc() or IO failure), clear the bit in the pInJournal[]
+ ** array. Otherwise, if the page is loaded and written again in
+ ** this transaction, it may be written to the database file before
+ ** it is synced into the journal file. This way, it may end up in
+ ** the journal file twice, but that is not a problem.
+ */
+ PgHdr *pPgHdr;
+ rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
+ if( rc!=SQLITE_OK ){
+ if( needSyncPgno<=pPager->dbOrigSize ){
+ assert( pPager->pTmpSpace!=0 );
+ sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
+ }
+ return rc;
+ }
+ pPgHdr->flags |= PGHDR_NEED_SYNC;
+ sqlite3PcacheMakeDirty(pPgHdr);
+ sqlite3PagerUnref(pPgHdr);
+ }
+
+ return SQLITE_OK;
+}
+#endif
+
+/*
+** Return a pointer to the data for the specified page.
+*/
+SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
+ assert( pPg->nRef>0 || pPg->pPager->memDb );
+ return pPg->pData;
+}
+
+/*
+** Return a pointer to the Pager.nExtra bytes of "extra" space
+** allocated along with the specified page.
+*/
+SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
+ return pPg->pExtra;
+}
+
+/*
+** Get/set the locking-mode for this pager. Parameter eMode must be one
+** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
+** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
+** the locking-mode is set to the value specified.
+**
+** The returned value is either PAGER_LOCKINGMODE_NORMAL or
+** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
+** locking-mode.
+*/
+SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
+ assert( eMode==PAGER_LOCKINGMODE_QUERY
+ || eMode==PAGER_LOCKINGMODE_NORMAL
+ || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
+ assert( PAGER_LOCKINGMODE_QUERY<0 );
+ assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
+ assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
+ if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
+ pPager->exclusiveMode = (u8)eMode;
+ }
+ return (int)pPager->exclusiveMode;
+}
+
+/*
+** Set the journal-mode for this pager. Parameter eMode must be one of:
+**
+** PAGER_JOURNALMODE_DELETE
+** PAGER_JOURNALMODE_TRUNCATE
+** PAGER_JOURNALMODE_PERSIST
+** PAGER_JOURNALMODE_OFF
+** PAGER_JOURNALMODE_MEMORY
+** PAGER_JOURNALMODE_WAL
+**
+** The journalmode is set to the value specified if the change is allowed.
+** The change may be disallowed for the following reasons:
+**
+** * An in-memory database can only have its journal_mode set to _OFF
+** or _MEMORY.
+**
+** * Temporary databases cannot have _WAL journalmode.
+**
+** The returned indicate the current (possibly updated) journal-mode.
+*/
+SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
+ u8 eOld = pPager->journalMode; /* Prior journalmode */
+
+#ifdef SQLITE_DEBUG
+ /* The print_pager_state() routine is intended to be used by the debugger
+ ** only. We invoke it once here to suppress a compiler warning. */
+ print_pager_state(pPager);
+#endif
+
+
+ /* The eMode parameter is always valid */
+ assert( eMode==PAGER_JOURNALMODE_DELETE
+ || eMode==PAGER_JOURNALMODE_TRUNCATE
+ || eMode==PAGER_JOURNALMODE_PERSIST
+ || eMode==PAGER_JOURNALMODE_OFF
+ || eMode==PAGER_JOURNALMODE_WAL
+ || eMode==PAGER_JOURNALMODE_MEMORY );
+
+ /* This routine is only called from the OP_JournalMode opcode, and
+ ** the logic there will never allow a temporary file to be changed
+ ** to WAL mode.
+ */
+ assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );
+
+ /* Do allow the journalmode of an in-memory database to be set to
+ ** anything other than MEMORY or OFF
+ */
+ if( MEMDB ){
+ assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
+ if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
+ eMode = eOld;
+ }
+ }
+
+ if( eMode!=eOld ){
+
+ /* Change the journal mode. */
+ assert( pPager->eState!=PAGER_ERROR );
+ pPager->journalMode = (u8)eMode;
+
+ /* When transistioning from TRUNCATE or PERSIST to any other journal
+ ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
+ ** delete the journal file.
+ */
+ assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
+ assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
+ assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
+ assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
+ assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
+ assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
+
+ assert( isOpen(pPager->fd) || pPager->exclusiveMode );
+ if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
+
+ /* In this case we would like to delete the journal file. If it is
+ ** not possible, then that is not a problem. Deleting the journal file
+ ** here is an optimization only.
+ **
+ ** Before deleting the journal file, obtain a RESERVED lock on the
+ ** database file. This ensures that the journal file is not deleted
+ ** while it is in use by some other client.
+ */
+ sqlite3OsClose(pPager->jfd);
+ if( pPager->eLock>=RESERVED_LOCK ){
+ sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+ }else{
+ int rc = SQLITE_OK;
+ int state = pPager->eState;
+ assert( state==PAGER_OPEN || state==PAGER_READER );
+ if( state==PAGER_OPEN ){
+ rc = sqlite3PagerSharedLock(pPager);
+ }
+ if( pPager->eState==PAGER_READER ){
+ assert( rc==SQLITE_OK );
+ rc = pagerLockDb(pPager, RESERVED_LOCK);
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+ }
+ if( rc==SQLITE_OK && state==PAGER_READER ){
+ pagerUnlockDb(pPager, SHARED_LOCK);
+ }else if( state==PAGER_OPEN ){
+ pager_unlock(pPager);
+ }
+ assert( state==pPager->eState );
+ }
+ }
+ }
+
+ /* Return the new journal mode */
+ return (int)pPager->journalMode;
+}
+
+/*
+** Return the current journal mode.
+*/
+SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
+ return (int)pPager->journalMode;
+}
+
+/*
+** Return TRUE if the pager is in a state where it is OK to change the
+** journalmode. Journalmode changes can only happen when the database
+** is unmodified.
+*/
+SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
+ assert( assert_pager_state(pPager) );
+ if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
+ if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
+ return 1;
+}
+
+/*
+** Get/set the size-limit used for persistent journal files.
+**
+** Setting the size limit to -1 means no limit is enforced.
+** An attempt to set a limit smaller than -1 is a no-op.
+*/
+SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
+ if( iLimit>=-1 ){
+ pPager->journalSizeLimit = iLimit;
+ sqlite3WalLimit(pPager->pWal, iLimit);
+ }
+ return pPager->journalSizeLimit;
+}
+
+/*
+** Return a pointer to the pPager->pBackup variable. The backup module
+** in backup.c maintains the content of this variable. This module
+** uses it opaquely as an argument to sqlite3BackupRestart() and
+** sqlite3BackupUpdate() only.
+*/
+SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
+ return &pPager->pBackup;
+}
+
+#ifndef SQLITE_OMIT_VACUUM
+/*
+** Unless this is an in-memory or temporary database, clear the pager cache.
+*/
+SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
+ if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
+}
+#endif
+
+#ifndef SQLITE_OMIT_WAL
+/*
+** This function is called when the user invokes "PRAGMA wal_checkpoint",
+** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
+** or wal_blocking_checkpoint() API functions.
+**
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
+*/
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
+ int rc = SQLITE_OK;
+ if( pPager->pWal ){
+ rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
+ pPager->xBusyHandler, pPager->pBusyHandlerArg,
+ pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
+ pnLog, pnCkpt
+ );
+ }
+ return rc;
+}
+
+SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
+ return sqlite3WalCallback(pPager->pWal);
+}
+
+/*
+** Return true if the underlying VFS for the given pager supports the
+** primitives necessary for write-ahead logging.
+*/
+SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
+ const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
+ return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
+}
+
+/*
+** Attempt to take an exclusive lock on the database file. If a PENDING lock
+** is obtained instead, immediately release it.
+*/
+static int pagerExclusiveLock(Pager *pPager){
+ int rc; /* Return code */
+
+ assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
+ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+ if( rc!=SQLITE_OK ){
+ /* If the attempt to grab the exclusive lock failed, release the
+ ** pending lock that may have been obtained instead. */
+ pagerUnlockDb(pPager, SHARED_LOCK);
+ }
+
+ return rc;
+}
+
+/*
+** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
+** exclusive-locking mode when this function is called, take an EXCLUSIVE
+** lock on the database file and use heap-memory to store the wal-index
+** in. Otherwise, use the normal shared-memory.
+*/
+static int pagerOpenWal(Pager *pPager){
+ int rc = SQLITE_OK;
+
+ assert( pPager->pWal==0 && pPager->tempFile==0 );
+ assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
+
+ /* If the pager is already in exclusive-mode, the WAL module will use
+ ** heap-memory for the wal-index instead of the VFS shared-memory
+ ** implementation. Take the exclusive lock now, before opening the WAL
+ ** file, to make sure this is safe.
+ */
+ if( pPager->exclusiveMode ){
+ rc = pagerExclusiveLock(pPager);
+ }
+
+ /* Open the connection to the log file. If this operation fails,
+ ** (e.g. due to malloc() failure), return an error code.
+ */
+ if( rc==SQLITE_OK ){
+ rc = sqlite3WalOpen(pPager->pVfs,
+ pPager->fd, pPager->zWal, pPager->exclusiveMode,
+ pPager->journalSizeLimit, &pPager->pWal
+ );
+ }
+
+ return rc;
+}
+
+
+/*
+** The caller must be holding a SHARED lock on the database file to call
+** this function.
+**
+** If the pager passed as the first argument is open on a real database
+** file (not a temp file or an in-memory database), and the WAL file
+** is not already open, make an attempt to open it now. If successful,
+** return SQLITE_OK. If an error occurs or the VFS used by the pager does
+** not support the xShmXXX() methods, return an error code. *pbOpen is
+** not modified in either case.
+**
+** If the pager is open on a temp-file (or in-memory database), or if
+** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
+** without doing anything.
+*/
+SQLITE_PRIVATE int sqlite3PagerOpenWal(
+ Pager *pPager, /* Pager object */
+ int *pbOpen /* OUT: Set to true if call is a no-op */
+){
+ int rc = SQLITE_OK; /* Return code */
+
+ assert( assert_pager_state(pPager) );
+ assert( pPager->eState==PAGER_OPEN || pbOpen );
+ assert( pPager->eState==PAGER_READER || !pbOpen );
+ assert( pbOpen==0 || *pbOpen==0 );
+ assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
+
+ if( !pPager->tempFile && !pPager->pWal ){
+ if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
+
+ /* Close any rollback journal previously open */
+ sqlite3OsClose(pPager->jfd);
+
+ rc = pagerOpenWal(pPager);
+ if( rc==SQLITE_OK ){
+ pPager->journalMode = PAGER_JOURNALMODE_WAL;
+ pPager->eState = PAGER_OPEN;
+ }
+ }else{
+ *pbOpen = 1;
+ }
+
+ return rc;
+}
+
+/*
+** This function is called to close the connection to the log file prior
+** to switching from WAL to rollback mode.
+**
+** Before closing the log file, this function attempts to take an
+** EXCLUSIVE lock on the database file. If this cannot be obtained, an
+** error (SQLITE_BUSY) is returned and the log connection is not closed.
+** If successful, the EXCLUSIVE lock is not released before returning.
+*/
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
+ int rc = SQLITE_OK;
+
+ assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
+
+ /* If the log file is not already open, but does exist in the file-system,
+ ** it may need to be checkpointed before the connection can switch to
+ ** rollback mode. Open it now so this can happen.
+ */
+ if( !pPager->pWal ){
+ int logexists = 0;
+ rc = pagerLockDb(pPager, SHARED_LOCK);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
+ );
+ }
+ if( rc==SQLITE_OK && logexists ){
+ rc = pagerOpenWal(pPager);
+ }
+ }
+
+ /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
+ ** the database file, the log and log-summary files will be deleted.
+ */
+ if( rc==SQLITE_OK && pPager->pWal ){
+ rc = pagerExclusiveLock(pPager);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
+ pPager->pageSize, (u8*)pPager->pTmpSpace);
+ pPager->pWal = 0;
+ }
+ }
+ return rc;
+}
+
+#endif /* !SQLITE_OMIT_WAL */
+
+#ifdef SQLITE_ENABLE_ZIPVFS
+/*
+** A read-lock must be held on the pager when this function is called. If
+** the pager is in WAL mode and the WAL file currently contains one or more
+** frames, return the size in bytes of the page images stored within the
+** WAL frames. Otherwise, if this is not a WAL database or the WAL file
+** is empty, return 0.
+*/
+SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
+ assert( pPager->eState==PAGER_READER );
+ return sqlite3WalFramesize(pPager->pWal);
+}
+#endif
+
+#ifdef SQLITE_HAS_CODEC
+/*
+** This function is called by the wal module when writing page content
+** into the log file.
+**
+** This function returns a pointer to a buffer containing the encrypted
+** page content. If a malloc fails, this function may return NULL.
+*/
+SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
+ void *aData = 0;
+ CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
+ return aData;
+}
+#endif /* SQLITE_HAS_CODEC */
+
+#endif /* SQLITE_OMIT_DISKIO */
+
+/************** End of pager.c ***********************************************/
+/************** Begin file wal.c *********************************************/
+/*
+** 2010 February 1
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains the implementation of a write-ahead log (WAL) used in
+** "journal_mode=WAL" mode.
+**
+** WRITE-AHEAD LOG (WAL) FILE FORMAT
+**
+** A WAL file consists of a header followed by zero or more "frames".
+** Each frame records the revised content of a single page from the
+** database file. All changes to the database are recorded by writing
+** frames into the WAL. Transactions commit when a frame is written that
+** contains a commit marker. A single WAL can and usually does record
+** multiple transactions. Periodically, the content of the WAL is
+** transferred back into the database file in an operation called a
+** "checkpoint".
+**
+** A single WAL file can be used multiple times. In other words, the
+** WAL can fill up with frames and then be checkpointed and then new
+** frames can overwrite the old ones. A WAL always grows from beginning
+** toward the end. Checksums and counters attached to each frame are
+** used to determine which frames within the WAL are valid and which
+** are leftovers from prior checkpoints.
+**
+** The WAL header is 32 bytes in size and consists of the following eight
+** big-endian 32-bit unsigned integer values:
+**
+** 0: Magic number. 0x377f0682 or 0x377f0683
+** 4: File format version. Currently 3007000
+** 8: Database page size. Example: 1024
+** 12: Checkpoint sequence number
+** 16: Salt-1, random integer incremented with each checkpoint
+** 20: Salt-2, a different random integer changing with each ckpt
+** 24: Checksum-1 (first part of checksum for first 24 bytes of header).
+** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
+**
+** Immediately following the wal-header are zero or more frames. Each
+** frame consists of a 24-byte frame-header followed by a <page-size> bytes
+** of page data. The frame-header is six big-endian 32-bit unsigned
+** integer values, as follows:
+**
+** 0: Page number.
+** 4: For commit records, the size of the database image in pages
+** after the commit. For all other records, zero.
+** 8: Salt-1 (copied from the header)
+** 12: Salt-2 (copied from the header)
+** 16: Checksum-1.
+** 20: Checksum-2.
+**
+** A frame is considered valid if and only if the following conditions are
+** true:
+**
+** (1) The salt-1 and salt-2 values in the frame-header match
+** salt values in the wal-header
+**
+** (2) The checksum values in the final 8 bytes of the frame-header
+** exactly match the checksum computed consecutively on the
+** WAL header and the first 8 bytes and the content of all frames
+** up to and including the current frame.
+**
+** The checksum is computed using 32-bit big-endian integers if the
+** magic number in the first 4 bytes of the WAL is 0x377f0683 and it
+** is computed using little-endian if the magic number is 0x377f0682.
+** The checksum values are always stored in the frame header in a
+** big-endian format regardless of which byte order is used to compute
+** the checksum. The checksum is computed by interpreting the input as
+** an even number of unsigned 32-bit integers: x[0] through x[N]. The
+** algorithm used for the checksum is as follows:
+**
+** for i from 0 to n-1 step 2:
+** s0 += x[i] + s1;
+** s1 += x[i+1] + s0;
+** endfor
+**
+** Note that s0 and s1 are both weighted checksums using fibonacci weights
+** in reverse order (the largest fibonacci weight occurs on the first element
+** of the sequence being summed.) The s1 value spans all 32-bit
+** terms of the sequence whereas s0 omits the final term.
+**
+** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
+** WAL is transferred into the database, then the database is VFS.xSync-ed.
+** The VFS.xSync operations serve as write barriers - all writes launched
+** before the xSync must complete before any write that launches after the
+** xSync begins.
+**
+** After each checkpoint, the salt-1 value is incremented and the salt-2
+** value is randomized. This prevents old and new frames in the WAL from
+** being considered valid at the same time and being checkpointing together
+** following a crash.
+**
+** READER ALGORITHM
+**
+** To read a page from the database (call it page number P), a reader
+** first checks the WAL to see if it contains page P. If so, then the
+** last valid instance of page P that is a followed by a commit frame
+** or is a commit frame itself becomes the value read. If the WAL
+** contains no copies of page P that are valid and which are a commit
+** frame or are followed by a commit frame, then page P is read from
+** the database file.
+**
+** To start a read transaction, the reader records the index of the last
+** valid frame in the WAL. The reader uses this recorded "mxFrame" value
+** for all subsequent read operations. New transactions can be appended
+** to the WAL, but as long as the reader uses its original mxFrame value
+** and ignores the newly appended content, it will see a consistent snapshot
+** of the database from a single point in time. This technique allows
+** multiple concurrent readers to view different versions of the database
+** content simultaneously.
+**
+** The reader algorithm in the previous paragraphs works correctly, but
+** because frames for page P can appear anywhere within the WAL, the
+** reader has to scan the entire WAL looking for page P frames. If the
+** WAL is large (multiple megabytes is typical) that scan can be slow,
+** and read performance suffers. To overcome this problem, a separate
+** data structure called the wal-index is maintained to expedite the
+** search for frames of a particular page.
+**
+** WAL-INDEX FORMAT
+**
+** Conceptually, the wal-index is shared memory, though VFS implementations
+** might choose to implement the wal-index using a mmapped file. Because
+** the wal-index is shared memory, SQLite does not support journal_mode=WAL
+** on a network filesystem. All users of the database must be able to
+** share memory.
+**
+** The wal-index is transient. After a crash, the wal-index can (and should
+** be) reconstructed from the original WAL file. In fact, the VFS is required
+** to either truncate or zero the header of the wal-index when the last
+** connection to it closes. Because the wal-index is transient, it can
+** use an architecture-specific format; it does not have to be cross-platform.
+** Hence, unlike the database and WAL file formats which store all values
+** as big endian, the wal-index can store multi-byte values in the native
+** byte order of the host computer.
+**
+** The purpose of the wal-index is to answer this question quickly: Given
+** a page number P and a maximum frame index M, return the index of the
+** last frame in the wal before frame M for page P in the WAL, or return
+** NULL if there are no frames for page P in the WAL prior to M.
+**
+** The wal-index consists of a header region, followed by an one or
+** more index blocks.
+**
+** The wal-index header contains the total number of frames within the WAL
+** in the mxFrame field.
+**
+** Each index block except for the first contains information on
+** HASHTABLE_NPAGE frames. The first index block contains information on
+** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
+** HASHTABLE_NPAGE are selected so that together the wal-index header and
+** first index block are the same size as all other index blocks in the
+** wal-index.
+**
+** Each index block contains two sections, a page-mapping that contains the
+** database page number associated with each wal frame, and a hash-table
+** that allows readers to query an index block for a specific page number.
+** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
+** for the first index block) 32-bit page numbers. The first entry in the
+** first index-block contains the database page number corresponding to the
+** first frame in the WAL file. The first entry in the second index block
+** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
+** the log, and so on.
+**
+** The last index block in a wal-index usually contains less than the full
+** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers,
+** depending on the contents of the WAL file. This does not change the
+** allocated size of the page-mapping array - the page-mapping array merely
+** contains unused entries.
+**
+** Even without using the hash table, the last frame for page P
+** can be found by scanning the page-mapping sections of each index block
+** starting with the last index block and moving toward the first, and
+** within each index block, starting at the end and moving toward the
+** beginning. The first entry that equals P corresponds to the frame
+** holding the content for that page.
+**
+** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers.
+** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the
+** hash table for each page number in the mapping section, so the hash
+** table is never more than half full. The expected number of collisions
+** prior to finding a match is 1. Each entry of the hash table is an
+** 1-based index of an entry in the mapping section of the same
+** index block. Let K be the 1-based index of the largest entry in
+** the mapping section. (For index blocks other than the last, K will
+** always be exactly HASHTABLE_NPAGE (4096) and for the last index block
+** K will be (mxFrame%HASHTABLE_NPAGE).) Unused slots of the hash table
+** contain a value of 0.
+**
+** To look for page P in the hash table, first compute a hash iKey on
+** P as follows:
+**
+** iKey = (P * 383) % HASHTABLE_NSLOT
+**
+** Then start scanning entries of the hash table, starting with iKey
+** (wrapping around to the beginning when the end of the hash table is
+** reached) until an unused hash slot is found. Let the first unused slot
+** be at index iUnused. (iUnused might be less than iKey if there was
+** wrap-around.) Because the hash table is never more than half full,
+** the search is guaranteed to eventually hit an unused entry. Let
+** iMax be the value between iKey and iUnused, closest to iUnused,
+** where aHash[iMax]==P. If there is no iMax entry (if there exists
+** no hash slot such that aHash[i]==p) then page P is not in the
+** current index block. Otherwise the iMax-th mapping entry of the
+** current index block corresponds to the last entry that references
+** page P.
+**
+** A hash search begins with the last index block and moves toward the
+** first index block, looking for entries corresponding to page P. On
+** average, only two or three slots in each index block need to be
+** examined in order to either find the last entry for page P, or to
+** establish that no such entry exists in the block. Each index block
+** holds over 4000 entries. So two or three index blocks are sufficient
+** to cover a typical 10 megabyte WAL file, assuming 1K pages. 8 or 10
+** comparisons (on average) suffice to either locate a frame in the
+** WAL or to establish that the frame does not exist in the WAL. This
+** is much faster than scanning the entire 10MB WAL.
+**
+** Note that entries are added in order of increasing K. Hence, one
+** reader might be using some value K0 and a second reader that started
+** at a later time (after additional transactions were added to the WAL
+** and to the wal-index) might be using a different value K1, where K1>K0.
+** Both readers can use the same hash table and mapping section to get
+** the correct result. There may be entries in the hash table with
+** K>K0 but to the first reader, those entries will appear to be unused
+** slots in the hash table and so the first reader will get an answer as
+** if no values greater than K0 had ever been inserted into the hash table
+** in the first place - which is what reader one wants. Meanwhile, the
+** second reader using K1 will see additional values that were inserted
+** later, which is exactly what reader two wants.
+**
+** When a rollback occurs, the value of K is decreased. Hash table entries
+** that correspond to frames greater than the new K value are removed
+** from the hash table at this point.
+*/
+#ifndef SQLITE_OMIT_WAL
+
+
+/*
+** Trace output macros
+*/
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3WalTrace = 0;
+# define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X
+#else
+# define WALTRACE(X)
+#endif
+
+/*
+** The maximum (and only) versions of the wal and wal-index formats
+** that may be interpreted by this version of SQLite.
+**
+** If a client begins recovering a WAL file and finds that (a) the checksum
+** values in the wal-header are correct and (b) the version field is not
+** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
+**
+** Similarly, if a client successfully reads a wal-index header (i.e. the
+** checksum test is successful) and finds that the version field is not
+** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
+** returns SQLITE_CANTOPEN.
+*/
+#define WAL_MAX_VERSION 3007000
+#define WALINDEX_MAX_VERSION 3007000
+
+/*
+** Indices of various locking bytes. WAL_NREADER is the number
+** of available reader locks and should be at least 3.
+*/
+#define WAL_WRITE_LOCK 0
+#define WAL_ALL_BUT_WRITE 1
+#define WAL_CKPT_LOCK 1
+#define WAL_RECOVER_LOCK 2
+#define WAL_READ_LOCK(I) (3+(I))
+#define WAL_NREADER (SQLITE_SHM_NLOCK-3)
+
+
+/* Object declarations */
+typedef struct WalIndexHdr WalIndexHdr;
+typedef struct WalIterator WalIterator;
+typedef struct WalCkptInfo WalCkptInfo;
+
+
+/*
+** The following object holds a copy of the wal-index header content.
+**
+** The actual header in the wal-index consists of two copies of this
+** object.
+**
+** The szPage value can be any power of 2 between 512 and 32768, inclusive.
+** Or it can be 1 to represent a 65536-byte page. The latter case was
+** added in 3.7.1 when support for 64K pages was added.
+*/
+struct WalIndexHdr {
+ u32 iVersion; /* Wal-index version */
+ u32 unused; /* Unused (padding) field */
+ u32 iChange; /* Counter incremented each transaction */
+ u8 isInit; /* 1 when initialized */
+ u8 bigEndCksum; /* True if checksums in WAL are big-endian */
+ u16 szPage; /* Database page size in bytes. 1==64K */
+ u32 mxFrame; /* Index of last valid frame in the WAL */
+ u32 nPage; /* Size of database in pages */
+ u32 aFrameCksum[2]; /* Checksum of last frame in log */
+ u32 aSalt[2]; /* Two salt values copied from WAL header */
+ u32 aCksum[2]; /* Checksum over all prior fields */
+};
+
+/*
+** A copy of the following object occurs in the wal-index immediately
+** following the second copy of the WalIndexHdr. This object stores
+** information used by checkpoint.
+**
+** nBackfill is the number of frames in the WAL that have been written
+** back into the database. (We call the act of moving content from WAL to
+** database "backfilling".) The nBackfill number is never greater than
+** WalIndexHdr.mxFrame. nBackfill can only be increased by threads
+** holding the WAL_CKPT_LOCK lock (which includes a recovery thread).
+** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from
+** mxFrame back to zero when the WAL is reset.
+**
+** There is one entry in aReadMark[] for each reader lock. If a reader
+** holds read-lock K, then the value in aReadMark[K] is no greater than
+** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
+** for any aReadMark[] means that entry is unused. aReadMark[0] is
+** a special case; its value is never used and it exists as a place-holder
+** to avoid having to offset aReadMark[] indexs by one. Readers holding
+** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
+** directly from the database.
+**
+** The value of aReadMark[K] may only be changed by a thread that
+** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of
+** aReadMark[K] cannot changed while there is a reader is using that mark
+** since the reader will be holding a shared lock on WAL_READ_LOCK(K).
+**
+** The checkpointer may only transfer frames from WAL to database where
+** the frame numbers are less than or equal to every aReadMark[] that is
+** in use (that is, every aReadMark[j] for which there is a corresponding
+** WAL_READ_LOCK(j)). New readers (usually) pick the aReadMark[] with the
+** largest value and will increase an unused aReadMark[] to mxFrame if there
+** is not already an aReadMark[] equal to mxFrame. The exception to the
+** previous sentence is when nBackfill equals mxFrame (meaning that everything
+** in the WAL has been backfilled into the database) then new readers
+** will choose aReadMark[0] which has value 0 and hence such reader will
+** get all their all content directly from the database file and ignore
+** the WAL.
+**
+** Writers normally append new frames to the end of the WAL. However,
+** if nBackfill equals mxFrame (meaning that all WAL content has been
+** written back into the database) and if no readers are using the WAL
+** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then
+** the writer will first "reset" the WAL back to the beginning and start
+** writing new content beginning at frame 1.
+**
+** We assume that 32-bit loads are atomic and so no locks are needed in
+** order to read from any aReadMark[] entries.
+*/
+struct WalCkptInfo {
+ u32 nBackfill; /* Number of WAL frames backfilled into DB */
+ u32 aReadMark[WAL_NREADER]; /* Reader marks */
+};
+#define READMARK_NOT_USED 0xffffffff
+
+
+/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
+** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
+** only support mandatory file-locks, we do not read or write data
+** from the region of the file on which locks are applied.
+*/
+#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo))
+#define WALINDEX_LOCK_RESERVED 16
+#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)
+
+/* Size of header before each frame in wal */
+#define WAL_FRAME_HDRSIZE 24
+
+/* Size of write ahead log header, including checksum. */
+/* #define WAL_HDRSIZE 24 */
+#define WAL_HDRSIZE 32
+
+/* WAL magic value. Either this value, or the same value with the least
+** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit
+** big-endian format in the first 4 bytes of a WAL file.
+**
+** If the LSB is set, then the checksums for each frame within the WAL
+** file are calculated by treating all data as an array of 32-bit
+** big-endian words. Otherwise, they are calculated by interpreting
+** all data as 32-bit little-endian words.
+*/
+#define WAL_MAGIC 0x377f0682
+
+/*
+** Return the offset of frame iFrame in the write-ahead log file,
+** assuming a database page size of szPage bytes. The offset returned
+** is to the start of the write-ahead log frame-header.
+*/
+#define walFrameOffset(iFrame, szPage) ( \
+ WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \
+)
+
+/*
+** An open write-ahead log file is represented by an instance of the
+** following object.
+*/
+struct Wal {
+ sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
+ sqlite3_file *pDbFd; /* File handle for the database file */
+ sqlite3_file *pWalFd; /* File handle for WAL file */
+ u32 iCallback; /* Value to pass to log callback (or 0) */
+ i64 mxWalSize; /* Truncate WAL to this size upon reset */
+ int nWiData; /* Size of array apWiData */
+ int szFirstBlock; /* Size of first block written to WAL file */
+ volatile u32 **apWiData; /* Pointer to wal-index content in memory */
+ u32 szPage; /* Database page size */
+ i16 readLock; /* Which read lock is being held. -1 for none */
+ u8 syncFlags; /* Flags to use to sync header writes */
+ u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
+ u8 writeLock; /* True if in a write transaction */
+ u8 ckptLock; /* True if holding a checkpoint lock */
+ u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
+ u8 truncateOnCommit; /* True to truncate WAL file on commit */
+ u8 syncHeader; /* Fsync the WAL header if true */
+ u8 padToSectorBoundary; /* Pad transactions out to the next sector */
+ WalIndexHdr hdr; /* Wal-index header for current transaction */
+ const char *zWalName; /* Name of WAL file */
+ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
+#ifdef SQLITE_DEBUG
+ u8 lockError; /* True if a locking error has occurred */
+#endif
+};
+
+/*
+** Candidate values for Wal.exclusiveMode.
+*/
+#define WAL_NORMAL_MODE 0
+#define WAL_EXCLUSIVE_MODE 1
+#define WAL_HEAPMEMORY_MODE 2
+
+/*
+** Possible values for WAL.readOnly
+*/
+#define WAL_RDWR 0 /* Normal read/write connection */
+#define WAL_RDONLY 1 /* The WAL file is readonly */
+#define WAL_SHM_RDONLY 2 /* The SHM file is readonly */
+
+/*
+** Each page of the wal-index mapping contains a hash-table made up of
+** an array of HASHTABLE_NSLOT elements of the following type.
+*/
+typedef u16 ht_slot;
+
+/*
+** This structure is used to implement an iterator that loops through
+** all frames in the WAL in database page order. Where two or more frames
+** correspond to the same database page, the iterator visits only the
+** frame most recently written to the WAL (in other words, the frame with
+** the largest index).
+**
+** The internals of this structure are only accessed by:
+**
+** walIteratorInit() - Create a new iterator,
+** walIteratorNext() - Step an iterator,
+** walIteratorFree() - Free an iterator.
+**
+** This functionality is used by the checkpoint code (see walCheckpoint()).
+*/
+struct WalIterator {
+ int iPrior; /* Last result returned from the iterator */
+ int nSegment; /* Number of entries in aSegment[] */
+ struct WalSegment {
+ int iNext; /* Next slot in aIndex[] not yet returned */
+ ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
+ u32 *aPgno; /* Array of page numbers. */
+ int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
+ int iZero; /* Frame number associated with aPgno[0] */
+ } aSegment[1]; /* One for every 32KB page in the wal-index */
+};
+
+/*
+** Define the parameters of the hash tables in the wal-index file. There
+** is a hash-table following every HASHTABLE_NPAGE page numbers in the
+** wal-index.
+**
+** Changing any of these constants will alter the wal-index format and
+** create incompatibilities.
+*/
+#define HASHTABLE_NPAGE 4096 /* Must be power of 2 */
+#define HASHTABLE_HASH_1 383 /* Should be prime */
+#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */
+
+/*
+** The block of page numbers associated with the first hash-table in a
+** wal-index is smaller than usual. This is so that there is a complete
+** hash-table on each aligned 32KB page of the wal-index.
+*/
+#define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32)))
+
+/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */
+#define WALINDEX_PGSZ ( \
+ sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
+)
+
+/*
+** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
+** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
+** numbered from zero.
+**
+** If this call is successful, *ppPage is set to point to the wal-index
+** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
+** then an SQLite error code is returned and *ppPage is set to 0.
+*/
+static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
+ int rc = SQLITE_OK;
+
+ /* Enlarge the pWal->apWiData[] array if required */
+ if( pWal->nWiData<=iPage ){
+ int nByte = sizeof(u32*)*(iPage+1);
+ volatile u32 **apNew;
+ apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
+ if( !apNew ){
+ *ppPage = 0;
+ return SQLITE_NOMEM;
+ }
+ memset((void*)&apNew[pWal->nWiData], 0,
+ sizeof(u32*)*(iPage+1-pWal->nWiData));
+ pWal->apWiData = apNew;
+ pWal->nWiData = iPage+1;
+ }
+
+ /* Request a pointer to the required page from the VFS */
+ if( pWal->apWiData[iPage]==0 ){
+ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+ pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
+ if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
+ pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
+ );
+ if( rc==SQLITE_READONLY ){
+ pWal->readOnly |= WAL_SHM_RDONLY;
+ rc = SQLITE_OK;
+ }
+ }
+ }
+
+ *ppPage = pWal->apWiData[iPage];
+ assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
+ return rc;
+}
+
+/*
+** Return a pointer to the WalCkptInfo structure in the wal-index.
+*/
+static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
+ assert( pWal->nWiData>0 && pWal->apWiData[0] );
+ return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
+}
+
+/*
+** Return a pointer to the WalIndexHdr structure in the wal-index.
+*/
+static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
+ assert( pWal->nWiData>0 && pWal->apWiData[0] );
+ return (volatile WalIndexHdr*)pWal->apWiData[0];
+}
+
+/*
+** The argument to this macro must be of type u32. On a little-endian
+** architecture, it returns the u32 value that results from interpreting
+** the 4 bytes as a big-endian value. On a big-endian architecture, it
+** returns the value that would be produced by intepreting the 4 bytes
+** of the input value as a little-endian integer.
+*/
+#define BYTESWAP32(x) ( \
+ (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \
+ + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \
+)
+
+/*
+** Generate or extend an 8 byte checksum based on the data in
+** array aByte[] and the initial values of aIn[0] and aIn[1] (or
+** initial values of 0 and 0 if aIn==NULL).
+**
+** The checksum is written back into aOut[] before returning.
+**
+** nByte must be a positive multiple of 8.
+*/
+static void walChecksumBytes(
+ int nativeCksum, /* True for native byte-order, false for non-native */
+ u8 *a, /* Content to be checksummed */
+ int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */
+ const u32 *aIn, /* Initial checksum value input */
+ u32 *aOut /* OUT: Final checksum value output */
+){
+ u32 s1, s2;
+ u32 *aData = (u32 *)a;
+ u32 *aEnd = (u32 *)&a[nByte];
+
+ if( aIn ){
+ s1 = aIn[0];
+ s2 = aIn[1];
+ }else{
+ s1 = s2 = 0;
+ }
+
+ assert( nByte>=8 );
+ assert( (nByte&0x00000007)==0 );
+
+ if( nativeCksum ){
+ do {
+ s1 += *aData++ + s2;
+ s2 += *aData++ + s1;
+ }while( aData<aEnd );
+ }else{
+ do {
+ s1 += BYTESWAP32(aData[0]) + s2;
+ s2 += BYTESWAP32(aData[1]) + s1;
+ aData += 2;
+ }while( aData<aEnd );
+ }
+
+ aOut[0] = s1;
+ aOut[1] = s2;
+}
+
+static void walShmBarrier(Wal *pWal){
+ if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
+ sqlite3OsShmBarrier(pWal->pDbFd);
+ }
+}
+
+/*
+** Write the header information in pWal->hdr into the wal-index.
+**
+** The checksum on pWal->hdr is updated before it is written.
+*/
+static void walIndexWriteHdr(Wal *pWal){
+ volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
+ const int nCksum = offsetof(WalIndexHdr, aCksum);
+
+ assert( pWal->writeLock );
+ pWal->hdr.isInit = 1;
+ pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
+ walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
+ memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr));
+ walShmBarrier(pWal);
+ memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr));
+}
+
+/*
+** This function encodes a single frame header and writes it to a buffer
+** supplied by the caller. A frame-header is made up of a series of
+** 4-byte big-endian integers, as follows:
+**
+** 0: Page number.
+** 4: For commit records, the size of the database image in pages
+** after the commit. For all other records, zero.
+** 8: Salt-1 (copied from the wal-header)
+** 12: Salt-2 (copied from the wal-header)
+** 16: Checksum-1.
+** 20: Checksum-2.
+*/
+static void walEncodeFrame(
+ Wal *pWal, /* The write-ahead log */
+ u32 iPage, /* Database page number for frame */
+ u32 nTruncate, /* New db size (or 0 for non-commit frames) */
+ u8 *aData, /* Pointer to page data */
+ u8 *aFrame /* OUT: Write encoded frame here */
+){
+ int nativeCksum; /* True for native byte-order checksums */
+ u32 *aCksum = pWal->hdr.aFrameCksum;
+ assert( WAL_FRAME_HDRSIZE==24 );
+ sqlite3Put4byte(&aFrame[0], iPage);
+ sqlite3Put4byte(&aFrame[4], nTruncate);
+ memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
+
+ nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
+ walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
+ walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
+
+ sqlite3Put4byte(&aFrame[16], aCksum[0]);
+ sqlite3Put4byte(&aFrame[20], aCksum[1]);
+}
+
+/*
+** Check to see if the frame with header in aFrame[] and content
+** in aData[] is valid. If it is a valid frame, fill *piPage and
+** *pnTruncate and return true. Return if the frame is not valid.
+*/
+static int walDecodeFrame(
+ Wal *pWal, /* The write-ahead log */
+ u32 *piPage, /* OUT: Database page number for frame */
+ u32 *pnTruncate, /* OUT: New db size (or 0 if not commit) */
+ u8 *aData, /* Pointer to page data (for checksum) */
+ u8 *aFrame /* Frame data */
+){
+ int nativeCksum; /* True for native byte-order checksums */
+ u32 *aCksum = pWal->hdr.aFrameCksum;
+ u32 pgno; /* Page number of the frame */
+ assert( WAL_FRAME_HDRSIZE==24 );
+
+ /* A frame is only valid if the salt values in the frame-header
+ ** match the salt values in the wal-header.
+ */
+ if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){
+ return 0;
+ }
+
+ /* A frame is only valid if the page number is creater than zero.
+ */
+ pgno = sqlite3Get4byte(&aFrame[0]);
+ if( pgno==0 ){
+ return 0;
+ }
+
+ /* A frame is only valid if a checksum of the WAL header,
+ ** all prior frams, the first 16 bytes of this frame-header,
+ ** and the frame-data matches the checksum in the last 8
+ ** bytes of this frame-header.
+ */
+ nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
+ walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
+ walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
+ if( aCksum[0]!=sqlite3Get4byte(&aFrame[16])
+ || aCksum[1]!=sqlite3Get4byte(&aFrame[20])
+ ){
+ /* Checksum failed. */
+ return 0;
+ }
+
+ /* If we reach this point, the frame is valid. Return the page number
+ ** and the new database size.
+ */
+ *piPage = pgno;
+ *pnTruncate = sqlite3Get4byte(&aFrame[4]);
+ return 1;
+}
+
+
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+/*
+** Names of locks. This routine is used to provide debugging output and is not
+** a part of an ordinary build.
+*/
+static const char *walLockName(int lockIdx){
+ if( lockIdx==WAL_WRITE_LOCK ){
+ return "WRITE-LOCK";
+ }else if( lockIdx==WAL_CKPT_LOCK ){
+ return "CKPT-LOCK";
+ }else if( lockIdx==WAL_RECOVER_LOCK ){
+ return "RECOVER-LOCK";
+ }else{
+ static char zName[15];
+ sqlite3_snprintf(sizeof(zName), zName, "READ-LOCK[%d]",
+ lockIdx-WAL_READ_LOCK(0));
+ return zName;
+ }
+}
+#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
+
+
+/*
+** Set or release locks on the WAL. Locks are either shared or exclusive.
+** A lock cannot be moved directly between shared and exclusive - it must go
+** through the unlocked state first.
+**
+** In locking_mode=EXCLUSIVE, all of these routines become no-ops.
+*/
+static int walLockShared(Wal *pWal, int lockIdx){
+ int rc;
+ if( pWal->exclusiveMode ) return SQLITE_OK;
+ rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
+ SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
+ WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
+ walLockName(lockIdx), rc ? "failed" : "ok"));
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ return rc;
+}
+static void walUnlockShared(Wal *pWal, int lockIdx){
+ if( pWal->exclusiveMode ) return;
+ (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
+ SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
+ WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
+}
+static int walLockExclusive(Wal *pWal, int lockIdx, int n){
+ int rc;
+ if( pWal->exclusiveMode ) return SQLITE_OK;
+ rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
+ SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
+ WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
+ walLockName(lockIdx), n, rc ? "failed" : "ok"));
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ return rc;
+}
+static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
+ if( pWal->exclusiveMode ) return;
+ (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
+ SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
+ WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
+ walLockName(lockIdx), n));
+}
+
+/*
+** Compute a hash on a page number. The resulting hash value must land
+** between 0 and (HASHTABLE_NSLOT-1). The walHashNext() function advances
+** the hash to the next value in the event of a collision.
+*/
+static int walHash(u32 iPage){
+ assert( iPage>0 );
+ assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 );
+ return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1);
+}
+static int walNextHash(int iPriorHash){
+ return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
+}
+
+/*
+** Return pointers to the hash table and page number array stored on
+** page iHash of the wal-index. The wal-index is broken into 32KB pages
+** numbered starting from 0.
+**
+** Set output variable *paHash to point to the start of the hash table
+** in the wal-index file. Set *piZero to one less than the frame
+** number of the first frame indexed by this hash table. If a
+** slot in the hash table is set to N, it refers to frame number
+** (*piZero+N) in the log.
+**
+** Finally, set *paPgno so that *paPgno[1] is the page number of the
+** first frame indexed by the hash table, frame (*piZero+1).
+*/
+static int walHashGet(
+ Wal *pWal, /* WAL handle */
+ int iHash, /* Find the iHash'th table */
+ volatile ht_slot **paHash, /* OUT: Pointer to hash index */
+ volatile u32 **paPgno, /* OUT: Pointer to page number array */
+ u32 *piZero /* OUT: Frame associated with *paPgno[0] */
+){
+ int rc; /* Return code */
+ volatile u32 *aPgno;
+
+ rc = walIndexPage(pWal, iHash, &aPgno);
+ assert( rc==SQLITE_OK || iHash>0 );
+
+ if( rc==SQLITE_OK ){
+ u32 iZero;
+ volatile ht_slot *aHash;
+
+ aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE];
+ if( iHash==0 ){
+ aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
+ iZero = 0;
+ }else{
+ iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
+ }
+
+ *paPgno = &aPgno[-1];
+ *paHash = aHash;
+ *piZero = iZero;
+ }
+ return rc;
+}
+
+/*
+** Return the number of the wal-index page that contains the hash-table
+** and page-number array that contain entries corresponding to WAL frame
+** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages
+** are numbered starting from 0.
+*/
+static int walFramePage(u32 iFrame){
+ int iHash = (iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1) / HASHTABLE_NPAGE;
+ assert( (iHash==0 || iFrame>HASHTABLE_NPAGE_ONE)
+ && (iHash>=1 || iFrame<=HASHTABLE_NPAGE_ONE)
+ && (iHash<=1 || iFrame>(HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE))
+ && (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)
+ && (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE))
+ );
+ return iHash;
+}
+
+/*
+** Return the page number associated with frame iFrame in this WAL.
+*/
+static u32 walFramePgno(Wal *pWal, u32 iFrame){
+ int iHash = walFramePage(iFrame);
+ if( iHash==0 ){
+ return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1];
+ }
+ return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE];
+}
+
+/*
+** Remove entries from the hash table that point to WAL slots greater
+** than pWal->hdr.mxFrame.
+**
+** This function is called whenever pWal->hdr.mxFrame is decreased due
+** to a rollback or savepoint.
+**
+** At most only the hash table containing pWal->hdr.mxFrame needs to be
+** updated. Any later hash tables will be automatically cleared when
+** pWal->hdr.mxFrame advances to the point where those hash tables are
+** actually needed.
+*/
+static void walCleanupHash(Wal *pWal){
+ volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */
+ volatile u32 *aPgno = 0; /* Page number array for hash table */
+ u32 iZero = 0; /* frame == (aHash[x]+iZero) */
+ int iLimit = 0; /* Zero values greater than this */
+ int nByte; /* Number of bytes to zero in aPgno[] */
+ int i; /* Used to iterate through aHash[] */
+
+ assert( pWal->writeLock );
+ testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
+ testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE );
+ testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 );
+
+ if( pWal->hdr.mxFrame==0 ) return;
+
+ /* Obtain pointers to the hash-table and page-number array containing
+ ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
+ ** that the page said hash-table and array reside on is already mapped.
+ */
+ assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
+ assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
+ walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero);
+
+ /* Zero all hash-table entries that correspond to frame numbers greater
+ ** than pWal->hdr.mxFrame.
+ */
+ iLimit = pWal->hdr.mxFrame - iZero;
+ assert( iLimit>0 );
+ for(i=0; i<HASHTABLE_NSLOT; i++){
+ if( aHash[i]>iLimit ){
+ aHash[i] = 0;
+ }
+ }
+
+ /* Zero the entries in the aPgno array that correspond to frames with
+ ** frame numbers greater than pWal->hdr.mxFrame.
+ */
+ nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
+ memset((void *)&aPgno[iLimit+1], 0, nByte);
+
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+ /* Verify that the every entry in the mapping region is still reachable
+ ** via the hash table even after the cleanup.
+ */
+ if( iLimit ){
+ int i; /* Loop counter */
+ int iKey; /* Hash key */
+ for(i=1; i<=iLimit; i++){
+ for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){
+ if( aHash[iKey]==i ) break;
+ }
+ assert( aHash[iKey]==i );
+ }
+ }
+#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
+}
+
+
+/*
+** Set an entry in the wal-index that will map database page number
+** pPage into WAL frame iFrame.
+*/
+static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
+ int rc; /* Return code */
+ u32 iZero = 0; /* One less than frame number of aPgno[1] */
+ volatile u32 *aPgno = 0; /* Page number array */
+ volatile ht_slot *aHash = 0; /* Hash table */
+
+ rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero);
+
+ /* Assuming the wal-index file was successfully mapped, populate the
+ ** page number array and hash table entry.
+ */
+ if( rc==SQLITE_OK ){
+ int iKey; /* Hash table key */
+ int idx; /* Value to write to hash-table slot */
+ int nCollide; /* Number of hash collisions */
+
+ idx = iFrame - iZero;
+ assert( idx <= HASHTABLE_NSLOT/2 + 1 );
+
+ /* If this is the first entry to be added to this hash-table, zero the
+ ** entire hash table and aPgno[] array before proceding.
+ */
+ if( idx==1 ){
+ int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
+ memset((void*)&aPgno[1], 0, nByte);
+ }
+
+ /* If the entry in aPgno[] is already set, then the previous writer
+ ** must have exited unexpectedly in the middle of a transaction (after
+ ** writing one or more dirty pages to the WAL to free up memory).
+ ** Remove the remnants of that writers uncommitted transaction from
+ ** the hash-table before writing any new entries.
+ */
+ if( aPgno[idx] ){
+ walCleanupHash(pWal);
+ assert( !aPgno[idx] );
+ }
+
+ /* Write the aPgno[] array entry and the hash-table slot. */
+ nCollide = idx;
+ for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){
+ if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
+ }
+ aPgno[idx] = iPage;
+ aHash[iKey] = (ht_slot)idx;
+
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+ /* Verify that the number of entries in the hash table exactly equals
+ ** the number of entries in the mapping region.
+ */
+ {
+ int i; /* Loop counter */
+ int nEntry = 0; /* Number of entries in the hash table */
+ for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; }
+ assert( nEntry==idx );
+ }
+
+ /* Verify that the every entry in the mapping region is reachable
+ ** via the hash table. This turns out to be a really, really expensive
+ ** thing to check, so only do this occasionally - not on every
+ ** iteration.
+ */
+ if( (idx&0x3ff)==0 ){
+ int i; /* Loop counter */
+ for(i=1; i<=idx; i++){
+ for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){
+ if( aHash[iKey]==i ) break;
+ }
+ assert( aHash[iKey]==i );
+ }
+ }
+#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
+ }
+
+
+ return rc;
+}
+
+
+/*
+** Recover the wal-index by reading the write-ahead log file.
+**
+** This routine first tries to establish an exclusive lock on the
+** wal-index to prevent other threads/processes from doing anything
+** with the WAL or wal-index while recovery is running. The
+** WAL_RECOVER_LOCK is also held so that other threads will know
+** that this thread is running recovery. If unable to establish
+** the necessary locks, this routine returns SQLITE_BUSY.
+*/
+static int walIndexRecover(Wal *pWal){
+ int rc; /* Return Code */
+ i64 nSize; /* Size of log file */
+ u32 aFrameCksum[2] = {0, 0};
+ int iLock; /* Lock offset to lock for checkpoint */
+ int nLock; /* Number of locks to hold */
+
+ /* Obtain an exclusive lock on all byte in the locking range not already
+ ** locked by the caller. The caller is guaranteed to have locked the
+ ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
+ ** If successful, the same bytes that are locked here are unlocked before
+ ** this function returns.
+ */
+ assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
+ assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
+ assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
+ assert( pWal->writeLock );
+ iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
+ nLock = SQLITE_SHM_NLOCK - iLock;
+ rc = walLockExclusive(pWal, iLock, nLock);
+ if( rc ){
+ return rc;
+ }
+ WALTRACE(("WAL%p: recovery begin...\n", pWal));
+
+ memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
+
+ rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
+ if( rc!=SQLITE_OK ){
+ goto recovery_error;
+ }
+
+ if( nSize>WAL_HDRSIZE ){
+ u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */
+ u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */
+ int szFrame; /* Number of bytes in buffer aFrame[] */
+ u8 *aData; /* Pointer to data part of aFrame buffer */
+ int iFrame; /* Index of last frame read */
+ i64 iOffset; /* Next offset to read from log file */
+ int szPage; /* Page size according to the log */
+ u32 magic; /* Magic value read from WAL header */
+ u32 version; /* Magic value read from WAL header */
+ int isValid; /* True if this frame is valid */
+
+ /* Read in the WAL header. */
+ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
+ if( rc!=SQLITE_OK ){
+ goto recovery_error;
+ }
+
+ /* If the database page size is not a power of two, or is greater than
+ ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid
+ ** data. Similarly, if the 'magic' value is invalid, ignore the whole
+ ** WAL file.
+ */
+ magic = sqlite3Get4byte(&aBuf[0]);
+ szPage = sqlite3Get4byte(&aBuf[8]);
+ if( (magic&0xFFFFFFFE)!=WAL_MAGIC
+ || szPage&(szPage-1)
+ || szPage>SQLITE_MAX_PAGE_SIZE
+ || szPage<512
+ ){
+ goto finished;
+ }
+ pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
+ pWal->szPage = szPage;
+ pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
+ memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
+
+ /* Verify that the WAL header checksum is correct */
+ walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
+ aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
+ );
+ if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
+ || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28])
+ ){
+ goto finished;
+ }
+
+ /* Verify that the version number on the WAL format is one that
+ ** are able to understand */
+ version = sqlite3Get4byte(&aBuf[4]);
+ if( version!=WAL_MAX_VERSION ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ goto finished;
+ }
+
+ /* Malloc a buffer to read frames into. */
+ szFrame = szPage + WAL_FRAME_HDRSIZE;
+ aFrame = (u8 *)sqlite3_malloc(szFrame);
+ if( !aFrame ){
+ rc = SQLITE_NOMEM;
+ goto recovery_error;
+ }
+ aData = &aFrame[WAL_FRAME_HDRSIZE];
+
+ /* Read all frames from the log file. */
+ iFrame = 0;
+ for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){
+ u32 pgno; /* Database page number for frame */
+ u32 nTruncate; /* dbsize field from frame header */
+
+ /* Read and decode the next log frame. */
+ iFrame++;
+ rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
+ if( rc!=SQLITE_OK ) break;
+ isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
+ if( !isValid ) break;
+ rc = walIndexAppend(pWal, iFrame, pgno);
+ if( rc!=SQLITE_OK ) break;
+
+ /* If nTruncate is non-zero, this is a commit record. */
+ if( nTruncate ){
+ pWal->hdr.mxFrame = iFrame;
+ pWal->hdr.nPage = nTruncate;
+ pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
+ testcase( szPage<=32768 );
+ testcase( szPage>=65536 );
+ aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
+ aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
+ }
+ }
+
+ sqlite3_free(aFrame);
+ }
+
+finished:
+ if( rc==SQLITE_OK ){
+ volatile WalCkptInfo *pInfo;
+ int i;
+ pWal->hdr.aFrameCksum[0] = aFrameCksum[0];
+ pWal->hdr.aFrameCksum[1] = aFrameCksum[1];
+ walIndexWriteHdr(pWal);
+
+ /* Reset the checkpoint-header. This is safe because this thread is
+ ** currently holding locks that exclude all other readers, writers and
+ ** checkpointers.
+ */
+ pInfo = walCkptInfo(pWal);
+ pInfo->nBackfill = 0;
+ pInfo->aReadMark[0] = 0;
+ for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
+ if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
+
+ /* If more than one frame was recovered from the log file, report an
+ ** event via sqlite3_log(). This is to help with identifying performance
+ ** problems caused by applications routinely shutting down without
+ ** checkpointing the log file.
+ */
+ if( pWal->hdr.nPage ){
+ sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s",
+ pWal->hdr.nPage, pWal->zWalName
+ );
+ }
+ }
+
+recovery_error:
+ WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
+ walUnlockExclusive(pWal, iLock, nLock);
+ return rc;
+}
+
+/*
+** Close an open wal-index.
+*/
+static void walIndexClose(Wal *pWal, int isDelete){
+ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+ int i;
+ for(i=0; i<pWal->nWiData; i++){
+ sqlite3_free((void *)pWal->apWiData[i]);
+ pWal->apWiData[i] = 0;
+ }
+ }else{
+ sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
+ }
+}
+
+/*
+** Open a connection to the WAL file zWalName. The database file must
+** already be opened on connection pDbFd. The buffer that zWalName points
+** to must remain valid for the lifetime of the returned Wal* handle.
+**
+** A SHARED lock should be held on the database file when this function
+** is called. The purpose of this SHARED lock is to prevent any other
+** client from unlinking the WAL or wal-index file. If another process
+** were to do this just after this client opened one of these files, the
+** system would be badly broken.
+**
+** If the log file is successfully opened, SQLITE_OK is returned and
+** *ppWal is set to point to a new WAL handle. If an error occurs,
+** an SQLite error code is returned and *ppWal is left unmodified.
+*/
+SQLITE_PRIVATE int sqlite3WalOpen(
+ sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
+ sqlite3_file *pDbFd, /* The open database file */
+ const char *zWalName, /* Name of the WAL file */
+ int bNoShm, /* True to run in heap-memory mode */
+ i64 mxWalSize, /* Truncate WAL to this size on reset */
+ Wal **ppWal /* OUT: Allocated Wal handle */
+){
+ int rc; /* Return Code */
+ Wal *pRet; /* Object to allocate and return */
+ int flags; /* Flags passed to OsOpen() */
+
+ assert( zWalName && zWalName[0] );
+ assert( pDbFd );
+
+ /* In the amalgamation, the os_unix.c and os_win.c source files come before
+ ** this source file. Verify that the #defines of the locking byte offsets
+ ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
+ */
+#ifdef WIN_SHM_BASE
+ assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
+#endif
+#ifdef UNIX_SHM_BASE
+ assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET );
+#endif
+
+
+ /* Allocate an instance of struct Wal to return. */
+ *ppWal = 0;
+ pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile);
+ if( !pRet ){
+ return SQLITE_NOMEM;
+ }
+
+ pRet->pVfs = pVfs;
+ pRet->pWalFd = (sqlite3_file *)&pRet[1];
+ pRet->pDbFd = pDbFd;
+ pRet->readLock = -1;
+ pRet->mxWalSize = mxWalSize;
+ pRet->zWalName = zWalName;
+ pRet->syncHeader = 1;
+ pRet->padToSectorBoundary = 1;
+ pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
+
+ /* Open file handle on the write-ahead log file. */
+ flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
+ rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
+ if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){
+ pRet->readOnly = WAL_RDONLY;
+ }
+
+ if( rc!=SQLITE_OK ){
+ walIndexClose(pRet, 0);
+ sqlite3OsClose(pRet->pWalFd);
+ sqlite3_free(pRet);
+ }else{
+ int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
+ if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
+ if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
+ pRet->padToSectorBoundary = 0;
+ }
+ *ppWal = pRet;
+ WALTRACE(("WAL%d: opened\n", pRet));
+ }
+ return rc;
+}
+
+/*
+** Change the size to which the WAL file is trucated on each reset.
+*/
+SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){
+ if( pWal ) pWal->mxWalSize = iLimit;
+}
+
+/*
+** Find the smallest page number out of all pages held in the WAL that
+** has not been returned by any prior invocation of this method on the
+** same WalIterator object. Write into *piFrame the frame index where
+** that page was last written into the WAL. Write into *piPage the page
+** number.
+**
+** Return 0 on success. If there are no pages in the WAL with a page
+** number larger than *piPage, then return 1.
+*/
+static int walIteratorNext(
+ WalIterator *p, /* Iterator */
+ u32 *piPage, /* OUT: The page number of the next page */
+ u32 *piFrame /* OUT: Wal frame index of next page */
+){
+ u32 iMin; /* Result pgno must be greater than iMin */
+ u32 iRet = 0xFFFFFFFF; /* 0xffffffff is never a valid page number */
+ int i; /* For looping through segments */
+
+ iMin = p->iPrior;
+ assert( iMin<0xffffffff );
+ for(i=p->nSegment-1; i>=0; i--){
+ struct WalSegment *pSegment = &p->aSegment[i];
+ while( pSegment->iNext<pSegment->nEntry ){
+ u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
+ if( iPg>iMin ){
+ if( iPg<iRet ){
+ iRet = iPg;
+ *piFrame = pSegment->iZero + pSegment->aIndex[pSegment->iNext];
+ }
+ break;
+ }
+ pSegment->iNext++;
+ }
+ }
+
+ *piPage = p->iPrior = iRet;
+ return (iRet==0xFFFFFFFF);
+}
+
+/*
+** This function merges two sorted lists into a single sorted list.
+**
+** aLeft[] and aRight[] are arrays of indices. The sort key is
+** aContent[aLeft[]] and aContent[aRight[]]. Upon entry, the following
+** is guaranteed for all J<K:
+**
+** aContent[aLeft[J]] < aContent[aLeft[K]]
+** aContent[aRight[J]] < aContent[aRight[K]]
+**
+** This routine overwrites aRight[] with a new (probably longer) sequence
+** of indices such that the aRight[] contains every index that appears in
+** either aLeft[] or the old aRight[] and such that the second condition
+** above is still met.
+**
+** The aContent[aLeft[X]] values will be unique for all X. And the
+** aContent[aRight[X]] values will be unique too. But there might be
+** one or more combinations of X and Y such that
+**
+** aLeft[X]!=aRight[Y] && aContent[aLeft[X]] == aContent[aRight[Y]]
+**
+** When that happens, omit the aLeft[X] and use the aRight[Y] index.
+*/
+static void walMerge(
+ const u32 *aContent, /* Pages in wal - keys for the sort */
+ ht_slot *aLeft, /* IN: Left hand input list */
+ int nLeft, /* IN: Elements in array *paLeft */
+ ht_slot **paRight, /* IN/OUT: Right hand input list */
+ int *pnRight, /* IN/OUT: Elements in *paRight */
+ ht_slot *aTmp /* Temporary buffer */
+){
+ int iLeft = 0; /* Current index in aLeft */
+ int iRight = 0; /* Current index in aRight */
+ int iOut = 0; /* Current index in output buffer */
+ int nRight = *pnRight;
+ ht_slot *aRight = *paRight;
+
+ assert( nLeft>0 && nRight>0 );
+ while( iRight<nRight || iLeft<nLeft ){
+ ht_slot logpage;
+ Pgno dbpage;
+
+ if( (iLeft<nLeft)
+ && (iRight>=nRight || aContent[aLeft[iLeft]]<aContent[aRight[iRight]])
+ ){
+ logpage = aLeft[iLeft++];
+ }else{
+ logpage = aRight[iRight++];
+ }
+ dbpage = aContent[logpage];
+
+ aTmp[iOut++] = logpage;
+ if( iLeft<nLeft && aContent[aLeft[iLeft]]==dbpage ) iLeft++;
+
+ assert( iLeft>=nLeft || aContent[aLeft[iLeft]]>dbpage );
+ assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage );
+ }
+
+ *paRight = aLeft;
+ *pnRight = iOut;
+ memcpy(aLeft, aTmp, sizeof(aTmp[0])*iOut);
+}
+
+/*
+** Sort the elements in list aList using aContent[] as the sort key.
+** Remove elements with duplicate keys, preferring to keep the
+** larger aList[] values.
+**
+** The aList[] entries are indices into aContent[]. The values in
+** aList[] are to be sorted so that for all J<K:
+**
+** aContent[aList[J]] < aContent[aList[K]]
+**
+** For any X and Y such that
+**
+** aContent[aList[X]] == aContent[aList[Y]]
+**
+** Keep the larger of the two values aList[X] and aList[Y] and discard
+** the smaller.
+*/
+static void walMergesort(
+ const u32 *aContent, /* Pages in wal */
+ ht_slot *aBuffer, /* Buffer of at least *pnList items to use */
+ ht_slot *aList, /* IN/OUT: List to sort */
+ int *pnList /* IN/OUT: Number of elements in aList[] */
+){
+ struct Sublist {
+ int nList; /* Number of elements in aList */
+ ht_slot *aList; /* Pointer to sub-list content */
+ };
+
+ const int nList = *pnList; /* Size of input list */
+ int nMerge = 0; /* Number of elements in list aMerge */
+ ht_slot *aMerge = 0; /* List to be merged */
+ int iList; /* Index into input list */
+ int iSub = 0; /* Index into aSub array */
+ struct Sublist aSub[13]; /* Array of sub-lists */
+
+ memset(aSub, 0, sizeof(aSub));
+ assert( nList<=HASHTABLE_NPAGE && nList>0 );
+ assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) );
+
+ for(iList=0; iList<nList; iList++){
+ nMerge = 1;
+ aMerge = &aList[iList];
+ for(iSub=0; iList & (1<<iSub); iSub++){
+ struct Sublist *p = &aSub[iSub];
+ assert( p->aList && p->nList<=(1<<iSub) );
+ assert( p->aList==&aList[iList&~((2<<iSub)-1)] );
+ walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);
+ }
+ aSub[iSub].aList = aMerge;
+ aSub[iSub].nList = nMerge;
+ }
+
+ for(iSub++; iSub<ArraySize(aSub); iSub++){
+ if( nList & (1<<iSub) ){
+ struct Sublist *p = &aSub[iSub];
+ assert( p->nList<=(1<<iSub) );
+ assert( p->aList==&aList[nList&~((2<<iSub)-1)] );
+ walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer);
+ }
+ }
+ assert( aMerge==aList );
+ *pnList = nMerge;
+
+#ifdef SQLITE_DEBUG
+ {
+ int i;
+ for(i=1; i<*pnList; i++){
+ assert( aContent[aList[i]] > aContent[aList[i-1]] );
+ }
+ }
+#endif
+}
+
+/*
+** Free an iterator allocated by walIteratorInit().
+*/
+static void walIteratorFree(WalIterator *p){
+ sqlite3ScratchFree(p);
+}
+
+/*
+** Construct a WalInterator object that can be used to loop over all
+** pages in the WAL in ascending order. The caller must hold the checkpoint
+** lock.
+**
+** On success, make *pp point to the newly allocated WalInterator object
+** return SQLITE_OK. Otherwise, return an error code. If this routine
+** returns an error, the value of *pp is undefined.
+**
+** The calling routine should invoke walIteratorFree() to destroy the
+** WalIterator object when it has finished with it.
+*/
+static int walIteratorInit(Wal *pWal, WalIterator **pp){
+ WalIterator *p; /* Return value */
+ int nSegment; /* Number of segments to merge */
+ u32 iLast; /* Last frame in log */
+ int nByte; /* Number of bytes to allocate */
+ int i; /* Iterator variable */
+ ht_slot *aTmp; /* Temp space used by merge-sort */
+ int rc = SQLITE_OK; /* Return Code */
+
+ /* This routine only runs while holding the checkpoint lock. And
+ ** it only runs if there is actually content in the log (mxFrame>0).
+ */
+ assert( pWal->ckptLock && pWal->hdr.mxFrame>0 );
+ iLast = pWal->hdr.mxFrame;
+
+ /* Allocate space for the WalIterator object. */
+ nSegment = walFramePage(iLast) + 1;
+ nByte = sizeof(WalIterator)
+ + (nSegment-1)*sizeof(struct WalSegment)
+ + iLast*sizeof(ht_slot);
+ p = (WalIterator *)sqlite3ScratchMalloc(nByte);
+ if( !p ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, nByte);
+ p->nSegment = nSegment;
+
+ /* Allocate temporary space used by the merge-sort routine. This block
+ ** of memory will be freed before this function returns.
+ */
+ aTmp = (ht_slot *)sqlite3ScratchMalloc(
+ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
+ );
+ if( !aTmp ){
+ rc = SQLITE_NOMEM;
+ }
+
+ for(i=0; rc==SQLITE_OK && i<nSegment; i++){
+ volatile ht_slot *aHash;
+ u32 iZero;
+ volatile u32 *aPgno;
+
+ rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero);
+ if( rc==SQLITE_OK ){
+ int j; /* Counter variable */
+ int nEntry; /* Number of entries in this segment */
+ ht_slot *aIndex; /* Sorted index for this segment */
+
+ aPgno++;
+ if( (i+1)==nSegment ){
+ nEntry = (int)(iLast - iZero);
+ }else{
+ nEntry = (int)((u32*)aHash - (u32*)aPgno);
+ }
+ aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
+ iZero++;
+
+ for(j=0; j<nEntry; j++){
+ aIndex[j] = (ht_slot)j;
+ }
+ walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry);
+ p->aSegment[i].iZero = iZero;
+ p->aSegment[i].nEntry = nEntry;
+ p->aSegment[i].aIndex = aIndex;
+ p->aSegment[i].aPgno = (u32 *)aPgno;
+ }
+ }
+ sqlite3ScratchFree(aTmp);
+
+ if( rc!=SQLITE_OK ){
+ walIteratorFree(p);
+ }
+ *pp = p;
+ return rc;
+}
+
+/*
+** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
+** n. If the attempt fails and parameter xBusy is not NULL, then it is a
+** busy-handler function. Invoke it and retry the lock until either the
+** lock is successfully obtained or the busy-handler returns 0.
+*/
+static int walBusyLock(
+ Wal *pWal, /* WAL connection */
+ int (*xBusy)(void*), /* Function to call when busy */
+ void *pBusyArg, /* Context argument for xBusyHandler */
+ int lockIdx, /* Offset of first byte to lock */
+ int n /* Number of bytes to lock */
+){
+ int rc;
+ do {
+ rc = walLockExclusive(pWal, lockIdx, n);
+ }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
+ return rc;
+}
+
+/*
+** The cache of the wal-index header must be valid to call this function.
+** Return the page-size in bytes used by the database.
+*/
+static int walPagesize(Wal *pWal){
+ return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
+}
+
+/*
+** Copy as much content as we can from the WAL back into the database file
+** in response to an sqlite3_wal_checkpoint() request or the equivalent.
+**
+** The amount of information copies from WAL to database might be limited
+** by active readers. This routine will never overwrite a database page
+** that a concurrent reader might be using.
+**
+** All I/O barrier operations (a.k.a fsyncs) occur in this routine when
+** SQLite is in WAL-mode in synchronous=NORMAL. That means that if
+** checkpoints are always run by a background thread or background
+** process, foreground threads will never block on a lengthy fsync call.
+**
+** Fsync is called on the WAL before writing content out of the WAL and
+** into the database. This ensures that if the new content is persistent
+** in the WAL and can be recovered following a power-loss or hard reset.
+**
+** Fsync is also called on the database file if (and only if) the entire
+** WAL content is copied into the database file. This second fsync makes
+** it safe to delete the WAL since the new content will persist in the
+** database file.
+**
+** This routine uses and updates the nBackfill field of the wal-index header.
+** This is the only routine tha will increase the value of nBackfill.
+** (A WAL reset or recovery will revert nBackfill to zero, but not increase
+** its value.)
+**
+** The caller must be holding sufficient locks to ensure that no other
+** checkpoint is running (in any other thread or process) at the same
+** time.
+*/
+static int walCheckpoint(
+ Wal *pWal, /* Wal connection */
+ int eMode, /* One of PASSIVE, FULL or RESTART */
+ int (*xBusyCall)(void*), /* Function to call when busy */
+ void *pBusyArg, /* Context argument for xBusyHandler */
+ int sync_flags, /* Flags for OsSync() (or 0) */
+ u8 *zBuf /* Temporary buffer to use */
+){
+ int rc; /* Return code */
+ int szPage; /* Database page-size */
+ WalIterator *pIter = 0; /* Wal iterator context */
+ u32 iDbpage = 0; /* Next database page to write */
+ u32 iFrame = 0; /* Wal frame containing data for iDbpage */
+ u32 mxSafeFrame; /* Max frame that can be backfilled */
+ u32 mxPage; /* Max database page to write */
+ int i; /* Loop counter */
+ volatile WalCkptInfo *pInfo; /* The checkpoint status information */
+ int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */
+
+ szPage = walPagesize(pWal);
+ testcase( szPage<=32768 );
+ testcase( szPage>=65536 );
+ pInfo = walCkptInfo(pWal);
+ if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
+
+ /* Allocate the iterator */
+ rc = walIteratorInit(pWal, &pIter);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ assert( pIter );
+
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall;
+
+ /* Compute in mxSafeFrame the index of the last frame of the WAL that is
+ ** safe to write into the database. Frames beyond mxSafeFrame might
+ ** overwrite database pages that are in use by active readers and thus
+ ** cannot be backfilled from the WAL.
+ */
+ mxSafeFrame = pWal->hdr.mxFrame;
+ mxPage = pWal->hdr.nPage;
+ for(i=1; i<WAL_NREADER; i++){
+ u32 y = pInfo->aReadMark[i];
+ if( mxSafeFrame>y ){
+ assert( y<=pWal->hdr.mxFrame );
+ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
+ if( rc==SQLITE_OK ){
+ pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ }else if( rc==SQLITE_BUSY ){
+ mxSafeFrame = y;
+ xBusy = 0;
+ }else{
+ goto walcheckpoint_out;
+ }
+ }
+ }
+
+ if( pInfo->nBackfill<mxSafeFrame
+ && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK
+ ){
+ i64 nSize; /* Current size of database file */
+ u32 nBackfill = pInfo->nBackfill;
+
+ /* Sync the WAL to disk */
+ if( sync_flags ){
+ rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
+ }
+
+ /* If the database file may grow as a result of this checkpoint, hint
+ ** about the eventual size of the db file to the VFS layer.
+ */
+ if( rc==SQLITE_OK ){
+ i64 nReq = ((i64)mxPage * szPage);
+ rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
+ if( rc==SQLITE_OK && nSize<nReq ){
+ sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
+ }
+ }
+
+ /* Iterate through the contents of the WAL, copying data to the db file. */
+ while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
+ i64 iOffset;
+ assert( walFramePgno(pWal, iFrame)==iDbpage );
+ if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
+ iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
+ rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
+ if( rc!=SQLITE_OK ) break;
+ iOffset = (iDbpage-1)*(i64)szPage;
+ testcase( IS_BIG_INT(iOffset) );
+ rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
+ if( rc!=SQLITE_OK ) break;
+ }
+
+ /* If work was actually accomplished... */
+ if( rc==SQLITE_OK ){
+ if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
+ i64 szDb = pWal->hdr.nPage*(i64)szPage;
+ testcase( IS_BIG_INT(szDb) );
+ rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
+ if( rc==SQLITE_OK && sync_flags ){
+ rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ pInfo->nBackfill = mxSafeFrame;
+ }
+ }
+
+ /* Release the reader lock held while backfilling */
+ walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
+ }
+
+ if( rc==SQLITE_BUSY ){
+ /* Reset the return code so as not to report a checkpoint failure
+ ** just because there are active readers. */
+ rc = SQLITE_OK;
+ }
+
+ /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal
+ ** file has been copied into the database file, then block until all
+ ** readers have finished using the wal file. This ensures that the next
+ ** process to write to the database restarts the wal file.
+ */
+ if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
+ assert( pWal->writeLock );
+ if( pInfo->nBackfill<pWal->hdr.mxFrame ){
+ rc = SQLITE_BUSY;
+ }else if( eMode==SQLITE_CHECKPOINT_RESTART ){
+ assert( mxSafeFrame==pWal->hdr.mxFrame );
+ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
+ if( rc==SQLITE_OK ){
+ walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+ }
+ }
+ }
+
+ walcheckpoint_out:
+ walIteratorFree(pIter);
+ return rc;
+}
+
+/*
+** If the WAL file is currently larger than nMax bytes in size, truncate
+** it to exactly nMax bytes. If an error occurs while doing so, ignore it.
+*/
+static void walLimitSize(Wal *pWal, i64 nMax){
+ i64 sz;
+ int rx;
+ sqlite3BeginBenignMalloc();
+ rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
+ if( rx==SQLITE_OK && (sz > nMax ) ){
+ rx = sqlite3OsTruncate(pWal->pWalFd, nMax);
+ }
+ sqlite3EndBenignMalloc();
+ if( rx ){
+ sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
+ }
+}
+
+/*
+** Close a connection to a log file.
+*/
+SQLITE_PRIVATE int sqlite3WalClose(
+ Wal *pWal, /* Wal to close */
+ int sync_flags, /* Flags to pass to OsSync() (or 0) */
+ int nBuf,
+ u8 *zBuf /* Buffer of at least nBuf bytes */
+){
+ int rc = SQLITE_OK;
+ if( pWal ){
+ int isDelete = 0; /* True to unlink wal and wal-index files */
+
+ /* If an EXCLUSIVE lock can be obtained on the database file (using the
+ ** ordinary, rollback-mode locking methods, this guarantees that the
+ ** connection associated with this log file is the only connection to
+ ** the database. In this case checkpoint the database and unlink both
+ ** the wal and wal-index files.
+ **
+ ** The EXCLUSIVE lock is not released before returning.
+ */
+ rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
+ if( rc==SQLITE_OK ){
+ if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
+ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
+ }
+ rc = sqlite3WalCheckpoint(
+ pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
+ );
+ if( rc==SQLITE_OK ){
+ int bPersist = -1;
+ sqlite3OsFileControlHint(
+ pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
+ );
+ if( bPersist!=1 ){
+ /* Try to delete the WAL file if the checkpoint completed and
+ ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal
+ ** mode (!bPersist) */
+ isDelete = 1;
+ }else if( pWal->mxWalSize>=0 ){
+ /* Try to truncate the WAL file to zero bytes if the checkpoint
+ ** completed and fsynced (rc==SQLITE_OK) and we are in persistent
+ ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a
+ ** non-negative value (pWal->mxWalSize>=0). Note that we truncate
+ ** to zero bytes as truncating to the journal_size_limit might
+ ** leave a corrupt WAL file on disk. */
+ walLimitSize(pWal, 0);
+ }
+ }
+ }
+
+ walIndexClose(pWal, isDelete);
+ sqlite3OsClose(pWal->pWalFd);
+ if( isDelete ){
+ sqlite3BeginBenignMalloc();
+ sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
+ sqlite3EndBenignMalloc();
+ }
+ WALTRACE(("WAL%p: closed\n", pWal));
+ sqlite3_free((void *)pWal->apWiData);
+ sqlite3_free(pWal);
+ }
+ return rc;
+}
+
+/*
+** Try to read the wal-index header. Return 0 on success and 1 if
+** there is a problem.
+**
+** The wal-index is in shared memory. Another thread or process might
+** be writing the header at the same time this procedure is trying to
+** read it, which might result in inconsistency. A dirty read is detected
+** by verifying that both copies of the header are the same and also by
+** a checksum on the header.
+**
+** If and only if the read is consistent and the header is different from
+** pWal->hdr, then pWal->hdr is updated to the content of the new header
+** and *pChanged is set to 1.
+**
+** If the checksum cannot be verified return non-zero. If the header
+** is read successfully and the checksum verified, return zero.
+*/
+static int walIndexTryHdr(Wal *pWal, int *pChanged){
+ u32 aCksum[2]; /* Checksum on the header content */
+ WalIndexHdr h1, h2; /* Two copies of the header content */
+ WalIndexHdr volatile *aHdr; /* Header in shared memory */
+
+ /* The first page of the wal-index must be mapped at this point. */
+ assert( pWal->nWiData>0 && pWal->apWiData[0] );
+
+ /* Read the header. This might happen concurrently with a write to the
+ ** same area of shared memory on a different CPU in a SMP,
+ ** meaning it is possible that an inconsistent snapshot is read
+ ** from the file. If this happens, return non-zero.
+ **
+ ** There are two copies of the header at the beginning of the wal-index.
+ ** When reading, read [0] first then [1]. Writes are in the reverse order.
+ ** Memory barriers are used to prevent the compiler or the hardware from
+ ** reordering the reads and writes.
+ */
+ aHdr = walIndexHdr(pWal);
+ memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
+ walShmBarrier(pWal);
+ memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
+
+ if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
+ return 1; /* Dirty read */
+ }
+ if( h1.isInit==0 ){
+ return 1; /* Malformed header - probably all zeros */
+ }
+ walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
+ if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
+ return 1; /* Checksum does not match */
+ }
+
+ if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
+ *pChanged = 1;
+ memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr));
+ pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
+ testcase( pWal->szPage<=32768 );
+ testcase( pWal->szPage>=65536 );
+ }
+
+ /* The header was successfully read. Return zero. */
+ return 0;
+}
+
+/*
+** Read the wal-index header from the wal-index and into pWal->hdr.
+** If the wal-header appears to be corrupt, try to reconstruct the
+** wal-index from the WAL before returning.
+**
+** Set *pChanged to 1 if the wal-index header value in pWal->hdr is
+** changed by this opertion. If pWal->hdr is unchanged, set *pChanged
+** to 0.
+**
+** If the wal-index header is successfully read, return SQLITE_OK.
+** Otherwise an SQLite error code.
+*/
+static int walIndexReadHdr(Wal *pWal, int *pChanged){
+ int rc; /* Return code */
+ int badHdr; /* True if a header read failed */
+ volatile u32 *page0; /* Chunk of wal-index containing header */
+
+ /* Ensure that page 0 of the wal-index (the page that contains the
+ ** wal-index header) is mapped. Return early if an error occurs here.
+ */
+ assert( pChanged );
+ rc = walIndexPage(pWal, 0, &page0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ };
+ assert( page0 || pWal->writeLock==0 );
+
+ /* If the first page of the wal-index has been mapped, try to read the
+ ** wal-index header immediately, without holding any lock. This usually
+ ** works, but may fail if the wal-index header is corrupt or currently
+ ** being modified by another thread or process.
+ */
+ badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
+
+ /* If the first attempt failed, it might have been due to a race
+ ** with a writer. So get a WRITE lock and try again.
+ */
+ assert( badHdr==0 || pWal->writeLock==0 );
+ if( badHdr ){
+ if( pWal->readOnly & WAL_SHM_RDONLY ){
+ if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
+ walUnlockShared(pWal, WAL_WRITE_LOCK);
+ rc = SQLITE_READONLY_RECOVERY;
+ }
+ }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
+ pWal->writeLock = 1;
+ if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
+ badHdr = walIndexTryHdr(pWal, pChanged);
+ if( badHdr ){
+ /* If the wal-index header is still malformed even while holding
+ ** a WRITE lock, it can only mean that the header is corrupted and
+ ** needs to be reconstructed. So run recovery to do exactly that.
+ */
+ rc = walIndexRecover(pWal);
+ *pChanged = 1;
+ }
+ }
+ pWal->writeLock = 0;
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ }
+ }
+
+ /* If the header is read successfully, check the version number to make
+ ** sure the wal-index was not constructed with some future format that
+ ** this version of SQLite cannot understand.
+ */
+ if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+
+ return rc;
+}
+
+/*
+** This is the value that walTryBeginRead returns when it needs to
+** be retried.
+*/
+#define WAL_RETRY (-1)
+
+/*
+** Attempt to start a read transaction. This might fail due to a race or
+** other transient condition. When that happens, it returns WAL_RETRY to
+** indicate to the caller that it is safe to retry immediately.
+**
+** On success return SQLITE_OK. On a permanent failure (such an
+** I/O error or an SQLITE_BUSY because another process is running
+** recovery) return a positive error code.
+**
+** The useWal parameter is true to force the use of the WAL and disable
+** the case where the WAL is bypassed because it has been completely
+** checkpointed. If useWal==0 then this routine calls walIndexReadHdr()
+** to make a copy of the wal-index header into pWal->hdr. If the
+** wal-index header has changed, *pChanged is set to 1 (as an indication
+** to the caller that the local paget cache is obsolete and needs to be
+** flushed.) When useWal==1, the wal-index header is assumed to already
+** be loaded and the pChanged parameter is unused.
+**
+** The caller must set the cnt parameter to the number of prior calls to
+** this routine during the current read attempt that returned WAL_RETRY.
+** This routine will start taking more aggressive measures to clear the
+** race conditions after multiple WAL_RETRY returns, and after an excessive
+** number of errors will ultimately return SQLITE_PROTOCOL. The
+** SQLITE_PROTOCOL return indicates that some other process has gone rogue
+** and is not honoring the locking protocol. There is a vanishingly small
+** chance that SQLITE_PROTOCOL could be returned because of a run of really
+** bad luck when there is lots of contention for the wal-index, but that
+** possibility is so small that it can be safely neglected, we believe.
+**
+** On success, this routine obtains a read lock on
+** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is
+** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1)
+** that means the Wal does not hold any read lock. The reader must not
+** access any database page that is modified by a WAL frame up to and
+** including frame number aReadMark[pWal->readLock]. The reader will
+** use WAL frames up to and including pWal->hdr.mxFrame if pWal->readLock>0
+** Or if pWal->readLock==0, then the reader will ignore the WAL
+** completely and get all content directly from the database file.
+** If the useWal parameter is 1 then the WAL will never be ignored and
+** this routine will always set pWal->readLock>0 on success.
+** When the read transaction is completed, the caller must release the
+** lock on WAL_READ_LOCK(pWal->readLock) and set pWal->readLock to -1.
+**
+** This routine uses the nBackfill and aReadMark[] fields of the header
+** to select a particular WAL_READ_LOCK() that strives to let the
+** checkpoint process do as much work as possible. This routine might
+** update values of the aReadMark[] array in the header, but if it does
+** so it takes care to hold an exclusive lock on the corresponding
+** WAL_READ_LOCK() while changing values.
+*/
+static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
+ volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
+ u32 mxReadMark; /* Largest aReadMark[] value */
+ int mxI; /* Index of largest aReadMark[] value */
+ int i; /* Loop counter */
+ int rc = SQLITE_OK; /* Return code */
+
+ assert( pWal->readLock<0 ); /* Not currently locked */
+
+ /* Take steps to avoid spinning forever if there is a protocol error.
+ **
+ ** Circumstances that cause a RETRY should only last for the briefest
+ ** instances of time. No I/O or other system calls are done while the
+ ** locks are held, so the locks should not be held for very long. But
+ ** if we are unlucky, another process that is holding a lock might get
+ ** paged out or take a page-fault that is time-consuming to resolve,
+ ** during the few nanoseconds that it is holding the lock. In that case,
+ ** it might take longer than normal for the lock to free.
+ **
+ ** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few
+ ** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this
+ ** is more of a scheduler yield than an actual delay. But on the 10th
+ ** an subsequent retries, the delays start becoming longer and longer,
+ ** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
+ ** The total delay time before giving up is less than 1 second.
+ */
+ if( cnt>5 ){
+ int nDelay = 1; /* Pause time in microseconds */
+ if( cnt>100 ){
+ VVA_ONLY( pWal->lockError = 1; )
+ return SQLITE_PROTOCOL;
+ }
+ if( cnt>=10 ) nDelay = (cnt-9)*238; /* Max delay 21ms. Total delay 996ms */
+ sqlite3OsSleep(pWal->pVfs, nDelay);
+ }
+
+ if( !useWal ){
+ rc = walIndexReadHdr(pWal, pChanged);
+ if( rc==SQLITE_BUSY ){
+ /* If there is not a recovery running in another thread or process
+ ** then convert BUSY errors to WAL_RETRY. If recovery is known to
+ ** be running, convert BUSY to BUSY_RECOVERY. There is a race here
+ ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY
+ ** would be technically correct. But the race is benign since with
+ ** WAL_RETRY this routine will be called again and will probably be
+ ** right on the second iteration.
+ */
+ if( pWal->apWiData[0]==0 ){
+ /* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
+ ** We assume this is a transient condition, so return WAL_RETRY. The
+ ** xShmMap() implementation used by the default unix and win32 VFS
+ ** modules may return SQLITE_BUSY due to a race condition in the
+ ** code that determines whether or not the shared-memory region
+ ** must be zeroed before the requested page is returned.
+ */
+ rc = WAL_RETRY;
+ }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){
+ walUnlockShared(pWal, WAL_RECOVER_LOCK);
+ rc = WAL_RETRY;
+ }else if( rc==SQLITE_BUSY ){
+ rc = SQLITE_BUSY_RECOVERY;
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+
+ pInfo = walCkptInfo(pWal);
+ if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
+ /* The WAL has been completely backfilled (or it is empty).
+ ** and can be safely ignored.
+ */
+ rc = walLockShared(pWal, WAL_READ_LOCK(0));
+ walShmBarrier(pWal);
+ if( rc==SQLITE_OK ){
+ if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
+ /* It is not safe to allow the reader to continue here if frames
+ ** may have been appended to the log before READ_LOCK(0) was obtained.
+ ** When holding READ_LOCK(0), the reader ignores the entire log file,
+ ** which implies that the database file contains a trustworthy
+ ** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from
+ ** happening, this is usually correct.
+ **
+ ** However, if frames have been appended to the log (or if the log
+ ** is wrapped and written for that matter) before the READ_LOCK(0)
+ ** is obtained, that is not necessarily true. A checkpointer may
+ ** have started to backfill the appended frames but crashed before
+ ** it finished. Leaving a corrupt image in the database file.
+ */
+ walUnlockShared(pWal, WAL_READ_LOCK(0));
+ return WAL_RETRY;
+ }
+ pWal->readLock = 0;
+ return SQLITE_OK;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+
+ /* If we get this far, it means that the reader will want to use
+ ** the WAL to get at content from recent commits. The job now is
+ ** to select one of the aReadMark[] entries that is closest to
+ ** but not exceeding pWal->hdr.mxFrame and lock that entry.
+ */
+ mxReadMark = 0;
+ mxI = 0;
+ for(i=1; i<WAL_NREADER; i++){
+ u32 thisMark = pInfo->aReadMark[i];
+ if( mxReadMark<=thisMark && thisMark<=pWal->hdr.mxFrame ){
+ assert( thisMark!=READMARK_NOT_USED );
+ mxReadMark = thisMark;
+ mxI = i;
+ }
+ }
+ /* There was once an "if" here. The extra "{" is to preserve indentation. */
+ {
+ if( (pWal->readOnly & WAL_SHM_RDONLY)==0
+ && (mxReadMark<pWal->hdr.mxFrame || mxI==0)
+ ){
+ for(i=1; i<WAL_NREADER; i++){
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ if( rc==SQLITE_OK ){
+ mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
+ mxI = i;
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ break;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+ }
+ if( mxI==0 ){
+ assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
+ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
+ }
+
+ rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
+ if( rc ){
+ return rc==SQLITE_BUSY ? WAL_RETRY : rc;
+ }
+ /* Now that the read-lock has been obtained, check that neither the
+ ** value in the aReadMark[] array or the contents of the wal-index
+ ** header have changed.
+ **
+ ** It is necessary to check that the wal-index header did not change
+ ** between the time it was read and when the shared-lock was obtained
+ ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
+ ** that the log file may have been wrapped by a writer, or that frames
+ ** that occur later in the log than pWal->hdr.mxFrame may have been
+ ** copied into the database by a checkpointer. If either of these things
+ ** happened, then reading the database with the current value of
+ ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
+ ** instead.
+ **
+ ** This does not guarantee that the copy of the wal-index header is up to
+ ** date before proceeding. That would not be possible without somehow
+ ** blocking writers. It only guarantees that a dangerous checkpoint or
+ ** log-wrap (either of which would require an exclusive lock on
+ ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
+ */
+ walShmBarrier(pWal);
+ if( pInfo->aReadMark[mxI]!=mxReadMark
+ || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
+ ){
+ walUnlockShared(pWal, WAL_READ_LOCK(mxI));
+ return WAL_RETRY;
+ }else{
+ assert( mxReadMark<=pWal->hdr.mxFrame );
+ pWal->readLock = (i16)mxI;
+ }
+ }
+ return rc;
+}
+
+/*
+** Begin a read transaction on the database.
+**
+** This routine used to be called sqlite3OpenSnapshot() and with good reason:
+** it takes a snapshot of the state of the WAL and wal-index for the current
+** instant in time. The current thread will continue to use this snapshot.
+** Other threads might append new content to the WAL and wal-index but
+** that extra content is ignored by the current thread.
+**
+** If the database contents have changes since the previous read
+** transaction, then *pChanged is set to 1 before returning. The
+** Pager layer will use this to know that is cache is stale and
+** needs to be flushed.
+*/
+SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
+ int rc; /* Return code */
+ int cnt = 0; /* Number of TryBeginRead attempts */
+
+ do{
+ rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
+ }while( rc==WAL_RETRY );
+ testcase( (rc&0xff)==SQLITE_BUSY );
+ testcase( (rc&0xff)==SQLITE_IOERR );
+ testcase( rc==SQLITE_PROTOCOL );
+ testcase( rc==SQLITE_OK );
+ return rc;
+}
+
+/*
+** Finish with a read transaction. All this does is release the
+** read-lock.
+*/
+SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){
+ sqlite3WalEndWriteTransaction(pWal);
+ if( pWal->readLock>=0 ){
+ walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
+ pWal->readLock = -1;
+ }
+}
+
+/*
+** Read a page from the WAL, if it is present in the WAL and if the
+** current read transaction is configured to use the WAL.
+**
+** The *pInWal is set to 1 if the requested page is in the WAL and
+** has been loaded. Or *pInWal is set to 0 if the page was not in
+** the WAL and needs to be read out of the database.
+*/
+SQLITE_PRIVATE int sqlite3WalRead(
+ Wal *pWal, /* WAL handle */
+ Pgno pgno, /* Database page number to read data for */
+ int *pInWal, /* OUT: True if data is read from WAL */
+ int nOut, /* Size of buffer pOut in bytes */
+ u8 *pOut /* Buffer to write page data to */
+){
+ u32 iRead = 0; /* If !=0, WAL frame to return data from */
+ u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */
+ int iHash; /* Used to loop through N hash tables */
+
+ /* This routine is only be called from within a read transaction. */
+ assert( pWal->readLock>=0 || pWal->lockError );
+
+ /* If the "last page" field of the wal-index header snapshot is 0, then
+ ** no data will be read from the wal under any circumstances. Return early
+ ** in this case as an optimization. Likewise, if pWal->readLock==0,
+ ** then the WAL is ignored by the reader so return early, as if the
+ ** WAL were empty.
+ */
+ if( iLast==0 || pWal->readLock==0 ){
+ *pInWal = 0;
+ return SQLITE_OK;
+ }
+
+ /* Search the hash table or tables for an entry matching page number
+ ** pgno. Each iteration of the following for() loop searches one
+ ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
+ **
+ ** This code might run concurrently to the code in walIndexAppend()
+ ** that adds entries to the wal-index (and possibly to this hash
+ ** table). This means the value just read from the hash
+ ** slot (aHash[iKey]) may have been added before or after the
+ ** current read transaction was opened. Values added after the
+ ** read transaction was opened may have been written incorrectly -
+ ** i.e. these slots may contain garbage data. However, we assume
+ ** that any slots written before the current read transaction was
+ ** opened remain unmodified.
+ **
+ ** For the reasons above, the if(...) condition featured in the inner
+ ** loop of the following block is more stringent that would be required
+ ** if we had exclusive access to the hash-table:
+ **
+ ** (aPgno[iFrame]==pgno):
+ ** This condition filters out normal hash-table collisions.
+ **
+ ** (iFrame<=iLast):
+ ** This condition filters out entries that were added to the hash
+ ** table after the current read-transaction had started.
+ */
+ for(iHash=walFramePage(iLast); iHash>=0 && iRead==0; iHash--){
+ volatile ht_slot *aHash; /* Pointer to hash table */
+ volatile u32 *aPgno; /* Pointer to array of page numbers */
+ u32 iZero; /* Frame number corresponding to aPgno[0] */
+ int iKey; /* Hash slot index */
+ int nCollide; /* Number of hash collisions remaining */
+ int rc; /* Error code */
+
+ rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ nCollide = HASHTABLE_NSLOT;
+ for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
+ u32 iFrame = aHash[iKey] + iZero;
+ if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){
+ /* assert( iFrame>iRead ); -- not true if there is corruption */
+ iRead = iFrame;
+ }
+ if( (nCollide--)==0 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+ }
+
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+ /* If expensive assert() statements are available, do a linear search
+ ** of the wal-index file content. Make sure the results agree with the
+ ** result obtained using the hash indexes above. */
+ {
+ u32 iRead2 = 0;
+ u32 iTest;
+ for(iTest=iLast; iTest>0; iTest--){
+ if( walFramePgno(pWal, iTest)==pgno ){
+ iRead2 = iTest;
+ break;
+ }
+ }
+ assert( iRead==iRead2 );
+ }
+#endif
+
+ /* If iRead is non-zero, then it is the log frame number that contains the
+ ** required page. Read and return data from the log file.
+ */
+ if( iRead ){
+ int sz;
+ i64 iOffset;
+ sz = pWal->hdr.szPage;
+ sz = (sz&0xfe00) + ((sz&0x0001)<<16);
+ testcase( sz<=32768 );
+ testcase( sz>=65536 );
+ iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
+ *pInWal = 1;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
+ return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
+ }
+
+ *pInWal = 0;
+ return SQLITE_OK;
+}
+
+
+/*
+** Return the size of the database in pages (or zero, if unknown).
+*/
+SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
+ if( pWal && ALWAYS(pWal->readLock>=0) ){
+ return pWal->hdr.nPage;
+ }
+ return 0;
+}
+
+
+/*
+** This function starts a write transaction on the WAL.
+**
+** A read transaction must have already been started by a prior call
+** to sqlite3WalBeginReadTransaction().
+**
+** If another thread or process has written into the database since
+** the read transaction was started, then it is not possible for this
+** thread to write as doing so would cause a fork. So this routine
+** returns SQLITE_BUSY in that case and no write transaction is started.
+**
+** There can only be a single writer active at a time.
+*/
+SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
+ int rc;
+
+ /* Cannot start a write transaction without first holding a read
+ ** transaction. */
+ assert( pWal->readLock>=0 );
+
+ if( pWal->readOnly ){
+ return SQLITE_READONLY;
+ }
+
+ /* Only one writer allowed at a time. Get the write lock. Return
+ ** SQLITE_BUSY if unable.
+ */
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ if( rc ){
+ return rc;
+ }
+ pWal->writeLock = 1;
+
+ /* If another connection has written to the database file since the
+ ** time the read transaction on this connection was started, then
+ ** the write is disallowed.
+ */
+ if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ pWal->writeLock = 0;
+ rc = SQLITE_BUSY;
+ }
+
+ return rc;
+}
+
+/*
+** End a write transaction. The commit has already been done. This
+** routine merely releases the lock.
+*/
+SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){
+ if( pWal->writeLock ){
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ pWal->writeLock = 0;
+ pWal->truncateOnCommit = 0;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** If any data has been written (but not committed) to the log file, this
+** function moves the write-pointer back to the start of the transaction.
+**
+** Additionally, the callback function is invoked for each frame written
+** to the WAL since the start of the transaction. If the callback returns
+** other than SQLITE_OK, it is not invoked again and the error code is
+** returned to the caller.
+**
+** Otherwise, if the callback function does not return an error, this
+** function returns SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
+ int rc = SQLITE_OK;
+ if( ALWAYS(pWal->writeLock) ){
+ Pgno iMax = pWal->hdr.mxFrame;
+ Pgno iFrame;
+
+ /* Restore the clients cache of the wal-index header to the state it
+ ** was in before the client began writing to the database.
+ */
+ memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
+
+ for(iFrame=pWal->hdr.mxFrame+1;
+ ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
+ iFrame++
+ ){
+ /* This call cannot fail. Unless the page for which the page number
+ ** is passed as the second argument is (a) in the cache and
+ ** (b) has an outstanding reference, then xUndo is either a no-op
+ ** (if (a) is false) or simply expels the page from the cache (if (b)
+ ** is false).
+ **
+ ** If the upper layer is doing a rollback, it is guaranteed that there
+ ** are no outstanding references to any page other than page 1. And
+ ** page 1 is never written to the log until the transaction is
+ ** committed. As a result, the call to xUndo may not fail.
+ */
+ assert( walFramePgno(pWal, iFrame)!=1 );
+ rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
+ }
+ if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
+ }
+ assert( rc==SQLITE_OK );
+ return rc;
+}
+
+/*
+** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
+** values. This function populates the array with values required to
+** "rollback" the write position of the WAL handle back to the current
+** point in the event of a savepoint rollback (via WalSavepointUndo()).
+*/
+SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
+ assert( pWal->writeLock );
+ aWalData[0] = pWal->hdr.mxFrame;
+ aWalData[1] = pWal->hdr.aFrameCksum[0];
+ aWalData[2] = pWal->hdr.aFrameCksum[1];
+ aWalData[3] = pWal->nCkpt;
+}
+
+/*
+** Move the write position of the WAL back to the point identified by
+** the values in the aWalData[] array. aWalData must point to an array
+** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
+** by a call to WalSavepoint().
+*/
+SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
+ int rc = SQLITE_OK;
+
+ assert( pWal->writeLock );
+ assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame );
+
+ if( aWalData[3]!=pWal->nCkpt ){
+ /* This savepoint was opened immediately after the write-transaction
+ ** was started. Right after that, the writer decided to wrap around
+ ** to the start of the log. Update the savepoint values to match.
+ */
+ aWalData[0] = 0;
+ aWalData[3] = pWal->nCkpt;
+ }
+
+ if( aWalData[0]<pWal->hdr.mxFrame ){
+ pWal->hdr.mxFrame = aWalData[0];
+ pWal->hdr.aFrameCksum[0] = aWalData[1];
+ pWal->hdr.aFrameCksum[1] = aWalData[2];
+ walCleanupHash(pWal);
+ }
+
+ return rc;
+}
+
+
+/*
+** This function is called just before writing a set of frames to the log
+** file (see sqlite3WalFrames()). It checks to see if, instead of appending
+** to the current log file, it is possible to overwrite the start of the
+** existing log file with the new frames (i.e. "reset" the log). If so,
+** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left
+** unchanged.
+**
+** SQLITE_OK is returned if no error is encountered (regardless of whether
+** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned
+** if an error occurs.
+*/
+static int walRestartLog(Wal *pWal){
+ int rc = SQLITE_OK;
+ int cnt;
+
+ if( pWal->readLock==0 ){
+ volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+ assert( pInfo->nBackfill==pWal->hdr.mxFrame );
+ if( pInfo->nBackfill>0 ){
+ u32 salt1;
+ sqlite3_randomness(4, &salt1);
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+ if( rc==SQLITE_OK ){
+ /* If all readers are using WAL_READ_LOCK(0) (in other words if no
+ ** readers are currently using the WAL), then the transactions
+ ** frames will overwrite the start of the existing log. Update the
+ ** wal-index header to reflect this.
+ **
+ ** In theory it would be Ok to update the cache of the header only
+ ** at this point. But updating the actual wal-index header is also
+ ** safe and means there is no special case for sqlite3WalUndo()
+ ** to handle if this transaction is rolled back.
+ */
+ int i; /* Loop counter */
+ u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
+
+ pWal->nCkpt++;
+ pWal->hdr.mxFrame = 0;
+ sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
+ aSalt[1] = salt1;
+ walIndexWriteHdr(pWal);
+ pInfo->nBackfill = 0;
+ pInfo->aReadMark[1] = 0;
+ for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
+ assert( pInfo->aReadMark[0]==0 );
+ walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+ walUnlockShared(pWal, WAL_READ_LOCK(0));
+ pWal->readLock = -1;
+ cnt = 0;
+ do{
+ int notUsed;
+ rc = walTryBeginRead(pWal, &notUsed, 1, ++cnt);
+ }while( rc==WAL_RETRY );
+ assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */
+ testcase( (rc&0xff)==SQLITE_IOERR );
+ testcase( rc==SQLITE_PROTOCOL );
+ testcase( rc==SQLITE_OK );
+ }
+ return rc;
+}
+
+/*
+** Information about the current state of the WAL file and where
+** the next fsync should occur - passed from sqlite3WalFrames() into
+** walWriteToLog().
+*/
+typedef struct WalWriter {
+ Wal *pWal; /* The complete WAL information */
+ sqlite3_file *pFd; /* The WAL file to which we write */
+ sqlite3_int64 iSyncPoint; /* Fsync at this offset */
+ int syncFlags; /* Flags for the fsync */
+ int szPage; /* Size of one page */
+} WalWriter;
+
+/*
+** Write iAmt bytes of content into the WAL file beginning at iOffset.
+** Do a sync when crossing the p->iSyncPoint boundary.
+**
+** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt,
+** first write the part before iSyncPoint, then sync, then write the
+** rest.
+*/
+static int walWriteToLog(
+ WalWriter *p, /* WAL to write to */
+ void *pContent, /* Content to be written */
+ int iAmt, /* Number of bytes to write */
+ sqlite3_int64 iOffset /* Start writing at this offset */
+){
+ int rc;
+ if( iOffset<p->iSyncPoint && iOffset+iAmt>=p->iSyncPoint ){
+ int iFirstAmt = (int)(p->iSyncPoint - iOffset);
+ rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset);
+ if( rc ) return rc;
+ iOffset += iFirstAmt;
+ iAmt -= iFirstAmt;
+ pContent = (void*)(iFirstAmt + (char*)pContent);
+ assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
+ rc = sqlite3OsSync(p->pFd, p->syncFlags);
+ if( iAmt==0 || rc ) return rc;
+ }
+ rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
+ return rc;
+}
+
+/*
+** Write out a single frame of the WAL
+*/
+static int walWriteOneFrame(
+ WalWriter *p, /* Where to write the frame */
+ PgHdr *pPage, /* The page of the frame to be written */
+ int nTruncate, /* The commit flag. Usually 0. >0 for commit */
+ sqlite3_int64 iOffset /* Byte offset at which to write */
+){
+ int rc; /* Result code from subfunctions */
+ void *pData; /* Data actually written */
+ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
+#if defined(SQLITE_HAS_CODEC)
+ if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM;
+#else
+ pData = pPage->pData;
+#endif
+ walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
+ rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
+ if( rc ) return rc;
+ /* Write the page data */
+ rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
+ return rc;
+}
+
+/*
+** Write a set of frames to the log. The caller must hold the write-lock
+** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
+*/
+SQLITE_PRIVATE int sqlite3WalFrames(
+ Wal *pWal, /* Wal handle to write to */
+ int szPage, /* Database page-size in bytes */
+ PgHdr *pList, /* List of dirty pages to write */
+ Pgno nTruncate, /* Database size after this commit */
+ int isCommit, /* True if this is a commit */
+ int sync_flags /* Flags to pass to OsSync() (or 0) */
+){
+ int rc; /* Used to catch return codes */
+ u32 iFrame; /* Next frame address */
+ PgHdr *p; /* Iterator to run through pList with. */
+ PgHdr *pLast = 0; /* Last frame in list */
+ int nExtra = 0; /* Number of extra copies of last page */
+ int szFrame; /* The size of a single frame */
+ i64 iOffset; /* Next byte to write in WAL file */
+ WalWriter w; /* The writer */
+
+ assert( pList );
+ assert( pWal->writeLock );
+
+ /* If this frame set completes a transaction, then nTruncate>0. If
+ ** nTruncate==0 then this frame set does not complete the transaction. */
+ assert( (isCommit!=0)==(nTruncate!=0) );
+
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+ { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
+ WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
+ pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
+ }
+#endif
+
+ /* See if it is possible to write these frames into the start of the
+ ** log file, instead of appending to it at pWal->hdr.mxFrame.
+ */
+ if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
+ return rc;
+ }
+
+ /* If this is the first frame written into the log, write the WAL
+ ** header to the start of the WAL file. See comments at the top of
+ ** this source file for a description of the WAL header format.
+ */
+ iFrame = pWal->hdr.mxFrame;
+ if( iFrame==0 ){
+ u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assemble wal-header in */
+ u32 aCksum[2]; /* Checksum for wal-header */
+
+ sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
+ sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION);
+ sqlite3Put4byte(&aWalHdr[8], szPage);
+ sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
+ if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt);
+ memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
+ walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
+ sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
+ sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
+
+ pWal->szPage = szPage;
+ pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
+ pWal->hdr.aFrameCksum[0] = aCksum[0];
+ pWal->hdr.aFrameCksum[1] = aCksum[1];
+ pWal->truncateOnCommit = 1;
+
+ rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
+ WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok"));
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless
+ ** all syncing is turned off by PRAGMA synchronous=OFF). Otherwise
+ ** an out-of-order write following a WAL restart could result in
+ ** database corruption. See the ticket:
+ **
+ ** http://localhost:591/sqlite/info/ff5be73dee
+ */
+ if( pWal->syncHeader && sync_flags ){
+ rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK);
+ if( rc ) return rc;
+ }
+ }
+ assert( (int)pWal->szPage==szPage );
+
+ /* Setup information needed to write frames into the WAL */
+ w.pWal = pWal;
+ w.pFd = pWal->pWalFd;
+ w.iSyncPoint = 0;
+ w.syncFlags = sync_flags;
+ w.szPage = szPage;
+ iOffset = walFrameOffset(iFrame+1, szPage);
+ szFrame = szPage + WAL_FRAME_HDRSIZE;
+
+ /* Write all frames into the log file exactly once */
+ for(p=pList; p; p=p->pDirty){
+ int nDbSize; /* 0 normally. Positive == commit flag */
+ iFrame++;
+ assert( iOffset==walFrameOffset(iFrame, szPage) );
+ nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
+ rc = walWriteOneFrame(&w, p, nDbSize, iOffset);
+ if( rc ) return rc;
+ pLast = p;
+ iOffset += szFrame;
+ }
+
+ /* If this is the end of a transaction, then we might need to pad
+ ** the transaction and/or sync the WAL file.
+ **
+ ** Padding and syncing only occur if this set of frames complete a
+ ** transaction and if PRAGMA synchronous=FULL. If synchronous==NORMAL
+ ** or synchonous==OFF, then no padding or syncing are needed.
+ **
+ ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not
+ ** needed and only the sync is done. If padding is needed, then the
+ ** final frame is repeated (with its commit mark) until the next sector
+ ** boundary is crossed. Only the part of the WAL prior to the last
+ ** sector boundary is synced; the part of the last frame that extends
+ ** past the sector boundary is written after the sync.
+ */
+ if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
+ if( pWal->padToSectorBoundary ){
+ int sectorSize = sqlite3SectorSize(pWal->pWalFd);
+ w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
+ while( iOffset<w.iSyncPoint ){
+ rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset);
+ if( rc ) return rc;
+ iOffset += szFrame;
+ nExtra++;
+ }
+ }else{
+ rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
+ }
+ }
+
+ /* If this frame set completes the first transaction in the WAL and
+ ** if PRAGMA journal_size_limit is set, then truncate the WAL to the
+ ** journal size limit, if possible.
+ */
+ if( isCommit && pWal->truncateOnCommit && pWal->mxWalSize>=0 ){
+ i64 sz = pWal->mxWalSize;
+ if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){
+ sz = walFrameOffset(iFrame+nExtra+1, szPage);
+ }
+ walLimitSize(pWal, sz);
+ pWal->truncateOnCommit = 0;
+ }
+
+ /* Append data to the wal-index. It is not necessary to lock the
+ ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index
+ ** guarantees that there are no other writers, and no data that may
+ ** be in use by existing readers is being overwritten.
+ */
+ iFrame = pWal->hdr.mxFrame;
+ for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
+ iFrame++;
+ rc = walIndexAppend(pWal, iFrame, p->pgno);
+ }
+ while( rc==SQLITE_OK && nExtra>0 ){
+ iFrame++;
+ nExtra--;
+ rc = walIndexAppend(pWal, iFrame, pLast->pgno);
+ }
+
+ if( rc==SQLITE_OK ){
+ /* Update the private copy of the header. */
+ pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
+ testcase( szPage<=32768 );
+ testcase( szPage>=65536 );
+ pWal->hdr.mxFrame = iFrame;
+ if( isCommit ){
+ pWal->hdr.iChange++;
+ pWal->hdr.nPage = nTruncate;
+ }
+ /* If this is a commit, update the wal-index header too. */
+ if( isCommit ){
+ walIndexWriteHdr(pWal);
+ pWal->iCallback = iFrame;
+ }
+ }
+
+ WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok"));
+ return rc;
+}
+
+/*
+** This routine is called to implement sqlite3_wal_checkpoint() and
+** related interfaces.
+**
+** Obtain a CHECKPOINT lock and then backfill as much information as
+** we can from WAL into the database.
+**
+** If parameter xBusy is not NULL, it is a pointer to a busy-handler
+** callback. In this case this function runs a blocking checkpoint.
+*/
+SQLITE_PRIVATE int sqlite3WalCheckpoint(
+ Wal *pWal, /* Wal connection */
+ int eMode, /* PASSIVE, FULL or RESTART */
+ int (*xBusy)(void*), /* Function to call when busy */
+ void *pBusyArg, /* Context argument for xBusyHandler */
+ int sync_flags, /* Flags to sync db file with (or 0) */
+ int nBuf, /* Size of temporary buffer */
+ u8 *zBuf, /* Temporary buffer to use */
+ int *pnLog, /* OUT: Number of frames in WAL */
+ int *pnCkpt /* OUT: Number of backfilled frames in WAL */
+){
+ int rc; /* Return code */
+ int isChanged = 0; /* True if a new wal-index header is loaded */
+ int eMode2 = eMode; /* Mode to pass to walCheckpoint() */
+
+ assert( pWal->ckptLock==0 );
+ assert( pWal->writeLock==0 );
+
+ if( pWal->readOnly ) return SQLITE_READONLY;
+ WALTRACE(("WAL%p: checkpoint begins\n", pWal));
+ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ if( rc ){
+ /* Usually this is SQLITE_BUSY meaning that another thread or process
+ ** is already running a checkpoint, or maybe a recovery. But it might
+ ** also be SQLITE_IOERR. */
+ return rc;
+ }
+ pWal->ckptLock = 1;
+
+ /* If this is a blocking-checkpoint, then obtain the write-lock as well
+ ** to prevent any writers from running while the checkpoint is underway.
+ ** This has to be done before the call to walIndexReadHdr() below.
+ **
+ ** If the writer lock cannot be obtained, then a passive checkpoint is
+ ** run instead. Since the checkpointer is not holding the writer lock,
+ ** there is no point in blocking waiting for any readers. Assuming no
+ ** other error occurs, this function will return SQLITE_BUSY to the caller.
+ */
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
+ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
+ if( rc==SQLITE_OK ){
+ pWal->writeLock = 1;
+ }else if( rc==SQLITE_BUSY ){
+ eMode2 = SQLITE_CHECKPOINT_PASSIVE;
+ rc = SQLITE_OK;
+ }
+ }
+
+ /* Read the wal-index header. */
+ if( rc==SQLITE_OK ){
+ rc = walIndexReadHdr(pWal, &isChanged);
+ }
+
+ /* Copy data from the log to the database file. */
+ if( rc==SQLITE_OK ){
+ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
+ }
+
+ /* If no error occurred, set the output variables. */
+ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
+ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
+ if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
+ }
+ }
+
+ if( isChanged ){
+ /* If a new wal-index header was loaded before the checkpoint was
+ ** performed, then the pager-cache associated with pWal is now
+ ** out of date. So zero the cached wal-index header to ensure that
+ ** next time the pager opens a snapshot on this database it knows that
+ ** the cache needs to be reset.
+ */
+ memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
+ }
+
+ /* Release the locks. */
+ sqlite3WalEndWriteTransaction(pWal);
+ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ pWal->ckptLock = 0;
+ WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
+ return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
+}
+
+/* Return the value to pass to a sqlite3_wal_hook callback, the
+** number of frames in the WAL at the point of the last commit since
+** sqlite3WalCallback() was called. If no commits have occurred since
+** the last call, then return 0.
+*/
+SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal){
+ u32 ret = 0;
+ if( pWal ){
+ ret = pWal->iCallback;
+ pWal->iCallback = 0;
+ }
+ return (int)ret;
+}
+
+/*
+** This function is called to change the WAL subsystem into or out
+** of locking_mode=EXCLUSIVE.
+**
+** If op is zero, then attempt to change from locking_mode=EXCLUSIVE
+** into locking_mode=NORMAL. This means that we must acquire a lock
+** on the pWal->readLock byte. If the WAL is already in locking_mode=NORMAL
+** or if the acquisition of the lock fails, then return 0. If the
+** transition out of exclusive-mode is successful, return 1. This
+** operation must occur while the pager is still holding the exclusive
+** lock on the main database file.
+**
+** If op is one, then change from locking_mode=NORMAL into
+** locking_mode=EXCLUSIVE. This means that the pWal->readLock must
+** be released. Return 1 if the transition is made and 0 if the
+** WAL is already in exclusive-locking mode - meaning that this
+** routine is a no-op. The pager must already hold the exclusive lock
+** on the main database file before invoking this operation.
+**
+** If op is negative, then do a dry-run of the op==1 case but do
+** not actually change anything. The pager uses this to see if it
+** should acquire the database exclusive lock prior to invoking
+** the op==1 case.
+*/
+SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
+ int rc;
+ assert( pWal->writeLock==0 );
+ assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
+
+ /* pWal->readLock is usually set, but might be -1 if there was a
+ ** prior error while attempting to acquire are read-lock. This cannot
+ ** happen if the connection is actually in exclusive mode (as no xShmLock
+ ** locks are taken in this case). Nor should the pager attempt to
+ ** upgrade to exclusive-mode following such an error.
+ */
+ assert( pWal->readLock>=0 || pWal->lockError );
+ assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
+
+ if( op==0 ){
+ if( pWal->exclusiveMode ){
+ pWal->exclusiveMode = 0;
+ if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){
+ pWal->exclusiveMode = 1;
+ }
+ rc = pWal->exclusiveMode==0;
+ }else{
+ /* Already in locking_mode=NORMAL */
+ rc = 0;
+ }
+ }else if( op>0 ){
+ assert( pWal->exclusiveMode==0 );
+ assert( pWal->readLock>=0 );
+ walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
+ pWal->exclusiveMode = 1;
+ rc = 1;
+ }else{
+ rc = pWal->exclusiveMode==0;
+ }
+ return rc;
+}
+
+/*
+** Return true if the argument is non-NULL and the WAL module is using
+** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
+** WAL module is using shared-memory, return false.
+*/
+SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
+ return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
+}
+
+#ifdef SQLITE_ENABLE_ZIPVFS
+/*
+** If the argument is not NULL, it points to a Wal object that holds a
+** read-lock. This function returns the database page-size if it is known,
+** or zero if it is not (or if pWal is NULL).
+*/
+SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
+ assert( pWal==0 || pWal->readLock>=0 );
+ return (pWal ? pWal->szPage : 0);
+}
+#endif
+
+#endif /* #ifndef SQLITE_OMIT_WAL */
+
+/************** End of wal.c *************************************************/
+/************** Begin file btmutex.c *****************************************/
+/*
+** 2007 August 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code used to implement mutexes on Btree objects.
+** This code really belongs in btree.c. But btree.c is getting too
+** big and we want to break it down some. This packaged seemed like
+** a good breakout.
+*/
+/************** Include btreeInt.h in the middle of btmutex.c ****************/
+/************** Begin file btreeInt.h ****************************************/
+/*
+** 2004 April 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements a external (disk-based) database using BTrees.
+** For a detailed discussion of BTrees, refer to
+**
+** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
+** "Sorting And Searching", pages 473-480. Addison-Wesley
+** Publishing Company, Reading, Massachusetts.
+**
+** The basic idea is that each page of the file contains N database
+** entries and N+1 pointers to subpages.
+**
+** ----------------------------------------------------------------
+** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) |
+** ----------------------------------------------------------------
+**
+** All of the keys on the page that Ptr(0) points to have values less
+** than Key(0). All of the keys on page Ptr(1) and its subpages have
+** values greater than Key(0) and less than Key(1). All of the keys
+** on Ptr(N) and its subpages have values greater than Key(N-1). And
+** so forth.
+**
+** Finding a particular key requires reading O(log(M)) pages from the
+** disk where M is the number of entries in the tree.
+**
+** In this implementation, a single file can hold one or more separate
+** BTrees. Each BTree is identified by the index of its root page. The
+** key and data for any entry are combined to form the "payload". A
+** fixed amount of payload can be carried directly on the database
+** page. If the payload is larger than the preset amount then surplus
+** bytes are stored on overflow pages. The payload for an entry
+** and the preceding pointer are combined to form a "Cell". Each
+** page has a small header which contains the Ptr(N) pointer and other
+** information such as the size of key and data.
+**
+** FORMAT DETAILS
+**
+** The file is divided into pages. The first page is called page 1,
+** the second is page 2, and so forth. A page number of zero indicates
+** "no such page". The page size can be any power of 2 between 512 and 65536.
+** Each page can be either a btree page, a freelist page, an overflow
+** page, or a pointer-map page.
+**
+** The first page is always a btree page. The first 100 bytes of the first
+** page contain a special header (the "file header") that describes the file.
+** The format of the file header is as follows:
+**
+** OFFSET SIZE DESCRIPTION
+** 0 16 Header string: "SQLite format 3\000"
+** 16 2 Page size in bytes.
+** 18 1 File format write version
+** 19 1 File format read version
+** 20 1 Bytes of unused space at the end of each page
+** 21 1 Max embedded payload fraction
+** 22 1 Min embedded payload fraction
+** 23 1 Min leaf payload fraction
+** 24 4 File change counter
+** 28 4 Reserved for future use
+** 32 4 First freelist page
+** 36 4 Number of freelist pages in the file
+** 40 60 15 4-byte meta values passed to higher layers
+**
+** 40 4 Schema cookie
+** 44 4 File format of schema layer
+** 48 4 Size of page cache
+** 52 4 Largest root-page (auto/incr_vacuum)
+** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
+** 60 4 User version
+** 64 4 Incremental vacuum mode
+** 68 4 unused
+** 72 4 unused
+** 76 4 unused
+**
+** All of the integer values are big-endian (most significant byte first).
+**
+** The file change counter is incremented when the database is changed
+** This counter allows other processes to know when the file has changed
+** and thus when they need to flush their cache.
+**
+** The max embedded payload fraction is the amount of the total usable
+** space in a page that can be consumed by a single cell for standard
+** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default
+** is to limit the maximum cell size so that at least 4 cells will fit
+** on one page. Thus the default max embedded payload fraction is 64.
+**
+** If the payload for a cell is larger than the max payload, then extra
+** payload is spilled to overflow pages. Once an overflow page is allocated,
+** as many bytes as possible are moved into the overflow pages without letting
+** the cell size drop below the min embedded payload fraction.
+**
+** The min leaf payload fraction is like the min embedded payload fraction
+** except that it applies to leaf nodes in a LEAFDATA tree. The maximum
+** payload fraction for a LEAFDATA tree is always 100% (or 255) and it
+** not specified in the header.
+**
+** Each btree pages is divided into three sections: The header, the
+** cell pointer array, and the cell content area. Page 1 also has a 100-byte
+** file header that occurs before the page header.
+**
+** |----------------|
+** | file header | 100 bytes. Page 1 only.
+** |----------------|
+** | page header | 8 bytes for leaves. 12 bytes for interior nodes
+** |----------------|
+** | cell pointer | | 2 bytes per cell. Sorted order.
+** | array | | Grows downward
+** | | v
+** |----------------|
+** | unallocated |
+** | space |
+** |----------------| ^ Grows upwards
+** | cell content | | Arbitrary order interspersed with freeblocks.
+** | area | | and free space fragments.
+** |----------------|
+**
+** The page headers looks like this:
+**
+** OFFSET SIZE DESCRIPTION
+** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf
+** 1 2 byte offset to the first freeblock
+** 3 2 number of cells on this page
+** 5 2 first byte of the cell content area
+** 7 1 number of fragmented free bytes
+** 8 4 Right child (the Ptr(N) value). Omitted on leaves.
+**
+** The flags define the format of this btree page. The leaf flag means that
+** this page has no children. The zerodata flag means that this page carries
+** only keys and no data. The intkey flag means that the key is a integer
+** which is stored in the key size entry of the cell header rather than in
+** the payload area.
+**
+** The cell pointer array begins on the first byte after the page header.
+** The cell pointer array contains zero or more 2-byte numbers which are
+** offsets from the beginning of the page to the cell content in the cell
+** content area. The cell pointers occur in sorted order. The system strives
+** to keep free space after the last cell pointer so that new cells can
+** be easily added without having to defragment the page.
+**
+** Cell content is stored at the very end of the page and grows toward the
+** beginning of the page.
+**
+** Unused space within the cell content area is collected into a linked list of
+** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset
+** to the first freeblock is given in the header. Freeblocks occur in
+** increasing order. Because a freeblock must be at least 4 bytes in size,
+** any group of 3 or fewer unused bytes in the cell content area cannot
+** exist on the freeblock chain. A group of 3 or fewer free bytes is called
+** a fragment. The total number of bytes in all fragments is recorded.
+** in the page header at offset 7.
+**
+** SIZE DESCRIPTION
+** 2 Byte offset of the next freeblock
+** 2 Bytes in this freeblock
+**
+** Cells are of variable length. Cells are stored in the cell content area at
+** the end of the page. Pointers to the cells are in the cell pointer array
+** that immediately follows the page header. Cells is not necessarily
+** contiguous or in order, but cell pointers are contiguous and in order.
+**
+** Cell content makes use of variable length integers. A variable
+** length integer is 1 to 9 bytes where the lower 7 bits of each
+** byte are used. The integer consists of all bytes that have bit 8 set and
+** the first byte with bit 8 clear. The most significant byte of the integer
+** appears first. A variable-length integer may not be more than 9 bytes long.
+** As a special case, all 8 bytes of the 9th byte are used as data. This
+** allows a 64-bit integer to be encoded in 9 bytes.
+**
+** 0x00 becomes 0x00000000
+** 0x7f becomes 0x0000007f
+** 0x81 0x00 becomes 0x00000080
+** 0x82 0x00 becomes 0x00000100
+** 0x80 0x7f becomes 0x0000007f
+** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678
+** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081
+**
+** Variable length integers are used for rowids and to hold the number of
+** bytes of key and data in a btree cell.
+**
+** The content of a cell looks like this:
+**
+** SIZE DESCRIPTION
+** 4 Page number of the left child. Omitted if leaf flag is set.
+** var Number of bytes of data. Omitted if the zerodata flag is set.
+** var Number of bytes of key. Or the key itself if intkey flag is set.
+** * Payload
+** 4 First page of the overflow chain. Omitted if no overflow
+**
+** Overflow pages form a linked list. Each page except the last is completely
+** filled with data (pagesize - 4 bytes). The last page can have as little
+** as 1 byte of data.
+**
+** SIZE DESCRIPTION
+** 4 Page number of next overflow page
+** * Data
+**
+** Freelist pages come in two subtypes: trunk pages and leaf pages. The
+** file header points to the first in a linked list of trunk page. Each trunk
+** page points to multiple leaf pages. The content of a leaf page is
+** unspecified. A trunk page looks like this:
+**
+** SIZE DESCRIPTION
+** 4 Page number of next trunk page
+** 4 Number of leaf pointers on this page
+** * zero or more pages numbers of leaves
+*/
+
+
+/* The following value is the maximum cell size assuming a maximum page
+** size give above.
+*/
+#define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8))
+
+/* The maximum number of cells on a single page of the database. This
+** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself
+** plus 2 bytes for the index to the cell in the page header). Such
+** small cells will be rare, but they are possible.
+*/
+#define MX_CELL(pBt) ((pBt->pageSize-8)/6)
+
+/* Forward declarations */
+typedef struct MemPage MemPage;
+typedef struct BtLock BtLock;
+
+/*
+** This is a magic string that appears at the beginning of every
+** SQLite database in order to identify the file as a real database.
+**
+** You can change this value at compile-time by specifying a
+** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
+** header must be exactly 16 bytes including the zero-terminator so
+** the string itself should be 15 characters long. If you change
+** the header, then your custom library will not be able to read
+** databases generated by the standard tools and the standard tools
+** will not be able to read databases created by your custom library.
+*/
+#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
+# define SQLITE_FILE_HEADER "SQLite format 3"
+#endif
+
+/*
+** Page type flags. An ORed combination of these flags appear as the
+** first byte of on-disk image of every BTree page.
+*/
+#define PTF_INTKEY 0x01
+#define PTF_ZERODATA 0x02
+#define PTF_LEAFDATA 0x04
+#define PTF_LEAF 0x08
+
+/*
+** As each page of the file is loaded into memory, an instance of the following
+** structure is appended and initialized to zero. This structure stores
+** information about the page that is decoded from the raw file page.
+**
+** The pParent field points back to the parent page. This allows us to
+** walk up the BTree from any leaf to the root. Care must be taken to
+** unref() the parent page pointer when this page is no longer referenced.
+** The pageDestructor() routine handles that chore.
+**
+** Access to all fields of this structure is controlled by the mutex
+** stored in MemPage.pBt->mutex.
+*/
+struct MemPage {
+ u8 isInit; /* True if previously initialized. MUST BE FIRST! */
+ u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
+ u8 intKey; /* True if intkey flag is set */
+ u8 leaf; /* True if leaf flag is set */
+ u8 hasData; /* True if this page stores data */
+ u8 hdrOffset; /* 100 for page 1. 0 otherwise */
+ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
+ u8 max1bytePayload; /* min(maxLocal,127) */
+ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
+ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
+ u16 cellOffset; /* Index in aData of first cell pointer */
+ u16 nFree; /* Number of free bytes on the page */
+ u16 nCell; /* Number of cells on this page, local and ovfl */
+ u16 maskPage; /* Mask for page offset */
+ u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th
+ ** non-overflow cell */
+ u8 *apOvfl[5]; /* Pointers to the body of overflow cells */
+ BtShared *pBt; /* Pointer to BtShared that this page is part of */
+ u8 *aData; /* Pointer to disk image of the page data */
+ u8 *aDataEnd; /* One byte past the end of usable data */
+ u8 *aCellIdx; /* The cell index area */
+ DbPage *pDbPage; /* Pager page handle */
+ Pgno pgno; /* Page number for this page */
+};
+
+/*
+** The in-memory image of a disk page has the auxiliary information appended
+** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
+** that extra information.
+*/
+#define EXTRA_SIZE sizeof(MemPage)
+
+/*
+** A linked list of the following structures is stored at BtShared.pLock.
+** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
+** is opened on the table with root page BtShared.iTable. Locks are removed
+** from this list when a transaction is committed or rolled back, or when
+** a btree handle is closed.
+*/
+struct BtLock {
+ Btree *pBtree; /* Btree handle holding this lock */
+ Pgno iTable; /* Root page of table */
+ u8 eLock; /* READ_LOCK or WRITE_LOCK */
+ BtLock *pNext; /* Next in BtShared.pLock list */
+};
+
+/* Candidate values for BtLock.eLock */
+#define READ_LOCK 1
+#define WRITE_LOCK 2
+
+/* A Btree handle
+**
+** A database connection contains a pointer to an instance of
+** this object for every database file that it has open. This structure
+** is opaque to the database connection. The database connection cannot
+** see the internals of this structure and only deals with pointers to
+** this structure.
+**
+** For some database files, the same underlying database cache might be
+** shared between multiple connections. In that case, each connection
+** has it own instance of this object. But each instance of this object
+** points to the same BtShared object. The database cache and the
+** schema associated with the database file are all contained within
+** the BtShared object.
+**
+** All fields in this structure are accessed under sqlite3.mutex.
+** The pBt pointer itself may not be changed while there exists cursors
+** in the referenced BtShared that point back to this Btree since those
+** cursors have to go through this Btree to find their BtShared and
+** they often do so without holding sqlite3.mutex.
+*/
+struct Btree {
+ sqlite3 *db; /* The database connection holding this btree */
+ BtShared *pBt; /* Sharable content of this btree */
+ u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
+ u8 sharable; /* True if we can share pBt with another db */
+ u8 locked; /* True if db currently has pBt locked */
+ int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
+ int nBackup; /* Number of backup operations reading this btree */
+ Btree *pNext; /* List of other sharable Btrees from the same db */
+ Btree *pPrev; /* Back pointer of the same list */
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ BtLock lock; /* Object used to lock page 1 */
+#endif
+};
+
+/*
+** Btree.inTrans may take one of the following values.
+**
+** If the shared-data extension is enabled, there may be multiple users
+** of the Btree structure. At most one of these may open a write transaction,
+** but any number may have active read transactions.
+*/
+#define TRANS_NONE 0
+#define TRANS_READ 1
+#define TRANS_WRITE 2
+
+/*
+** An instance of this object represents a single database file.
+**
+** A single database file can be in use at the same time by two
+** or more database connections. When two or more connections are
+** sharing the same database file, each connection has it own
+** private Btree object for the file and each of those Btrees points
+** to this one BtShared object. BtShared.nRef is the number of
+** connections currently sharing this database file.
+**
+** Fields in this structure are accessed under the BtShared.mutex
+** mutex, except for nRef and pNext which are accessed under the
+** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field
+** may not be modified once it is initially set as long as nRef>0.
+** The pSchema field may be set once under BtShared.mutex and
+** thereafter is unchanged as long as nRef>0.
+**
+** isPending:
+**
+** If a BtShared client fails to obtain a write-lock on a database
+** table (because there exists one or more read-locks on the table),
+** the shared-cache enters 'pending-lock' state and isPending is
+** set to true.
+**
+** The shared-cache leaves the 'pending lock' state when either of
+** the following occur:
+**
+** 1) The current writer (BtShared.pWriter) concludes its transaction, OR
+** 2) The number of locks held by other connections drops to zero.
+**
+** while in the 'pending-lock' state, no connection may start a new
+** transaction.
+**
+** This feature is included to help prevent writer-starvation.
+*/
+struct BtShared {
+ Pager *pPager; /* The page cache */
+ sqlite3 *db; /* Database connection currently using this Btree */
+ BtCursor *pCursor; /* A list of all open cursors */
+ MemPage *pPage1; /* First page of the database */
+ u8 openFlags; /* Flags to sqlite3BtreeOpen() */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ u8 autoVacuum; /* True if auto-vacuum is enabled */
+ u8 incrVacuum; /* True if incr-vacuum is enabled */
+ u8 bDoTruncate; /* True to truncate db on commit */
+#endif
+ u8 inTransaction; /* Transaction state */
+ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
+ u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
+ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
+ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
+ u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
+ u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
+ u32 pageSize; /* Total number of bytes on a page */
+ u32 usableSize; /* Number of usable bytes on each page */
+ int nTransaction; /* Number of open transactions (read + write) */
+ u32 nPage; /* Number of pages in the database */
+ void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
+ void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
+ sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */
+ Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ int nRef; /* Number of references to this structure */
+ BtShared *pNext; /* Next on a list of sharable BtShared structs */
+ BtLock *pLock; /* List of locks held on this shared-btree struct */
+ Btree *pWriter; /* Btree with currently open write transaction */
+#endif
+ u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */
+};
+
+/*
+** Allowed values for BtShared.btsFlags
+*/
+#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
+#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
+#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
+#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */
+#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */
+#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */
+#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */
+
+/*
+** An instance of the following structure is used to hold information
+** about a cell. The parseCellPtr() function fills in this structure
+** based on information extract from the raw disk page.
+*/
+typedef struct CellInfo CellInfo;
+struct CellInfo {
+ i64 nKey; /* The key for INTKEY tables, or number of bytes in key */
+ u8 *pCell; /* Pointer to the start of cell content */
+ u32 nData; /* Number of bytes of data */
+ u32 nPayload; /* Total amount of payload */
+ u16 nHeader; /* Size of the cell content header in bytes */
+ u16 nLocal; /* Amount of payload held locally */
+ u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
+ u16 nSize; /* Size of the cell content on the main b-tree page */
+};
+
+/*
+** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
+** this will be declared corrupt. This value is calculated based on a
+** maximum database size of 2^31 pages a minimum fanout of 2 for a
+** root-node and 3 for all other internal nodes.
+**
+** If a tree that appears to be taller than this is encountered, it is
+** assumed that the database is corrupt.
+*/
+#define BTCURSOR_MAX_DEPTH 20
+
+/*
+** A cursor is a pointer to a particular entry within a particular
+** b-tree within a database file.
+**
+** The entry is identified by its MemPage and the index in
+** MemPage.aCell[] of the entry.
+**
+** A single database file can be shared by two more database connections,
+** but cursors cannot be shared. Each cursor is associated with a
+** particular database connection identified BtCursor.pBtree.db.
+**
+** Fields in this structure are accessed under the BtShared.mutex
+** found at self->pBt->mutex.
+*/
+struct BtCursor {
+ Btree *pBtree; /* The Btree to which this cursor belongs */
+ BtShared *pBt; /* The BtShared this cursor points to */
+ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
+ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
+#ifndef SQLITE_OMIT_INCRBLOB
+ Pgno *aOverflow; /* Cache of overflow page locations */
+#endif
+ Pgno pgnoRoot; /* The root page of this tree */
+ sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */
+ CellInfo info; /* A parse of the cell we are pointing at */
+ i64 nKey; /* Size of pKey, or last integer key */
+ void *pKey; /* Saved key that was cursor's last known position */
+ int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
+ u8 wrFlag; /* True if writable */
+ u8 atLast; /* Cursor pointing to the last entry */
+ u8 validNKey; /* True if info.nKey is valid */
+ u8 eState; /* One of the CURSOR_XXX constants (see below) */
+#ifndef SQLITE_OMIT_INCRBLOB
+ u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
+#endif
+ u8 hints; /* As configured by CursorSetHints() */
+ i16 iPage; /* Index of current page in apPage */
+ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
+ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
+};
+
+/*
+** Potential values for BtCursor.eState.
+**
+** CURSOR_VALID:
+** Cursor points to a valid entry. getPayload() etc. may be called.
+**
+** CURSOR_INVALID:
+** Cursor does not point to a valid entry. This can happen (for example)
+** because the table is empty or because BtreeCursorFirst() has not been
+** called.
+**
+** CURSOR_REQUIRESEEK:
+** The table that this cursor was opened on still exists, but has been
+** modified since the cursor was last used. The cursor position is saved
+** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
+** this state, restoreCursorPosition() can be called to attempt to
+** seek the cursor to the saved position.
+**
+** CURSOR_FAULT:
+** A unrecoverable error (an I/O error or a malloc failure) has occurred
+** on a different connection that shares the BtShared cache with this
+** cursor. The error has left the cache in an inconsistent state.
+** Do nothing else with this cursor. Any attempt to use the cursor
+** should return the error code stored in BtCursor.skip
+*/
+#define CURSOR_INVALID 0
+#define CURSOR_VALID 1
+#define CURSOR_REQUIRESEEK 2
+#define CURSOR_FAULT 3
+
+/*
+** The database page the PENDING_BYTE occupies. This page is never used.
+*/
+# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
+
+/*
+** These macros define the location of the pointer-map entry for a
+** database page. The first argument to each is the number of usable
+** bytes on each page of the database (often 1024). The second is the
+** page number to look up in the pointer map.
+**
+** PTRMAP_PAGENO returns the database page number of the pointer-map
+** page that stores the required pointer. PTRMAP_PTROFFSET returns
+** the offset of the requested map entry.
+**
+** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
+** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
+** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
+** this test.
+*/
+#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
+#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1))
+#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
+
+/*
+** The pointer map is a lookup table that identifies the parent page for
+** each child page in the database file. The parent page is the page that
+** contains a pointer to the child. Every page in the database contains
+** 0 or 1 parent pages. (In this context 'database page' refers
+** to any page that is not part of the pointer map itself.) Each pointer map
+** entry consists of a single byte 'type' and a 4 byte parent page number.
+** The PTRMAP_XXX identifiers below are the valid types.
+**
+** The purpose of the pointer map is to facility moving pages from one
+** position in the file to another as part of autovacuum. When a page
+** is moved, the pointer in its parent must be updated to point to the
+** new location. The pointer map is used to locate the parent page quickly.
+**
+** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
+** used in this case.
+**
+** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
+** is not used in this case.
+**
+** PTRMAP_OVERFLOW1: The database page is the first page in a list of
+** overflow pages. The page number identifies the page that
+** contains the cell with a pointer to this overflow page.
+**
+** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
+** overflow pages. The page-number identifies the previous
+** page in the overflow page list.
+**
+** PTRMAP_BTREE: The database page is a non-root btree page. The page number
+** identifies the parent page in the btree.
+*/
+#define PTRMAP_ROOTPAGE 1
+#define PTRMAP_FREEPAGE 2
+#define PTRMAP_OVERFLOW1 3
+#define PTRMAP_OVERFLOW2 4
+#define PTRMAP_BTREE 5
+
+/* A bunch of assert() statements to check the transaction state variables
+** of handle p (type Btree*) are internally consistent.
+*/
+#define btreeIntegrity(p) \
+ assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
+ assert( p->pBt->inTransaction>=p->inTrans );
+
+
+/*
+** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
+** if the database supports auto-vacuum or not. Because it is used
+** within an expression that is an argument to another macro
+** (sqliteMallocRaw), it is not possible to use conditional compilation.
+** So, this macro is defined instead.
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define ISAUTOVACUUM (pBt->autoVacuum)
+#else
+#define ISAUTOVACUUM 0
+#endif
+
+
+/*
+** This structure is passed around through all the sanity checking routines
+** in order to keep track of some global state information.
+**
+** The aRef[] array is allocated so that there is 1 bit for each page in
+** the database. As the integrity-check proceeds, for each page used in
+** the database the corresponding bit is set. This allows integrity-check to
+** detect pages that are used twice and orphaned pages (both of which
+** indicate corruption).
+*/
+typedef struct IntegrityCk IntegrityCk;
+struct IntegrityCk {
+ BtShared *pBt; /* The tree being checked out */
+ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
+ u8 *aPgRef; /* 1 bit per page in the db (see above) */
+ Pgno nPage; /* Number of pages in the database */
+ int mxErr; /* Stop accumulating errors when this reaches zero */
+ int nErr; /* Number of messages written to zErrMsg so far */
+ int mallocFailed; /* A memory allocation error has occurred */
+ StrAccum errMsg; /* Accumulate the error message text here */
+};
+
+/*
+** Routines to read or write a two- and four-byte big-endian integer values.
+*/
+#define get2byte(x) ((x)[0]<<8 | (x)[1])
+#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v))
+#define get4byte sqlite3Get4byte
+#define put4byte sqlite3Put4byte
+
+/************** End of btreeInt.h ********************************************/
+/************** Continuing where we left off in btmutex.c ********************/
+#ifndef SQLITE_OMIT_SHARED_CACHE
+#if SQLITE_THREADSAFE
+
+/*
+** Obtain the BtShared mutex associated with B-Tree handle p. Also,
+** set BtShared.db to the database handle associated with p and the
+** p->locked boolean to true.
+*/
+static void lockBtreeMutex(Btree *p){
+ assert( p->locked==0 );
+ assert( sqlite3_mutex_notheld(p->pBt->mutex) );
+ assert( sqlite3_mutex_held(p->db->mutex) );
+
+ sqlite3_mutex_enter(p->pBt->mutex);
+ p->pBt->db = p->db;
+ p->locked = 1;
+}
+
+/*
+** Release the BtShared mutex associated with B-Tree handle p and
+** clear the p->locked boolean.
+*/
+static void unlockBtreeMutex(Btree *p){
+ BtShared *pBt = p->pBt;
+ assert( p->locked==1 );
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ assert( p->db==pBt->db );
+
+ sqlite3_mutex_leave(pBt->mutex);
+ p->locked = 0;
+}
+
+/*
+** Enter a mutex on the given BTree object.
+**
+** If the object is not sharable, then no mutex is ever required
+** and this routine is a no-op. The underlying mutex is non-recursive.
+** But we keep a reference count in Btree.wantToLock so the behavior
+** of this interface is recursive.
+**
+** To avoid deadlocks, multiple Btrees are locked in the same order
+** by all database connections. The p->pNext is a list of other
+** Btrees belonging to the same database connection as the p Btree
+** which need to be locked after p. If we cannot get a lock on
+** p, then first unlock all of the others on p->pNext, then wait
+** for the lock to become available on p, then relock all of the
+** subsequent Btrees that desire a lock.
+*/
+SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){
+ Btree *pLater;
+
+ /* Some basic sanity checking on the Btree. The list of Btrees
+ ** connected by pNext and pPrev should be in sorted order by
+ ** Btree.pBt value. All elements of the list should belong to
+ ** the same connection. Only shared Btrees are on the list. */
+ assert( p->pNext==0 || p->pNext->pBt>p->pBt );
+ assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
+ assert( p->pNext==0 || p->pNext->db==p->db );
+ assert( p->pPrev==0 || p->pPrev->db==p->db );
+ assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
+
+ /* Check for locking consistency */
+ assert( !p->locked || p->wantToLock>0 );
+ assert( p->sharable || p->wantToLock==0 );
+
+ /* We should already hold a lock on the database connection */
+ assert( sqlite3_mutex_held(p->db->mutex) );
+
+ /* Unless the database is sharable and unlocked, then BtShared.db
+ ** should already be set correctly. */
+ assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db );
+
+ if( !p->sharable ) return;
+ p->wantToLock++;
+ if( p->locked ) return;
+
+ /* In most cases, we should be able to acquire the lock we
+ ** want without having to go throught the ascending lock
+ ** procedure that follows. Just be sure not to block.
+ */
+ if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
+ p->pBt->db = p->db;
+ p->locked = 1;
+ return;
+ }
+
+ /* To avoid deadlock, first release all locks with a larger
+ ** BtShared address. Then acquire our lock. Then reacquire
+ ** the other BtShared locks that we used to hold in ascending
+ ** order.
+ */
+ for(pLater=p->pNext; pLater; pLater=pLater->pNext){
+ assert( pLater->sharable );
+ assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
+ assert( !pLater->locked || pLater->wantToLock>0 );
+ if( pLater->locked ){
+ unlockBtreeMutex(pLater);
+ }
+ }
+ lockBtreeMutex(p);
+ for(pLater=p->pNext; pLater; pLater=pLater->pNext){
+ if( pLater->wantToLock ){
+ lockBtreeMutex(pLater);
+ }
+ }
+}
+
+/*
+** Exit the recursive mutex on a Btree.
+*/
+SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){
+ if( p->sharable ){
+ assert( p->wantToLock>0 );
+ p->wantToLock--;
+ if( p->wantToLock==0 ){
+ unlockBtreeMutex(p);
+ }
+ }
+}
+
+#ifndef NDEBUG
+/*
+** Return true if the BtShared mutex is held on the btree, or if the
+** B-Tree is not marked as sharable.
+**
+** This routine is used only from within assert() statements.
+*/
+SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
+ assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 );
+ assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db );
+ assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) );
+ assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) );
+
+ return (p->sharable==0 || p->locked);
+}
+#endif
+
+
+#ifndef SQLITE_OMIT_INCRBLOB
+/*
+** Enter and leave a mutex on a Btree given a cursor owned by that
+** Btree. These entry points are used by incremental I/O and can be
+** omitted if that module is not used.
+*/
+SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
+ sqlite3BtreeEnter(pCur->pBtree);
+}
+SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
+ sqlite3BtreeLeave(pCur->pBtree);
+}
+#endif /* SQLITE_OMIT_INCRBLOB */
+
+
+/*
+** Enter the mutex on every Btree associated with a database
+** connection. This is needed (for example) prior to parsing
+** a statement since we will be comparing table and column names
+** against all schemas and we do not want those schemas being
+** reset out from under us.
+**
+** There is a corresponding leave-all procedures.
+**
+** Enter the mutexes in accending order by BtShared pointer address
+** to avoid the possibility of deadlock when two threads with
+** two or more btrees in common both try to lock all their btrees
+** at the same instant.
+*/
+SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
+ int i;
+ Btree *p;
+ assert( sqlite3_mutex_held(db->mutex) );
+ for(i=0; i<db->nDb; i++){
+ p = db->aDb[i].pBt;
+ if( p ) sqlite3BtreeEnter(p);
+ }
+}
+SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
+ int i;
+ Btree *p;
+ assert( sqlite3_mutex_held(db->mutex) );
+ for(i=0; i<db->nDb; i++){
+ p = db->aDb[i].pBt;
+ if( p ) sqlite3BtreeLeave(p);
+ }
+}
+
+/*
+** Return true if a particular Btree requires a lock. Return FALSE if
+** no lock is ever required since it is not sharable.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){
+ return p->sharable;
+}
+
+#ifndef NDEBUG
+/*
+** Return true if the current thread holds the database connection
+** mutex and all required BtShared mutexes.
+**
+** This routine is used inside assert() statements only.
+*/
+SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
+ int i;
+ if( !sqlite3_mutex_held(db->mutex) ){
+ return 0;
+ }
+ for(i=0; i<db->nDb; i++){
+ Btree *p;
+ p = db->aDb[i].pBt;
+ if( p && p->sharable &&
+ (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
+ return 0;
+ }
+ }
+ return 1;
+}
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/*
+** Return true if the correct mutexes are held for accessing the
+** db->aDb[iDb].pSchema structure. The mutexes required for schema
+** access are:
+**
+** (1) The mutex on db
+** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt.
+**
+** If pSchema is not NULL, then iDb is computed from pSchema and
+** db using sqlite3SchemaToIndex().
+*/
+SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
+ Btree *p;
+ assert( db!=0 );
+ if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
+ assert( iDb>=0 && iDb<db->nDb );
+ if( !sqlite3_mutex_held(db->mutex) ) return 0;
+ if( iDb==1 ) return 1;
+ p = db->aDb[iDb].pBt;
+ assert( p!=0 );
+ return p->sharable==0 || p->locked==1;
+}
+#endif /* NDEBUG */
+
+#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
+/*
+** The following are special cases for mutex enter routines for use
+** in single threaded applications that use shared cache. Except for
+** these two routines, all mutex operations are no-ops in that case and
+** are null #defines in btree.h.
+**
+** If shared cache is disabled, then all btree mutex routines, including
+** the ones below, are no-ops and are null #defines in btree.h.
+*/
+
+SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){
+ p->pBt->db = p->db;
+}
+SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
+ int i;
+ for(i=0; i<db->nDb; i++){
+ Btree *p = db->aDb[i].pBt;
+ if( p ){
+ p->pBt->db = p->db;
+ }
+ }
+}
+#endif /* if SQLITE_THREADSAFE */
+#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */
+
+/************** End of btmutex.c *********************************************/
+/************** Begin file btree.c *******************************************/
+/*
+** 2004 April 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements a external (disk-based) database using BTrees.
+** See the header comment on "btreeInt.h" for additional information.
+** Including a description of file format and an overview of operation.
+*/
+
+/*
+** The header string that appears at the beginning of every
+** SQLite database.
+*/
+static const char zMagicHeader[] = SQLITE_FILE_HEADER;
+
+/*
+** Set this global variable to 1 to enable tracing using the TRACE
+** macro.
+*/
+#if 0
+int sqlite3BtreeTrace=1; /* True to enable tracing */
+# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);}
+#else
+# define TRACE(X)
+#endif
+
+/*
+** Extract a 2-byte big-endian integer from an array of unsigned bytes.
+** But if the value is zero, make it 65536.
+**
+** This routine is used to extract the "offset to cell content area" value
+** from the header of a btree page. If the page size is 65536 and the page
+** is empty, the offset should be 65536, but the 2-byte value stores zero.
+** This routine makes the necessary adjustment to 65536.
+*/
+#define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1)
+
+/*
+** Values passed as the 5th argument to allocateBtreePage()
+*/
+#define BTALLOC_ANY 0 /* Allocate any page */
+#define BTALLOC_EXACT 1 /* Allocate exact page if possible */
+#define BTALLOC_LE 2 /* Allocate any page <= the parameter */
+
+/*
+** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
+** defined, or 0 if it is. For example:
+**
+** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum);
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define IfNotOmitAV(expr) (expr)
+#else
+#define IfNotOmitAV(expr) 0
+#endif
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/*
+** A list of BtShared objects that are eligible for participation
+** in shared cache. This variable has file scope during normal builds,
+** but the test harness needs to access it so we make it global for
+** test builds.
+**
+** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER.
+*/
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
+#else
+static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
+#endif
+#endif /* SQLITE_OMIT_SHARED_CACHE */
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/*
+** Enable or disable the shared pager and schema features.
+**
+** This routine has no effect on existing database connections.
+** The shared cache setting effects only future calls to
+** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
+*/
+SQLITE_API int sqlite3_enable_shared_cache(int enable){
+ sqlite3GlobalConfig.sharedCacheEnabled = enable;
+ return SQLITE_OK;
+}
+#endif
+
+
+
+#ifdef SQLITE_OMIT_SHARED_CACHE
+ /*
+ ** The functions querySharedCacheTableLock(), setSharedCacheTableLock(),
+ ** and clearAllSharedCacheTableLocks()
+ ** manipulate entries in the BtShared.pLock linked list used to store
+ ** shared-cache table level locks. If the library is compiled with the
+ ** shared-cache feature disabled, then there is only ever one user
+ ** of each BtShared structure and so this locking is not necessary.
+ ** So define the lock related functions as no-ops.
+ */
+ #define querySharedCacheTableLock(a,b,c) SQLITE_OK
+ #define setSharedCacheTableLock(a,b,c) SQLITE_OK
+ #define clearAllSharedCacheTableLocks(a)
+ #define downgradeAllSharedCacheTableLocks(a)
+ #define hasSharedCacheTableLock(a,b,c,d) 1
+ #define hasReadConflicts(a, b) 0
+#endif
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+
+#ifdef SQLITE_DEBUG
+/*
+**** This function is only used as part of an assert() statement. ***
+**
+** Check to see if pBtree holds the required locks to read or write to the
+** table with root page iRoot. Return 1 if it does and 0 if not.
+**
+** For example, when writing to a table with root-page iRoot via
+** Btree connection pBtree:
+**
+** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) );
+**
+** When writing to an index that resides in a sharable database, the
+** caller should have first obtained a lock specifying the root page of
+** the corresponding table. This makes things a bit more complicated,
+** as this module treats each table as a separate structure. To determine
+** the table corresponding to the index being written, this
+** function has to search through the database schema.
+**
+** Instead of a lock on the table/index rooted at page iRoot, the caller may
+** hold a write-lock on the schema table (root page 1). This is also
+** acceptable.
+*/
+static int hasSharedCacheTableLock(
+ Btree *pBtree, /* Handle that must hold lock */
+ Pgno iRoot, /* Root page of b-tree */
+ int isIndex, /* True if iRoot is the root of an index b-tree */
+ int eLockType /* Required lock type (READ_LOCK or WRITE_LOCK) */
+){
+ Schema *pSchema = (Schema *)pBtree->pBt->pSchema;
+ Pgno iTab = 0;
+ BtLock *pLock;
+
+ /* If this database is not shareable, or if the client is reading
+ ** and has the read-uncommitted flag set, then no lock is required.
+ ** Return true immediately.
+ */
+ if( (pBtree->sharable==0)
+ || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted))
+ ){
+ return 1;
+ }
+
+ /* If the client is reading or writing an index and the schema is
+ ** not loaded, then it is too difficult to actually check to see if
+ ** the correct locks are held. So do not bother - just return true.
+ ** This case does not come up very often anyhow.
+ */
+ if( isIndex && (!pSchema || (pSchema->flags&DB_SchemaLoaded)==0) ){
+ return 1;
+ }
+
+ /* Figure out the root-page that the lock should be held on. For table
+ ** b-trees, this is just the root page of the b-tree being read or
+ ** written. For index b-trees, it is the root page of the associated
+ ** table. */
+ if( isIndex ){
+ HashElem *p;
+ for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
+ Index *pIdx = (Index *)sqliteHashData(p);
+ if( pIdx->tnum==(int)iRoot ){
+ iTab = pIdx->pTable->tnum;
+ }
+ }
+ }else{
+ iTab = iRoot;
+ }
+
+ /* Search for the required lock. Either a write-lock on root-page iTab, a
+ ** write-lock on the schema table, or (if the client is reading) a
+ ** read-lock on iTab will suffice. Return 1 if any of these are found. */
+ for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){
+ if( pLock->pBtree==pBtree
+ && (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1))
+ && pLock->eLock>=eLockType
+ ){
+ return 1;
+ }
+ }
+
+ /* Failed to find the required lock. */
+ return 0;
+}
+#endif /* SQLITE_DEBUG */
+
+#ifdef SQLITE_DEBUG
+/*
+**** This function may be used as part of assert() statements only. ****
+**
+** Return true if it would be illegal for pBtree to write into the
+** table or index rooted at iRoot because other shared connections are
+** simultaneously reading that same table or index.
+**
+** It is illegal for pBtree to write if some other Btree object that
+** shares the same BtShared object is currently reading or writing
+** the iRoot table. Except, if the other Btree object has the
+** read-uncommitted flag set, then it is OK for the other object to
+** have a read cursor.
+**
+** For example, before writing to any part of the table or index
+** rooted at page iRoot, one should call:
+**
+** assert( !hasReadConflicts(pBtree, iRoot) );
+*/
+static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
+ BtCursor *p;
+ for(p=pBtree->pBt->pCursor; p; p=p->pNext){
+ if( p->pgnoRoot==iRoot
+ && p->pBtree!=pBtree
+ && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted)
+ ){
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif /* #ifdef SQLITE_DEBUG */
+
+/*
+** Query to see if Btree handle p may obtain a lock of type eLock
+** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
+** SQLITE_OK if the lock may be obtained (by calling
+** setSharedCacheTableLock()), or SQLITE_LOCKED if not.
+*/
+static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
+ BtShared *pBt = p->pBt;
+ BtLock *pIter;
+
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
+ assert( p->db!=0 );
+ assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 );
+
+ /* If requesting a write-lock, then the Btree must have an open write
+ ** transaction on this file. And, obviously, for this to be so there
+ ** must be an open write transaction on the file itself.
+ */
+ assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
+ assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
+
+ /* This routine is a no-op if the shared-cache is not enabled */
+ if( !p->sharable ){
+ return SQLITE_OK;
+ }
+
+ /* If some other connection is holding an exclusive lock, the
+ ** requested lock may not be obtained.
+ */
+ if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){
+ sqlite3ConnectionBlocked(p->db, pBt->pWriter->db);
+ return SQLITE_LOCKED_SHAREDCACHE;
+ }
+
+ for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
+ /* The condition (pIter->eLock!=eLock) in the following if(...)
+ ** statement is a simplification of:
+ **
+ ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
+ **
+ ** since we know that if eLock==WRITE_LOCK, then no other connection
+ ** may hold a WRITE_LOCK on any table in this file (since there can
+ ** only be a single writer).
+ */
+ assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK );
+ assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK);
+ if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
+ sqlite3ConnectionBlocked(p->db, pIter->pBtree->db);
+ if( eLock==WRITE_LOCK ){
+ assert( p==pBt->pWriter );
+ pBt->btsFlags |= BTS_PENDING;
+ }
+ return SQLITE_LOCKED_SHAREDCACHE;
+ }
+ }
+ return SQLITE_OK;
+}
+#endif /* !SQLITE_OMIT_SHARED_CACHE */
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/*
+** Add a lock on the table with root-page iTable to the shared-btree used
+** by Btree handle p. Parameter eLock must be either READ_LOCK or
+** WRITE_LOCK.
+**
+** This function assumes the following:
+**
+** (a) The specified Btree object p is connected to a sharable
+** database (one with the BtShared.sharable flag set), and
+**
+** (b) No other Btree objects hold a lock that conflicts
+** with the requested lock (i.e. querySharedCacheTableLock() has
+** already been called and returned SQLITE_OK).
+**
+** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
+** is returned if a malloc attempt fails.
+*/
+static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
+ BtShared *pBt = p->pBt;
+ BtLock *pLock = 0;
+ BtLock *pIter;
+
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
+ assert( p->db!=0 );
+
+ /* A connection with the read-uncommitted flag set will never try to
+ ** obtain a read-lock using this function. The only read-lock obtained
+ ** by a connection in read-uncommitted mode is on the sqlite_master
+ ** table, and that lock is obtained in BtreeBeginTrans(). */
+ assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK );
+
+ /* This function should only be called on a sharable b-tree after it
+ ** has been determined that no other b-tree holds a conflicting lock. */
+ assert( p->sharable );
+ assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) );
+
+ /* First search the list for an existing lock on this table. */
+ for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
+ if( pIter->iTable==iTable && pIter->pBtree==p ){
+ pLock = pIter;
+ break;
+ }
+ }
+
+ /* If the above search did not find a BtLock struct associating Btree p
+ ** with table iTable, allocate one and link it into the list.
+ */
+ if( !pLock ){
+ pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock));
+ if( !pLock ){
+ return SQLITE_NOMEM;
+ }
+ pLock->iTable = iTable;
+ pLock->pBtree = p;
+ pLock->pNext = pBt->pLock;
+ pBt->pLock = pLock;
+ }
+
+ /* Set the BtLock.eLock variable to the maximum of the current lock
+ ** and the requested lock. This means if a write-lock was already held
+ ** and a read-lock requested, we don't incorrectly downgrade the lock.
+ */
+ assert( WRITE_LOCK>READ_LOCK );
+ if( eLock>pLock->eLock ){
+ pLock->eLock = eLock;
+ }
+
+ return SQLITE_OK;
+}
+#endif /* !SQLITE_OMIT_SHARED_CACHE */
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/*
+** Release all the table locks (locks obtained via calls to
+** the setSharedCacheTableLock() procedure) held by Btree object p.
+**
+** This function assumes that Btree p has an open read or write
+** transaction. If it does not, then the BTS_PENDING flag
+** may be incorrectly cleared.
+*/
+static void clearAllSharedCacheTableLocks(Btree *p){
+ BtShared *pBt = p->pBt;
+ BtLock **ppIter = &pBt->pLock;
+
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( p->sharable || 0==*ppIter );
+ assert( p->inTrans>0 );
+
+ while( *ppIter ){
+ BtLock *pLock = *ppIter;
+ assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree );
+ assert( pLock->pBtree->inTrans>=pLock->eLock );
+ if( pLock->pBtree==p ){
+ *ppIter = pLock->pNext;
+ assert( pLock->iTable!=1 || pLock==&p->lock );
+ if( pLock->iTable!=1 ){
+ sqlite3_free(pLock);
+ }
+ }else{
+ ppIter = &pLock->pNext;
+ }
+ }
+
+ assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter );
+ if( pBt->pWriter==p ){
+ pBt->pWriter = 0;
+ pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
+ }else if( pBt->nTransaction==2 ){
+ /* This function is called when Btree p is concluding its
+ ** transaction. If there currently exists a writer, and p is not
+ ** that writer, then the number of locks held by connections other
+ ** than the writer must be about to drop to zero. In this case
+ ** set the BTS_PENDING flag to 0.
+ **
+ ** If there is not currently a writer, then BTS_PENDING must
+ ** be zero already. So this next line is harmless in that case.
+ */
+ pBt->btsFlags &= ~BTS_PENDING;
+ }
+}
+
+/*
+** This function changes all write-locks held by Btree p into read-locks.
+*/
+static void downgradeAllSharedCacheTableLocks(Btree *p){
+ BtShared *pBt = p->pBt;
+ if( pBt->pWriter==p ){
+ BtLock *pLock;
+ pBt->pWriter = 0;
+ pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
+ for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
+ assert( pLock->eLock==READ_LOCK || pLock->pBtree==p );
+ pLock->eLock = READ_LOCK;
+ }
+ }
+}
+
+#endif /* SQLITE_OMIT_SHARED_CACHE */
+
+static void releasePage(MemPage *pPage); /* Forward reference */
+
+/*
+***** This routine is used inside of assert() only ****
+**
+** Verify that the cursor holds the mutex on its BtShared
+*/
+#ifdef SQLITE_DEBUG
+static int cursorHoldsMutex(BtCursor *p){
+ return sqlite3_mutex_held(p->pBt->mutex);
+}
+#endif
+
+
+#ifndef SQLITE_OMIT_INCRBLOB
+/*
+** Invalidate the overflow page-list cache for cursor pCur, if any.
+*/
+static void invalidateOverflowCache(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ sqlite3_free(pCur->aOverflow);
+ pCur->aOverflow = 0;
+}
+
+/*
+** Invalidate the overflow page-list cache for all cursors opened
+** on the shared btree structure pBt.
+*/
+static void invalidateAllOverflowCache(BtShared *pBt){
+ BtCursor *p;
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ for(p=pBt->pCursor; p; p=p->pNext){
+ invalidateOverflowCache(p);
+ }
+}
+
+/*
+** This function is called before modifying the contents of a table
+** to invalidate any incrblob cursors that are open on the
+** row or one of the rows being modified.
+**
+** If argument isClearTable is true, then the entire contents of the
+** table is about to be deleted. In this case invalidate all incrblob
+** cursors open on any row within the table with root-page pgnoRoot.
+**
+** Otherwise, if argument isClearTable is false, then the row with
+** rowid iRow is being replaced or deleted. In this case invalidate
+** only those incrblob cursors open on that specific row.
+*/
+static void invalidateIncrblobCursors(
+ Btree *pBtree, /* The database file to check */
+ i64 iRow, /* The rowid that might be changing */
+ int isClearTable /* True if all rows are being deleted */
+){
+ BtCursor *p;
+ BtShared *pBt = pBtree->pBt;
+ assert( sqlite3BtreeHoldsMutex(pBtree) );
+ for(p=pBt->pCursor; p; p=p->pNext){
+ if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){
+ p->eState = CURSOR_INVALID;
+ }
+ }
+}
+
+#else
+ /* Stub functions when INCRBLOB is omitted */
+ #define invalidateOverflowCache(x)
+ #define invalidateAllOverflowCache(x)
+ #define invalidateIncrblobCursors(x,y,z)
+#endif /* SQLITE_OMIT_INCRBLOB */
+
+/*
+** Set bit pgno of the BtShared.pHasContent bitvec. This is called
+** when a page that previously contained data becomes a free-list leaf
+** page.
+**
+** The BtShared.pHasContent bitvec exists to work around an obscure
+** bug caused by the interaction of two useful IO optimizations surrounding
+** free-list leaf pages:
+**
+** 1) When all data is deleted from a page and the page becomes
+** a free-list leaf page, the page is not written to the database
+** (as free-list leaf pages contain no meaningful data). Sometimes
+** such a page is not even journalled (as it will not be modified,
+** why bother journalling it?).
+**
+** 2) When a free-list leaf page is reused, its content is not read
+** from the database or written to the journal file (why should it
+** be, if it is not at all meaningful?).
+**
+** By themselves, these optimizations work fine and provide a handy
+** performance boost to bulk delete or insert operations. However, if
+** a page is moved to the free-list and then reused within the same
+** transaction, a problem comes up. If the page is not journalled when
+** it is moved to the free-list and it is also not journalled when it
+** is extracted from the free-list and reused, then the original data
+** may be lost. In the event of a rollback, it may not be possible
+** to restore the database to its original configuration.
+**
+** The solution is the BtShared.pHasContent bitvec. Whenever a page is
+** moved to become a free-list leaf page, the corresponding bit is
+** set in the bitvec. Whenever a leaf page is extracted from the free-list,
+** optimization 2 above is omitted if the corresponding bit is already
+** set in BtShared.pHasContent. The contents of the bitvec are cleared
+** at the end of every transaction.
+*/
+static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
+ int rc = SQLITE_OK;
+ if( !pBt->pHasContent ){
+ assert( pgno<=pBt->nPage );
+ pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
+ if( !pBt->pHasContent ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+ if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
+ rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
+ }
+ return rc;
+}
+
+/*
+** Query the BtShared.pHasContent vector.
+**
+** This function is called when a free-list leaf page is removed from the
+** free-list for reuse. It returns false if it is safe to retrieve the
+** page from the pager layer with the 'no-content' flag set. True otherwise.
+*/
+static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
+ Bitvec *p = pBt->pHasContent;
+ return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
+}
+
+/*
+** Clear (destroy) the BtShared.pHasContent bitvec. This should be
+** invoked at the conclusion of each write-transaction.
+*/
+static void btreeClearHasContent(BtShared *pBt){
+ sqlite3BitvecDestroy(pBt->pHasContent);
+ pBt->pHasContent = 0;
+}
+
+/*
+** Release all of the apPage[] pages for a cursor.
+*/
+static void btreeReleaseAllCursorPages(BtCursor *pCur){
+ int i;
+ for(i=0; i<=pCur->iPage; i++){
+ releasePage(pCur->apPage[i]);
+ pCur->apPage[i] = 0;
+ }
+ pCur->iPage = -1;
+}
+
+
+/*
+** Save the current cursor position in the variables BtCursor.nKey
+** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
+**
+** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
+** prior to calling this routine.
+*/
+static int saveCursorPosition(BtCursor *pCur){
+ int rc;
+
+ assert( CURSOR_VALID==pCur->eState );
+ assert( 0==pCur->pKey );
+ assert( cursorHoldsMutex(pCur) );
+
+ rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
+ assert( rc==SQLITE_OK ); /* KeySize() cannot fail */
+
+ /* If this is an intKey table, then the above call to BtreeKeySize()
+ ** stores the integer key in pCur->nKey. In this case this value is
+ ** all that is required. Otherwise, if pCur is not open on an intKey
+ ** table, then malloc space for and store the pCur->nKey bytes of key
+ ** data.
+ */
+ if( 0==pCur->apPage[0]->intKey ){
+ void *pKey = sqlite3Malloc( (int)pCur->nKey );
+ if( pKey ){
+ rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey);
+ if( rc==SQLITE_OK ){
+ pCur->pKey = pKey;
+ }else{
+ sqlite3_free(pKey);
+ }
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ }
+ assert( !pCur->apPage[0]->intKey || !pCur->pKey );
+
+ if( rc==SQLITE_OK ){
+ btreeReleaseAllCursorPages(pCur);
+ pCur->eState = CURSOR_REQUIRESEEK;
+ }
+
+ invalidateOverflowCache(pCur);
+ return rc;
+}
+
+/*
+** Save the positions of all cursors (except pExcept) that are open on
+** the table with root-page iRoot. Usually, this is called just before cursor
+** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()).
+*/
+static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
+ BtCursor *p;
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( pExcept==0 || pExcept->pBt==pBt );
+ for(p=pBt->pCursor; p; p=p->pNext){
+ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
+ if( p->eState==CURSOR_VALID ){
+ int rc = saveCursorPosition(p);
+ if( SQLITE_OK!=rc ){
+ return rc;
+ }
+ }else{
+ testcase( p->iPage>0 );
+ btreeReleaseAllCursorPages(p);
+ }
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Clear the current cursor position.
+*/
+SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ sqlite3_free(pCur->pKey);
+ pCur->pKey = 0;
+ pCur->eState = CURSOR_INVALID;
+}
+
+/*
+** In this version of BtreeMoveto, pKey is a packed index record
+** such as is generated by the OP_MakeRecord opcode. Unpack the
+** record and then call BtreeMovetoUnpacked() to do the work.
+*/
+static int btreeMoveto(
+ BtCursor *pCur, /* Cursor open on the btree to be searched */
+ const void *pKey, /* Packed key if the btree is an index */
+ i64 nKey, /* Integer key for tables. Size of pKey for indices */
+ int bias, /* Bias search to the high end */
+ int *pRes /* Write search results here */
+){
+ int rc; /* Status code */
+ UnpackedRecord *pIdxKey; /* Unpacked index key */
+ char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */
+ char *pFree = 0;
+
+ if( pKey ){
+ assert( nKey==(i64)(int)nKey );
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+ pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
+ );
+ if( pIdxKey==0 ) return SQLITE_NOMEM;
+ sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
+ }else{
+ pIdxKey = 0;
+ }
+ rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
+ if( pFree ){
+ sqlite3DbFree(pCur->pKeyInfo->db, pFree);
+ }
+ return rc;
+}
+
+/*
+** Restore the cursor to the position it was in (or as close to as possible)
+** when saveCursorPosition() was called. Note that this call deletes the
+** saved position info stored by saveCursorPosition(), so there can be
+** at most one effective restoreCursorPosition() call after each
+** saveCursorPosition().
+*/
+static int btreeRestoreCursorPosition(BtCursor *pCur){
+ int rc;
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState>=CURSOR_REQUIRESEEK );
+ if( pCur->eState==CURSOR_FAULT ){
+ return pCur->skipNext;
+ }
+ pCur->eState = CURSOR_INVALID;
+ rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext);
+ if( rc==SQLITE_OK ){
+ sqlite3_free(pCur->pKey);
+ pCur->pKey = 0;
+ assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
+ }
+ return rc;
+}
+
+#define restoreCursorPosition(p) \
+ (p->eState>=CURSOR_REQUIRESEEK ? \
+ btreeRestoreCursorPosition(p) : \
+ SQLITE_OK)
+
+/*
+** Determine whether or not a cursor has moved from the position it
+** was last placed at. Cursors can move when the row they are pointing
+** at is deleted out from under them.
+**
+** This routine returns an error code if something goes wrong. The
+** integer *pHasMoved is set to one if the cursor has moved and 0 if not.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
+ int rc;
+
+ rc = restoreCursorPosition(pCur);
+ if( rc ){
+ *pHasMoved = 1;
+ return rc;
+ }
+ if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){
+ *pHasMoved = 1;
+ }else{
+ *pHasMoved = 0;
+ }
+ return SQLITE_OK;
+}
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Given a page number of a regular database page, return the page
+** number for the pointer-map page that contains the entry for the
+** input page number.
+**
+** Return 0 (not a valid page) for pgno==1 since there is
+** no pointer map associated with page 1. The integrity_check logic
+** requires that ptrmapPageno(*,1)!=1.
+*/
+static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
+ int nPagesPerMapPage;
+ Pgno iPtrMap, ret;
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ if( pgno<2 ) return 0;
+ nPagesPerMapPage = (pBt->usableSize/5)+1;
+ iPtrMap = (pgno-2)/nPagesPerMapPage;
+ ret = (iPtrMap*nPagesPerMapPage) + 2;
+ if( ret==PENDING_BYTE_PAGE(pBt) ){
+ ret++;
+ }
+ return ret;
+}
+
+/*
+** Write an entry into the pointer map.
+**
+** This routine updates the pointer map entry for page number 'key'
+** so that it maps to type 'eType' and parent page number 'pgno'.
+**
+** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is
+** a no-op. If an error occurs, the appropriate error code is written
+** into *pRC.
+*/
+static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
+ DbPage *pDbPage; /* The pointer map page */
+ u8 *pPtrmap; /* The pointer map data */
+ Pgno iPtrmap; /* The pointer map page number */
+ int offset; /* Offset in pointer map page */
+ int rc; /* Return code from subfunctions */
+
+ if( *pRC ) return;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ /* The master-journal page number must never be used as a pointer map page */
+ assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
+
+ assert( pBt->autoVacuum );
+ if( key==0 ){
+ *pRC = SQLITE_CORRUPT_BKPT;
+ return;
+ }
+ iPtrmap = PTRMAP_PAGENO(pBt, key);
+ rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
+ if( rc!=SQLITE_OK ){
+ *pRC = rc;
+ return;
+ }
+ offset = PTRMAP_PTROFFSET(iPtrmap, key);
+ if( offset<0 ){
+ *pRC = SQLITE_CORRUPT_BKPT;
+ goto ptrmap_exit;
+ }
+ assert( offset <= (int)pBt->usableSize-5 );
+ pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
+
+ if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
+ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
+ *pRC= rc = sqlite3PagerWrite(pDbPage);
+ if( rc==SQLITE_OK ){
+ pPtrmap[offset] = eType;
+ put4byte(&pPtrmap[offset+1], parent);
+ }
+ }
+
+ptrmap_exit:
+ sqlite3PagerUnref(pDbPage);
+}
+
+/*
+** Read an entry from the pointer map.
+**
+** This routine retrieves the pointer map entry for page 'key', writing
+** the type and parent page number to *pEType and *pPgno respectively.
+** An error code is returned if something goes wrong, otherwise SQLITE_OK.
+*/
+static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
+ DbPage *pDbPage; /* The pointer map page */
+ int iPtrmap; /* Pointer map page index */
+ u8 *pPtrmap; /* Pointer map page data */
+ int offset; /* Offset of entry in pointer map */
+ int rc;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+
+ iPtrmap = PTRMAP_PAGENO(pBt, key);
+ rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
+ if( rc!=0 ){
+ return rc;
+ }
+ pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
+
+ offset = PTRMAP_PTROFFSET(iPtrmap, key);
+ if( offset<0 ){
+ sqlite3PagerUnref(pDbPage);
+ return SQLITE_CORRUPT_BKPT;
+ }
+ assert( offset <= (int)pBt->usableSize-5 );
+ assert( pEType!=0 );
+ *pEType = pPtrmap[offset];
+ if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
+
+ sqlite3PagerUnref(pDbPage);
+ if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
+ return SQLITE_OK;
+}
+
+#else /* if defined SQLITE_OMIT_AUTOVACUUM */
+ #define ptrmapPut(w,x,y,z,rc)
+ #define ptrmapGet(w,x,y,z) SQLITE_OK
+ #define ptrmapPutOvflPtr(x, y, rc)
+#endif
+
+/*
+** Given a btree page and a cell index (0 means the first cell on
+** the page, 1 means the second cell, and so forth) return a pointer
+** to the cell content.
+**
+** This routine works only for pages that do not contain overflow cells.
+*/
+#define findCell(P,I) \
+ ((P)->aData + ((P)->maskPage & get2byte(&(P)->aCellIdx[2*(I)])))
+#define findCellv2(D,M,O,I) (D+(M&get2byte(D+(O+2*(I)))))
+
+
+/*
+** This a more complex version of findCell() that works for
+** pages that do contain overflow cells.
+*/
+static u8 *findOverflowCell(MemPage *pPage, int iCell){
+ int i;
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ for(i=pPage->nOverflow-1; i>=0; i--){
+ int k;
+ k = pPage->aiOvfl[i];
+ if( k<=iCell ){
+ if( k==iCell ){
+ return pPage->apOvfl[i];
+ }
+ iCell--;
+ }
+ }
+ return findCell(pPage, iCell);
+}
+
+/*
+** Parse a cell content block and fill in the CellInfo structure. There
+** are two versions of this function. btreeParseCell() takes a
+** cell index as the second argument and btreeParseCellPtr()
+** takes a pointer to the body of the cell as its second argument.
+**
+** Within this file, the parseCell() macro can be called instead of
+** btreeParseCellPtr(). Using some compilers, this will be faster.
+*/
+static void btreeParseCellPtr(
+ MemPage *pPage, /* Page containing the cell */
+ u8 *pCell, /* Pointer to the cell text. */
+ CellInfo *pInfo /* Fill in this structure */
+){
+ u16 n; /* Number bytes in cell content header */
+ u32 nPayload; /* Number of bytes of cell payload */
+
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+
+ pInfo->pCell = pCell;
+ assert( pPage->leaf==0 || pPage->leaf==1 );
+ n = pPage->childPtrSize;
+ assert( n==4-4*pPage->leaf );
+ if( pPage->intKey ){
+ if( pPage->hasData ){
+ n += getVarint32(&pCell[n], nPayload);
+ }else{
+ nPayload = 0;
+ }
+ n += getVarint(&pCell[n], (u64*)&pInfo->nKey);
+ pInfo->nData = nPayload;
+ }else{
+ pInfo->nData = 0;
+ n += getVarint32(&pCell[n], nPayload);
+ pInfo->nKey = nPayload;
+ }
+ pInfo->nPayload = nPayload;
+ pInfo->nHeader = n;
+ testcase( nPayload==pPage->maxLocal );
+ testcase( nPayload==pPage->maxLocal+1 );
+ if( likely(nPayload<=pPage->maxLocal) ){
+ /* This is the (easy) common case where the entire payload fits
+ ** on the local page. No overflow is required.
+ */
+ if( (pInfo->nSize = (u16)(n+nPayload))<4 ) pInfo->nSize = 4;
+ pInfo->nLocal = (u16)nPayload;
+ pInfo->iOverflow = 0;
+ }else{
+ /* If the payload will not fit completely on the local page, we have
+ ** to decide how much to store locally and how much to spill onto
+ ** overflow pages. The strategy is to minimize the amount of unused
+ ** space on overflow pages while keeping the amount of local storage
+ ** in between minLocal and maxLocal.
+ **
+ ** Warning: changing the way overflow payload is distributed in any
+ ** way will result in an incompatible file format.
+ */
+ int minLocal; /* Minimum amount of payload held locally */
+ int maxLocal; /* Maximum amount of payload held locally */
+ int surplus; /* Overflow payload available for local storage */
+
+ minLocal = pPage->minLocal;
+ maxLocal = pPage->maxLocal;
+ surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4);
+ testcase( surplus==maxLocal );
+ testcase( surplus==maxLocal+1 );
+ if( surplus <= maxLocal ){
+ pInfo->nLocal = (u16)surplus;
+ }else{
+ pInfo->nLocal = (u16)minLocal;
+ }
+ pInfo->iOverflow = (u16)(pInfo->nLocal + n);
+ pInfo->nSize = pInfo->iOverflow + 4;
+ }
+}
+#define parseCell(pPage, iCell, pInfo) \
+ btreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo))
+static void btreeParseCell(
+ MemPage *pPage, /* Page containing the cell */
+ int iCell, /* The cell index. First cell is 0 */
+ CellInfo *pInfo /* Fill in this structure */
+){
+ parseCell(pPage, iCell, pInfo);
+}
+
+/*
+** Compute the total number of bytes that a Cell needs in the cell
+** data area of the btree-page. The return number includes the cell
+** data header and the local payload, but not any overflow page or
+** the space used by the cell pointer.
+*/
+static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
+ u8 *pIter = &pCell[pPage->childPtrSize];
+ u32 nSize;
+
+#ifdef SQLITE_DEBUG
+ /* The value returned by this function should always be the same as
+ ** the (CellInfo.nSize) value found by doing a full parse of the
+ ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
+ ** this function verifies that this invariant is not violated. */
+ CellInfo debuginfo;
+ btreeParseCellPtr(pPage, pCell, &debuginfo);
+#endif
+
+ if( pPage->intKey ){
+ u8 *pEnd;
+ if( pPage->hasData ){
+ pIter += getVarint32(pIter, nSize);
+ }else{
+ nSize = 0;
+ }
+
+ /* pIter now points at the 64-bit integer key value, a variable length
+ ** integer. The following block moves pIter to point at the first byte
+ ** past the end of the key value. */
+ pEnd = &pIter[9];
+ while( (*pIter++)&0x80 && pIter<pEnd );
+ }else{
+ pIter += getVarint32(pIter, nSize);
+ }
+
+ testcase( nSize==pPage->maxLocal );
+ testcase( nSize==pPage->maxLocal+1 );
+ if( nSize>pPage->maxLocal ){
+ int minLocal = pPage->minLocal;
+ nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
+ testcase( nSize==pPage->maxLocal );
+ testcase( nSize==pPage->maxLocal+1 );
+ if( nSize>pPage->maxLocal ){
+ nSize = minLocal;
+ }
+ nSize += 4;
+ }
+ nSize += (u32)(pIter - pCell);
+
+ /* The minimum size of any cell is 4 bytes. */
+ if( nSize<4 ){
+ nSize = 4;
+ }
+
+ assert( nSize==debuginfo.nSize );
+ return (u16)nSize;
+}
+
+#ifdef SQLITE_DEBUG
+/* This variation on cellSizePtr() is used inside of assert() statements
+** only. */
+static u16 cellSize(MemPage *pPage, int iCell){
+ return cellSizePtr(pPage, findCell(pPage, iCell));
+}
+#endif
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** If the cell pCell, part of page pPage contains a pointer
+** to an overflow page, insert an entry into the pointer-map
+** for the overflow page.
+*/
+static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
+ CellInfo info;
+ if( *pRC ) return;
+ assert( pCell!=0 );
+ btreeParseCellPtr(pPage, pCell, &info);
+ assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload );
+ if( info.iOverflow ){
+ Pgno ovfl = get4byte(&pCell[info.iOverflow]);
+ ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
+ }
+}
+#endif
+
+
+/*
+** Defragment the page given. All Cells are moved to the
+** end of the page and all free space is collected into one
+** big FreeBlk that occurs in between the header and cell
+** pointer array and the cell content area.
+*/
+static int defragmentPage(MemPage *pPage){
+ int i; /* Loop counter */
+ int pc; /* Address of a i-th cell */
+ int hdr; /* Offset to the page header */
+ int size; /* Size of a cell */
+ int usableSize; /* Number of usable bytes on a page */
+ int cellOffset; /* Offset to the cell pointer array */
+ int cbrk; /* Offset to the cell content area */
+ int nCell; /* Number of cells on the page */
+ unsigned char *data; /* The page data */
+ unsigned char *temp; /* Temp area for cell content */
+ int iCellFirst; /* First allowable cell index */
+ int iCellLast; /* Last possible cell index */
+
+
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ assert( pPage->pBt!=0 );
+ assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
+ assert( pPage->nOverflow==0 );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
+ data = pPage->aData;
+ hdr = pPage->hdrOffset;
+ cellOffset = pPage->cellOffset;
+ nCell = pPage->nCell;
+ assert( nCell==get2byte(&data[hdr+3]) );
+ usableSize = pPage->pBt->usableSize;
+ cbrk = get2byte(&data[hdr+5]);
+ memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk);
+ cbrk = usableSize;
+ iCellFirst = cellOffset + 2*nCell;
+ iCellLast = usableSize - 4;
+ for(i=0; i<nCell; i++){
+ u8 *pAddr; /* The i-th cell pointer */
+ pAddr = &data[cellOffset + i*2];
+ pc = get2byte(pAddr);
+ testcase( pc==iCellFirst );
+ testcase( pc==iCellLast );
+#if !defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
+ /* These conditions have already been verified in btreeInitPage()
+ ** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined
+ */
+ if( pc<iCellFirst || pc>iCellLast ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+#endif
+ assert( pc>=iCellFirst && pc<=iCellLast );
+ size = cellSizePtr(pPage, &temp[pc]);
+ cbrk -= size;
+#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
+ if( cbrk<iCellFirst ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+#else
+ if( cbrk<iCellFirst || pc+size>usableSize ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+#endif
+ assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
+ testcase( cbrk+size==usableSize );
+ testcase( pc+size==usableSize );
+ memcpy(&data[cbrk], &temp[pc], size);
+ put2byte(pAddr, cbrk);
+ }
+ assert( cbrk>=iCellFirst );
+ put2byte(&data[hdr+5], cbrk);
+ data[hdr+1] = 0;
+ data[hdr+2] = 0;
+ data[hdr+7] = 0;
+ memset(&data[iCellFirst], 0, cbrk-iCellFirst);
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ if( cbrk-iCellFirst!=pPage->nFree ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Allocate nByte bytes of space from within the B-Tree page passed
+** as the first argument. Write into *pIdx the index into pPage->aData[]
+** of the first byte of allocated space. Return either SQLITE_OK or
+** an error code (usually SQLITE_CORRUPT).
+**
+** The caller guarantees that there is sufficient space to make the
+** allocation. This routine might need to defragment in order to bring
+** all the space together, however. This routine will avoid using
+** the first two bytes past the cell pointer area since presumably this
+** allocation is being made in order to insert a new cell, so we will
+** also end up needing a new cell pointer.
+*/
+static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
+ const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */
+ u8 * const data = pPage->aData; /* Local cache of pPage->aData */
+ int nFrag; /* Number of fragmented bytes on pPage */
+ int top; /* First byte of cell content area */
+ int gap; /* First byte of gap between cell pointers and cell content */
+ int rc; /* Integer return code */
+ int usableSize; /* Usable size of the page */
+
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ assert( pPage->pBt );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( nByte>=0 ); /* Minimum cell size is 4 */
+ assert( pPage->nFree>=nByte );
+ assert( pPage->nOverflow==0 );
+ usableSize = pPage->pBt->usableSize;
+ assert( nByte < usableSize-8 );
+
+ nFrag = data[hdr+7];
+ assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
+ gap = pPage->cellOffset + 2*pPage->nCell;
+ top = get2byteNotZero(&data[hdr+5]);
+ if( gap>top ) return SQLITE_CORRUPT_BKPT;
+ testcase( gap+2==top );
+ testcase( gap+1==top );
+ testcase( gap==top );
+
+ if( nFrag>=60 ){
+ /* Always defragment highly fragmented pages */
+ rc = defragmentPage(pPage);
+ if( rc ) return rc;
+ top = get2byteNotZero(&data[hdr+5]);
+ }else if( gap+2<=top ){
+ /* Search the freelist looking for a free slot big enough to satisfy
+ ** the request. The allocation is made from the first free slot in
+ ** the list that is large enough to accomadate it.
+ */
+ int pc, addr;
+ for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){
+ int size; /* Size of the free slot */
+ if( pc>usableSize-4 || pc<addr+4 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ size = get2byte(&data[pc+2]);
+ if( size>=nByte ){
+ int x = size - nByte;
+ testcase( x==4 );
+ testcase( x==3 );
+ if( x<4 ){
+ /* Remove the slot from the free-list. Update the number of
+ ** fragmented bytes within the page. */
+ memcpy(&data[addr], &data[pc], 2);
+ data[hdr+7] = (u8)(nFrag + x);
+ }else if( size+pc > usableSize ){
+ return SQLITE_CORRUPT_BKPT;
+ }else{
+ /* The slot remains on the free-list. Reduce its size to account
+ ** for the portion used by the new allocation. */
+ put2byte(&data[pc+2], x);
+ }
+ *pIdx = pc + x;
+ return SQLITE_OK;
+ }
+ }
+ }
+
+ /* Check to make sure there is enough space in the gap to satisfy
+ ** the allocation. If not, defragment.
+ */
+ testcase( gap+2+nByte==top );
+ if( gap+2+nByte>top ){
+ rc = defragmentPage(pPage);
+ if( rc ) return rc;
+ top = get2byteNotZero(&data[hdr+5]);
+ assert( gap+nByte<=top );
+ }
+
+
+ /* Allocate memory from the gap in between the cell pointer array
+ ** and the cell content area. The btreeInitPage() call has already
+ ** validated the freelist. Given that the freelist is valid, there
+ ** is no way that the allocation can extend off the end of the page.
+ ** The assert() below verifies the previous sentence.
+ */
+ top -= nByte;
+ put2byte(&data[hdr+5], top);
+ assert( top+nByte <= (int)pPage->pBt->usableSize );
+ *pIdx = top;
+ return SQLITE_OK;
+}
+
+/*
+** Return a section of the pPage->aData to the freelist.
+** The first byte of the new free block is pPage->aDisk[start]
+** and the size of the block is "size" bytes.
+**
+** Most of the effort here is involved in coalesing adjacent
+** free blocks into a single big free block.
+*/
+static int freeSpace(MemPage *pPage, int start, int size){
+ int addr, pbegin, hdr;
+ int iLast; /* Largest possible freeblock offset */
+ unsigned char *data = pPage->aData;
+
+ assert( pPage->pBt!=0 );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ assert( start>=pPage->hdrOffset+6+pPage->childPtrSize );
+ assert( (start + size) <= (int)pPage->pBt->usableSize );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( size>=0 ); /* Minimum cell size is 4 */
+
+ if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){
+ /* Overwrite deleted information with zeros when the secure_delete
+ ** option is enabled */
+ memset(&data[start], 0, size);
+ }
+
+ /* Add the space back into the linked list of freeblocks. Note that
+ ** even though the freeblock list was checked by btreeInitPage(),
+ ** btreeInitPage() did not detect overlapping cells or
+ ** freeblocks that overlapped cells. Nor does it detect when the
+ ** cell content area exceeds the value in the page header. If these
+ ** situations arise, then subsequent insert operations might corrupt
+ ** the freelist. So we do need to check for corruption while scanning
+ ** the freelist.
+ */
+ hdr = pPage->hdrOffset;
+ addr = hdr + 1;
+ iLast = pPage->pBt->usableSize - 4;
+ assert( start<=iLast );
+ while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){
+ if( pbegin<addr+4 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ addr = pbegin;
+ }
+ if( pbegin>iLast ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ assert( pbegin>addr || pbegin==0 );
+ put2byte(&data[addr], start);
+ put2byte(&data[start], pbegin);
+ put2byte(&data[start+2], size);
+ pPage->nFree = pPage->nFree + (u16)size;
+
+ /* Coalesce adjacent free blocks */
+ addr = hdr + 1;
+ while( (pbegin = get2byte(&data[addr]))>0 ){
+ int pnext, psize, x;
+ assert( pbegin>addr );
+ assert( pbegin <= (int)pPage->pBt->usableSize-4 );
+ pnext = get2byte(&data[pbegin]);
+ psize = get2byte(&data[pbegin+2]);
+ if( pbegin + psize + 3 >= pnext && pnext>0 ){
+ int frag = pnext - (pbegin+psize);
+ if( (frag<0) || (frag>(int)data[hdr+7]) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ data[hdr+7] -= (u8)frag;
+ x = get2byte(&data[pnext]);
+ put2byte(&data[pbegin], x);
+ x = pnext + get2byte(&data[pnext+2]) - pbegin;
+ put2byte(&data[pbegin+2], x);
+ }else{
+ addr = pbegin;
+ }
+ }
+
+ /* If the cell content area begins with a freeblock, remove it. */
+ if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){
+ int top;
+ pbegin = get2byte(&data[hdr+1]);
+ memcpy(&data[hdr+1], &data[pbegin], 2);
+ top = get2byte(&data[hdr+5]) + get2byte(&data[pbegin+2]);
+ put2byte(&data[hdr+5], top);
+ }
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ return SQLITE_OK;
+}
+
+/*
+** Decode the flags byte (the first byte of the header) for a page
+** and initialize fields of the MemPage structure accordingly.
+**
+** Only the following combinations are supported. Anything different
+** indicates a corrupt database files:
+**
+** PTF_ZERODATA
+** PTF_ZERODATA | PTF_LEAF
+** PTF_LEAFDATA | PTF_INTKEY
+** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF
+*/
+static int decodeFlags(MemPage *pPage, int flagByte){
+ BtShared *pBt; /* A copy of pPage->pBt */
+
+ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
+ flagByte &= ~PTF_LEAF;
+ pPage->childPtrSize = 4-4*pPage->leaf;
+ pBt = pPage->pBt;
+ if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
+ pPage->intKey = 1;
+ pPage->hasData = pPage->leaf;
+ pPage->maxLocal = pBt->maxLeaf;
+ pPage->minLocal = pBt->minLeaf;
+ }else if( flagByte==PTF_ZERODATA ){
+ pPage->intKey = 0;
+ pPage->hasData = 0;
+ pPage->maxLocal = pBt->maxLocal;
+ pPage->minLocal = pBt->minLocal;
+ }else{
+ return SQLITE_CORRUPT_BKPT;
+ }
+ pPage->max1bytePayload = pBt->max1bytePayload;
+ return SQLITE_OK;
+}
+
+/*
+** Initialize the auxiliary information for a disk block.
+**
+** Return SQLITE_OK on success. If we see that the page does
+** not contain a well-formed database page, then return
+** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
+** guarantee that the page is well-formed. It only shows that
+** we failed to detect any corruption.
+*/
+static int btreeInitPage(MemPage *pPage){
+
+ assert( pPage->pBt!=0 );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
+ assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
+ assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+
+ if( !pPage->isInit ){
+ u16 pc; /* Address of a freeblock within pPage->aData[] */
+ u8 hdr; /* Offset to beginning of page header */
+ u8 *data; /* Equal to pPage->aData */
+ BtShared *pBt; /* The main btree structure */
+ int usableSize; /* Amount of usable space on each page */
+ u16 cellOffset; /* Offset from start of page to first cell pointer */
+ int nFree; /* Number of unused bytes on the page */
+ int top; /* First byte of the cell content area */
+ int iCellFirst; /* First allowable cell or freeblock offset */
+ int iCellLast; /* Last possible cell or freeblock offset */
+
+ pBt = pPage->pBt;
+
+ hdr = pPage->hdrOffset;
+ data = pPage->aData;
+ if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
+ assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+ pPage->maskPage = (u16)(pBt->pageSize - 1);
+ pPage->nOverflow = 0;
+ usableSize = pBt->usableSize;
+ pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
+ pPage->aDataEnd = &data[usableSize];
+ pPage->aCellIdx = &data[cellOffset];
+ top = get2byteNotZero(&data[hdr+5]);
+ pPage->nCell = get2byte(&data[hdr+3]);
+ if( pPage->nCell>MX_CELL(pBt) ){
+ /* To many cells for a single page. The page must be corrupt */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ testcase( pPage->nCell==MX_CELL(pBt) );
+
+ /* A malformed database page might cause us to read past the end
+ ** of page when parsing a cell.
+ **
+ ** The following block of code checks early to see if a cell extends
+ ** past the end of a page boundary and causes SQLITE_CORRUPT to be
+ ** returned if it does.
+ */
+ iCellFirst = cellOffset + 2*pPage->nCell;
+ iCellLast = usableSize - 4;
+#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
+ {
+ int i; /* Index into the cell pointer array */
+ int sz; /* Size of a cell */
+
+ if( !pPage->leaf ) iCellLast--;
+ for(i=0; i<pPage->nCell; i++){
+ pc = get2byte(&data[cellOffset+i*2]);
+ testcase( pc==iCellFirst );
+ testcase( pc==iCellLast );
+ if( pc<iCellFirst || pc>iCellLast ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ sz = cellSizePtr(pPage, &data[pc]);
+ testcase( pc+sz==usableSize );
+ if( pc+sz>usableSize ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+ if( !pPage->leaf ) iCellLast++;
+ }
+#endif
+
+ /* Compute the total free space on the page */
+ pc = get2byte(&data[hdr+1]);
+ nFree = data[hdr+7] + top;
+ while( pc>0 ){
+ u16 next, size;
+ if( pc<iCellFirst || pc>iCellLast ){
+ /* Start of free block is off the page */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ next = get2byte(&data[pc]);
+ size = get2byte(&data[pc+2]);
+ if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
+ /* Free blocks must be in ascending order. And the last byte of
+ ** the free-block must lie on the database page. */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nFree = nFree + size;
+ pc = next;
+ }
+
+ /* At this point, nFree contains the sum of the offset to the start
+ ** of the cell-content area plus the number of free bytes within
+ ** the cell-content area. If this is greater than the usable-size
+ ** of the page, then the page must be corrupted. This check also
+ ** serves to verify that the offset to the start of the cell-content
+ ** area, according to the page header, lies within the page.
+ */
+ if( nFree>usableSize ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ pPage->nFree = (u16)(nFree - iCellFirst);
+ pPage->isInit = 1;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Set up a raw page so that it looks like a database page holding
+** no entries.
+*/
+static void zeroPage(MemPage *pPage, int flags){
+ unsigned char *data = pPage->aData;
+ BtShared *pBt = pPage->pBt;
+ u8 hdr = pPage->hdrOffset;
+ u16 first;
+
+ assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
+ assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
+ assert( sqlite3PagerGetData(pPage->pDbPage) == data );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ if( pBt->btsFlags & BTS_SECURE_DELETE ){
+ memset(&data[hdr], 0, pBt->usableSize - hdr);
+ }
+ data[hdr] = (char)flags;
+ first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
+ memset(&data[hdr+1], 0, 4);
+ data[hdr+7] = 0;
+ put2byte(&data[hdr+5], pBt->usableSize);
+ pPage->nFree = (u16)(pBt->usableSize - first);
+ decodeFlags(pPage, flags);
+ pPage->hdrOffset = hdr;
+ pPage->cellOffset = first;
+ pPage->aDataEnd = &data[pBt->usableSize];
+ pPage->aCellIdx = &data[first];
+ pPage->nOverflow = 0;
+ assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+ pPage->maskPage = (u16)(pBt->pageSize - 1);
+ pPage->nCell = 0;
+ pPage->isInit = 1;
+}
+
+
+/*
+** Convert a DbPage obtained from the pager into a MemPage used by
+** the btree layer.
+*/
+static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
+ MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
+ pPage->aData = sqlite3PagerGetData(pDbPage);
+ pPage->pDbPage = pDbPage;
+ pPage->pBt = pBt;
+ pPage->pgno = pgno;
+ pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
+ return pPage;
+}
+
+/*
+** Get a page from the pager. Initialize the MemPage.pBt and
+** MemPage.aData elements if needed.
+**
+** If the noContent flag is set, it means that we do not care about
+** the content of the page at this time. So do not go to the disk
+** to fetch the content. Just fill in the content with zeros for now.
+** If in the future we call sqlite3PagerWrite() on this page, that
+** means we have started to be concerned about content and the disk
+** read should occur at that point.
+*/
+static int btreeGetPage(
+ BtShared *pBt, /* The btree */
+ Pgno pgno, /* Number of the page to fetch */
+ MemPage **ppPage, /* Return the page in this parameter */
+ int noContent /* Do not load page content if true */
+){
+ int rc;
+ DbPage *pDbPage;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
+ if( rc ) return rc;
+ *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
+ return SQLITE_OK;
+}
+
+/*
+** Retrieve a page from the pager cache. If the requested page is not
+** already in the pager cache return NULL. Initialize the MemPage.pBt and
+** MemPage.aData elements if needed.
+*/
+static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
+ DbPage *pDbPage;
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
+ if( pDbPage ){
+ return btreePageFromDbPage(pDbPage, pgno, pBt);
+ }
+ return 0;
+}
+
+/*
+** Return the size of the database file in pages. If there is any kind of
+** error, return ((unsigned int)-1).
+*/
+static Pgno btreePagecount(BtShared *pBt){
+ return pBt->nPage;
+}
+SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( ((p->pBt->nPage)&0x8000000)==0 );
+ return (int)btreePagecount(p->pBt);
+}
+
+/*
+** Get a page from the pager and initialize it. This routine is just a
+** convenience wrapper around separate calls to btreeGetPage() and
+** btreeInitPage().
+**
+** If an error occurs, then the value *ppPage is set to is undefined. It
+** may remain unchanged, or it may be set to an invalid value.
+*/
+static int getAndInitPage(
+ BtShared *pBt, /* The database file */
+ Pgno pgno, /* Number of the page to get */
+ MemPage **ppPage /* Write the page pointer here */
+){
+ int rc;
+ assert( sqlite3_mutex_held(pBt->mutex) );
+
+ if( pgno>btreePagecount(pBt) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = btreeGetPage(pBt, pgno, ppPage, 0);
+ if( rc==SQLITE_OK ){
+ rc = btreeInitPage(*ppPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ }
+ }
+ }
+
+ testcase( pgno==0 );
+ assert( pgno!=0 || rc==SQLITE_CORRUPT );
+ return rc;
+}
+
+/*
+** Release a MemPage. This should be called once for each prior
+** call to btreeGetPage.
+*/
+static void releasePage(MemPage *pPage){
+ if( pPage ){
+ assert( pPage->aData );
+ assert( pPage->pBt );
+ assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
+ assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ sqlite3PagerUnref(pPage->pDbPage);
+ }
+}
+
+/*
+** During a rollback, when the pager reloads information into the cache
+** so that the cache is restored to its original state at the start of
+** the transaction, for each page restored this routine is called.
+**
+** This routine needs to reset the extra data section at the end of the
+** page to agree with the restored data.
+*/
+static void pageReinit(DbPage *pData){
+ MemPage *pPage;
+ pPage = (MemPage *)sqlite3PagerGetExtra(pData);
+ assert( sqlite3PagerPageRefcount(pData)>0 );
+ if( pPage->isInit ){
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ pPage->isInit = 0;
+ if( sqlite3PagerPageRefcount(pData)>1 ){
+ /* pPage might not be a btree page; it might be an overflow page
+ ** or ptrmap page or a free page. In those cases, the following
+ ** call to btreeInitPage() will likely return SQLITE_CORRUPT.
+ ** But no harm is done by this. And it is very important that
+ ** btreeInitPage() be called on every btree page so we make
+ ** the call for every page that comes in for re-initing. */
+ btreeInitPage(pPage);
+ }
+ }
+}
+
+/*
+** Invoke the busy handler for a btree.
+*/
+static int btreeInvokeBusyHandler(void *pArg){
+ BtShared *pBt = (BtShared*)pArg;
+ assert( pBt->db );
+ assert( sqlite3_mutex_held(pBt->db->mutex) );
+ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
+}
+
+/*
+** Open a database file.
+**
+** zFilename is the name of the database file. If zFilename is NULL
+** then an ephemeral database is created. The ephemeral database might
+** be exclusively in memory, or it might use a disk-based memory cache.
+** Either way, the ephemeral database will be automatically deleted
+** when sqlite3BtreeClose() is called.
+**
+** If zFilename is ":memory:" then an in-memory database is created
+** that is automatically destroyed when it is closed.
+**
+** The "flags" parameter is a bitmask that might contain bits like
+** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY.
+**
+** If the database is already opened in the same database connection
+** and we are in shared cache mode, then the open will fail with an
+** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
+** objects in the same database connection since doing so will lead
+** to problems with locking.
+*/
+SQLITE_PRIVATE int sqlite3BtreeOpen(
+ sqlite3_vfs *pVfs, /* VFS to use for this b-tree */
+ const char *zFilename, /* Name of the file containing the BTree database */
+ sqlite3 *db, /* Associated database handle */
+ Btree **ppBtree, /* Pointer to new Btree object written here */
+ int flags, /* Options */
+ int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
+){
+ BtShared *pBt = 0; /* Shared part of btree structure */
+ Btree *p; /* Handle to return */
+ sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */
+ int rc = SQLITE_OK; /* Result code from this function */
+ u8 nReserve; /* Byte of unused space on each page */
+ unsigned char zDbHeader[100]; /* Database header content */
+
+ /* True if opening an ephemeral, temporary database */
+ const int isTempDb = zFilename==0 || zFilename[0]==0;
+
+ /* Set the variable isMemdb to true for an in-memory database, or
+ ** false for a file-based database.
+ */
+#ifdef SQLITE_OMIT_MEMORYDB
+ const int isMemdb = 0;
+#else
+ const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
+ || (isTempDb && sqlite3TempInMemory(db))
+ || (vfsFlags & SQLITE_OPEN_MEMORY)!=0;
+#endif
+
+ assert( db!=0 );
+ assert( pVfs!=0 );
+ assert( sqlite3_mutex_held(db->mutex) );
+ assert( (flags&0xff)==flags ); /* flags fit in 8 bits */
+
+ /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
+ assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
+
+ /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
+ assert( (flags & BTREE_SINGLE)==0 || isTempDb );
+
+ if( isMemdb ){
+ flags |= BTREE_MEMORY;
+ }
+ if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
+ vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
+ }
+ p = sqlite3MallocZero(sizeof(Btree));
+ if( !p ){
+ return SQLITE_NOMEM;
+ }
+ p->inTrans = TRANS_NONE;
+ p->db = db;
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ p->lock.pBtree = p;
+ p->lock.iTable = 1;
+#endif
+
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
+ /*
+ ** If this Btree is a candidate for shared cache, try to find an
+ ** existing BtShared object that we can share with
+ */
+ if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
+ if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
+ int nFullPathname = pVfs->mxPathname+1;
+ char *zFullPathname = sqlite3Malloc(nFullPathname);
+ MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
+ p->sharable = 1;
+ if( !zFullPathname ){
+ sqlite3_free(p);
+ return SQLITE_NOMEM;
+ }
+ if( isMemdb ){
+ memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
+ }else{
+ rc = sqlite3OsFullPathname(pVfs, zFilename,
+ nFullPathname, zFullPathname);
+ if( rc ){
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return rc;
+ }
+ }
+#if SQLITE_THREADSAFE
+ mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
+ sqlite3_mutex_enter(mutexOpen);
+ mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ sqlite3_mutex_enter(mutexShared);
+#endif
+ for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
+ assert( pBt->nRef>0 );
+ if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
+ && sqlite3PagerVfs(pBt->pPager)==pVfs ){
+ int iDb;
+ for(iDb=db->nDb-1; iDb>=0; iDb--){
+ Btree *pExisting = db->aDb[iDb].pBt;
+ if( pExisting && pExisting->pBt==pBt ){
+ sqlite3_mutex_leave(mutexShared);
+ sqlite3_mutex_leave(mutexOpen);
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return SQLITE_CONSTRAINT;
+ }
+ }
+ p->pBt = pBt;
+ pBt->nRef++;
+ break;
+ }
+ }
+ sqlite3_mutex_leave(mutexShared);
+ sqlite3_free(zFullPathname);
+ }
+#ifdef SQLITE_DEBUG
+ else{
+ /* In debug mode, we mark all persistent databases as sharable
+ ** even when they are not. This exercises the locking code and
+ ** gives more opportunity for asserts(sqlite3_mutex_held())
+ ** statements to find locking problems.
+ */
+ p->sharable = 1;
+ }
+#endif
+ }
+#endif
+ if( pBt==0 ){
+ /*
+ ** The following asserts make sure that structures used by the btree are
+ ** the right size. This is to guard against size changes that result
+ ** when compiling on a different architecture.
+ */
+ assert( sizeof(i64)==8 || sizeof(i64)==4 );
+ assert( sizeof(u64)==8 || sizeof(u64)==4 );
+ assert( sizeof(u32)==4 );
+ assert( sizeof(u16)==2 );
+ assert( sizeof(Pgno)==4 );
+
+ pBt = sqlite3MallocZero( sizeof(*pBt) );
+ if( pBt==0 ){
+ rc = SQLITE_NOMEM;
+ goto btree_open_out;
+ }
+ rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
+ EXTRA_SIZE, flags, vfsFlags, pageReinit);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
+ }
+ if( rc!=SQLITE_OK ){
+ goto btree_open_out;
+ }
+ pBt->openFlags = (u8)flags;
+ pBt->db = db;
+ sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
+ p->pBt = pBt;
+
+ pBt->pCursor = 0;
+ pBt->pPage1 = 0;
+ if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
+#ifdef SQLITE_SECURE_DELETE
+ pBt->btsFlags |= BTS_SECURE_DELETE;
+#endif
+ pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16);
+ if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
+ || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
+ pBt->pageSize = 0;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If the magic name ":memory:" will create an in-memory database, then
+ ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
+ ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if
+ ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a
+ ** regular file-name. In this case the auto-vacuum applies as per normal.
+ */
+ if( zFilename && !isMemdb ){
+ pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0);
+ pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0);
+ }
+#endif
+ nReserve = 0;
+ }else{
+ nReserve = zDbHeader[20];
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
+ pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);
+#endif
+ }
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
+ if( rc ) goto btree_open_out;
+ pBt->usableSize = pBt->pageSize - nReserve;
+ assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
+
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
+ /* Add the new BtShared object to the linked list sharable BtShareds.
+ */
+ if( p->sharable ){
+ MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
+ pBt->nRef = 1;
+ MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
+ if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
+ pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
+ if( pBt->mutex==0 ){
+ rc = SQLITE_NOMEM;
+ db->mallocFailed = 0;
+ goto btree_open_out;
+ }
+ }
+ sqlite3_mutex_enter(mutexShared);
+ pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;
+ sqlite3_mutex_leave(mutexShared);
+ }
+#endif
+ }
+
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
+ /* If the new Btree uses a sharable pBtShared, then link the new
+ ** Btree into the list of all sharable Btrees for the same connection.
+ ** The list is kept in ascending order by pBt address.
+ */
+ if( p->sharable ){
+ int i;
+ Btree *pSib;
+ for(i=0; i<db->nDb; i++){
+ if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){
+ while( pSib->pPrev ){ pSib = pSib->pPrev; }
+ if( p->pBt<pSib->pBt ){
+ p->pNext = pSib;
+ p->pPrev = 0;
+ pSib->pPrev = p;
+ }else{
+ while( pSib->pNext && pSib->pNext->pBt<p->pBt ){
+ pSib = pSib->pNext;
+ }
+ p->pNext = pSib->pNext;
+ p->pPrev = pSib;
+ if( p->pNext ){
+ p->pNext->pPrev = p;
+ }
+ pSib->pNext = p;
+ }
+ break;
+ }
+ }
+ }
+#endif
+ *ppBtree = p;
+
+btree_open_out:
+ if( rc!=SQLITE_OK ){
+ if( pBt && pBt->pPager ){
+ sqlite3PagerClose(pBt->pPager);
+ }
+ sqlite3_free(pBt);
+ sqlite3_free(p);
+ *ppBtree = 0;
+ }else{
+ /* If the B-Tree was successfully opened, set the pager-cache size to the
+ ** default value. Except, when opening on an existing shared pager-cache,
+ ** do not change the pager-cache size.
+ */
+ if( sqlite3BtreeSchema(p, 0, 0)==0 ){
+ sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
+ }
+ }
+ if( mutexOpen ){
+ assert( sqlite3_mutex_held(mutexOpen) );
+ sqlite3_mutex_leave(mutexOpen);
+ }
+ return rc;
+}
+
+/*
+** Decrement the BtShared.nRef counter. When it reaches zero,
+** remove the BtShared structure from the sharing list. Return
+** true if the BtShared.nRef counter reaches zero and return
+** false if it is still positive.
+*/
+static int removeFromSharingList(BtShared *pBt){
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ MUTEX_LOGIC( sqlite3_mutex *pMaster; )
+ BtShared *pList;
+ int removed = 0;
+
+ assert( sqlite3_mutex_notheld(pBt->mutex) );
+ MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+ sqlite3_mutex_enter(pMaster);
+ pBt->nRef--;
+ if( pBt->nRef<=0 ){
+ if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
+ }else{
+ pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
+ while( ALWAYS(pList) && pList->pNext!=pBt ){
+ pList=pList->pNext;
+ }
+ if( ALWAYS(pList) ){
+ pList->pNext = pBt->pNext;
+ }
+ }
+ if( SQLITE_THREADSAFE ){
+ sqlite3_mutex_free(pBt->mutex);
+ }
+ removed = 1;
+ }
+ sqlite3_mutex_leave(pMaster);
+ return removed;
+#else
+ return 1;
+#endif
+}
+
+/*
+** Make sure pBt->pTmpSpace points to an allocation of
+** MX_CELL_SIZE(pBt) bytes.
+*/
+static void allocateTempSpace(BtShared *pBt){
+ if( !pBt->pTmpSpace ){
+ pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
+ }
+}
+
+/*
+** Free the pBt->pTmpSpace allocation
+*/
+static void freeTempSpace(BtShared *pBt){
+ sqlite3PageFree( pBt->pTmpSpace);
+ pBt->pTmpSpace = 0;
+}
+
+/*
+** Close an open database and invalidate all cursors.
+*/
+SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
+ BtShared *pBt = p->pBt;
+ BtCursor *pCur;
+
+ /* Close all cursors opened via this handle. */
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ sqlite3BtreeEnter(p);
+ pCur = pBt->pCursor;
+ while( pCur ){
+ BtCursor *pTmp = pCur;
+ pCur = pCur->pNext;
+ if( pTmp->pBtree==p ){
+ sqlite3BtreeCloseCursor(pTmp);
+ }
+ }
+
+ /* Rollback any active transaction and free the handle structure.
+ ** The call to sqlite3BtreeRollback() drops any table-locks held by
+ ** this handle.
+ */
+ sqlite3BtreeRollback(p, SQLITE_OK);
+ sqlite3BtreeLeave(p);
+
+ /* If there are still other outstanding references to the shared-btree
+ ** structure, return now. The remainder of this procedure cleans
+ ** up the shared-btree.
+ */
+ assert( p->wantToLock==0 && p->locked==0 );
+ if( !p->sharable || removeFromSharingList(pBt) ){
+ /* The pBt is no longer on the sharing list, so we can access
+ ** it without having to hold the mutex.
+ **
+ ** Clean out and delete the BtShared object.
+ */
+ assert( !pBt->pCursor );
+ sqlite3PagerClose(pBt->pPager);
+ if( pBt->xFreeSchema && pBt->pSchema ){
+ pBt->xFreeSchema(pBt->pSchema);
+ }
+ sqlite3DbFree(0, pBt->pSchema);
+ freeTempSpace(pBt);
+ sqlite3_free(pBt);
+ }
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ assert( p->wantToLock==0 );
+ assert( p->locked==0 );
+ if( p->pPrev ) p->pPrev->pNext = p->pNext;
+ if( p->pNext ) p->pNext->pPrev = p->pPrev;
+#endif
+
+ sqlite3_free(p);
+ return SQLITE_OK;
+}
+
+/*
+** Change the limit on the number of pages allowed in the cache.
+**
+** The maximum number of cache pages is set to the absolute
+** value of mxPage. If mxPage is negative, the pager will
+** operate asynchronously - it will not stop to do fsync()s
+** to insure data is written to the disk surface before
+** continuing. Transactions still work if synchronous is off,
+** and the database cannot be corrupted if this program
+** crashes. But if the operating system crashes or there is
+** an abrupt power failure when synchronous is off, the database
+** could be left in an inconsistent and unrecoverable state.
+** Synchronous is on by default so database corruption is not
+** normally a worry.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
+ BtShared *pBt = p->pBt;
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ sqlite3BtreeEnter(p);
+ sqlite3PagerSetCachesize(pBt->pPager, mxPage);
+ sqlite3BtreeLeave(p);
+ return SQLITE_OK;
+}
+
+/*
+** Change the way data is synced to disk in order to increase or decrease
+** how well the database resists damage due to OS crashes and power
+** failures. Level 1 is the same as asynchronous (no syncs() occur and
+** there is a high probability of damage) Level 2 is the default. There
+** is a very low but non-zero probability of damage. Level 3 reduces the
+** probability of damage to near zero but with a write performance reduction.
+*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(
+ Btree *p, /* The btree to set the safety level on */
+ int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
+ int fullSync, /* PRAGMA fullfsync. */
+ int ckptFullSync /* PRAGMA checkpoint_fullfync */
+){
+ BtShared *pBt = p->pBt;
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ assert( level>=1 && level<=3 );
+ sqlite3BtreeEnter(p);
+ sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync);
+ sqlite3BtreeLeave(p);
+ return SQLITE_OK;
+}
+#endif
+
+/*
+** Return TRUE if the given btree is set to safety level 1. In other
+** words, return TRUE if no sync() occurs on the disk files.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree *p){
+ BtShared *pBt = p->pBt;
+ int rc;
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ sqlite3BtreeEnter(p);
+ assert( pBt && pBt->pPager );
+ rc = sqlite3PagerNosync(pBt->pPager);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** Change the default pages size and the number of reserved bytes per page.
+** Or, if the page size has already been fixed, return SQLITE_READONLY
+** without changing anything.
+**
+** The page size must be a power of 2 between 512 and 65536. If the page
+** size supplied does not meet this constraint then the page size is not
+** changed.
+**
+** Page sizes are constrained to be a power of two so that the region
+** of the database file used for locking (beginning at PENDING_BYTE,
+** the first byte past the 1GB boundary, 0x40000000) needs to occur
+** at the beginning of a page.
+**
+** If parameter nReserve is less than zero, then the number of reserved
+** bytes per page is left unchanged.
+**
+** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size
+** and autovacuum mode can no longer be changed.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
+ int rc = SQLITE_OK;
+ BtShared *pBt = p->pBt;
+ assert( nReserve>=-1 && nReserve<=255 );
+ sqlite3BtreeEnter(p);
+ if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
+ sqlite3BtreeLeave(p);
+ return SQLITE_READONLY;
+ }
+ if( nReserve<0 ){
+ nReserve = pBt->pageSize - pBt->usableSize;
+ }
+ assert( nReserve>=0 && nReserve<=255 );
+ if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
+ ((pageSize-1)&pageSize)==0 ){
+ assert( (pageSize & 7)==0 );
+ assert( !pBt->pPage1 && !pBt->pCursor );
+ pBt->pageSize = (u32)pageSize;
+ freeTempSpace(pBt);
+ }
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
+ pBt->usableSize = pBt->pageSize - (u16)nReserve;
+ if( iFix ) pBt->btsFlags |= BTS_PAGESIZE_FIXED;
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** Return the currently defined page size
+*/
+SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
+ return p->pBt->pageSize;
+}
+
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+/*
+** This function is similar to sqlite3BtreeGetReserve(), except that it
+** may only be called if it is guaranteed that the b-tree mutex is already
+** held.
+**
+** This is useful in one special case in the backup API code where it is
+** known that the shared b-tree mutex is held, but the mutex on the
+** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
+** were to be called, it might collide with some other operation on the
+** database handle that owns *p, causing undefined behavior.
+*/
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
+ assert( sqlite3_mutex_held(p->pBt->mutex) );
+ return p->pBt->pageSize - p->pBt->usableSize;
+}
+#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */
+
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
+/*
+** Return the number of bytes of space at the end of every page that
+** are intentually left unused. This is the "reserved" space that is
+** sometimes used by extensions.
+*/
+SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree *p){
+ int n;
+ sqlite3BtreeEnter(p);
+ n = p->pBt->pageSize - p->pBt->usableSize;
+ sqlite3BtreeLeave(p);
+ return n;
+}
+
+/*
+** Set the maximum page count for a database if mxPage is positive.
+** No changes are made if mxPage is 0 or negative.
+** Regardless of the value of mxPage, return the maximum page count.
+*/
+SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
+ int n;
+ sqlite3BtreeEnter(p);
+ n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
+ sqlite3BtreeLeave(p);
+ return n;
+}
+
+/*
+** Set the BTS_SECURE_DELETE flag if newFlag is 0 or 1. If newFlag is -1,
+** then make no changes. Always return the value of the BTS_SECURE_DELETE
+** setting after the change.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
+ int b;
+ if( p==0 ) return 0;
+ sqlite3BtreeEnter(p);
+ if( newFlag>=0 ){
+ p->pBt->btsFlags &= ~BTS_SECURE_DELETE;
+ if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE;
+ }
+ b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0;
+ sqlite3BtreeLeave(p);
+ return b;
+}
+#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
+
+/*
+** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
+** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
+** is disabled. The default value for the auto-vacuum property is
+** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ return SQLITE_READONLY;
+#else
+ BtShared *pBt = p->pBt;
+ int rc = SQLITE_OK;
+ u8 av = (u8)autoVacuum;
+
+ sqlite3BtreeEnter(p);
+ if( (pBt->btsFlags & BTS_PAGESIZE_FIXED)!=0 && (av ?1:0)!=pBt->autoVacuum ){
+ rc = SQLITE_READONLY;
+ }else{
+ pBt->autoVacuum = av ?1:0;
+ pBt->incrVacuum = av==2 ?1:0;
+ }
+ sqlite3BtreeLeave(p);
+ return rc;
+#endif
+}
+
+/*
+** Return the value of the 'auto-vacuum' property. If auto-vacuum is
+** enabled 1 is returned. Otherwise 0.
+*/
+SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ return BTREE_AUTOVACUUM_NONE;
+#else
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = (
+ (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE:
+ (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL:
+ BTREE_AUTOVACUUM_INCR
+ );
+ sqlite3BtreeLeave(p);
+ return rc;
+#endif
+}
+
+
+/*
+** Get a reference to pPage1 of the database file. This will
+** also acquire a readlock on that file.
+**
+** SQLITE_OK is returned on success. If the file is not a
+** well-formed database file, then SQLITE_CORRUPT is returned.
+** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
+** is returned if we run out of memory.
+*/
+static int lockBtree(BtShared *pBt){
+ int rc; /* Result code from subfunctions */
+ MemPage *pPage1; /* Page 1 of the database file */
+ int nPage; /* Number of pages in the database */
+ int nPageFile = 0; /* Number of pages in the database file */
+ int nPageHeader; /* Number of pages in the database according to hdr */
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( pBt->pPage1==0 );
+ rc = sqlite3PagerSharedLock(pBt->pPager);
+ if( rc!=SQLITE_OK ) return rc;
+ rc = btreeGetPage(pBt, 1, &pPage1, 0);
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* Do some checking to help insure the file we opened really is
+ ** a valid database file.
+ */
+ nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
+ sqlite3PagerPagecount(pBt->pPager, &nPageFile);
+ if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
+ nPage = nPageFile;
+ }
+ if( nPage>0 ){
+ u32 pageSize;
+ u32 usableSize;
+ u8 *page1 = pPage1->aData;
+ rc = SQLITE_NOTADB;
+ if( memcmp(page1, zMagicHeader, 16)!=0 ){
+ goto page1_init_failed;
+ }
+
+#ifdef SQLITE_OMIT_WAL
+ if( page1[18]>1 ){
+ pBt->btsFlags |= BTS_READ_ONLY;
+ }
+ if( page1[19]>1 ){
+ goto page1_init_failed;
+ }
+#else
+ if( page1[18]>2 ){
+ pBt->btsFlags |= BTS_READ_ONLY;
+ }
+ if( page1[19]>2 ){
+ goto page1_init_failed;
+ }
+
+ /* If the write version is set to 2, this database should be accessed
+ ** in WAL mode. If the log is not already open, open it now. Then
+ ** return SQLITE_OK and return without populating BtShared.pPage1.
+ ** The caller detects this and calls this function again. This is
+ ** required as the version of page 1 currently in the page1 buffer
+ ** may not be the latest version - there may be a newer one in the log
+ ** file.
+ */
+ if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
+ int isOpen = 0;
+ rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
+ if( rc!=SQLITE_OK ){
+ goto page1_init_failed;
+ }else if( isOpen==0 ){
+ releasePage(pPage1);
+ return SQLITE_OK;
+ }
+ rc = SQLITE_NOTADB;
+ }
+#endif
+
+ /* The maximum embedded fraction must be exactly 25%. And the minimum
+ ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data.
+ ** The original design allowed these amounts to vary, but as of
+ ** version 3.6.0, we require them to be fixed.
+ */
+ if( memcmp(&page1[21], "\100\040\040",3)!=0 ){
+ goto page1_init_failed;
+ }
+ pageSize = (page1[16]<<8) | (page1[17]<<16);
+ if( ((pageSize-1)&pageSize)!=0
+ || pageSize>SQLITE_MAX_PAGE_SIZE
+ || pageSize<=256
+ ){
+ goto page1_init_failed;
+ }
+ assert( (pageSize & 7)==0 );
+ usableSize = pageSize - page1[20];
+ if( (u32)pageSize!=pBt->pageSize ){
+ /* After reading the first page of the database assuming a page size
+ ** of BtShared.pageSize, we have discovered that the page-size is
+ ** actually pageSize. Unlock the database, leave pBt->pPage1 at
+ ** zero and return SQLITE_OK. The caller will call this function
+ ** again with the correct page-size.
+ */
+ releasePage(pPage1);
+ pBt->usableSize = usableSize;
+ pBt->pageSize = pageSize;
+ freeTempSpace(pBt);
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
+ pageSize-usableSize);
+ return rc;
+ }
+ if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto page1_init_failed;
+ }
+ if( usableSize<480 ){
+ goto page1_init_failed;
+ }
+ pBt->pageSize = pageSize;
+ pBt->usableSize = usableSize;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);
+ pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0);
+#endif
+ }
+
+ /* maxLocal is the maximum amount of payload to store locally for
+ ** a cell. Make sure it is small enough so that at least minFanout
+ ** cells can will fit on one page. We assume a 10-byte page header.
+ ** Besides the payload, the cell must store:
+ ** 2-byte pointer to the cell
+ ** 4-byte child pointer
+ ** 9-byte nKey value
+ ** 4-byte nData value
+ ** 4-byte overflow page pointer
+ ** So a cell consists of a 2-byte pointer, a header which is as much as
+ ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow
+ ** page pointer.
+ */
+ pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23);
+ pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23);
+ pBt->maxLeaf = (u16)(pBt->usableSize - 35);
+ pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23);
+ if( pBt->maxLocal>127 ){
+ pBt->max1bytePayload = 127;
+ }else{
+ pBt->max1bytePayload = (u8)pBt->maxLocal;
+ }
+ assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
+ pBt->pPage1 = pPage1;
+ pBt->nPage = nPage;
+ return SQLITE_OK;
+
+page1_init_failed:
+ releasePage(pPage1);
+ pBt->pPage1 = 0;
+ return rc;
+}
+
+/*
+** If there are no outstanding cursors and we are not in the middle
+** of a transaction but there is a read lock on the database, then
+** this routine unrefs the first page of the database file which
+** has the effect of releasing the read lock.
+**
+** If there is a transaction in progress, this routine is a no-op.
+*/
+static void unlockBtreeIfUnused(BtShared *pBt){
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( pBt->pCursor==0 || pBt->inTransaction>TRANS_NONE );
+ if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
+ assert( pBt->pPage1->aData );
+ assert( sqlite3PagerRefcount(pBt->pPager)==1 );
+ assert( pBt->pPage1->aData );
+ releasePage(pBt->pPage1);
+ pBt->pPage1 = 0;
+ }
+}
+
+/*
+** If pBt points to an empty file then convert that empty file
+** into a new empty database by initializing the first page of
+** the database.
+*/
+static int newDatabase(BtShared *pBt){
+ MemPage *pP1;
+ unsigned char *data;
+ int rc;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ if( pBt->nPage>0 ){
+ return SQLITE_OK;
+ }
+ pP1 = pBt->pPage1;
+ assert( pP1!=0 );
+ data = pP1->aData;
+ rc = sqlite3PagerWrite(pP1->pDbPage);
+ if( rc ) return rc;
+ memcpy(data, zMagicHeader, sizeof(zMagicHeader));
+ assert( sizeof(zMagicHeader)==16 );
+ data[16] = (u8)((pBt->pageSize>>8)&0xff);
+ data[17] = (u8)((pBt->pageSize>>16)&0xff);
+ data[18] = 1;
+ data[19] = 1;
+ assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);
+ data[20] = (u8)(pBt->pageSize - pBt->usableSize);
+ data[21] = 64;
+ data[22] = 32;
+ data[23] = 32;
+ memset(&data[24], 0, 100-24);
+ zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
+ assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
+ put4byte(&data[36 + 4*4], pBt->autoVacuum);
+ put4byte(&data[36 + 7*4], pBt->incrVacuum);
+#endif
+ pBt->nPage = 1;
+ data[31] = 1;
+ return SQLITE_OK;
+}
+
+/*
+** Initialize the first page of the database file (creating a database
+** consisting of a single page and no schema objects). Return SQLITE_OK
+** if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
+ int rc;
+ sqlite3BtreeEnter(p);
+ p->pBt->nPage = 0;
+ rc = newDatabase(p->pBt);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** Attempt to start a new transaction. A write-transaction
+** is started if the second argument is nonzero, otherwise a read-
+** transaction. If the second argument is 2 or more and exclusive
+** transaction is started, meaning that no other process is allowed
+** to access the database. A preexisting transaction may not be
+** upgraded to exclusive by calling this routine a second time - the
+** exclusivity flag only works for a new transaction.
+**
+** A write-transaction must be started before attempting any
+** changes to the database. None of the following routines
+** will work unless a transaction is started first:
+**
+** sqlite3BtreeCreateTable()
+** sqlite3BtreeCreateIndex()
+** sqlite3BtreeClearTable()
+** sqlite3BtreeDropTable()
+** sqlite3BtreeInsert()
+** sqlite3BtreeDelete()
+** sqlite3BtreeUpdateMeta()
+**
+** If an initial attempt to acquire the lock fails because of lock contention
+** and the database was previously unlocked, then invoke the busy handler
+** if there is one. But if there was previously a read-lock, do not
+** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
+** returned when there is already a read-lock in order to avoid a deadlock.
+**
+** Suppose there are two processes A and B. A has a read lock and B has
+** a reserved lock. B tries to promote to exclusive but is blocked because
+** of A's read lock. A tries to promote to reserved but is blocked by B.
+** One or the other of the two processes must give way or there can be
+** no progress. By returning SQLITE_BUSY and not invoking the busy callback
+** when A already has a read lock, we encourage A to give up and let B
+** proceed.
+*/
+SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
+ sqlite3 *pBlock = 0;
+ BtShared *pBt = p->pBt;
+ int rc = SQLITE_OK;
+
+ sqlite3BtreeEnter(p);
+ btreeIntegrity(p);
+
+ /* If the btree is already in a write-transaction, or it
+ ** is already in a read-transaction and a read-transaction
+ ** is requested, this is a no-op.
+ */
+ if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
+ goto trans_begun;
+ }
+ assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
+
+ /* Write transactions are not possible on a read-only database */
+ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
+ rc = SQLITE_READONLY;
+ goto trans_begun;
+ }
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ /* If another database handle has already opened a write transaction
+ ** on this shared-btree structure and a second write transaction is
+ ** requested, return SQLITE_LOCKED.
+ */
+ if( (wrflag && pBt->inTransaction==TRANS_WRITE)
+ || (pBt->btsFlags & BTS_PENDING)!=0
+ ){
+ pBlock = pBt->pWriter->db;
+ }else if( wrflag>1 ){
+ BtLock *pIter;
+ for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
+ if( pIter->pBtree!=p ){
+ pBlock = pIter->pBtree->db;
+ break;
+ }
+ }
+ }
+ if( pBlock ){
+ sqlite3ConnectionBlocked(p->db, pBlock);
+ rc = SQLITE_LOCKED_SHAREDCACHE;
+ goto trans_begun;
+ }
+#endif
+
+ /* Any read-only or read-write transaction implies a read-lock on
+ ** page 1. So if some other shared-cache client already has a write-lock
+ ** on page 1, the transaction cannot be opened. */
+ rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
+ if( SQLITE_OK!=rc ) goto trans_begun;
+
+ pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
+ if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
+ do {
+ /* Call lockBtree() until either pBt->pPage1 is populated or
+ ** lockBtree() returns something other than SQLITE_OK. lockBtree()
+ ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
+ ** reading page 1 it discovers that the page-size of the database
+ ** file is not pBt->pageSize. In this case lockBtree() will update
+ ** pBt->pageSize to the page-size of the file on disk.
+ */
+ while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) );
+
+ if( rc==SQLITE_OK && wrflag ){
+ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
+ rc = SQLITE_READONLY;
+ }else{
+ rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
+ if( rc==SQLITE_OK ){
+ rc = newDatabase(pBt);
+ }
+ }
+ }
+
+ if( rc!=SQLITE_OK ){
+ unlockBtreeIfUnused(pBt);
+ }
+ }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
+ btreeInvokeBusyHandler(pBt) );
+
+ if( rc==SQLITE_OK ){
+ if( p->inTrans==TRANS_NONE ){
+ pBt->nTransaction++;
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ if( p->sharable ){
+ assert( p->lock.pBtree==p && p->lock.iTable==1 );
+ p->lock.eLock = READ_LOCK;
+ p->lock.pNext = pBt->pLock;
+ pBt->pLock = &p->lock;
+ }
+#endif
+ }
+ p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);
+ if( p->inTrans>pBt->inTransaction ){
+ pBt->inTransaction = p->inTrans;
+ }
+ if( wrflag ){
+ MemPage *pPage1 = pBt->pPage1;
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ assert( !pBt->pWriter );
+ pBt->pWriter = p;
+ pBt->btsFlags &= ~BTS_EXCLUSIVE;
+ if( wrflag>1 ) pBt->btsFlags |= BTS_EXCLUSIVE;
+#endif
+
+ /* If the db-size header field is incorrect (as it may be if an old
+ ** client has been writing the database file), update it now. Doing
+ ** this sooner rather than later means the database size can safely
+ ** re-read the database size from page 1 if a savepoint or transaction
+ ** rollback occurs within the transaction.
+ */
+ if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){
+ rc = sqlite3PagerWrite(pPage1->pDbPage);
+ if( rc==SQLITE_OK ){
+ put4byte(&pPage1->aData[28], pBt->nPage);
+ }
+ }
+ }
+ }
+
+
+trans_begun:
+ if( rc==SQLITE_OK && wrflag ){
+ /* This call makes sure that the pager has the correct number of
+ ** open savepoints. If the second parameter is greater than 0 and
+ ** the sub-journal is not already open, then it will be opened here.
+ */
+ rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
+ }
+
+ btreeIntegrity(p);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+
+/*
+** Set the pointer-map entries for all children of page pPage. Also, if
+** pPage contains cells that point to overflow pages, set the pointer
+** map entries for the overflow pages as well.
+*/
+static int setChildPtrmaps(MemPage *pPage){
+ int i; /* Counter variable */
+ int nCell; /* Number of cells in page pPage */
+ int rc; /* Return code */
+ BtShared *pBt = pPage->pBt;
+ u8 isInitOrig = pPage->isInit;
+ Pgno pgno = pPage->pgno;
+
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ rc = btreeInitPage(pPage);
+ if( rc!=SQLITE_OK ){
+ goto set_child_ptrmaps_out;
+ }
+ nCell = pPage->nCell;
+
+ for(i=0; i<nCell; i++){
+ u8 *pCell = findCell(pPage, i);
+
+ ptrmapPutOvflPtr(pPage, pCell, &rc);
+
+ if( !pPage->leaf ){
+ Pgno childPgno = get4byte(pCell);
+ ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
+ }
+ }
+
+ if( !pPage->leaf ){
+ Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
+ }
+
+set_child_ptrmaps_out:
+ pPage->isInit = isInitOrig;
+ return rc;
+}
+
+/*
+** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so
+** that it points to iTo. Parameter eType describes the type of pointer to
+** be modified, as follows:
+**
+** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
+** page of pPage.
+**
+** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
+** page pointed to by one of the cells on pPage.
+**
+** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next
+** overflow page in the list.
+*/
+static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ if( eType==PTRMAP_OVERFLOW2 ){
+ /* The pointer is always the first 4 bytes of the page in this case. */
+ if( get4byte(pPage->aData)!=iFrom ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ put4byte(pPage->aData, iTo);
+ }else{
+ u8 isInitOrig = pPage->isInit;
+ int i;
+ int nCell;
+
+ btreeInitPage(pPage);
+ nCell = pPage->nCell;
+
+ for(i=0; i<nCell; i++){
+ u8 *pCell = findCell(pPage, i);
+ if( eType==PTRMAP_OVERFLOW1 ){
+ CellInfo info;
+ btreeParseCellPtr(pPage, pCell, &info);
+ if( info.iOverflow
+ && pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
+ && iFrom==get4byte(&pCell[info.iOverflow])
+ ){
+ put4byte(&pCell[info.iOverflow], iTo);
+ break;
+ }
+ }else{
+ if( get4byte(pCell)==iFrom ){
+ put4byte(pCell, iTo);
+ break;
+ }
+ }
+ }
+
+ if( i==nCell ){
+ if( eType!=PTRMAP_BTREE ||
+ get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
+ }
+
+ pPage->isInit = isInitOrig;
+ }
+ return SQLITE_OK;
+}
+
+
+/*
+** Move the open database page pDbPage to location iFreePage in the
+** database. The pDbPage reference remains valid.
+**
+** The isCommit flag indicates that there is no need to remember that
+** the journal needs to be sync()ed before database page pDbPage->pgno
+** can be written to. The caller has already promised not to write to that
+** page.
+*/
+static int relocatePage(
+ BtShared *pBt, /* Btree */
+ MemPage *pDbPage, /* Open page to move */
+ u8 eType, /* Pointer map 'type' entry for pDbPage */
+ Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */
+ Pgno iFreePage, /* The location to move pDbPage to */
+ int isCommit /* isCommit flag passed to sqlite3PagerMovepage */
+){
+ MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */
+ Pgno iDbPage = pDbPage->pgno;
+ Pager *pPager = pBt->pPager;
+ int rc;
+
+ assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
+ eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( pDbPage->pBt==pBt );
+
+ /* Move page iDbPage from its current location to page number iFreePage */
+ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
+ iDbPage, iFreePage, iPtrPage, eType));
+ rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pDbPage->pgno = iFreePage;
+
+ /* If pDbPage was a btree-page, then it may have child pages and/or cells
+ ** that point to overflow pages. The pointer map entries for all these
+ ** pages need to be changed.
+ **
+ ** If pDbPage is an overflow page, then the first 4 bytes may store a
+ ** pointer to a subsequent overflow page. If this is the case, then
+ ** the pointer map needs to be updated for the subsequent overflow page.
+ */
+ if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){
+ rc = setChildPtrmaps(pDbPage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }else{
+ Pgno nextOvfl = get4byte(pDbPage->aData);
+ if( nextOvfl!=0 ){
+ ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage, &rc);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+ }
+
+ /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
+ ** that it points at iFreePage. Also fix the pointer map entry for
+ ** iPtrPage.
+ */
+ if( eType!=PTRMAP_ROOTPAGE ){
+ rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = sqlite3PagerWrite(pPtrPage->pDbPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(pPtrPage);
+ return rc;
+ }
+ rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
+ releasePage(pPtrPage);
+ if( rc==SQLITE_OK ){
+ ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc);
+ }
+ }
+ return rc;
+}
+
+/* Forward declaration required by incrVacuumStep(). */
+static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
+
+/*
+** Perform a single step of an incremental-vacuum. If successful, return
+** SQLITE_OK. If there is no work to do (and therefore no point in
+** calling this function again), return SQLITE_DONE. Or, if an error
+** occurs, return some other error code.
+**
+** More specificly, this function attempts to re-organize the database so
+** that the last page of the file currently in use is no longer in use.
+**
+** Parameter nFin is the number of pages that this database would contain
+** were this function called until it returns SQLITE_DONE.
+**
+** If the bCommit parameter is non-zero, this function assumes that the
+** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
+** or an error. bCommit is passed true for an auto-vacuum-on-commmit
+** operation, or false for an incremental vacuum.
+*/
+static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
+ Pgno nFreeList; /* Number of pages still on the free-list */
+ int rc;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( iLastPg>nFin );
+
+ if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
+ u8 eType;
+ Pgno iPtrPage;
+
+ nFreeList = get4byte(&pBt->pPage1->aData[36]);
+ if( nFreeList==0 ){
+ return SQLITE_DONE;
+ }
+
+ rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ if( eType==PTRMAP_ROOTPAGE ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ if( eType==PTRMAP_FREEPAGE ){
+ if( bCommit==0 ){
+ /* Remove the page from the files free-list. This is not required
+ ** if bCommit is non-zero. In that case, the free-list will be
+ ** truncated to zero after this function returns, so it doesn't
+ ** matter if it still contains some garbage entries.
+ */
+ Pgno iFreePg;
+ MemPage *pFreePg;
+ rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ assert( iFreePg==iLastPg );
+ releasePage(pFreePg);
+ }
+ } else {
+ Pgno iFreePg; /* Index of free page to move pLastPg to */
+ MemPage *pLastPg;
+ u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */
+ Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */
+
+ rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* If bCommit is zero, this loop runs exactly once and page pLastPg
+ ** is swapped with the first free page pulled off the free list.
+ **
+ ** On the other hand, if bCommit is greater than zero, then keep
+ ** looping until a free-page located within the first nFin pages
+ ** of the file is found.
+ */
+ if( bCommit==0 ){
+ eMode = BTALLOC_LE;
+ iNear = nFin;
+ }
+ do {
+ MemPage *pFreePg;
+ rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
+ if( rc!=SQLITE_OK ){
+ releasePage(pLastPg);
+ return rc;
+ }
+ releasePage(pFreePg);
+ }while( bCommit && iFreePg>nFin );
+ assert( iFreePg<iLastPg );
+
+ rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
+ releasePage(pLastPg);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+ }
+
+ if( bCommit==0 ){
+ do {
+ iLastPg--;
+ }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) );
+ pBt->bDoTruncate = 1;
+ pBt->nPage = iLastPg;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** The database opened by the first argument is an auto-vacuum database
+** nOrig pages in size containing nFree free pages. Return the expected
+** size of the database in pages following an auto-vacuum operation.
+*/
+static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
+ int nEntry; /* Number of entries on one ptrmap page */
+ Pgno nPtrmap; /* Number of PtrMap pages to be freed */
+ Pgno nFin; /* Return value */
+
+ nEntry = pBt->usableSize/5;
+ nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
+ nFin = nOrig - nFree - nPtrmap;
+ if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
+ nFin--;
+ }
+ while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
+ nFin--;
+ }
+
+ return nFin;
+}
+
+/*
+** A write-transaction must be opened before calling this function.
+** It performs a single unit of work towards an incremental vacuum.
+**
+** If the incremental vacuum is finished after this function has run,
+** SQLITE_DONE is returned. If it is not finished, but no error occurred,
+** SQLITE_OK is returned. Otherwise an SQLite error code.
+*/
+SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
+ int rc;
+ BtShared *pBt = p->pBt;
+
+ sqlite3BtreeEnter(p);
+ assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
+ if( !pBt->autoVacuum ){
+ rc = SQLITE_DONE;
+ }else{
+ Pgno nOrig = btreePagecount(pBt);
+ Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
+ Pgno nFin = finalDbSize(pBt, nOrig, nFree);
+
+ if( nOrig<nFin ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else if( nFree>0 ){
+ invalidateAllOverflowCache(pBt);
+ rc = incrVacuumStep(pBt, nFin, nOrig, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+ }
+ }else{
+ rc = SQLITE_DONE;
+ }
+ }
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** This routine is called prior to sqlite3PagerCommit when a transaction
+** is commited for an auto-vacuum database.
+**
+** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
+** the database file should be truncated to during the commit process.
+** i.e. the database has been reorganized so that only the first *pnTrunc
+** pages are in use.
+*/
+static int autoVacuumCommit(BtShared *pBt){
+ int rc = SQLITE_OK;
+ Pager *pPager = pBt->pPager;
+ VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager) );
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ invalidateAllOverflowCache(pBt);
+ assert(pBt->autoVacuum);
+ if( !pBt->incrVacuum ){
+ Pgno nFin; /* Number of pages in database after autovacuuming */
+ Pgno nFree; /* Number of pages on the freelist initially */
+ Pgno iFree; /* The next page to be freed */
+ Pgno nOrig; /* Database size before freeing */
+
+ nOrig = btreePagecount(pBt);
+ if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){
+ /* It is not possible to create a database for which the final page
+ ** is either a pointer-map page or the pending-byte page. If one
+ ** is encountered, this indicates corruption.
+ */
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ nFree = get4byte(&pBt->pPage1->aData[36]);
+ nFin = finalDbSize(pBt, nOrig, nFree);
+ if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
+
+ for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
+ rc = incrVacuumStep(pBt, nFin, iFree, 1);
+ }
+ if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
+ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ put4byte(&pBt->pPage1->aData[32], 0);
+ put4byte(&pBt->pPage1->aData[36], 0);
+ put4byte(&pBt->pPage1->aData[28], nFin);
+ pBt->bDoTruncate = 1;
+ pBt->nPage = nFin;
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3PagerRollback(pPager);
+ }
+ }
+
+ assert( nRef==sqlite3PagerRefcount(pPager) );
+ return rc;
+}
+
+#else /* ifndef SQLITE_OMIT_AUTOVACUUM */
+# define setChildPtrmaps(x) SQLITE_OK
+#endif
+
+/*
+** This routine does the first phase of a two-phase commit. This routine
+** causes a rollback journal to be created (if it does not already exist)
+** and populated with enough information so that if a power loss occurs
+** the database can be restored to its original state by playing back
+** the journal. Then the contents of the journal are flushed out to
+** the disk. After the journal is safely on oxide, the changes to the
+** database are written into the database file and flushed to oxide.
+** At the end of this call, the rollback journal still exists on the
+** disk and we are still holding all locks, so the transaction has not
+** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the
+** commit process.
+**
+** This call is a no-op if no write-transaction is currently active on pBt.
+**
+** Otherwise, sync the database file for the btree pBt. zMaster points to
+** the name of a master journal file that should be written into the
+** individual journal file, or is NULL, indicating no master journal file
+** (single database transaction).
+**
+** When this is called, the master journal should already have been
+** created, populated with this journal pointer and synced to disk.
+**
+** Once this is routine has returned, the only thing required to commit
+** the write-transaction for this database file is to delete the journal.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
+ int rc = SQLITE_OK;
+ if( p->inTrans==TRANS_WRITE ){
+ BtShared *pBt = p->pBt;
+ sqlite3BtreeEnter(p);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ rc = autoVacuumCommit(pBt);
+ if( rc!=SQLITE_OK ){
+ sqlite3BtreeLeave(p);
+ return rc;
+ }
+ }
+ if( pBt->bDoTruncate ){
+ sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
+ }
+#endif
+ rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
+ sqlite3BtreeLeave(p);
+ }
+ return rc;
+}
+
+/*
+** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback()
+** at the conclusion of a transaction.
+*/
+static void btreeEndTransaction(Btree *p){
+ BtShared *pBt = p->pBt;
+ assert( sqlite3BtreeHoldsMutex(p) );
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ pBt->bDoTruncate = 0;
+#endif
+ btreeClearHasContent(pBt);
+ if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
+ /* If there are other active statements that belong to this database
+ ** handle, downgrade to a read-only transaction. The other statements
+ ** may still be reading from the database. */
+ downgradeAllSharedCacheTableLocks(p);
+ p->inTrans = TRANS_READ;
+ }else{
+ /* If the handle had any kind of transaction open, decrement the
+ ** transaction count of the shared btree. If the transaction count
+ ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
+ ** call below will unlock the pager. */
+ if( p->inTrans!=TRANS_NONE ){
+ clearAllSharedCacheTableLocks(p);
+ pBt->nTransaction--;
+ if( 0==pBt->nTransaction ){
+ pBt->inTransaction = TRANS_NONE;
+ }
+ }
+
+ /* Set the current transaction state to TRANS_NONE and unlock the
+ ** pager if this call closed the only read or write transaction. */
+ p->inTrans = TRANS_NONE;
+ unlockBtreeIfUnused(pBt);
+ }
+
+ btreeIntegrity(p);
+}
+
+/*
+** Commit the transaction currently in progress.
+**
+** This routine implements the second phase of a 2-phase commit. The
+** sqlite3BtreeCommitPhaseOne() routine does the first phase and should
+** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne()
+** routine did all the work of writing information out to disk and flushing the
+** contents so that they are written onto the disk platter. All this
+** routine has to do is delete or truncate or zero the header in the
+** the rollback journal (which causes the transaction to commit) and
+** drop locks.
+**
+** Normally, if an error occurs while the pager layer is attempting to
+** finalize the underlying journal file, this function returns an error and
+** the upper layer will attempt a rollback. However, if the second argument
+** is non-zero then this b-tree transaction is part of a multi-file
+** transaction. In this case, the transaction has already been committed
+** (by deleting a master journal file) and the caller will ignore this
+** functions return code. So, even if an error occurs in the pager layer,
+** reset the b-tree objects internal state to indicate that the write
+** transaction has been closed. This is quite safe, as the pager will have
+** transitioned to the error state.
+**
+** This will release the write lock on the database file. If there
+** are no active cursors, it also releases the read lock.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
+
+ if( p->inTrans==TRANS_NONE ) return SQLITE_OK;
+ sqlite3BtreeEnter(p);
+ btreeIntegrity(p);
+
+ /* If the handle has a write-transaction open, commit the shared-btrees
+ ** transaction and set the shared state to TRANS_READ.
+ */
+ if( p->inTrans==TRANS_WRITE ){
+ int rc;
+ BtShared *pBt = p->pBt;
+ assert( pBt->inTransaction==TRANS_WRITE );
+ assert( pBt->nTransaction>0 );
+ rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
+ if( rc!=SQLITE_OK && bCleanup==0 ){
+ sqlite3BtreeLeave(p);
+ return rc;
+ }
+ pBt->inTransaction = TRANS_READ;
+ }
+
+ btreeEndTransaction(p);
+ sqlite3BtreeLeave(p);
+ return SQLITE_OK;
+}
+
+/*
+** Do both phases of a commit.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = sqlite3BtreeCommitPhaseOne(p, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeCommitPhaseTwo(p, 0);
+ }
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+#ifndef NDEBUG
+/*
+** Return the number of write-cursors open on this handle. This is for use
+** in assert() expressions, so it is only compiled if NDEBUG is not
+** defined.
+**
+** For the purposes of this routine, a write-cursor is any cursor that
+** is capable of writing to the databse. That means the cursor was
+** originally opened for writing and the cursor has not be disabled
+** by having its state changed to CURSOR_FAULT.
+*/
+static int countWriteCursors(BtShared *pBt){
+ BtCursor *pCur;
+ int r = 0;
+ for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
+ if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++;
+ }
+ return r;
+}
+#endif
+
+/*
+** This routine sets the state to CURSOR_FAULT and the error
+** code to errCode for every cursor on BtShared that pBtree
+** references.
+**
+** Every cursor is tripped, including cursors that belong
+** to other database connections that happen to be sharing
+** the cache with pBtree.
+**
+** This routine gets called when a rollback occurs.
+** All cursors using the same cache must be tripped
+** to prevent them from trying to use the btree after
+** the rollback. The rollback may have deleted tables
+** or moved root pages, so it is not sufficient to
+** save the state of the cursor. The cursor must be
+** invalidated.
+*/
+SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
+ BtCursor *p;
+ if( pBtree==0 ) return;
+ sqlite3BtreeEnter(pBtree);
+ for(p=pBtree->pBt->pCursor; p; p=p->pNext){
+ int i;
+ sqlite3BtreeClearCursor(p);
+ p->eState = CURSOR_FAULT;
+ p->skipNext = errCode;
+ for(i=0; i<=p->iPage; i++){
+ releasePage(p->apPage[i]);
+ p->apPage[i] = 0;
+ }
+ }
+ sqlite3BtreeLeave(pBtree);
+}
+
+/*
+** Rollback the transaction in progress. All cursors will be
+** invalided by this operation. Any attempt to use a cursor
+** that was open at the beginning of this operation will result
+** in an error.
+**
+** This will release the write lock on the database file. If there
+** are no active cursors, it also releases the read lock.
+*/
+SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
+ int rc;
+ BtShared *pBt = p->pBt;
+ MemPage *pPage1;
+
+ sqlite3BtreeEnter(p);
+ if( tripCode==SQLITE_OK ){
+ rc = tripCode = saveAllCursors(pBt, 0, 0);
+ }else{
+ rc = SQLITE_OK;
+ }
+ if( tripCode ){
+ sqlite3BtreeTripAllCursors(p, tripCode);
+ }
+ btreeIntegrity(p);
+
+ if( p->inTrans==TRANS_WRITE ){
+ int rc2;
+
+ assert( TRANS_WRITE==pBt->inTransaction );
+ rc2 = sqlite3PagerRollback(pBt->pPager);
+ if( rc2!=SQLITE_OK ){
+ rc = rc2;
+ }
+
+ /* The rollback may have destroyed the pPage1->aData value. So
+ ** call btreeGetPage() on page 1 again to make
+ ** sure pPage1->aData is set correctly. */
+ if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
+ int nPage = get4byte(28+(u8*)pPage1->aData);
+ testcase( nPage==0 );
+ if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
+ testcase( pBt->nPage!=nPage );
+ pBt->nPage = nPage;
+ releasePage(pPage1);
+ }
+ assert( countWriteCursors(pBt)==0 );
+ pBt->inTransaction = TRANS_READ;
+ }
+
+ btreeEndTransaction(p);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** Start a statement subtransaction. The subtransaction can can be rolled
+** back independently of the main transaction. You must start a transaction
+** before starting a subtransaction. The subtransaction is ended automatically
+** if the main transaction commits or rolls back.
+**
+** Statement subtransactions are used around individual SQL statements
+** that are contained within a BEGIN...COMMIT block. If a constraint
+** error occurs within the statement, the effect of that one statement
+** can be rolled back without having to rollback the entire transaction.
+**
+** A statement sub-transaction is implemented as an anonymous savepoint. The
+** value passed as the second parameter is the total number of savepoints,
+** including the new anonymous savepoint, open on the B-Tree. i.e. if there
+** are no active savepoints and no other statement-transactions open,
+** iStatement is 1. This anonymous savepoint can be released or rolled back
+** using the sqlite3BtreeSavepoint() function.
+*/
+SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
+ int rc;
+ BtShared *pBt = p->pBt;
+ sqlite3BtreeEnter(p);
+ assert( p->inTrans==TRANS_WRITE );
+ assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
+ assert( iStatement>0 );
+ assert( iStatement>p->db->nSavepoint );
+ assert( pBt->inTransaction==TRANS_WRITE );
+ /* At the pager level, a statement transaction is a savepoint with
+ ** an index greater than all savepoints created explicitly using
+ ** SQL statements. It is illegal to open, release or rollback any
+ ** such savepoints while the statement transaction savepoint is active.
+ */
+ rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
+** or SAVEPOINT_RELEASE. This function either releases or rolls back the
+** savepoint identified by parameter iSavepoint, depending on the value
+** of op.
+**
+** Normally, iSavepoint is greater than or equal to zero. However, if op is
+** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
+** contents of the entire transaction are rolled back. This is different
+** from a normal transaction rollback, as no locks are released and the
+** transaction remains open.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
+ int rc = SQLITE_OK;
+ if( p && p->inTrans==TRANS_WRITE ){
+ BtShared *pBt = p->pBt;
+ assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
+ assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
+ sqlite3BtreeEnter(p);
+ rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
+ if( rc==SQLITE_OK ){
+ if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
+ pBt->nPage = 0;
+ }
+ rc = newDatabase(pBt);
+ pBt->nPage = get4byte(28 + pBt->pPage1->aData);
+
+ /* The database size was written into the offset 28 of the header
+ ** when the transaction started, so we know that the value at offset
+ ** 28 is nonzero. */
+ assert( pBt->nPage>0 );
+ }
+ sqlite3BtreeLeave(p);
+ }
+ return rc;
+}
+
+/*
+** Create a new cursor for the BTree whose root is on the page
+** iTable. If a read-only cursor is requested, it is assumed that
+** the caller already has at least a read-only transaction open
+** on the database already. If a write-cursor is requested, then
+** the caller is assumed to have an open write transaction.
+**
+** If wrFlag==0, then the cursor can only be used for reading.
+** If wrFlag==1, then the cursor can be used for reading or for
+** writing if other conditions for writing are also met. These
+** are the conditions that must be met in order for writing to
+** be allowed:
+**
+** 1: The cursor must have been opened with wrFlag==1
+**
+** 2: Other database connections that share the same pager cache
+** but which are not in the READ_UNCOMMITTED state may not have
+** cursors open with wrFlag==0 on the same table. Otherwise
+** the changes made by this write cursor would be visible to
+** the read cursors in the other database connection.
+**
+** 3: The database must be writable (not on read-only media)
+**
+** 4: There must be an active transaction.
+**
+** No checking is done to make sure that page iTable really is the
+** root page of a b-tree. If it is not, then the cursor acquired
+** will not work correctly.
+**
+** It is assumed that the sqlite3BtreeCursorZero() has been called
+** on pCur to initialize the memory space prior to invoking this routine.
+*/
+static int btreeCursor(
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
+ BtCursor *pCur /* Space for new cursor */
+){
+ BtShared *pBt = p->pBt; /* Shared b-tree handle */
+
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( wrFlag==0 || wrFlag==1 );
+
+ /* The following assert statements verify that if this is a sharable
+ ** b-tree database, the connection is holding the required table locks,
+ ** and that no other connection has any open cursor that conflicts with
+ ** this lock. */
+ assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) );
+ assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
+
+ /* Assert that the caller has opened the required transaction. */
+ assert( p->inTrans>TRANS_NONE );
+ assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
+ assert( pBt->pPage1 && pBt->pPage1->aData );
+
+ if( NEVER(wrFlag && (pBt->btsFlags & BTS_READ_ONLY)!=0) ){
+ return SQLITE_READONLY;
+ }
+ if( iTable==1 && btreePagecount(pBt)==0 ){
+ assert( wrFlag==0 );
+ iTable = 0;
+ }
+
+ /* Now that no other errors can occur, finish filling in the BtCursor
+ ** variables and link the cursor into the BtShared list. */
+ pCur->pgnoRoot = (Pgno)iTable;
+ pCur->iPage = -1;
+ pCur->pKeyInfo = pKeyInfo;
+ pCur->pBtree = p;
+ pCur->pBt = pBt;
+ pCur->wrFlag = (u8)wrFlag;
+ pCur->pNext = pBt->pCursor;
+ if( pCur->pNext ){
+ pCur->pNext->pPrev = pCur;
+ }
+ pBt->pCursor = pCur;
+ pCur->eState = CURSOR_INVALID;
+ pCur->cachedRowid = 0;
+ return SQLITE_OK;
+}
+SQLITE_PRIVATE int sqlite3BtreeCursor(
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
+ BtCursor *pCur /* Write new cursor here */
+){
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** Return the size of a BtCursor object in bytes.
+**
+** This interfaces is needed so that users of cursors can preallocate
+** sufficient storage to hold a cursor. The BtCursor object is opaque
+** to users so they cannot do the sizeof() themselves - they must call
+** this routine.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){
+ return ROUND8(sizeof(BtCursor));
+}
+
+/*
+** Initialize memory that will be converted into a BtCursor object.
+**
+** The simple approach here would be to memset() the entire object
+** to zero. But it turns out that the apPage[] and aiIdx[] arrays
+** do not need to be zeroed and they are large, so we can save a lot
+** of run-time by skipping the initialization of those elements.
+*/
+SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){
+ memset(p, 0, offsetof(BtCursor, iPage));
+}
+
+/*
+** Set the cached rowid value of every cursor in the same database file
+** as pCur and having the same root page number as pCur. The value is
+** set to iRowid.
+**
+** Only positive rowid values are considered valid for this cache.
+** The cache is initialized to zero, indicating an invalid cache.
+** A btree will work fine with zero or negative rowids. We just cannot
+** cache zero or negative rowids, which means tables that use zero or
+** negative rowids might run a little slower. But in practice, zero
+** or negative rowids are very uncommon so this should not be a problem.
+*/
+SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor *pCur, sqlite3_int64 iRowid){
+ BtCursor *p;
+ for(p=pCur->pBt->pCursor; p; p=p->pNext){
+ if( p->pgnoRoot==pCur->pgnoRoot ) p->cachedRowid = iRowid;
+ }
+ assert( pCur->cachedRowid==iRowid );
+}
+
+/*
+** Return the cached rowid for the given cursor. A negative or zero
+** return value indicates that the rowid cache is invalid and should be
+** ignored. If the rowid cache has never before been set, then a
+** zero is returned.
+*/
+SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor *pCur){
+ return pCur->cachedRowid;
+}
+
+/*
+** Close a cursor. The read lock on the database file is released
+** when the last cursor is closed.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
+ Btree *pBtree = pCur->pBtree;
+ if( pBtree ){
+ int i;
+ BtShared *pBt = pCur->pBt;
+ sqlite3BtreeEnter(pBtree);
+ sqlite3BtreeClearCursor(pCur);
+ if( pCur->pPrev ){
+ pCur->pPrev->pNext = pCur->pNext;
+ }else{
+ pBt->pCursor = pCur->pNext;
+ }
+ if( pCur->pNext ){
+ pCur->pNext->pPrev = pCur->pPrev;
+ }
+ for(i=0; i<=pCur->iPage; i++){
+ releasePage(pCur->apPage[i]);
+ }
+ unlockBtreeIfUnused(pBt);
+ invalidateOverflowCache(pCur);
+ /* sqlite3_free(pCur); */
+ sqlite3BtreeLeave(pBtree);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Make sure the BtCursor* given in the argument has a valid
+** BtCursor.info structure. If it is not already valid, call
+** btreeParseCell() to fill it in.
+**
+** BtCursor.info is a cache of the information in the current cell.
+** Using this cache reduces the number of calls to btreeParseCell().
+**
+** 2007-06-25: There is a bug in some versions of MSVC that cause the
+** compiler to crash when getCellInfo() is implemented as a macro.
+** But there is a measureable speed advantage to using the macro on gcc
+** (when less compiler optimizations like -Os or -O0 are used and the
+** compiler is not doing agressive inlining.) So we use a real function
+** for MSVC and a macro for everything else. Ticket #2457.
+*/
+#ifndef NDEBUG
+ static void assertCellInfo(BtCursor *pCur){
+ CellInfo info;
+ int iPage = pCur->iPage;
+ memset(&info, 0, sizeof(info));
+ btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
+ assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
+ }
+#else
+ #define assertCellInfo(x)
+#endif
+#ifdef _MSC_VER
+ /* Use a real function in MSVC to work around bugs in that compiler. */
+ static void getCellInfo(BtCursor *pCur){
+ if( pCur->info.nSize==0 ){
+ int iPage = pCur->iPage;
+ btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
+ pCur->validNKey = 1;
+ }else{
+ assertCellInfo(pCur);
+ }
+ }
+#else /* if not _MSC_VER */
+ /* Use a macro in all other compilers so that the function is inlined */
+#define getCellInfo(pCur) \
+ if( pCur->info.nSize==0 ){ \
+ int iPage = pCur->iPage; \
+ btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
+ pCur->validNKey = 1; \
+ }else{ \
+ assertCellInfo(pCur); \
+ }
+#endif /* _MSC_VER */
+
+#ifndef NDEBUG /* The next routine used only within assert() statements */
+/*
+** Return true if the given BtCursor is valid. A valid cursor is one
+** that is currently pointing to a row in a (non-empty) table.
+** This is a verification routine is used only within assert() statements.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){
+ return pCur && pCur->eState==CURSOR_VALID;
+}
+#endif /* NDEBUG */
+
+/*
+** Set *pSize to the size of the buffer needed to hold the value of
+** the key for the current entry. If the cursor is not pointing
+** to a valid entry, *pSize is set to 0.
+**
+** For a table with the INTKEY flag set, this routine returns the key
+** itself, not the number of bytes in the key.
+**
+** The caller must position the cursor prior to invoking this routine.
+**
+** This routine cannot fail. It always returns SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
+ if( pCur->eState!=CURSOR_VALID ){
+ *pSize = 0;
+ }else{
+ getCellInfo(pCur);
+ *pSize = pCur->info.nKey;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Set *pSize to the number of bytes of data in the entry the
+** cursor currently points to.
+**
+** The caller must guarantee that the cursor is pointing to a non-NULL
+** valid entry. In other words, the calling procedure must guarantee
+** that the cursor has Cursor.eState==CURSOR_VALID.
+**
+** Failure is not possible. This function always returns SQLITE_OK.
+** It might just as well be a procedure (returning void) but we continue
+** to return an integer result code for historical reasons.
+*/
+SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ getCellInfo(pCur);
+ *pSize = pCur->info.nData;
+ return SQLITE_OK;
+}
+
+/*
+** Given the page number of an overflow page in the database (parameter
+** ovfl), this function finds the page number of the next page in the
+** linked list of overflow pages. If possible, it uses the auto-vacuum
+** pointer-map data instead of reading the content of page ovfl to do so.
+**
+** If an error occurs an SQLite error code is returned. Otherwise:
+**
+** The page number of the next overflow page in the linked list is
+** written to *pPgnoNext. If page ovfl is the last page in its linked
+** list, *pPgnoNext is set to zero.
+**
+** If ppPage is not NULL, and a reference to the MemPage object corresponding
+** to page number pOvfl was obtained, then *ppPage is set to point to that
+** reference. It is the responsibility of the caller to call releasePage()
+** on *ppPage to free the reference. In no reference was obtained (because
+** the pointer-map was used to obtain the value for *pPgnoNext), then
+** *ppPage is set to zero.
+*/
+static int getOverflowPage(
+ BtShared *pBt, /* The database file */
+ Pgno ovfl, /* Current overflow page number */
+ MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */
+ Pgno *pPgnoNext /* OUT: Next overflow page number */
+){
+ Pgno next = 0;
+ MemPage *pPage = 0;
+ int rc = SQLITE_OK;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert(pPgnoNext);
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* Try to find the next page in the overflow list using the
+ ** autovacuum pointer-map pages. Guess that the next page in
+ ** the overflow list is page number (ovfl+1). If that guess turns
+ ** out to be wrong, fall back to loading the data of page
+ ** number ovfl to determine the next page number.
+ */
+ if( pBt->autoVacuum ){
+ Pgno pgno;
+ Pgno iGuess = ovfl+1;
+ u8 eType;
+
+ while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){
+ iGuess++;
+ }
+
+ if( iGuess<=btreePagecount(pBt) ){
+ rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
+ if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
+ next = iGuess;
+ rc = SQLITE_DONE;
+ }
+ }
+ }
+#endif
+
+ assert( next==0 || rc==SQLITE_DONE );
+ if( rc==SQLITE_OK ){
+ rc = btreeGetPage(pBt, ovfl, &pPage, 0);
+ assert( rc==SQLITE_OK || pPage==0 );
+ if( rc==SQLITE_OK ){
+ next = get4byte(pPage->aData);
+ }
+ }
+
+ *pPgnoNext = next;
+ if( ppPage ){
+ *ppPage = pPage;
+ }else{
+ releasePage(pPage);
+ }
+ return (rc==SQLITE_DONE ? SQLITE_OK : rc);
+}
+
+/*
+** Copy data from a buffer to a page, or from a page to a buffer.
+**
+** pPayload is a pointer to data stored on database page pDbPage.
+** If argument eOp is false, then nByte bytes of data are copied
+** from pPayload to the buffer pointed at by pBuf. If eOp is true,
+** then sqlite3PagerWrite() is called on pDbPage and nByte bytes
+** of data are copied from the buffer pBuf to pPayload.
+**
+** SQLITE_OK is returned on success, otherwise an error code.
+*/
+static int copyPayload(
+ void *pPayload, /* Pointer to page data */
+ void *pBuf, /* Pointer to buffer */
+ int nByte, /* Number of bytes to copy */
+ int eOp, /* 0 -> copy from page, 1 -> copy to page */
+ DbPage *pDbPage /* Page containing pPayload */
+){
+ if( eOp ){
+ /* Copy data from buffer to page (a write operation) */
+ int rc = sqlite3PagerWrite(pDbPage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ memcpy(pPayload, pBuf, nByte);
+ }else{
+ /* Copy data from page to buffer (a read operation) */
+ memcpy(pBuf, pPayload, nByte);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** This function is used to read or overwrite payload information
+** for the entry that the pCur cursor is pointing to. If the eOp
+** parameter is 0, this is a read operation (data copied into
+** buffer pBuf). If it is non-zero, a write (data copied from
+** buffer pBuf).
+**
+** A total of "amt" bytes are read or written beginning at "offset".
+** Data is read to or from the buffer pBuf.
+**
+** The content being read or written might appear on the main page
+** or be scattered out on multiple overflow pages.
+**
+** If the BtCursor.isIncrblobHandle flag is set, and the current
+** cursor entry uses one or more overflow pages, this function
+** allocates space for and lazily popluates the overflow page-list
+** cache array (BtCursor.aOverflow). Subsequent calls use this
+** cache to make seeking to the supplied offset more efficient.
+**
+** Once an overflow page-list cache has been allocated, it may be
+** invalidated if some other cursor writes to the same table, or if
+** the cursor is moved to a different row. Additionally, in auto-vacuum
+** mode, the following events may invalidate an overflow page-list cache.
+**
+** * An incremental vacuum,
+** * A commit in auto_vacuum="full" mode,
+** * Creating a table (may require moving an overflow page).
+*/
+static int accessPayload(
+ BtCursor *pCur, /* Cursor pointing to entry to read from */
+ u32 offset, /* Begin reading this far into payload */
+ u32 amt, /* Read this many bytes */
+ unsigned char *pBuf, /* Write the bytes into this buffer */
+ int eOp /* zero to read. non-zero to write. */
+){
+ unsigned char *aPayload;
+ int rc = SQLITE_OK;
+ u32 nKey;
+ int iIdx = 0;
+ MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
+ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
+
+ assert( pPage );
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
+ assert( cursorHoldsMutex(pCur) );
+
+ getCellInfo(pCur);
+ aPayload = pCur->info.pCell + pCur->info.nHeader;
+ nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
+
+ if( NEVER(offset+amt > nKey+pCur->info.nData)
+ || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
+ ){
+ /* Trying to read or write past the end of the data is an error */
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ /* Check if data must be read/written to/from the btree page itself. */
+ if( offset<pCur->info.nLocal ){
+ int a = amt;
+ if( a+offset>pCur->info.nLocal ){
+ a = pCur->info.nLocal - offset;
+ }
+ rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
+ offset = 0;
+ pBuf += a;
+ amt -= a;
+ }else{
+ offset -= pCur->info.nLocal;
+ }
+
+ if( rc==SQLITE_OK && amt>0 ){
+ const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
+ Pgno nextPage;
+
+ nextPage = get4byte(&aPayload[pCur->info.nLocal]);
+
+#ifndef SQLITE_OMIT_INCRBLOB
+ /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[]
+ ** has not been allocated, allocate it now. The array is sized at
+ ** one entry for each overflow page in the overflow chain. The
+ ** page number of the first overflow page is stored in aOverflow[0],
+ ** etc. A value of 0 in the aOverflow[] array means "not yet known"
+ ** (the cache is lazily populated).
+ */
+ if( pCur->isIncrblobHandle && !pCur->aOverflow ){
+ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
+ pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl);
+ /* nOvfl is always positive. If it were zero, fetchPayload would have
+ ** been used instead of this routine. */
+ if( ALWAYS(nOvfl) && !pCur->aOverflow ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+
+ /* If the overflow page-list cache has been allocated and the
+ ** entry for the first required overflow page is valid, skip
+ ** directly to it.
+ */
+ if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){
+ iIdx = (offset/ovflSize);
+ nextPage = pCur->aOverflow[iIdx];
+ offset = (offset%ovflSize);
+ }
+#endif
+
+ for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
+
+#ifndef SQLITE_OMIT_INCRBLOB
+ /* If required, populate the overflow page-list cache. */
+ if( pCur->aOverflow ){
+ assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
+ pCur->aOverflow[iIdx] = nextPage;
+ }
+#endif
+
+ if( offset>=ovflSize ){
+ /* The only reason to read this page is to obtain the page
+ ** number for the next page in the overflow chain. The page
+ ** data is not required. So first try to lookup the overflow
+ ** page-list cache, if any, then fall back to the getOverflowPage()
+ ** function.
+ */
+#ifndef SQLITE_OMIT_INCRBLOB
+ if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){
+ nextPage = pCur->aOverflow[iIdx+1];
+ } else
+#endif
+ rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
+ offset -= ovflSize;
+ }else{
+ /* Need to read this page properly. It contains some of the
+ ** range of data that is being read (eOp==0) or written (eOp!=0).
+ */
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ sqlite3_file *fd;
+#endif
+ int a = amt;
+ if( a + offset > ovflSize ){
+ a = ovflSize - offset;
+ }
+
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ /* If all the following are true:
+ **
+ ** 1) this is a read operation, and
+ ** 2) data is required from the start of this overflow page, and
+ ** 3) the database is file-backed, and
+ ** 4) there is no open write-transaction, and
+ ** 5) the database is not a WAL database,
+ **
+ ** then data can be read directly from the database file into the
+ ** output buffer, bypassing the page-cache altogether. This speeds
+ ** up loading large records that span many overflow pages.
+ */
+ if( eOp==0 /* (1) */
+ && offset==0 /* (2) */
+ && pBt->inTransaction==TRANS_READ /* (4) */
+ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
+ && pBt->pPage1->aData[19]==0x01 /* (5) */
+ ){
+ u8 aSave[4];
+ u8 *aWrite = &pBuf[-4];
+ memcpy(aSave, aWrite, 4);
+ rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
+ nextPage = get4byte(aWrite);
+ memcpy(aWrite, aSave, 4);
+ }else
+#endif
+
+ {
+ DbPage *pDbPage;
+ rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
+ if( rc==SQLITE_OK ){
+ aPayload = sqlite3PagerGetData(pDbPage);
+ nextPage = get4byte(aPayload);
+ rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
+ sqlite3PagerUnref(pDbPage);
+ offset = 0;
+ }
+ }
+ amt -= a;
+ pBuf += a;
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK && amt>0 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ return rc;
+}
+
+/*
+** Read part of the key associated with cursor pCur. Exactly
+** "amt" bytes will be transfered into pBuf[]. The transfer
+** begins at "offset".
+**
+** The caller must ensure that pCur is pointing to a valid row
+** in the table.
+**
+** Return SQLITE_OK on success or an error code if anything goes
+** wrong. An error is returned if "offset+amt" is larger than
+** the available payload.
+*/
+SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
+ assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+ return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
+}
+
+/*
+** Read part of the data associated with cursor pCur. Exactly
+** "amt" bytes will be transfered into pBuf[]. The transfer
+** begins at "offset".
+**
+** Return SQLITE_OK on success or an error code if anything goes
+** wrong. An error is returned if "offset+amt" is larger than
+** the available payload.
+*/
+SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+ int rc;
+
+#ifndef SQLITE_OMIT_INCRBLOB
+ if ( pCur->eState==CURSOR_INVALID ){
+ return SQLITE_ABORT;
+ }
+#endif
+
+ assert( cursorHoldsMutex(pCur) );
+ rc = restoreCursorPosition(pCur);
+ if( rc==SQLITE_OK ){
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
+ assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+ rc = accessPayload(pCur, offset, amt, pBuf, 0);
+ }
+ return rc;
+}
+
+/*
+** Return a pointer to payload information from the entry that the
+** pCur cursor is pointing to. The pointer is to the beginning of
+** the key if skipKey==0 and it points to the beginning of data if
+** skipKey==1. The number of bytes of available key/data is written
+** into *pAmt. If *pAmt==0, then the value returned will not be
+** a valid pointer.
+**
+** This routine is an optimization. It is common for the entire key
+** and data to fit on the local page and for there to be no overflow
+** pages. When that is so, this routine can be used to access the
+** key and data without making a copy. If the key and/or data spills
+** onto overflow pages, then accessPayload() must be used to reassemble
+** the key/data and copy it into a preallocated buffer.
+**
+** The pointer returned by this routine looks directly into the cached
+** page of the database. The data might change or move the next time
+** any btree routine is called.
+*/
+static const unsigned char *fetchPayload(
+ BtCursor *pCur, /* Cursor pointing to entry to read from */
+ int *pAmt, /* Write the number of available bytes here */
+ int skipKey /* read beginning at data if this is true */
+){
+ unsigned char *aPayload;
+ MemPage *pPage;
+ u32 nKey;
+ u32 nLocal;
+
+ assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
+ assert( pCur->eState==CURSOR_VALID );
+ assert( cursorHoldsMutex(pCur) );
+ pPage = pCur->apPage[pCur->iPage];
+ assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
+ if( NEVER(pCur->info.nSize==0) ){
+ btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
+ &pCur->info);
+ }
+ aPayload = pCur->info.pCell;
+ aPayload += pCur->info.nHeader;
+ if( pPage->intKey ){
+ nKey = 0;
+ }else{
+ nKey = (int)pCur->info.nKey;
+ }
+ if( skipKey ){
+ aPayload += nKey;
+ nLocal = pCur->info.nLocal - nKey;
+ }else{
+ nLocal = pCur->info.nLocal;
+ assert( nLocal<=nKey );
+ }
+ *pAmt = nLocal;
+ return aPayload;
+}
+
+
+/*
+** For the entry that cursor pCur is point to, return as
+** many bytes of the key or data as are available on the local
+** b-tree page. Write the number of available bytes into *pAmt.
+**
+** The pointer returned is ephemeral. The key/data may move
+** or be destroyed on the next call to any Btree routine,
+** including calls from other threads against the same cache.
+** Hence, a mutex on the BtShared should be held prior to calling
+** this routine.
+**
+** These routines is used to get quick access to key and data
+** in the common case where no overflow pages are used.
+*/
+SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){
+ const void *p = 0;
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+ assert( cursorHoldsMutex(pCur) );
+ if( ALWAYS(pCur->eState==CURSOR_VALID) ){
+ p = (const void*)fetchPayload(pCur, pAmt, 0);
+ }
+ return p;
+}
+SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
+ const void *p = 0;
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+ assert( cursorHoldsMutex(pCur) );
+ if( ALWAYS(pCur->eState==CURSOR_VALID) ){
+ p = (const void*)fetchPayload(pCur, pAmt, 1);
+ }
+ return p;
+}
+
+
+/*
+** Move the cursor down to a new child page. The newPgno argument is the
+** page number of the child page to move to.
+**
+** This function returns SQLITE_CORRUPT if the page-header flags field of
+** the new child page does not match the flags field of the parent (i.e.
+** if an intkey page appears to be the parent of a non-intkey page, or
+** vice-versa).
+*/
+static int moveToChild(BtCursor *pCur, u32 newPgno){
+ int rc;
+ int i = pCur->iPage;
+ MemPage *pNewPage;
+ BtShared *pBt = pCur->pBt;
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
+ if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ rc = getAndInitPage(pBt, newPgno, &pNewPage);
+ if( rc ) return rc;
+ pCur->apPage[i+1] = pNewPage;
+ pCur->aiIdx[i+1] = 0;
+ pCur->iPage++;
+
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+ if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ return SQLITE_OK;
+}
+
+#if 0
+/*
+** Page pParent is an internal (non-leaf) tree page. This function
+** asserts that page number iChild is the left-child if the iIdx'th
+** cell in page pParent. Or, if iIdx is equal to the total number of
+** cells in pParent, that page number iChild is the right-child of
+** the page.
+*/
+static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
+ assert( iIdx<=pParent->nCell );
+ if( iIdx==pParent->nCell ){
+ assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
+ }else{
+ assert( get4byte(findCell(pParent, iIdx))==iChild );
+ }
+}
+#else
+# define assertParentIndex(x,y,z)
+#endif
+
+/*
+** Move the cursor up to the parent page.
+**
+** pCur->idx is set to the cell index that contains the pointer
+** to the page we are coming from. If we are coming from the
+** right-most child page then pCur->idx is set to one more than
+** the largest cell index.
+*/
+static void moveToParent(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->iPage>0 );
+ assert( pCur->apPage[pCur->iPage] );
+
+ /* UPDATE: It is actually possible for the condition tested by the assert
+ ** below to be untrue if the database file is corrupt. This can occur if
+ ** one cursor has modified page pParent while a reference to it is held
+ ** by a second cursor. Which can only happen if a single page is linked
+ ** into more than one b-tree structure in a corrupt database. */
+#if 0
+ assertParentIndex(
+ pCur->apPage[pCur->iPage-1],
+ pCur->aiIdx[pCur->iPage-1],
+ pCur->apPage[pCur->iPage]->pgno
+ );
+#endif
+ testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
+
+ releasePage(pCur->apPage[pCur->iPage]);
+ pCur->iPage--;
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+}
+
+/*
+** Move the cursor to point to the root page of its b-tree structure.
+**
+** If the table has a virtual root page, then the cursor is moved to point
+** to the virtual root page instead of the actual root page. A table has a
+** virtual root page when the actual root page contains no cells and a
+** single child page. This can only happen with the table rooted at page 1.
+**
+** If the b-tree structure is empty, the cursor state is set to
+** CURSOR_INVALID. Otherwise, the cursor is set to point to the first
+** cell located on the root (or virtual root) page and the cursor state
+** is set to CURSOR_VALID.
+**
+** If this function returns successfully, it may be assumed that the
+** page-header flags indicate that the [virtual] root-page is the expected
+** kind of b-tree page (i.e. if when opening the cursor the caller did not
+** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D,
+** indicating a table b-tree, or if the caller did specify a KeyInfo
+** structure the flags byte is set to 0x02 or 0x0A, indicating an index
+** b-tree).
+*/
+static int moveToRoot(BtCursor *pCur){
+ MemPage *pRoot;
+ int rc = SQLITE_OK;
+ Btree *p = pCur->pBtree;
+ BtShared *pBt = p->pBt;
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
+ assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
+ assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
+ if( pCur->eState>=CURSOR_REQUIRESEEK ){
+ if( pCur->eState==CURSOR_FAULT ){
+ assert( pCur->skipNext!=SQLITE_OK );
+ return pCur->skipNext;
+ }
+ sqlite3BtreeClearCursor(pCur);
+ }
+
+ if( pCur->iPage>=0 ){
+ int i;
+ for(i=1; i<=pCur->iPage; i++){
+ releasePage(pCur->apPage[i]);
+ }
+ pCur->iPage = 0;
+ }else if( pCur->pgnoRoot==0 ){
+ pCur->eState = CURSOR_INVALID;
+ return SQLITE_OK;
+ }else{
+ rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
+ if( rc!=SQLITE_OK ){
+ pCur->eState = CURSOR_INVALID;
+ return rc;
+ }
+ pCur->iPage = 0;
+
+ /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
+ ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
+ ** NULL, the caller expects a table b-tree. If this is not the case,
+ ** return an SQLITE_CORRUPT error. */
+ assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 );
+ if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+
+ /* Assert that the root page is of the correct type. This must be the
+ ** case as the call to this function that loaded the root-page (either
+ ** this call or a previous invocation) would have detected corruption
+ ** if the assumption were not true, and it is not possible for the flags
+ ** byte to have been modified while this cursor is holding a reference
+ ** to the page. */
+ pRoot = pCur->apPage[0];
+ assert( pRoot->pgno==pCur->pgnoRoot );
+ assert( pRoot->isInit && (pCur->pKeyInfo==0)==pRoot->intKey );
+
+ pCur->aiIdx[0] = 0;
+ pCur->info.nSize = 0;
+ pCur->atLast = 0;
+ pCur->validNKey = 0;
+
+ if( pRoot->nCell==0 && !pRoot->leaf ){
+ Pgno subpage;
+ if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
+ subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
+ pCur->eState = CURSOR_VALID;
+ rc = moveToChild(pCur, subpage);
+ }else{
+ pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
+ }
+ return rc;
+}
+
+/*
+** Move the cursor down to the left-most leaf entry beneath the
+** entry to which it is currently pointing.
+**
+** The left-most leaf is the one with the smallest key - the first
+** in ascending order.
+*/
+static int moveToLeftmost(BtCursor *pCur){
+ Pgno pgno;
+ int rc = SQLITE_OK;
+ MemPage *pPage;
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
+ assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
+ pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
+ rc = moveToChild(pCur, pgno);
+ }
+ return rc;
+}
+
+/*
+** Move the cursor down to the right-most leaf entry beneath the
+** page to which it is currently pointing. Notice the difference
+** between moveToLeftmost() and moveToRightmost(). moveToLeftmost()
+** finds the left-most entry beneath the *entry* whereas moveToRightmost()
+** finds the right-most entry beneath the *page*.
+**
+** The right-most entry is the one with the largest key - the last
+** key in ascending order.
+*/
+static int moveToRightmost(BtCursor *pCur){
+ Pgno pgno;
+ int rc = SQLITE_OK;
+ MemPage *pPage = 0;
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
+ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ pCur->aiIdx[pCur->iPage] = pPage->nCell;
+ rc = moveToChild(pCur, pgno);
+ }
+ if( rc==SQLITE_OK ){
+ pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+ }
+ return rc;
+}
+
+/* Move the cursor to the first entry in the table. Return SQLITE_OK
+** on success. Set *pRes to 0 if the cursor actually points to something
+** or set *pRes to 1 if the table is empty.
+*/
+SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
+ int rc;
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+ rc = moveToRoot(pCur);
+ if( rc==SQLITE_OK ){
+ if( pCur->eState==CURSOR_INVALID ){
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
+ *pRes = 1;
+ }else{
+ assert( pCur->apPage[pCur->iPage]->nCell>0 );
+ *pRes = 0;
+ rc = moveToLeftmost(pCur);
+ }
+ }
+ return rc;
+}
+
+/* Move the cursor to the last entry in the table. Return SQLITE_OK
+** on success. Set *pRes to 0 if the cursor actually points to something
+** or set *pRes to 1 if the table is empty.
+*/
+SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
+ int rc;
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+ /* If the cursor already points to the last entry, this is a no-op. */
+ if( CURSOR_VALID==pCur->eState && pCur->atLast ){
+#ifdef SQLITE_DEBUG
+ /* This block serves to assert() that the cursor really does point
+ ** to the last entry in the b-tree. */
+ int ii;
+ for(ii=0; ii<pCur->iPage; ii++){
+ assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
+ }
+ assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 );
+ assert( pCur->apPage[pCur->iPage]->leaf );
+#endif
+ return SQLITE_OK;
+ }
+
+ rc = moveToRoot(pCur);
+ if( rc==SQLITE_OK ){
+ if( CURSOR_INVALID==pCur->eState ){
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
+ *pRes = 1;
+ }else{
+ assert( pCur->eState==CURSOR_VALID );
+ *pRes = 0;
+ rc = moveToRightmost(pCur);
+ pCur->atLast = rc==SQLITE_OK ?1:0;
+ }
+ }
+ return rc;
+}
+
+/* Move the cursor so that it points to an entry near the key
+** specified by pIdxKey or intKey. Return a success code.
+**
+** For INTKEY tables, the intKey parameter is used. pIdxKey
+** must be NULL. For index tables, pIdxKey is used and intKey
+** is ignored.
+**
+** If an exact match is not found, then the cursor is always
+** left pointing at a leaf page which would hold the entry if it
+** were present. The cursor might point to an entry that comes
+** before or after the key.
+**
+** An integer is written into *pRes which is the result of
+** comparing the key with the entry to which the cursor is
+** pointing. The meaning of the integer written into
+** *pRes is as follows:
+**
+** *pRes<0 The cursor is left pointing at an entry that
+** is smaller than intKey/pIdxKey or if the table is empty
+** and the cursor is therefore left point to nothing.
+**
+** *pRes==0 The cursor is left pointing at an entry that
+** exactly matches intKey/pIdxKey.
+**
+** *pRes>0 The cursor is left pointing at an entry that
+** is larger than intKey/pIdxKey.
+**
+*/
+SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+ BtCursor *pCur, /* The cursor to be moved */
+ UnpackedRecord *pIdxKey, /* Unpacked index key */
+ i64 intKey, /* The table key */
+ int biasRight, /* If true, bias the search to the high end */
+ int *pRes /* Write search results here */
+){
+ int rc;
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+ assert( pRes );
+ assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
+
+ /* If the cursor is already positioned at the point we are trying
+ ** to move to, then just return without doing any work */
+ if( pCur->eState==CURSOR_VALID && pCur->validNKey
+ && pCur->apPage[0]->intKey
+ ){
+ if( pCur->info.nKey==intKey ){
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ if( pCur->atLast && pCur->info.nKey<intKey ){
+ *pRes = -1;
+ return SQLITE_OK;
+ }
+ }
+
+ rc = moveToRoot(pCur);
+ if( rc ){
+ return rc;
+ }
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
+ assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
+ if( pCur->eState==CURSOR_INVALID ){
+ *pRes = -1;
+ assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
+ return SQLITE_OK;
+ }
+ assert( pCur->apPage[0]->intKey || pIdxKey );
+ for(;;){
+ int lwr, upr, idx;
+ Pgno chldPg;
+ MemPage *pPage = pCur->apPage[pCur->iPage];
+ int c;
+
+ /* pPage->nCell must be greater than zero. If this is the root-page
+ ** the cursor would have been INVALID above and this for(;;) loop
+ ** not run. If this is not the root-page, then the moveToChild() routine
+ ** would have already detected db corruption. Similarly, pPage must
+ ** be the right kind (index or table) of b-tree page. Otherwise
+ ** a moveToChild() or moveToRoot() call would have detected corruption. */
+ assert( pPage->nCell>0 );
+ assert( pPage->intKey==(pIdxKey==0) );
+ lwr = 0;
+ upr = pPage->nCell-1;
+ if( biasRight ){
+ pCur->aiIdx[pCur->iPage] = (u16)(idx = upr);
+ }else{
+ pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2);
+ }
+ for(;;){
+ u8 *pCell; /* Pointer to current cell in pPage */
+
+ assert( idx==pCur->aiIdx[pCur->iPage] );
+ pCur->info.nSize = 0;
+ pCell = findCell(pPage, idx) + pPage->childPtrSize;
+ if( pPage->intKey ){
+ i64 nCellKey;
+ if( pPage->hasData ){
+ u32 dummy;
+ pCell += getVarint32(pCell, dummy);
+ }
+ getVarint(pCell, (u64*)&nCellKey);
+ if( nCellKey==intKey ){
+ c = 0;
+ }else if( nCellKey<intKey ){
+ c = -1;
+ }else{
+ assert( nCellKey>intKey );
+ c = +1;
+ }
+ pCur->validNKey = 1;
+ pCur->info.nKey = nCellKey;
+ }else{
+ /* The maximum supported page-size is 65536 bytes. This means that
+ ** the maximum number of record bytes stored on an index B-Tree
+ ** page is less than 16384 bytes and may be stored as a 2-byte
+ ** varint. This information is used to attempt to avoid parsing
+ ** the entire cell by checking for the cases where the record is
+ ** stored entirely within the b-tree page by inspecting the first
+ ** 2 bytes of the cell.
+ */
+ int nCell = pCell[0];
+ if( nCell<=pPage->max1bytePayload
+ /* && (pCell+nCell)<pPage->aDataEnd */
+ ){
+ /* This branch runs if the record-size field of the cell is a
+ ** single byte varint and the record fits entirely on the main
+ ** b-tree page. */
+ testcase( pCell+nCell+1==pPage->aDataEnd );
+ c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
+ }else if( !(pCell[1] & 0x80)
+ && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
+ /* && (pCell+nCell+2)<=pPage->aDataEnd */
+ ){
+ /* The record-size field is a 2 byte varint and the record
+ ** fits entirely on the main b-tree page. */
+ testcase( pCell+nCell+2==pPage->aDataEnd );
+ c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
+ }else{
+ /* The record flows over onto one or more overflow pages. In
+ ** this case the whole cell needs to be parsed, a buffer allocated
+ ** and accessPayload() used to retrieve the record into the
+ ** buffer before VdbeRecordCompare() can be called. */
+ void *pCellKey;
+ u8 * const pCellBody = pCell - pPage->childPtrSize;
+ btreeParseCellPtr(pPage, pCellBody, &pCur->info);
+ nCell = (int)pCur->info.nKey;
+ pCellKey = sqlite3Malloc( nCell );
+ if( pCellKey==0 ){
+ rc = SQLITE_NOMEM;
+ goto moveto_finish;
+ }
+ rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+ if( rc ){
+ sqlite3_free(pCellKey);
+ goto moveto_finish;
+ }
+ c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
+ sqlite3_free(pCellKey);
+ }
+ }
+ if( c==0 ){
+ if( pPage->intKey && !pPage->leaf ){
+ lwr = idx;
+ break;
+ }else{
+ *pRes = 0;
+ rc = SQLITE_OK;
+ goto moveto_finish;
+ }
+ }
+ if( c<0 ){
+ lwr = idx+1;
+ }else{
+ upr = idx-1;
+ }
+ if( lwr>upr ){
+ break;
+ }
+ pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
+ }
+ assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
+ assert( pPage->isInit );
+ if( pPage->leaf ){
+ chldPg = 0;
+ }else if( lwr>=pPage->nCell ){
+ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ }else{
+ chldPg = get4byte(findCell(pPage, lwr));
+ }
+ if( chldPg==0 ){
+ assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+ *pRes = c;
+ rc = SQLITE_OK;
+ goto moveto_finish;
+ }
+ pCur->aiIdx[pCur->iPage] = (u16)lwr;
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+ rc = moveToChild(pCur, chldPg);
+ if( rc ) goto moveto_finish;
+ }
+moveto_finish:
+ return rc;
+}
+
+
+/*
+** Return TRUE if the cursor is not pointing at an entry of the table.
+**
+** TRUE will be returned after a call to sqlite3BtreeNext() moves
+** past the last entry in the table or sqlite3BtreePrev() moves past
+** the first entry. TRUE is also returned if the table is empty.
+*/
+SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
+ /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries
+ ** have been deleted? This API will need to change to return an error code
+ ** as well as the boolean result value.
+ */
+ return (CURSOR_VALID!=pCur->eState);
+}
+
+/*
+** Advance the cursor to the next entry in the database. If
+** successful then set *pRes=0. If the cursor
+** was already pointing to the last entry in the database before
+** this routine was called, then set *pRes=1.
+*/
+SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
+ int rc;
+ int idx;
+ MemPage *pPage;
+
+ assert( cursorHoldsMutex(pCur) );
+ rc = restoreCursorPosition(pCur);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ assert( pRes!=0 );
+ if( CURSOR_INVALID==pCur->eState ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ if( pCur->skipNext>0 ){
+ pCur->skipNext = 0;
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ pCur->skipNext = 0;
+
+ pPage = pCur->apPage[pCur->iPage];
+ idx = ++pCur->aiIdx[pCur->iPage];
+ assert( pPage->isInit );
+
+ /* If the database file is corrupt, it is possible for the value of idx
+ ** to be invalid here. This can only occur if a second cursor modifies
+ ** the page while cursor pCur is holding a reference to it. Which can
+ ** only happen if the database is corrupt in such a way as to link the
+ ** page into more than one b-tree structure. */
+ testcase( idx>pPage->nCell );
+
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+ if( idx>=pPage->nCell ){
+ if( !pPage->leaf ){
+ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
+ if( rc ) return rc;
+ rc = moveToLeftmost(pCur);
+ *pRes = 0;
+ return rc;
+ }
+ do{
+ if( pCur->iPage==0 ){
+ *pRes = 1;
+ pCur->eState = CURSOR_INVALID;
+ return SQLITE_OK;
+ }
+ moveToParent(pCur);
+ pPage = pCur->apPage[pCur->iPage];
+ }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell );
+ *pRes = 0;
+ if( pPage->intKey ){
+ rc = sqlite3BtreeNext(pCur, pRes);
+ }else{
+ rc = SQLITE_OK;
+ }
+ return rc;
+ }
+ *pRes = 0;
+ if( pPage->leaf ){
+ return SQLITE_OK;
+ }
+ rc = moveToLeftmost(pCur);
+ return rc;
+}
+
+
+/*
+** Step the cursor to the back to the previous entry in the database. If
+** successful then set *pRes=0. If the cursor
+** was already pointing to the first entry in the database before
+** this routine was called, then set *pRes=1.
+*/
+SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
+ int rc;
+ MemPage *pPage;
+
+ assert( cursorHoldsMutex(pCur) );
+ rc = restoreCursorPosition(pCur);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pCur->atLast = 0;
+ if( CURSOR_INVALID==pCur->eState ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ if( pCur->skipNext<0 ){
+ pCur->skipNext = 0;
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ pCur->skipNext = 0;
+
+ pPage = pCur->apPage[pCur->iPage];
+ assert( pPage->isInit );
+ if( !pPage->leaf ){
+ int idx = pCur->aiIdx[pCur->iPage];
+ rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
+ if( rc ){
+ return rc;
+ }
+ rc = moveToRightmost(pCur);
+ }else{
+ while( pCur->aiIdx[pCur->iPage]==0 ){
+ if( pCur->iPage==0 ){
+ pCur->eState = CURSOR_INVALID;
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ moveToParent(pCur);
+ }
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+
+ pCur->aiIdx[pCur->iPage]--;
+ pPage = pCur->apPage[pCur->iPage];
+ if( pPage->intKey && !pPage->leaf ){
+ rc = sqlite3BtreePrevious(pCur, pRes);
+ }else{
+ rc = SQLITE_OK;
+ }
+ }
+ *pRes = 0;
+ return rc;
+}
+
+/*
+** Allocate a new page from the database file.
+**
+** The new page is marked as dirty. (In other words, sqlite3PagerWrite()
+** has already been called on the new page.) The new page has also
+** been referenced and the calling routine is responsible for calling
+** sqlite3PagerUnref() on the new page when it is done.
+**
+** SQLITE_OK is returned on success. Any other return value indicates
+** an error. *ppPage and *pPgno are undefined in the event of an error.
+** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
+**
+** If the "nearby" parameter is not 0, then an effort is made to
+** locate a page close to the page number "nearby". This can be used in an
+** attempt to keep related pages close to each other in the database file,
+** which in turn can make database access faster.
+**
+** If the eMode parameter is BTALLOC_EXACT and the nearby page exists
+** anywhere on the free-list, then it is guaranteed to be returned. If
+** eMode is BTALLOC_LT then the page returned will be less than or equal
+** to nearby if any such page exists. If eMode is BTALLOC_ANY then there
+** are no restrictions on which page is returned.
+*/
+static int allocateBtreePage(
+ BtShared *pBt, /* The btree */
+ MemPage **ppPage, /* Store pointer to the allocated page here */
+ Pgno *pPgno, /* Store the page number here */
+ Pgno nearby, /* Search for a page near this one */
+ u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
+){
+ MemPage *pPage1;
+ int rc;
+ u32 n; /* Number of pages on the freelist */
+ u32 k; /* Number of leaves on the trunk of the freelist */
+ MemPage *pTrunk = 0;
+ MemPage *pPrevTrunk = 0;
+ Pgno mxPage; /* Total size of the database file */
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) );
+ pPage1 = pBt->pPage1;
+ mxPage = btreePagecount(pBt);
+ n = get4byte(&pPage1->aData[36]);
+ testcase( n==mxPage-1 );
+ if( n>=mxPage ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( n>0 ){
+ /* There are pages on the freelist. Reuse one of those pages. */
+ Pgno iTrunk;
+ u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
+
+ /* If eMode==BTALLOC_EXACT and a query of the pointer-map
+ ** shows that the page 'nearby' is somewhere on the free-list, then
+ ** the entire-list will be searched for that page.
+ */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( eMode==BTALLOC_EXACT ){
+ if( nearby<=mxPage ){
+ u8 eType;
+ assert( nearby>0 );
+ assert( pBt->autoVacuum );
+ rc = ptrmapGet(pBt, nearby, &eType, 0);
+ if( rc ) return rc;
+ if( eType==PTRMAP_FREEPAGE ){
+ searchList = 1;
+ }
+ }
+ }else if( eMode==BTALLOC_LE ){
+ searchList = 1;
+ }
+#endif
+
+ /* Decrement the free-list count by 1. Set iTrunk to the index of the
+ ** first free-list trunk page. iPrevTrunk is initially 1.
+ */
+ rc = sqlite3PagerWrite(pPage1->pDbPage);
+ if( rc ) return rc;
+ put4byte(&pPage1->aData[36], n-1);
+
+ /* The code within this loop is run only once if the 'searchList' variable
+ ** is not true. Otherwise, it runs once for each trunk-page on the
+ ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT)
+ ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT)
+ */
+ do {
+ pPrevTrunk = pTrunk;
+ if( pPrevTrunk ){
+ iTrunk = get4byte(&pPrevTrunk->aData[0]);
+ }else{
+ iTrunk = get4byte(&pPage1->aData[32]);
+ }
+ testcase( iTrunk==mxPage );
+ if( iTrunk>mxPage ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
+ }
+ if( rc ){
+ pTrunk = 0;
+ goto end_allocate_page;
+ }
+ assert( pTrunk!=0 );
+ assert( pTrunk->aData!=0 );
+
+ k = get4byte(&pTrunk->aData[4]); /* # of leaves on this trunk page */
+ if( k==0 && !searchList ){
+ /* The trunk has no leaves and the list is not being searched.
+ ** So extract the trunk page itself and use it as the newly
+ ** allocated page */
+ assert( pPrevTrunk==0 );
+ rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ if( rc ){
+ goto end_allocate_page;
+ }
+ *pPgno = iTrunk;
+ memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+ *ppPage = pTrunk;
+ pTrunk = 0;
+ TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
+ }else if( k>(u32)(pBt->usableSize/4 - 2) ){
+ /* Value of k is out of range. Database corruption */
+ rc = SQLITE_CORRUPT_BKPT;
+ goto end_allocate_page;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ }else if( searchList
+ && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE))
+ ){
+ /* The list is being searched and this trunk page is the page
+ ** to allocate, regardless of whether it has leaves.
+ */
+ *pPgno = iTrunk;
+ *ppPage = pTrunk;
+ searchList = 0;
+ rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ if( rc ){
+ goto end_allocate_page;
+ }
+ if( k==0 ){
+ if( !pPrevTrunk ){
+ memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+ }else{
+ rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
+ if( rc!=SQLITE_OK ){
+ goto end_allocate_page;
+ }
+ memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
+ }
+ }else{
+ /* The trunk page is required by the caller but it contains
+ ** pointers to free-list leaves. The first leaf becomes a trunk
+ ** page in this case.
+ */
+ MemPage *pNewTrunk;
+ Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
+ if( iNewTrunk>mxPage ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto end_allocate_page;
+ }
+ testcase( iNewTrunk==mxPage );
+ rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
+ if( rc!=SQLITE_OK ){
+ goto end_allocate_page;
+ }
+ rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(pNewTrunk);
+ goto end_allocate_page;
+ }
+ memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
+ put4byte(&pNewTrunk->aData[4], k-1);
+ memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
+ releasePage(pNewTrunk);
+ if( !pPrevTrunk ){
+ assert( sqlite3PagerIswriteable(pPage1->pDbPage) );
+ put4byte(&pPage1->aData[32], iNewTrunk);
+ }else{
+ rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
+ if( rc ){
+ goto end_allocate_page;
+ }
+ put4byte(&pPrevTrunk->aData[0], iNewTrunk);
+ }
+ }
+ pTrunk = 0;
+ TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
+#endif
+ }else if( k>0 ){
+ /* Extract a leaf from the trunk */
+ u32 closest;
+ Pgno iPage;
+ unsigned char *aData = pTrunk->aData;
+ if( nearby>0 ){
+ u32 i;
+ closest = 0;
+ if( eMode==BTALLOC_LE ){
+ for(i=0; i<k; i++){
+ iPage = get4byte(&aData[8+i*4]);
+ if( iPage<=nearby ){
+ closest = i;
+ break;
+ }
+ }
+ }else{
+ int dist;
+ dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
+ for(i=1; i<k; i++){
+ int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
+ if( d2<dist ){
+ closest = i;
+ dist = d2;
+ }
+ }
+ }
+ }else{
+ closest = 0;
+ }
+
+ iPage = get4byte(&aData[8+closest*4]);
+ testcase( iPage==mxPage );
+ if( iPage>mxPage ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto end_allocate_page;
+ }
+ testcase( iPage==mxPage );
+ if( !searchList
+ || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
+ ){
+ int noContent;
+ *pPgno = iPage;
+ TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
+ ": %d more free pages\n",
+ *pPgno, closest+1, k, pTrunk->pgno, n-1));
+ rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ if( rc ) goto end_allocate_page;
+ if( closest<k-1 ){
+ memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
+ }
+ put4byte(&aData[4], k-1);
+ noContent = !btreeGetHasContent(pBt, *pPgno);
+ rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite((*ppPage)->pDbPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ }
+ }
+ searchList = 0;
+ }
+ }
+ releasePage(pPrevTrunk);
+ pPrevTrunk = 0;
+ }while( searchList );
+ }else{
+ /* There are no pages on the freelist, so append a new page to the
+ ** database image.
+ **
+ ** Normally, new pages allocated by this block can be requested from the
+ ** pager layer with the 'no-content' flag set. This prevents the pager
+ ** from trying to read the pages content from disk. However, if the
+ ** current transaction has already run one or more incremental-vacuum
+ ** steps, then the page we are about to allocate may contain content
+ ** that is required in the event of a rollback. In this case, do
+ ** not set the no-content flag. This causes the pager to load and journal
+ ** the current page content before overwriting it.
+ **
+ ** Note that the pager will not actually attempt to load or journal
+ ** content for any page that really does lie past the end of the database
+ ** file on disk. So the effects of disabling the no-content optimization
+ ** here are confined to those pages that lie between the end of the
+ ** database image and the end of the database file.
+ */
+ int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate));
+
+ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ if( rc ) return rc;
+ pBt->nPage++;
+ if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){
+ /* If *pPgno refers to a pointer-map page, allocate two new pages
+ ** at the end of the file instead of one. The first allocated page
+ ** becomes a new pointer-map page, the second is used by the caller.
+ */
+ MemPage *pPg = 0;
+ TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
+ assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
+ rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pPg->pDbPage);
+ releasePage(pPg);
+ }
+ if( rc ) return rc;
+ pBt->nPage++;
+ if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
+ }
+#endif
+ put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
+ *pPgno = pBt->nPage;
+
+ assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+ rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
+ if( rc ) return rc;
+ rc = sqlite3PagerWrite((*ppPage)->pDbPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ }
+ TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
+ }
+
+ assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+
+end_allocate_page:
+ releasePage(pTrunk);
+ releasePage(pPrevTrunk);
+ if( rc==SQLITE_OK ){
+ if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
+ releasePage(*ppPage);
+ return SQLITE_CORRUPT_BKPT;
+ }
+ (*ppPage)->isInit = 0;
+ }else{
+ *ppPage = 0;
+ }
+ assert( rc!=SQLITE_OK || sqlite3PagerIswriteable((*ppPage)->pDbPage) );
+ return rc;
+}
+
+/*
+** This function is used to add page iPage to the database file free-list.
+** It is assumed that the page is not already a part of the free-list.
+**
+** The value passed as the second argument to this function is optional.
+** If the caller happens to have a pointer to the MemPage object
+** corresponding to page iPage handy, it may pass it as the second value.
+** Otherwise, it may pass NULL.
+**
+** If a pointer to a MemPage object is passed as the second argument,
+** its reference count is not altered by this function.
+*/
+static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
+ MemPage *pTrunk = 0; /* Free-list trunk page */
+ Pgno iTrunk = 0; /* Page number of free-list trunk page */
+ MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */
+ MemPage *pPage; /* Page being freed. May be NULL. */
+ int rc; /* Return Code */
+ int nFree; /* Initial number of pages on free-list */
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( iPage>1 );
+ assert( !pMemPage || pMemPage->pgno==iPage );
+
+ if( pMemPage ){
+ pPage = pMemPage;
+ sqlite3PagerRef(pPage->pDbPage);
+ }else{
+ pPage = btreePageLookup(pBt, iPage);
+ }
+
+ /* Increment the free page count on pPage1 */
+ rc = sqlite3PagerWrite(pPage1->pDbPage);
+ if( rc ) goto freepage_out;
+ nFree = get4byte(&pPage1->aData[36]);
+ put4byte(&pPage1->aData[36], nFree+1);
+
+ if( pBt->btsFlags & BTS_SECURE_DELETE ){
+ /* If the secure_delete option is enabled, then
+ ** always fully overwrite deleted information with zeros.
+ */
+ if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
+ || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
+ ){
+ goto freepage_out;
+ }
+ memset(pPage->aData, 0, pPage->pBt->pageSize);
+ }
+
+ /* If the database supports auto-vacuum, write an entry in the pointer-map
+ ** to indicate that the page is free.
+ */
+ if( ISAUTOVACUUM ){
+ ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc);
+ if( rc ) goto freepage_out;
+ }
+
+ /* Now manipulate the actual database free-list structure. There are two
+ ** possibilities. If the free-list is currently empty, or if the first
+ ** trunk page in the free-list is full, then this page will become a
+ ** new free-list trunk page. Otherwise, it will become a leaf of the
+ ** first trunk page in the current free-list. This block tests if it
+ ** is possible to add the page as a new free-list leaf.
+ */
+ if( nFree!=0 ){
+ u32 nLeaf; /* Initial number of leaf cells on trunk page */
+
+ iTrunk = get4byte(&pPage1->aData[32]);
+ rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
+ if( rc!=SQLITE_OK ){
+ goto freepage_out;
+ }
+
+ nLeaf = get4byte(&pTrunk->aData[4]);
+ assert( pBt->usableSize>32 );
+ if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto freepage_out;
+ }
+ if( nLeaf < (u32)pBt->usableSize/4 - 8 ){
+ /* In this case there is room on the trunk page to insert the page
+ ** being freed as a new leaf.
+ **
+ ** Note that the trunk page is not really full until it contains
+ ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have
+ ** coded. But due to a coding error in versions of SQLite prior to
+ ** 3.6.0, databases with freelist trunk pages holding more than
+ ** usableSize/4 - 8 entries will be reported as corrupt. In order
+ ** to maintain backwards compatibility with older versions of SQLite,
+ ** we will continue to restrict the number of entries to usableSize/4 - 8
+ ** for now. At some point in the future (once everyone has upgraded
+ ** to 3.6.0 or later) we should consider fixing the conditional above
+ ** to read "usableSize/4-2" instead of "usableSize/4-8".
+ */
+ rc = sqlite3PagerWrite(pTrunk->pDbPage);
+ if( rc==SQLITE_OK ){
+ put4byte(&pTrunk->aData[4], nLeaf+1);
+ put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
+ if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){
+ sqlite3PagerDontWrite(pPage->pDbPage);
+ }
+ rc = btreeSetHasContent(pBt, iPage);
+ }
+ TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
+ goto freepage_out;
+ }
+ }
+
+ /* If control flows to this point, then it was not possible to add the
+ ** the page being freed as a leaf page of the first trunk in the free-list.
+ ** Possibly because the free-list is empty, or possibly because the
+ ** first trunk in the free-list is full. Either way, the page being freed
+ ** will become the new first trunk page in the free-list.
+ */
+ if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
+ goto freepage_out;
+ }
+ rc = sqlite3PagerWrite(pPage->pDbPage);
+ if( rc!=SQLITE_OK ){
+ goto freepage_out;
+ }
+ put4byte(pPage->aData, iTrunk);
+ put4byte(&pPage->aData[4], 0);
+ put4byte(&pPage1->aData[32], iPage);
+ TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk));
+
+freepage_out:
+ if( pPage ){
+ pPage->isInit = 0;
+ }
+ releasePage(pPage);
+ releasePage(pTrunk);
+ return rc;
+}
+static void freePage(MemPage *pPage, int *pRC){
+ if( (*pRC)==SQLITE_OK ){
+ *pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
+ }
+}
+
+/*
+** Free any overflow pages associated with the given Cell.
+*/
+static int clearCell(MemPage *pPage, unsigned char *pCell){
+ BtShared *pBt = pPage->pBt;
+ CellInfo info;
+ Pgno ovflPgno;
+ int rc;
+ int nOvfl;
+ u32 ovflPageSize;
+
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ btreeParseCellPtr(pPage, pCell, &info);
+ if( info.iOverflow==0 ){
+ return SQLITE_OK; /* No overflow pages. Return without doing anything */
+ }
+ if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
+ return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
+ }
+ ovflPgno = get4byte(&pCell[info.iOverflow]);
+ assert( pBt->usableSize > 4 );
+ ovflPageSize = pBt->usableSize - 4;
+ nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
+ assert( ovflPgno==0 || nOvfl>0 );
+ while( nOvfl-- ){
+ Pgno iNext = 0;
+ MemPage *pOvfl = 0;
+ if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
+ /* 0 is not a legal page number and page 1 cannot be an
+ ** overflow page. Therefore if ovflPgno<2 or past the end of the
+ ** file the database must be corrupt. */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( nOvfl ){
+ rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
+ if( rc ) return rc;
+ }
+
+ if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
+ && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
+ ){
+ /* There is no reason any cursor should have an outstanding reference
+ ** to an overflow page belonging to a cell that is being deleted/updated.
+ ** So if there exists more than one reference to this page, then it
+ ** must not really be an overflow page and the database must be corrupt.
+ ** It is helpful to detect this before calling freePage2(), as
+ ** freePage2() may zero the page contents if secure-delete mode is
+ ** enabled. If this 'overflow' page happens to be a page that the
+ ** caller is iterating through or using in some other way, this
+ ** can be problematic.
+ */
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = freePage2(pBt, pOvfl, ovflPgno);
+ }
+
+ if( pOvfl ){
+ sqlite3PagerUnref(pOvfl->pDbPage);
+ }
+ if( rc ) return rc;
+ ovflPgno = iNext;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Create the byte sequence used to represent a cell on page pPage
+** and write that byte sequence into pCell[]. Overflow pages are
+** allocated and filled in as necessary. The calling procedure
+** is responsible for making sure sufficient space has been allocated
+** for pCell[].
+**
+** Note that pCell does not necessary need to point to the pPage->aData
+** area. pCell might point to some temporary storage. The cell will
+** be constructed in this temporary area then copied into pPage->aData
+** later.
+*/
+static int fillInCell(
+ MemPage *pPage, /* The page that contains the cell */
+ unsigned char *pCell, /* Complete text of the cell */
+ const void *pKey, i64 nKey, /* The key */
+ const void *pData,int nData, /* The data */
+ int nZero, /* Extra zero bytes to append to pData */
+ int *pnSize /* Write cell size here */
+){
+ int nPayload;
+ const u8 *pSrc;
+ int nSrc, n, rc;
+ int spaceLeft;
+ MemPage *pOvfl = 0;
+ MemPage *pToRelease = 0;
+ unsigned char *pPrior;
+ unsigned char *pPayload;
+ BtShared *pBt = pPage->pBt;
+ Pgno pgnoOvfl = 0;
+ int nHeader;
+ CellInfo info;
+
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+
+ /* pPage is not necessarily writeable since pCell might be auxiliary
+ ** buffer space that is separate from the pPage buffer area */
+ assert( pCell<pPage->aData || pCell>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+ /* Fill in the header. */
+ nHeader = 0;
+ if( !pPage->leaf ){
+ nHeader += 4;
+ }
+ if( pPage->hasData ){
+ nHeader += putVarint(&pCell[nHeader], nData+nZero);
+ }else{
+ nData = nZero = 0;
+ }
+ nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey);
+ btreeParseCellPtr(pPage, pCell, &info);
+ assert( info.nHeader==nHeader );
+ assert( info.nKey==nKey );
+ assert( info.nData==(u32)(nData+nZero) );
+
+ /* Fill in the payload */
+ nPayload = nData + nZero;
+ if( pPage->intKey ){
+ pSrc = pData;
+ nSrc = nData;
+ nData = 0;
+ }else{
+ if( NEVER(nKey>0x7fffffff || pKey==0) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nPayload += (int)nKey;
+ pSrc = pKey;
+ nSrc = (int)nKey;
+ }
+ *pnSize = info.nSize;
+ spaceLeft = info.nLocal;
+ pPayload = &pCell[nHeader];
+ pPrior = &pCell[info.iOverflow];
+
+ while( nPayload>0 ){
+ if( spaceLeft==0 ){
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
+ if( pBt->autoVacuum ){
+ do{
+ pgnoOvfl++;
+ } while(
+ PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
+ );
+ }
+#endif
+ rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If the database supports auto-vacuum, and the second or subsequent
+ ** overflow page is being allocated, add an entry to the pointer-map
+ ** for that page now.
+ **
+ ** If this is the first overflow page, then write a partial entry
+ ** to the pointer-map. If we write nothing to this pointer-map slot,
+ ** then the optimistic overflow chain processing in clearCell()
+ ** may misinterpret the uninitialized values and delete the
+ ** wrong pages from the database.
+ */
+ if( pBt->autoVacuum && rc==SQLITE_OK ){
+ u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1);
+ ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc);
+ if( rc ){
+ releasePage(pOvfl);
+ }
+ }
+#endif
+ if( rc ){
+ releasePage(pToRelease);
+ return rc;
+ }
+
+ /* If pToRelease is not zero than pPrior points into the data area
+ ** of pToRelease. Make sure pToRelease is still writeable. */
+ assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+ /* If pPrior is part of the data area of pPage, then make sure pPage
+ ** is still writeable */
+ assert( pPrior<pPage->aData || pPrior>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+ put4byte(pPrior, pgnoOvfl);
+ releasePage(pToRelease);
+ pToRelease = pOvfl;
+ pPrior = pOvfl->aData;
+ put4byte(pPrior, 0);
+ pPayload = &pOvfl->aData[4];
+ spaceLeft = pBt->usableSize - 4;
+ }
+ n = nPayload;
+ if( n>spaceLeft ) n = spaceLeft;
+
+ /* If pToRelease is not zero than pPayload points into the data area
+ ** of pToRelease. Make sure pToRelease is still writeable. */
+ assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+ /* If pPayload is part of the data area of pPage, then make sure pPage
+ ** is still writeable */
+ assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+ if( nSrc>0 ){
+ if( n>nSrc ) n = nSrc;
+ assert( pSrc );
+ memcpy(pPayload, pSrc, n);
+ }else{
+ memset(pPayload, 0, n);
+ }
+ nPayload -= n;
+ pPayload += n;
+ pSrc += n;
+ nSrc -= n;
+ spaceLeft -= n;
+ if( nSrc==0 ){
+ nSrc = nData;
+ pSrc = pData;
+ }
+ }
+ releasePage(pToRelease);
+ return SQLITE_OK;
+}
+
+/*
+** Remove the i-th cell from pPage. This routine effects pPage only.
+** The cell content is not freed or deallocated. It is assumed that
+** the cell content has been copied someplace else. This routine just
+** removes the reference to the cell from pPage.
+**
+** "sz" must be the number of bytes in the cell.
+*/
+static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
+ u32 pc; /* Offset to cell content of cell being deleted */
+ u8 *data; /* pPage->aData */
+ u8 *ptr; /* Used to move bytes around within data[] */
+ u8 *endPtr; /* End of loop */
+ int rc; /* The return code */
+ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
+
+ if( *pRC ) return;
+
+ assert( idx>=0 && idx<pPage->nCell );
+ assert( sz==cellSize(pPage, idx) );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ data = pPage->aData;
+ ptr = &pPage->aCellIdx[2*idx];
+ pc = get2byte(ptr);
+ hdr = pPage->hdrOffset;
+ testcase( pc==get2byte(&data[hdr+5]) );
+ testcase( pc+sz==pPage->pBt->usableSize );
+ if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
+ *pRC = SQLITE_CORRUPT_BKPT;
+ return;
+ }
+ rc = freeSpace(pPage, pc, sz);
+ if( rc ){
+ *pRC = rc;
+ return;
+ }
+ endPtr = &pPage->aCellIdx[2*pPage->nCell - 2];
+ assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
+ while( ptr<endPtr ){
+ *(u16*)ptr = *(u16*)&ptr[2];
+ ptr += 2;
+ }
+ pPage->nCell--;
+ put2byte(&data[hdr+3], pPage->nCell);
+ pPage->nFree += 2;
+}
+
+/*
+** Insert a new cell on pPage at cell index "i". pCell points to the
+** content of the cell.
+**
+** If the cell content will fit on the page, then put it there. If it
+** will not fit, then make a copy of the cell content into pTemp if
+** pTemp is not null. Regardless of pTemp, allocate a new entry
+** in pPage->apOvfl[] and make it point to the cell content (either
+** in pTemp or the original pCell) and also record its index.
+** Allocating a new entry in pPage->aCell[] implies that
+** pPage->nOverflow is incremented.
+**
+** If nSkip is non-zero, then do not copy the first nSkip bytes of the
+** cell. The caller will overwrite them after this function returns. If
+** nSkip is non-zero, then pCell may not point to an invalid memory location
+** (but pCell+nSkip is always valid).
+*/
+static void insertCell(
+ MemPage *pPage, /* Page into which we are copying */
+ int i, /* New cell becomes the i-th cell of the page */
+ u8 *pCell, /* Content of the new cell */
+ int sz, /* Bytes of content in pCell */
+ u8 *pTemp, /* Temp storage space for pCell, if needed */
+ Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
+ int *pRC /* Read and write return code from here */
+){
+ int idx = 0; /* Where to write new cell content in data[] */
+ int j; /* Loop counter */
+ int end; /* First byte past the last cell pointer in data[] */
+ int ins; /* Index in data[] where new cell pointer is inserted */
+ int cellOffset; /* Address of first cell pointer in data[] */
+ u8 *data; /* The content of the whole page */
+ u8 *ptr; /* Used for moving information around in data[] */
+ u8 *endPtr; /* End of the loop */
+
+ int nSkip = (iChild ? 4 : 0);
+
+ if( *pRC ) return;
+
+ assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
+ assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 );
+ assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
+ assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ /* The cell should normally be sized correctly. However, when moving a
+ ** malformed cell from a leaf page to an interior page, if the cell size
+ ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
+ ** might be less than 8 (leaf-size + pointer) on the interior node. Hence
+ ** the term after the || in the following assert(). */
+ assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) );
+ if( pPage->nOverflow || sz+2>pPage->nFree ){
+ if( pTemp ){
+ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
+ pCell = pTemp;
+ }
+ if( iChild ){
+ put4byte(pCell, iChild);
+ }
+ j = pPage->nOverflow++;
+ assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) );
+ pPage->apOvfl[j] = pCell;
+ pPage->aiOvfl[j] = (u16)i;
+ }else{
+ int rc = sqlite3PagerWrite(pPage->pDbPage);
+ if( rc!=SQLITE_OK ){
+ *pRC = rc;
+ return;
+ }
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+ data = pPage->aData;
+ cellOffset = pPage->cellOffset;
+ end = cellOffset + 2*pPage->nCell;
+ ins = cellOffset + 2*i;
+ rc = allocateSpace(pPage, sz, &idx);
+ if( rc ){ *pRC = rc; return; }
+ /* The allocateSpace() routine guarantees the following two properties
+ ** if it returns success */
+ assert( idx >= end+2 );
+ assert( idx+sz <= (int)pPage->pBt->usableSize );
+ pPage->nCell++;
+ pPage->nFree -= (u16)(2 + sz);
+ memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
+ if( iChild ){
+ put4byte(&data[idx], iChild);
+ }
+ ptr = &data[end];
+ endPtr = &data[ins];
+ assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
+ while( ptr>endPtr ){
+ *(u16*)ptr = *(u16*)&ptr[-2];
+ ptr -= 2;
+ }
+ put2byte(&data[ins], idx);
+ put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pPage->pBt->autoVacuum ){
+ /* The cell may contain a pointer to an overflow page. If so, write
+ ** the entry for the overflow page into the pointer map.
+ */
+ ptrmapPutOvflPtr(pPage, pCell, pRC);
+ }
+#endif
+ }
+}
+
+/*
+** Add a list of cells to a page. The page should be initially empty.
+** The cells are guaranteed to fit on the page.
+*/
+static void assemblePage(
+ MemPage *pPage, /* The page to be assemblied */
+ int nCell, /* The number of cells to add to this page */
+ u8 **apCell, /* Pointers to cell bodies */
+ u16 *aSize /* Sizes of the cells */
+){
+ int i; /* Loop counter */
+ u8 *pCellptr; /* Address of next cell pointer */
+ int cellbody; /* Address of next cell body */
+ u8 * const data = pPage->aData; /* Pointer to data for pPage */
+ const int hdr = pPage->hdrOffset; /* Offset of header on pPage */
+ const int nUsable = pPage->pBt->usableSize; /* Usable size of page */
+
+ assert( pPage->nOverflow==0 );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( nCell>=0 && nCell<=(int)MX_CELL(pPage->pBt)
+ && (int)MX_CELL(pPage->pBt)<=10921);
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+
+ /* Check that the page has just been zeroed by zeroPage() */
+ assert( pPage->nCell==0 );
+ assert( get2byteNotZero(&data[hdr+5])==nUsable );
+
+ pCellptr = &pPage->aCellIdx[nCell*2];
+ cellbody = nUsable;
+ for(i=nCell-1; i>=0; i--){
+ u16 sz = aSize[i];
+ pCellptr -= 2;
+ cellbody -= sz;
+ put2byte(pCellptr, cellbody);
+ memcpy(&data[cellbody], apCell[i], sz);
+ }
+ put2byte(&data[hdr+3], nCell);
+ put2byte(&data[hdr+5], cellbody);
+ pPage->nFree -= (nCell*2 + nUsable - cellbody);
+ pPage->nCell = (u16)nCell;
+}
+
+/*
+** The following parameters determine how many adjacent pages get involved
+** in a balancing operation. NN is the number of neighbors on either side
+** of the page that participate in the balancing operation. NB is the
+** total number of pages that participate, including the target page and
+** NN neighbors on either side.
+**
+** The minimum value of NN is 1 (of course). Increasing NN above 1
+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+** in exchange for a larger degradation in INSERT and UPDATE performance.
+** The value of NN appears to give the best results overall.
+*/
+#define NN 1 /* Number of neighbors on either side of pPage */
+#define NB (NN*2+1) /* Total pages involved in the balance */
+
+
+#ifndef SQLITE_OMIT_QUICKBALANCE
+/*
+** This version of balance() handles the common special case where
+** a new entry is being inserted on the extreme right-end of the
+** tree, in other words, when the new entry will become the largest
+** entry in the tree.
+**
+** Instead of trying to balance the 3 right-most leaf pages, just add
+** a new page to the right-hand side and put the one new entry in
+** that page. This leaves the right side of the tree somewhat
+** unbalanced. But odds are that we will be inserting new entries
+** at the end soon afterwards so the nearly empty page will quickly
+** fill up. On average.
+**
+** pPage is the leaf page which is the right-most page in the tree.
+** pParent is its parent. pPage must have a single overflow entry
+** which is also the right-most entry on the page.
+**
+** The pSpace buffer is used to store a temporary copy of the divider
+** cell that will be inserted into pParent. Such a cell consists of a 4
+** byte page number followed by a variable length integer. In other
+** words, at most 13 bytes. Hence the pSpace buffer must be at
+** least 13 bytes in size.
+*/
+static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
+ BtShared *const pBt = pPage->pBt; /* B-Tree Database */
+ MemPage *pNew; /* Newly allocated page */
+ int rc; /* Return Code */
+ Pgno pgnoNew; /* Page number of pNew */
+
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ assert( pPage->nOverflow==1 );
+
+ /* This error condition is now caught prior to reaching this function */
+ if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;
+
+ /* Allocate a new page. This page will become the right-sibling of
+ ** pPage. Make the parent page writable, so that the new divider cell
+ ** may be inserted. If both these operations are successful, proceed.
+ */
+ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+
+ if( rc==SQLITE_OK ){
+
+ u8 *pOut = &pSpace[4];
+ u8 *pCell = pPage->apOvfl[0];
+ u16 szCell = cellSizePtr(pPage, pCell);
+ u8 *pStop;
+
+ assert( sqlite3PagerIswriteable(pNew->pDbPage) );
+ assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
+ zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
+ assemblePage(pNew, 1, &pCell, &szCell);
+
+ /* If this is an auto-vacuum database, update the pointer map
+ ** with entries for the new page, and any pointer from the
+ ** cell on the page to an overflow page. If either of these
+ ** operations fails, the return code is set, but the contents
+ ** of the parent page are still manipulated by thh code below.
+ ** That is Ok, at this point the parent page is guaranteed to
+ ** be marked as dirty. Returning an error code will cause a
+ ** rollback, undoing any changes made to the parent page.
+ */
+ if( ISAUTOVACUUM ){
+ ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc);
+ if( szCell>pNew->minLocal ){
+ ptrmapPutOvflPtr(pNew, pCell, &rc);
+ }
+ }
+
+ /* Create a divider cell to insert into pParent. The divider cell
+ ** consists of a 4-byte page number (the page number of pPage) and
+ ** a variable length key value (which must be the same value as the
+ ** largest key on pPage).
+ **
+ ** To find the largest key value on pPage, first find the right-most
+ ** cell on pPage. The first two fields of this cell are the
+ ** record-length (a variable length integer at most 32-bits in size)
+ ** and the key value (a variable length integer, may have any value).
+ ** The first of the while(...) loops below skips over the record-length
+ ** field. The second while(...) loop copies the key value from the
+ ** cell on pPage into the pSpace buffer.
+ */
+ pCell = findCell(pPage, pPage->nCell-1);
+ pStop = &pCell[9];
+ while( (*(pCell++)&0x80) && pCell<pStop );
+ pStop = &pCell[9];
+ while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop );
+
+ /* Insert the new divider cell into pParent. */
+ insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
+ 0, pPage->pgno, &rc);
+
+ /* Set the right-child pointer of pParent to point to the new page. */
+ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+
+ /* Release the reference to the new page. */
+ releasePage(pNew);
+ }
+
+ return rc;
+}
+#endif /* SQLITE_OMIT_QUICKBALANCE */
+
+#if 0
+/*
+** This function does not contribute anything to the operation of SQLite.
+** it is sometimes activated temporarily while debugging code responsible
+** for setting pointer-map entries.
+*/
+static int ptrmapCheckPages(MemPage **apPage, int nPage){
+ int i, j;
+ for(i=0; i<nPage; i++){
+ Pgno n;
+ u8 e;
+ MemPage *pPage = apPage[i];
+ BtShared *pBt = pPage->pBt;
+ assert( pPage->isInit );
+
+ for(j=0; j<pPage->nCell; j++){
+ CellInfo info;
+ u8 *z;
+
+ z = findCell(pPage, j);
+ btreeParseCellPtr(pPage, z, &info);
+ if( info.iOverflow ){
+ Pgno ovfl = get4byte(&z[info.iOverflow]);
+ ptrmapGet(pBt, ovfl, &e, &n);
+ assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 );
+ }
+ if( !pPage->leaf ){
+ Pgno child = get4byte(z);
+ ptrmapGet(pBt, child, &e, &n);
+ assert( n==pPage->pgno && e==PTRMAP_BTREE );
+ }
+ }
+ if( !pPage->leaf ){
+ Pgno child = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ ptrmapGet(pBt, child, &e, &n);
+ assert( n==pPage->pgno && e==PTRMAP_BTREE );
+ }
+ }
+ return 1;
+}
+#endif
+
+/*
+** This function is used to copy the contents of the b-tree node stored
+** on page pFrom to page pTo. If page pFrom was not a leaf page, then
+** the pointer-map entries for each child page are updated so that the
+** parent page stored in the pointer map is page pTo. If pFrom contained
+** any cells with overflow page pointers, then the corresponding pointer
+** map entries are also updated so that the parent page is page pTo.
+**
+** If pFrom is currently carrying any overflow cells (entries in the
+** MemPage.apOvfl[] array), they are not copied to pTo.
+**
+** Before returning, page pTo is reinitialized using btreeInitPage().
+**
+** The performance of this function is not critical. It is only used by
+** the balance_shallower() and balance_deeper() procedures, neither of
+** which are called often under normal circumstances.
+*/
+static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
+ if( (*pRC)==SQLITE_OK ){
+ BtShared * const pBt = pFrom->pBt;
+ u8 * const aFrom = pFrom->aData;
+ u8 * const aTo = pTo->aData;
+ int const iFromHdr = pFrom->hdrOffset;
+ int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
+ int rc;
+ int iData;
+
+
+ assert( pFrom->isInit );
+ assert( pFrom->nFree>=iToHdr );
+ assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize );
+
+ /* Copy the b-tree node content from page pFrom to page pTo. */
+ iData = get2byte(&aFrom[iFromHdr+5]);
+ memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
+ memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
+
+ /* Reinitialize page pTo so that the contents of the MemPage structure
+ ** match the new data. The initialization of pTo can actually fail under
+ ** fairly obscure circumstances, even though it is a copy of initialized
+ ** page pFrom.
+ */
+ pTo->isInit = 0;
+ rc = btreeInitPage(pTo);
+ if( rc!=SQLITE_OK ){
+ *pRC = rc;
+ return;
+ }
+
+ /* If this is an auto-vacuum database, update the pointer-map entries
+ ** for any b-tree or overflow pages that pTo now contains the pointers to.
+ */
+ if( ISAUTOVACUUM ){
+ *pRC = setChildPtrmaps(pTo);
+ }
+ }
+}
+
+/*
+** This routine redistributes cells on the iParentIdx'th child of pParent
+** (hereafter "the page") and up to 2 siblings so that all pages have about the
+** same amount of free space. Usually a single sibling on either side of the
+** page are used in the balancing, though both siblings might come from one
+** side if the page is the first or last child of its parent. If the page
+** has fewer than 2 siblings (something which can only happen if the page
+** is a root page or a child of a root page) then all available siblings
+** participate in the balancing.
+**
+** The number of siblings of the page might be increased or decreased by
+** one or two in an effort to keep pages nearly full but not over full.
+**
+** Note that when this routine is called, some of the cells on the page
+** might not actually be stored in MemPage.aData[]. This can happen
+** if the page is overfull. This routine ensures that all cells allocated
+** to the page and its siblings fit into MemPage.aData[] before returning.
+**
+** In the course of balancing the page and its siblings, cells may be
+** inserted into or removed from the parent page (pParent). Doing so
+** may cause the parent page to become overfull or underfull. If this
+** happens, it is the responsibility of the caller to invoke the correct
+** balancing routine to fix this problem (see the balance() routine).
+**
+** If this routine fails for any reason, it might leave the database
+** in a corrupted state. So if this routine fails, the database should
+** be rolled back.
+**
+** The third argument to this function, aOvflSpace, is a pointer to a
+** buffer big enough to hold one page. If while inserting cells into the parent
+** page (pParent) the parent page becomes overfull, this buffer is
+** used to store the parent's overflow cells. Because this function inserts
+** a maximum of four divider cells into the parent page, and the maximum
+** size of a cell stored within an internal node is always less than 1/4
+** of the page-size, the aOvflSpace[] buffer is guaranteed to be large
+** enough for all overflow cells.
+**
+** If aOvflSpace is set to a null pointer, this function returns
+** SQLITE_NOMEM.
+*/
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
+#pragma optimize("", off)
+#endif
+static int balance_nonroot(
+ MemPage *pParent, /* Parent page of siblings being balanced */
+ int iParentIdx, /* Index of "the page" in pParent */
+ u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */
+ int isRoot, /* True if pParent is a root-page */
+ int bBulk /* True if this call is part of a bulk load */
+){
+ BtShared *pBt; /* The whole database */
+ int nCell = 0; /* Number of cells in apCell[] */
+ int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */
+ int nNew = 0; /* Number of pages in apNew[] */
+ int nOld; /* Number of pages in apOld[] */
+ int i, j, k; /* Loop counters */
+ int nxDiv; /* Next divider slot in pParent->aCell[] */
+ int rc = SQLITE_OK; /* The return code */
+ u16 leafCorrection; /* 4 if pPage is a leaf. 0 if not */
+ int leafData; /* True if pPage is a leaf of a LEAFDATA tree */
+ int usableSpace; /* Bytes in pPage beyond the header */
+ int pageFlags; /* Value of pPage->aData[0] */
+ int subtotal; /* Subtotal of bytes in cells on one page */
+ int iSpace1 = 0; /* First unused byte of aSpace1[] */
+ int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */
+ int szScratch; /* Size of scratch memory requested */
+ MemPage *apOld[NB]; /* pPage and up to two siblings */
+ MemPage *apCopy[NB]; /* Private copies of apOld[] pages */
+ MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */
+ u8 *pRight; /* Location in parent of right-sibling pointer */
+ u8 *apDiv[NB-1]; /* Divider cells in pParent */
+ int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */
+ int szNew[NB+2]; /* Combined size of cells place on i-th page */
+ u8 **apCell = 0; /* All cells begin balanced */
+ u16 *szCell; /* Local size of all cells in apCell[] */
+ u8 *aSpace1; /* Space for copies of dividers cells */
+ Pgno pgno; /* Temp var to store a page number in */
+
+ pBt = pParent->pBt;
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+
+#if 0
+ TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
+#endif
+
+ /* At this point pParent may have at most one overflow cell. And if
+ ** this overflow cell is present, it must be the cell with
+ ** index iParentIdx. This scenario comes about when this function
+ ** is called (indirectly) from sqlite3BtreeDelete().
+ */
+ assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
+ assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );
+
+ if( !aOvflSpace ){
+ return SQLITE_NOMEM;
+ }
+
+ /* Find the sibling pages to balance. Also locate the cells in pParent
+ ** that divide the siblings. An attempt is made to find NN siblings on
+ ** either side of pPage. More siblings are taken from one side, however,
+ ** if there are fewer than NN siblings on the other side. If pParent
+ ** has NB or fewer children then all children of pParent are taken.
+ **
+ ** This loop also drops the divider cells from the parent page. This
+ ** way, the remainder of the function does not have to deal with any
+ ** overflow cells in the parent page, since if any existed they will
+ ** have already been removed.
+ */
+ i = pParent->nOverflow + pParent->nCell;
+ if( i<2 ){
+ nxDiv = 0;
+ }else{
+ assert( bBulk==0 || bBulk==1 );
+ if( iParentIdx==0 ){
+ nxDiv = 0;
+ }else if( iParentIdx==i ){
+ nxDiv = i-2+bBulk;
+ }else{
+ assert( bBulk==0 );
+ nxDiv = iParentIdx-1;
+ }
+ i = 2-bBulk;
+ }
+ nOld = i+1;
+ if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
+ pRight = &pParent->aData[pParent->hdrOffset+8];
+ }else{
+ pRight = findCell(pParent, i+nxDiv-pParent->nOverflow);
+ }
+ pgno = get4byte(pRight);
+ while( 1 ){
+ rc = getAndInitPage(pBt, pgno, &apOld[i]);
+ if( rc ){
+ memset(apOld, 0, (i+1)*sizeof(MemPage*));
+ goto balance_cleanup;
+ }
+ nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
+ if( (i--)==0 ) break;
+
+ if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
+ apDiv[i] = pParent->apOvfl[0];
+ pgno = get4byte(apDiv[i]);
+ szNew[i] = cellSizePtr(pParent, apDiv[i]);
+ pParent->nOverflow = 0;
+ }else{
+ apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
+ pgno = get4byte(apDiv[i]);
+ szNew[i] = cellSizePtr(pParent, apDiv[i]);
+
+ /* Drop the cell from the parent page. apDiv[i] still points to
+ ** the cell within the parent, even though it has been dropped.
+ ** This is safe because dropping a cell only overwrites the first
+ ** four bytes of it, and this function does not need the first
+ ** four bytes of the divider cell. So the pointer is safe to use
+ ** later on.
+ **
+ ** But not if we are in secure-delete mode. In secure-delete mode,
+ ** the dropCell() routine will overwrite the entire cell with zeroes.
+ ** In this case, temporarily copy the cell into the aOvflSpace[]
+ ** buffer. It will be copied out again as soon as the aSpace[] buffer
+ ** is allocated. */
+ if( pBt->btsFlags & BTS_SECURE_DELETE ){
+ int iOff;
+
+ iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
+ if( (iOff+szNew[i])>(int)pBt->usableSize ){
+ rc = SQLITE_CORRUPT_BKPT;
+ memset(apOld, 0, (i+1)*sizeof(MemPage*));
+ goto balance_cleanup;
+ }else{
+ memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
+ apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
+ }
+ }
+ dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
+ }
+ }
+
+ /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
+ ** alignment */
+ nMaxCells = (nMaxCells + 3)&~3;
+
+ /*
+ ** Allocate space for memory structures
+ */
+ k = pBt->pageSize + ROUND8(sizeof(MemPage));
+ szScratch =
+ nMaxCells*sizeof(u8*) /* apCell */
+ + nMaxCells*sizeof(u16) /* szCell */
+ + pBt->pageSize /* aSpace1 */
+ + k*nOld; /* Page copies (apCopy) */
+ apCell = sqlite3ScratchMalloc( szScratch );
+ if( apCell==0 ){
+ rc = SQLITE_NOMEM;
+ goto balance_cleanup;
+ }
+ szCell = (u16*)&apCell[nMaxCells];
+ aSpace1 = (u8*)&szCell[nMaxCells];
+ assert( EIGHT_BYTE_ALIGNMENT(aSpace1) );
+
+ /*
+ ** Load pointers to all cells on sibling pages and the divider cells
+ ** into the local apCell[] array. Make copies of the divider cells
+ ** into space obtained from aSpace1[] and remove the divider cells
+ ** from pParent.
+ **
+ ** If the siblings are on leaf pages, then the child pointers of the
+ ** divider cells are stripped from the cells before they are copied
+ ** into aSpace1[]. In this way, all cells in apCell[] are without
+ ** child pointers. If siblings are not leaves, then all cell in
+ ** apCell[] include child pointers. Either way, all cells in apCell[]
+ ** are alike.
+ **
+ ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf.
+ ** leafData: 1 if pPage holds key+data and pParent holds only keys.
+ */
+ leafCorrection = apOld[0]->leaf*4;
+ leafData = apOld[0]->hasData;
+ for(i=0; i<nOld; i++){
+ int limit;
+
+ /* Before doing anything else, take a copy of the i'th original sibling
+ ** The rest of this function will use data from the copies rather
+ ** that the original pages since the original pages will be in the
+ ** process of being overwritten. */
+ MemPage *pOld = apCopy[i] = (MemPage*)&aSpace1[pBt->pageSize + k*i];
+ memcpy(pOld, apOld[i], sizeof(MemPage));
+ pOld->aData = (void*)&pOld[1];
+ memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize);
+
+ limit = pOld->nCell+pOld->nOverflow;
+ if( pOld->nOverflow>0 ){
+ for(j=0; j<limit; j++){
+ assert( nCell<nMaxCells );
+ apCell[nCell] = findOverflowCell(pOld, j);
+ szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
+ nCell++;
+ }
+ }else{
+ u8 *aData = pOld->aData;
+ u16 maskPage = pOld->maskPage;
+ u16 cellOffset = pOld->cellOffset;
+ for(j=0; j<limit; j++){
+ assert( nCell<nMaxCells );
+ apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j);
+ szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
+ nCell++;
+ }
+ }
+ if( i<nOld-1 && !leafData){
+ u16 sz = (u16)szNew[i];
+ u8 *pTemp;
+ assert( nCell<nMaxCells );
+ szCell[nCell] = sz;
+ pTemp = &aSpace1[iSpace1];
+ iSpace1 += sz;
+ assert( sz<=pBt->maxLocal+23 );
+ assert( iSpace1 <= (int)pBt->pageSize );
+ memcpy(pTemp, apDiv[i], sz);
+ apCell[nCell] = pTemp+leafCorrection;
+ assert( leafCorrection==0 || leafCorrection==4 );
+ szCell[nCell] = szCell[nCell] - leafCorrection;
+ if( !pOld->leaf ){
+ assert( leafCorrection==0 );
+ assert( pOld->hdrOffset==0 );
+ /* The right pointer of the child page pOld becomes the left
+ ** pointer of the divider cell */
+ memcpy(apCell[nCell], &pOld->aData[8], 4);
+ }else{
+ assert( leafCorrection==4 );
+ if( szCell[nCell]<4 ){
+ /* Do not allow any cells smaller than 4 bytes. */
+ szCell[nCell] = 4;
+ }
+ }
+ nCell++;
+ }
+ }
+
+ /*
+ ** Figure out the number of pages needed to hold all nCell cells.
+ ** Store this number in "k". Also compute szNew[] which is the total
+ ** size of all cells on the i-th page and cntNew[] which is the index
+ ** in apCell[] of the cell that divides page i from page i+1.
+ ** cntNew[k] should equal nCell.
+ **
+ ** Values computed by this block:
+ **
+ ** k: The total number of sibling pages
+ ** szNew[i]: Spaced used on the i-th sibling page.
+ ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to
+ ** the right of the i-th sibling page.
+ ** usableSpace: Number of bytes of space available on each sibling.
+ **
+ */
+ usableSpace = pBt->usableSize - 12 + leafCorrection;
+ for(subtotal=k=i=0; i<nCell; i++){
+ assert( i<nMaxCells );
+ subtotal += szCell[i] + 2;
+ if( subtotal > usableSpace ){
+ szNew[k] = subtotal - szCell[i];
+ cntNew[k] = i;
+ if( leafData ){ i--; }
+ subtotal = 0;
+ k++;
+ if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
+ }
+ }
+ szNew[k] = subtotal;
+ cntNew[k] = nCell;
+ k++;
+
+ /*
+ ** The packing computed by the previous block is biased toward the siblings
+ ** on the left side. The left siblings are always nearly full, while the
+ ** right-most sibling might be nearly empty. This block of code attempts
+ ** to adjust the packing of siblings to get a better balance.
+ **
+ ** This adjustment is more than an optimization. The packing above might
+ ** be so out of balance as to be illegal. For example, the right-most
+ ** sibling might be completely empty. This adjustment is not optional.
+ */
+ for(i=k-1; i>0; i--){
+ int szRight = szNew[i]; /* Size of sibling on the right */
+ int szLeft = szNew[i-1]; /* Size of sibling on the left */
+ int r; /* Index of right-most cell in left sibling */
+ int d; /* Index of first cell to the left of right sibling */
+
+ r = cntNew[i-1] - 1;
+ d = r + 1 - leafData;
+ assert( d<nMaxCells );
+ assert( r<nMaxCells );
+ while( szRight==0
+ || (!bBulk && szRight+szCell[d]+2<=szLeft-(szCell[r]+2))
+ ){
+ szRight += szCell[d] + 2;
+ szLeft -= szCell[r] + 2;
+ cntNew[i-1]--;
+ r = cntNew[i-1] - 1;
+ d = r + 1 - leafData;
+ }
+ szNew[i] = szRight;
+ szNew[i-1] = szLeft;
+ }
+
+ /* Either we found one or more cells (cntnew[0])>0) or pPage is
+ ** a virtual root page. A virtual root page is when the real root
+ ** page is page 1 and we are the only child of that page.
+ **
+ ** UPDATE: The assert() below is not necessarily true if the database
+ ** file is corrupt. The corruption will be detected and reported later
+ ** in this procedure so there is no need to act upon it now.
+ */
+#if 0
+ assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) );
+#endif
+
+ TRACE(("BALANCE: old: %d %d %d ",
+ apOld[0]->pgno,
+ nOld>=2 ? apOld[1]->pgno : 0,
+ nOld>=3 ? apOld[2]->pgno : 0
+ ));
+
+ /*
+ ** Allocate k new pages. Reuse old pages where possible.
+ */
+ if( apOld[0]->pgno<=1 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto balance_cleanup;
+ }
+ pageFlags = apOld[0]->aData[0];
+ for(i=0; i<k; i++){
+ MemPage *pNew;
+ if( i<nOld ){
+ pNew = apNew[i] = apOld[i];
+ apOld[i] = 0;
+ rc = sqlite3PagerWrite(pNew->pDbPage);
+ nNew++;
+ if( rc ) goto balance_cleanup;
+ }else{
+ assert( i>0 );
+ rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
+ if( rc ) goto balance_cleanup;
+ apNew[i] = pNew;
+ nNew++;
+
+ /* Set the pointer-map entry for the new sibling page. */
+ if( ISAUTOVACUUM ){
+ ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc);
+ if( rc!=SQLITE_OK ){
+ goto balance_cleanup;
+ }
+ }
+ }
+ }
+
+ /* Free any old pages that were not reused as new pages.
+ */
+ while( i<nOld ){
+ freePage(apOld[i], &rc);
+ if( rc ) goto balance_cleanup;
+ releasePage(apOld[i]);
+ apOld[i] = 0;
+ i++;
+ }
+
+ /*
+ ** Put the new pages in accending order. This helps to
+ ** keep entries in the disk file in order so that a scan
+ ** of the table is a linear scan through the file. That
+ ** in turn helps the operating system to deliver pages
+ ** from the disk more rapidly.
+ **
+ ** An O(n^2) insertion sort algorithm is used, but since
+ ** n is never more than NB (a small constant), that should
+ ** not be a problem.
+ **
+ ** When NB==3, this one optimization makes the database
+ ** about 25% faster for large insertions and deletions.
+ */
+ for(i=0; i<k-1; i++){
+ int minV = apNew[i]->pgno;
+ int minI = i;
+ for(j=i+1; j<k; j++){
+ if( apNew[j]->pgno<(unsigned)minV ){
+ minI = j;
+ minV = apNew[j]->pgno;
+ }
+ }
+ if( minI>i ){
+ MemPage *pT;
+ pT = apNew[i];
+ apNew[i] = apNew[minI];
+ apNew[minI] = pT;
+ }
+ }
+ TRACE(("new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n",
+ apNew[0]->pgno, szNew[0],
+ nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0,
+ nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0,
+ nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0,
+ nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0));
+
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ put4byte(pRight, apNew[nNew-1]->pgno);
+
+ /*
+ ** Evenly distribute the data in apCell[] across the new pages.
+ ** Insert divider cells into pParent as necessary.
+ */
+ j = 0;
+ for(i=0; i<nNew; i++){
+ /* Assemble the new sibling page. */
+ MemPage *pNew = apNew[i];
+ assert( j<nMaxCells );
+ zeroPage(pNew, pageFlags);
+ assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
+ assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) );
+ assert( pNew->nOverflow==0 );
+
+ j = cntNew[i];
+
+ /* If the sibling page assembled above was not the right-most sibling,
+ ** insert a divider cell into the parent page.
+ */
+ assert( i<nNew-1 || j==nCell );
+ if( j<nCell ){
+ u8 *pCell;
+ u8 *pTemp;
+ int sz;
+
+ assert( j<nMaxCells );
+ pCell = apCell[j];
+ sz = szCell[j] + leafCorrection;
+ pTemp = &aOvflSpace[iOvflSpace];
+ if( !pNew->leaf ){
+ memcpy(&pNew->aData[8], pCell, 4);
+ }else if( leafData ){
+ /* If the tree is a leaf-data tree, and the siblings are leaves,
+ ** then there is no divider cell in apCell[]. Instead, the divider
+ ** cell consists of the integer key for the right-most cell of
+ ** the sibling-page assembled above only.
+ */
+ CellInfo info;
+ j--;
+ btreeParseCellPtr(pNew, apCell[j], &info);
+ pCell = pTemp;
+ sz = 4 + putVarint(&pCell[4], info.nKey);
+ pTemp = 0;
+ }else{
+ pCell -= 4;
+ /* Obscure case for non-leaf-data trees: If the cell at pCell was
+ ** previously stored on a leaf node, and its reported size was 4
+ ** bytes, then it may actually be smaller than this
+ ** (see btreeParseCellPtr(), 4 bytes is the minimum size of
+ ** any cell). But it is important to pass the correct size to
+ ** insertCell(), so reparse the cell now.
+ **
+ ** Note that this can never happen in an SQLite data file, as all
+ ** cells are at least 4 bytes. It only happens in b-trees used
+ ** to evaluate "IN (SELECT ...)" and similar clauses.
+ */
+ if( szCell[j]==4 ){
+ assert(leafCorrection==4);
+ sz = cellSizePtr(pParent, pCell);
+ }
+ }
+ iOvflSpace += sz;
+ assert( sz<=pBt->maxLocal+23 );
+ assert( iOvflSpace <= (int)pBt->pageSize );
+ insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc);
+ if( rc!=SQLITE_OK ) goto balance_cleanup;
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+
+ j++;
+ nxDiv++;
+ }
+ }
+ assert( j==nCell );
+ assert( nOld>0 );
+ assert( nNew>0 );
+ if( (pageFlags & PTF_LEAF)==0 ){
+ u8 *zChild = &apCopy[nOld-1]->aData[8];
+ memcpy(&apNew[nNew-1]->aData[8], zChild, 4);
+ }
+
+ if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){
+ /* The root page of the b-tree now contains no cells. The only sibling
+ ** page is the right-child of the parent. Copy the contents of the
+ ** child page into the parent, decreasing the overall height of the
+ ** b-tree structure by one. This is described as the "balance-shallower"
+ ** sub-algorithm in some documentation.
+ **
+ ** If this is an auto-vacuum database, the call to copyNodeContent()
+ ** sets all pointer-map entries corresponding to database image pages
+ ** for which the pointer is stored within the content being copied.
+ **
+ ** The second assert below verifies that the child page is defragmented
+ ** (it must be, as it was just reconstructed using assemblePage()). This
+ ** is important if the parent page happens to be page 1 of the database
+ ** image. */
+ assert( nNew==1 );
+ assert( apNew[0]->nFree ==
+ (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
+ );
+ copyNodeContent(apNew[0], pParent, &rc);
+ freePage(apNew[0], &rc);
+ }else if( ISAUTOVACUUM ){
+ /* Fix the pointer-map entries for all the cells that were shifted around.
+ ** There are several different types of pointer-map entries that need to
+ ** be dealt with by this routine. Some of these have been set already, but
+ ** many have not. The following is a summary:
+ **
+ ** 1) The entries associated with new sibling pages that were not
+ ** siblings when this function was called. These have already
+ ** been set. We don't need to worry about old siblings that were
+ ** moved to the free-list - the freePage() code has taken care
+ ** of those.
+ **
+ ** 2) The pointer-map entries associated with the first overflow
+ ** page in any overflow chains used by new divider cells. These
+ ** have also already been taken care of by the insertCell() code.
+ **
+ ** 3) If the sibling pages are not leaves, then the child pages of
+ ** cells stored on the sibling pages may need to be updated.
+ **
+ ** 4) If the sibling pages are not internal intkey nodes, then any
+ ** overflow pages used by these cells may need to be updated
+ ** (internal intkey nodes never contain pointers to overflow pages).
+ **
+ ** 5) If the sibling pages are not leaves, then the pointer-map
+ ** entries for the right-child pages of each sibling may need
+ ** to be updated.
+ **
+ ** Cases 1 and 2 are dealt with above by other code. The next
+ ** block deals with cases 3 and 4 and the one after that, case 5. Since
+ ** setting a pointer map entry is a relatively expensive operation, this
+ ** code only sets pointer map entries for child or overflow pages that have
+ ** actually moved between pages. */
+ MemPage *pNew = apNew[0];
+ MemPage *pOld = apCopy[0];
+ int nOverflow = pOld->nOverflow;
+ int iNextOld = pOld->nCell + nOverflow;
+ int iOverflow = (nOverflow ? pOld->aiOvfl[0] : -1);
+ j = 0; /* Current 'old' sibling page */
+ k = 0; /* Current 'new' sibling page */
+ for(i=0; i<nCell; i++){
+ int isDivider = 0;
+ while( i==iNextOld ){
+ /* Cell i is the cell immediately following the last cell on old
+ ** sibling page j. If the siblings are not leaf pages of an
+ ** intkey b-tree, then cell i was a divider cell. */
+ assert( j+1 < ArraySize(apCopy) );
+ assert( j+1 < nOld );
+ pOld = apCopy[++j];
+ iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow;
+ if( pOld->nOverflow ){
+ nOverflow = pOld->nOverflow;
+ iOverflow = i + !leafData + pOld->aiOvfl[0];
+ }
+ isDivider = !leafData;
+ }
+
+ assert(nOverflow>0 || iOverflow<i );
+ assert(nOverflow<2 || pOld->aiOvfl[0]==pOld->aiOvfl[1]-1);
+ assert(nOverflow<3 || pOld->aiOvfl[1]==pOld->aiOvfl[2]-1);
+ if( i==iOverflow ){
+ isDivider = 1;
+ if( (--nOverflow)>0 ){
+ iOverflow++;
+ }
+ }
+
+ if( i==cntNew[k] ){
+ /* Cell i is the cell immediately following the last cell on new
+ ** sibling page k. If the siblings are not leaf pages of an
+ ** intkey b-tree, then cell i is a divider cell. */
+ pNew = apNew[++k];
+ if( !leafData ) continue;
+ }
+ assert( j<nOld );
+ assert( k<nNew );
+
+ /* If the cell was originally divider cell (and is not now) or
+ ** an overflow cell, or if the cell was located on a different sibling
+ ** page before the balancing, then the pointer map entries associated
+ ** with any child or overflow pages need to be updated. */
+ if( isDivider || pOld->pgno!=pNew->pgno ){
+ if( !leafCorrection ){
+ ptrmapPut(pBt, get4byte(apCell[i]), PTRMAP_BTREE, pNew->pgno, &rc);
+ }
+ if( szCell[i]>pNew->minLocal ){
+ ptrmapPutOvflPtr(pNew, apCell[i], &rc);
+ }
+ }
+ }
+
+ if( !leafCorrection ){
+ for(i=0; i<nNew; i++){
+ u32 key = get4byte(&apNew[i]->aData[8]);
+ ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc);
+ }
+ }
+
+#if 0
+ /* The ptrmapCheckPages() contains assert() statements that verify that
+ ** all pointer map pages are set correctly. This is helpful while
+ ** debugging. This is usually disabled because a corrupt database may
+ ** cause an assert() statement to fail. */
+ ptrmapCheckPages(apNew, nNew);
+ ptrmapCheckPages(&pParent, 1);
+#endif
+ }
+
+ assert( pParent->isInit );
+ TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n",
+ nOld, nNew, nCell));
+
+ /*
+ ** Cleanup before returning.
+ */
+balance_cleanup:
+ sqlite3ScratchFree(apCell);
+ for(i=0; i<nOld; i++){
+ releasePage(apOld[i]);
+ }
+ for(i=0; i<nNew; i++){
+ releasePage(apNew[i]);
+ }
+
+ return rc;
+}
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
+#pragma optimize("", on)
+#endif
+
+
+/*
+** This function is called when the root page of a b-tree structure is
+** overfull (has one or more overflow pages).
+**
+** A new child page is allocated and the contents of the current root
+** page, including overflow cells, are copied into the child. The root
+** page is then overwritten to make it an empty page with the right-child
+** pointer pointing to the new page.
+**
+** Before returning, all pointer-map entries corresponding to pages
+** that the new child-page now contains pointers to are updated. The
+** entry corresponding to the new right-child pointer of the root
+** page is also updated.
+**
+** If successful, *ppChild is set to contain a reference to the child
+** page and SQLITE_OK is returned. In this case the caller is required
+** to call releasePage() on *ppChild exactly once. If an error occurs,
+** an error code is returned and *ppChild is set to 0.
+*/
+static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
+ int rc; /* Return value from subprocedures */
+ MemPage *pChild = 0; /* Pointer to a new child page */
+ Pgno pgnoChild = 0; /* Page number of the new child page */
+ BtShared *pBt = pRoot->pBt; /* The BTree */
+
+ assert( pRoot->nOverflow>0 );
+ assert( sqlite3_mutex_held(pBt->mutex) );
+
+ /* Make pRoot, the root page of the b-tree, writable. Allocate a new
+ ** page that will become the new right-child of pPage. Copy the contents
+ ** of the node stored on pRoot into the new child page.
+ */
+ rc = sqlite3PagerWrite(pRoot->pDbPage);
+ if( rc==SQLITE_OK ){
+ rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
+ copyNodeContent(pRoot, pChild, &rc);
+ if( ISAUTOVACUUM ){
+ ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
+ }
+ }
+ if( rc ){
+ *ppChild = 0;
+ releasePage(pChild);
+ return rc;
+ }
+ assert( sqlite3PagerIswriteable(pChild->pDbPage) );
+ assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
+ assert( pChild->nCell==pRoot->nCell );
+
+ TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));
+
+ /* Copy the overflow cells from pRoot to pChild */
+ memcpy(pChild->aiOvfl, pRoot->aiOvfl,
+ pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
+ memcpy(pChild->apOvfl, pRoot->apOvfl,
+ pRoot->nOverflow*sizeof(pRoot->apOvfl[0]));
+ pChild->nOverflow = pRoot->nOverflow;
+
+ /* Zero the contents of pRoot. Then install pChild as the right-child. */
+ zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF);
+ put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);
+
+ *ppChild = pChild;
+ return SQLITE_OK;
+}
+
+/*
+** The page that pCur currently points to has just been modified in
+** some way. This function figures out if this modification means the
+** tree needs to be balanced, and if so calls the appropriate balancing
+** routine. Balancing routines are:
+**
+** balance_quick()
+** balance_deeper()
+** balance_nonroot()
+*/
+static int balance(BtCursor *pCur){
+ int rc = SQLITE_OK;
+ const int nMin = pCur->pBt->usableSize * 2 / 3;
+ u8 aBalanceQuickSpace[13];
+ u8 *pFree = 0;
+
+ TESTONLY( int balance_quick_called = 0 );
+ TESTONLY( int balance_deeper_called = 0 );
+
+ do {
+ int iPage = pCur->iPage;
+ MemPage *pPage = pCur->apPage[iPage];
+
+ if( iPage==0 ){
+ if( pPage->nOverflow ){
+ /* The root page of the b-tree is overfull. In this case call the
+ ** balance_deeper() function to create a new child for the root-page
+ ** and copy the current contents of the root-page to it. The
+ ** next iteration of the do-loop will balance the child page.
+ */
+ assert( (balance_deeper_called++)==0 );
+ rc = balance_deeper(pPage, &pCur->apPage[1]);
+ if( rc==SQLITE_OK ){
+ pCur->iPage = 1;
+ pCur->aiIdx[0] = 0;
+ pCur->aiIdx[1] = 0;
+ assert( pCur->apPage[1]->nOverflow );
+ }
+ }else{
+ break;
+ }
+ }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
+ break;
+ }else{
+ MemPage * const pParent = pCur->apPage[iPage-1];
+ int const iIdx = pCur->aiIdx[iPage-1];
+
+ rc = sqlite3PagerWrite(pParent->pDbPage);
+ if( rc==SQLITE_OK ){
+#ifndef SQLITE_OMIT_QUICKBALANCE
+ if( pPage->hasData
+ && pPage->nOverflow==1
+ && pPage->aiOvfl[0]==pPage->nCell
+ && pParent->pgno!=1
+ && pParent->nCell==iIdx
+ ){
+ /* Call balance_quick() to create a new sibling of pPage on which
+ ** to store the overflow cell. balance_quick() inserts a new cell
+ ** into pParent, which may cause pParent overflow. If this
+ ** happens, the next interation of the do-loop will balance pParent
+ ** use either balance_nonroot() or balance_deeper(). Until this
+ ** happens, the overflow cell is stored in the aBalanceQuickSpace[]
+ ** buffer.
+ **
+ ** The purpose of the following assert() is to check that only a
+ ** single call to balance_quick() is made for each call to this
+ ** function. If this were not verified, a subtle bug involving reuse
+ ** of the aBalanceQuickSpace[] might sneak in.
+ */
+ assert( (balance_quick_called++)==0 );
+ rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
+ }else
+#endif
+ {
+ /* In this case, call balance_nonroot() to redistribute cells
+ ** between pPage and up to 2 of its sibling pages. This involves
+ ** modifying the contents of pParent, which may cause pParent to
+ ** become overfull or underfull. The next iteration of the do-loop
+ ** will balance the parent page to correct this.
+ **
+ ** If the parent page becomes overfull, the overflow cell or cells
+ ** are stored in the pSpace buffer allocated immediately below.
+ ** A subsequent iteration of the do-loop will deal with this by
+ ** calling balance_nonroot() (balance_deeper() may be called first,
+ ** but it doesn't deal with overflow cells - just moves them to a
+ ** different page). Once this subsequent call to balance_nonroot()
+ ** has completed, it is safe to release the pSpace buffer used by
+ ** the previous call, as the overflow cell data will have been
+ ** copied either into the body of a database page or into the new
+ ** pSpace buffer passed to the latter call to balance_nonroot().
+ */
+ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
+ rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints);
+ if( pFree ){
+ /* If pFree is not NULL, it points to the pSpace buffer used
+ ** by a previous call to balance_nonroot(). Its contents are
+ ** now stored either on real database pages or within the
+ ** new pSpace buffer, so it may be safely freed here. */
+ sqlite3PageFree(pFree);
+ }
+
+ /* The pSpace buffer will be freed after the next call to
+ ** balance_nonroot(), or just before this function returns, whichever
+ ** comes first. */
+ pFree = pSpace;
+ }
+ }
+
+ pPage->nOverflow = 0;
+
+ /* The next iteration of the do-loop balances the parent page. */
+ releasePage(pPage);
+ pCur->iPage--;
+ }
+ }while( rc==SQLITE_OK );
+
+ if( pFree ){
+ sqlite3PageFree(pFree);
+ }
+ return rc;
+}
+
+
+/*
+** Insert a new record into the BTree. The key is given by (pKey,nKey)
+** and the data is given by (pData,nData). The cursor is used only to
+** define what table the record should be inserted into. The cursor
+** is left pointing at a random location.
+**
+** For an INTKEY table, only the nKey value of the key is used. pKey is
+** ignored. For a ZERODATA table, the pData and nData are both ignored.
+**
+** If the seekResult parameter is non-zero, then a successful call to
+** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
+** been performed. seekResult is the search result returned (a negative
+** number if pCur points at an entry that is smaller than (pKey, nKey), or
+** a positive value if pCur points at an etry that is larger than
+** (pKey, nKey)).
+**
+** If the seekResult parameter is non-zero, then the caller guarantees that
+** cursor pCur is pointing at the existing copy of a row that is to be
+** overwritten. If the seekResult parameter is 0, then cursor pCur may
+** point to any entry or to no entry at all and so this function has to seek
+** the cursor before the new key can be inserted.
+*/
+SQLITE_PRIVATE int sqlite3BtreeInsert(
+ BtCursor *pCur, /* Insert data into the table of this cursor */
+ const void *pKey, i64 nKey, /* The key of the new record */
+ const void *pData, int nData, /* The data of the new record */
+ int nZero, /* Number of extra 0 bytes to append to data */
+ int appendBias, /* True if this is likely an append */
+ int seekResult /* Result of prior MovetoUnpacked() call */
+){
+ int rc;
+ int loc = seekResult; /* -1: before desired location +1: after */
+ int szNew = 0;
+ int idx;
+ MemPage *pPage;
+ Btree *p = pCur->pBtree;
+ BtShared *pBt = p->pBt;
+ unsigned char *oldCell;
+ unsigned char *newCell = 0;
+
+ if( pCur->eState==CURSOR_FAULT ){
+ assert( pCur->skipNext!=SQLITE_OK );
+ return pCur->skipNext;
+ }
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE
+ && (pBt->btsFlags & BTS_READ_ONLY)==0 );
+ assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
+
+ /* Assert that the caller has been consistent. If this cursor was opened
+ ** expecting an index b-tree, then the caller should be inserting blob
+ ** keys with no associated data. If the cursor was opened expecting an
+ ** intkey table, the caller should be inserting integer keys with a
+ ** blob of associated data. */
+ assert( (pKey==0)==(pCur->pKeyInfo==0) );
+
+ /* Save the positions of any other cursors open on this table.
+ **
+ ** In some cases, the call to btreeMoveto() below is a no-op. For
+ ** example, when inserting data into a table with auto-generated integer
+ ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
+ ** integer key to use. It then calls this function to actually insert the
+ ** data into the intkey B-Tree. In this case btreeMoveto() recognizes
+ ** that the cursor is already where it needs to be and returns without
+ ** doing any work. To avoid thwarting these optimizations, it is important
+ ** not to clear the cursor here.
+ */
+ rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
+ if( rc ) return rc;
+
+ /* If this is an insert into a table b-tree, invalidate any incrblob
+ ** cursors open on the row being replaced (assuming this is a replace
+ ** operation - if it is not, the following is a no-op). */
+ if( pCur->pKeyInfo==0 ){
+ invalidateIncrblobCursors(p, nKey, 0);
+ }
+
+ if( !loc ){
+ rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
+ if( rc ) return rc;
+ }
+ assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
+
+ pPage = pCur->apPage[pCur->iPage];
+ assert( pPage->intKey || nKey>=0 );
+ assert( pPage->leaf || !pPage->intKey );
+
+ TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
+ pCur->pgnoRoot, nKey, nData, pPage->pgno,
+ loc==0 ? "overwrite" : "new entry"));
+ assert( pPage->isInit );
+ allocateTempSpace(pBt);
+ newCell = pBt->pTmpSpace;
+ if( newCell==0 ) return SQLITE_NOMEM;
+ rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
+ if( rc ) goto end_insert;
+ assert( szNew==cellSizePtr(pPage, newCell) );
+ assert( szNew <= MX_CELL_SIZE(pBt) );
+ idx = pCur->aiIdx[pCur->iPage];
+ if( loc==0 ){
+ u16 szOld;
+ assert( idx<pPage->nCell );
+ rc = sqlite3PagerWrite(pPage->pDbPage);
+ if( rc ){
+ goto end_insert;
+ }
+ oldCell = findCell(pPage, idx);
+ if( !pPage->leaf ){
+ memcpy(newCell, oldCell, 4);
+ }
+ szOld = cellSizePtr(pPage, oldCell);
+ rc = clearCell(pPage, oldCell);
+ dropCell(pPage, idx, szOld, &rc);
+ if( rc ) goto end_insert;
+ }else if( loc<0 && pPage->nCell>0 ){
+ assert( pPage->leaf );
+ idx = ++pCur->aiIdx[pCur->iPage];
+ }else{
+ assert( pPage->leaf );
+ }
+ insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
+ assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
+
+ /* If no error has occurred and pPage has an overflow cell, call balance()
+ ** to redistribute the cells within the tree. Since balance() may move
+ ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
+ ** variables.
+ **
+ ** Previous versions of SQLite called moveToRoot() to move the cursor
+ ** back to the root page as balance() used to invalidate the contents
+ ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that,
+ ** set the cursor state to "invalid". This makes common insert operations
+ ** slightly faster.
+ **
+ ** There is a subtle but important optimization here too. When inserting
+ ** multiple records into an intkey b-tree using a single cursor (as can
+ ** happen while processing an "INSERT INTO ... SELECT" statement), it
+ ** is advantageous to leave the cursor pointing to the last entry in
+ ** the b-tree if possible. If the cursor is left pointing to the last
+ ** entry in the table, and the next row inserted has an integer key
+ ** larger than the largest existing key, it is possible to insert the
+ ** row without seeking the cursor. This can be a big performance boost.
+ */
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+ if( rc==SQLITE_OK && pPage->nOverflow ){
+ rc = balance(pCur);
+
+ /* Must make sure nOverflow is reset to zero even if the balance()
+ ** fails. Internal data structure corruption will result otherwise.
+ ** Also, set the cursor state to invalid. This stops saveCursorPosition()
+ ** from trying to save the current position of the cursor. */
+ pCur->apPage[pCur->iPage]->nOverflow = 0;
+ pCur->eState = CURSOR_INVALID;
+ }
+ assert( pCur->apPage[pCur->iPage]->nOverflow==0 );
+
+end_insert:
+ return rc;
+}
+
+/*
+** Delete the entry that the cursor is pointing to. The cursor
+** is left pointing at a arbitrary location.
+*/
+SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
+ Btree *p = pCur->pBtree;
+ BtShared *pBt = p->pBt;
+ int rc; /* Return code */
+ MemPage *pPage; /* Page to delete cell from */
+ unsigned char *pCell; /* Pointer to cell to delete */
+ int iCellIdx; /* Index of cell to delete */
+ int iCellDepth; /* Depth of node containing pCell */
+
+ assert( cursorHoldsMutex(pCur) );
+ assert( pBt->inTransaction==TRANS_WRITE );
+ assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
+ assert( pCur->wrFlag );
+ assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
+ assert( !hasReadConflicts(p, pCur->pgnoRoot) );
+
+ if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell)
+ || NEVER(pCur->eState!=CURSOR_VALID)
+ ){
+ return SQLITE_ERROR; /* Something has gone awry. */
+ }
+
+ iCellDepth = pCur->iPage;
+ iCellIdx = pCur->aiIdx[iCellDepth];
+ pPage = pCur->apPage[iCellDepth];
+ pCell = findCell(pPage, iCellIdx);
+
+ /* If the page containing the entry to delete is not a leaf page, move
+ ** the cursor to the largest entry in the tree that is smaller than
+ ** the entry being deleted. This cell will replace the cell being deleted
+ ** from the internal node. The 'previous' entry is used for this instead
+ ** of the 'next' entry, as the previous entry is always a part of the
+ ** sub-tree headed by the child page of the cell being deleted. This makes
+ ** balancing the tree following the delete operation easier. */
+ if( !pPage->leaf ){
+ int notUsed;
+ rc = sqlite3BtreePrevious(pCur, &notUsed);
+ if( rc ) return rc;
+ }
+
+ /* Save the positions of any other cursors open on this table before
+ ** making any modifications. Make the page containing the entry to be
+ ** deleted writable. Then free any overflow pages associated with the
+ ** entry and finally remove the cell itself from within the page.
+ */
+ rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
+ if( rc ) return rc;
+
+ /* If this is a delete operation to remove a row from a table b-tree,
+ ** invalidate any incrblob cursors open on the row being deleted. */
+ if( pCur->pKeyInfo==0 ){
+ invalidateIncrblobCursors(p, pCur->info.nKey, 0);
+ }
+
+ rc = sqlite3PagerWrite(pPage->pDbPage);
+ if( rc ) return rc;
+ rc = clearCell(pPage, pCell);
+ dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc);
+ if( rc ) return rc;
+
+ /* If the cell deleted was not located on a leaf page, then the cursor
+ ** is currently pointing to the largest entry in the sub-tree headed
+ ** by the child-page of the cell that was just deleted from an internal
+ ** node. The cell from the leaf node needs to be moved to the internal
+ ** node to replace the deleted cell. */
+ if( !pPage->leaf ){
+ MemPage *pLeaf = pCur->apPage[pCur->iPage];
+ int nCell;
+ Pgno n = pCur->apPage[iCellDepth+1]->pgno;
+ unsigned char *pTmp;
+
+ pCell = findCell(pLeaf, pLeaf->nCell-1);
+ nCell = cellSizePtr(pLeaf, pCell);
+ assert( MX_CELL_SIZE(pBt) >= nCell );
+
+ allocateTempSpace(pBt);
+ pTmp = pBt->pTmpSpace;
+
+ rc = sqlite3PagerWrite(pLeaf->pDbPage);
+ insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
+ dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
+ if( rc ) return rc;
+ }
+
+ /* Balance the tree. If the entry deleted was located on a leaf page,
+ ** then the cursor still points to that page. In this case the first
+ ** call to balance() repairs the tree, and the if(...) condition is
+ ** never true.
+ **
+ ** Otherwise, if the entry deleted was on an internal node page, then
+ ** pCur is pointing to the leaf page from which a cell was removed to
+ ** replace the cell deleted from the internal node. This is slightly
+ ** tricky as the leaf node may be underfull, and the internal node may
+ ** be either under or overfull. In this case run the balancing algorithm
+ ** on the leaf node first. If the balance proceeds far enough up the
+ ** tree that we can be sure that any problem in the internal node has
+ ** been corrected, so be it. Otherwise, after balancing the leaf node,
+ ** walk the cursor up the tree to the internal node and balance it as
+ ** well. */
+ rc = balance(pCur);
+ if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
+ while( pCur->iPage>iCellDepth ){
+ releasePage(pCur->apPage[pCur->iPage--]);
+ }
+ rc = balance(pCur);
+ }
+
+ if( rc==SQLITE_OK ){
+ moveToRoot(pCur);
+ }
+ return rc;
+}
+
+/*
+** Create a new BTree table. Write into *piTable the page
+** number for the root page of the new table.
+**
+** The type of type is determined by the flags parameter. Only the
+** following values of flags are currently in use. Other values for
+** flags might not work:
+**
+** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys
+** BTREE_ZERODATA Used for SQL indices
+*/
+static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
+ BtShared *pBt = p->pBt;
+ MemPage *pRoot;
+ Pgno pgnoRoot;
+ int rc;
+ int ptfFlags; /* Page-type flage for the root page of new table */
+
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( pBt->inTransaction==TRANS_WRITE );
+ assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
+
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
+ if( rc ){
+ return rc;
+ }
+#else
+ if( pBt->autoVacuum ){
+ Pgno pgnoMove; /* Move a page here to make room for the root-page */
+ MemPage *pPageMove; /* The page to move to. */
+
+ /* Creating a new table may probably require moving an existing database
+ ** to make room for the new tables root page. In case this page turns
+ ** out to be an overflow page, delete all overflow page-map caches
+ ** held by open cursors.
+ */
+ invalidateAllOverflowCache(pBt);
+
+ /* Read the value of meta[3] from the database to determine where the
+ ** root page of the new table should go. meta[3] is the largest root-page
+ ** created so far, so the new root-page is (meta[3]+1).
+ */
+ sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
+ pgnoRoot++;
+
+ /* The new root-page may not be allocated on a pointer-map page, or the
+ ** PENDING_BYTE page.
+ */
+ while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) ||
+ pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
+ pgnoRoot++;
+ }
+ assert( pgnoRoot>=3 );
+
+ /* Allocate a page. The page that currently resides at pgnoRoot will
+ ** be moved to the allocated page (unless the allocated page happens
+ ** to reside at pgnoRoot).
+ */
+ rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ if( pgnoMove!=pgnoRoot ){
+ /* pgnoRoot is the page that will be used for the root-page of
+ ** the new table (assuming an error did not occur). But we were
+ ** allocated pgnoMove. If required (i.e. if it was not allocated
+ ** by extending the file), the current page at position pgnoMove
+ ** is already journaled.
+ */
+ u8 eType = 0;
+ Pgno iPtrPage = 0;
+
+ releasePage(pPageMove);
+
+ /* Move the page currently at pgnoRoot to pgnoMove. */
+ rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
+ if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+ if( rc!=SQLITE_OK ){
+ releasePage(pRoot);
+ return rc;
+ }
+ assert( eType!=PTRMAP_ROOTPAGE );
+ assert( eType!=PTRMAP_FREEPAGE );
+ rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
+ releasePage(pRoot);
+
+ /* Obtain the page at pgnoRoot */
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = sqlite3PagerWrite(pRoot->pDbPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(pRoot);
+ return rc;
+ }
+ }else{
+ pRoot = pPageMove;
+ }
+
+ /* Update the pointer-map and meta-data with the new root-page number. */
+ ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc);
+ if( rc ){
+ releasePage(pRoot);
+ return rc;
+ }
+
+ /* When the new root page was allocated, page 1 was made writable in
+ ** order either to increase the database filesize, or to decrement the
+ ** freelist count. Hence, the sqlite3BtreeUpdateMeta() call cannot fail.
+ */
+ assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) );
+ rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot);
+ if( NEVER(rc) ){
+ releasePage(pRoot);
+ return rc;
+ }
+
+ }else{
+ rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
+ if( rc ) return rc;
+ }
+#endif
+ assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
+ if( createTabFlags & BTREE_INTKEY ){
+ ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF;
+ }else{
+ ptfFlags = PTF_ZERODATA | PTF_LEAF;
+ }
+ zeroPage(pRoot, ptfFlags);
+ sqlite3PagerUnref(pRoot->pDbPage);
+ assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 );
+ *piTable = (int)pgnoRoot;
+ return SQLITE_OK;
+}
+SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = btreeCreateTable(p, piTable, flags);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** Erase the given database page and all its children. Return
+** the page to the freelist.
+*/
+static int clearDatabasePage(
+ BtShared *pBt, /* The BTree that contains the table */
+ Pgno pgno, /* Page number to clear */
+ int freePageFlag, /* Deallocate page if true */
+ int *pnChange /* Add number of Cells freed to this counter */
+){
+ MemPage *pPage;
+ int rc;
+ unsigned char *pCell;
+ int i;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ if( pgno>btreePagecount(pBt) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ rc = getAndInitPage(pBt, pgno, &pPage);
+ if( rc ) return rc;
+ for(i=0; i<pPage->nCell; i++){
+ pCell = findCell(pPage, i);
+ if( !pPage->leaf ){
+ rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
+ if( rc ) goto cleardatabasepage_out;
+ }
+ rc = clearCell(pPage, pCell);
+ if( rc ) goto cleardatabasepage_out;
+ }
+ if( !pPage->leaf ){
+ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange);
+ if( rc ) goto cleardatabasepage_out;
+ }else if( pnChange ){
+ assert( pPage->intKey );
+ *pnChange += pPage->nCell;
+ }
+ if( freePageFlag ){
+ freePage(pPage, &rc);
+ }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
+ zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
+ }
+
+cleardatabasepage_out:
+ releasePage(pPage);
+ return rc;
+}
+
+/*
+** Delete all information from a single table in the database. iTable is
+** the page number of the root of the table. After this routine returns,
+** the root page is empty, but still exists.
+**
+** This routine will fail with SQLITE_LOCKED if there are any open
+** read cursors on the table. Open write cursors are moved to the
+** root of the table.
+**
+** If pnChange is not NULL, then table iTable must be an intkey table. The
+** integer value pointed to by pnChange is incremented by the number of
+** entries in the table.
+*/
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
+ int rc;
+ BtShared *pBt = p->pBt;
+ sqlite3BtreeEnter(p);
+ assert( p->inTrans==TRANS_WRITE );
+
+ rc = saveAllCursors(pBt, (Pgno)iTable, 0);
+
+ if( SQLITE_OK==rc ){
+ /* Invalidate all incrblob cursors open on table iTable (assuming iTable
+ ** is the root of a table b-tree - if it is not, the following call is
+ ** a no-op). */
+ invalidateIncrblobCursors(p, 0, 1);
+ rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
+ }
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+/*
+** Erase all information in a table and add the root of the table to
+** the freelist. Except, the root of the principle table (the one on
+** page 1) is never added to the freelist.
+**
+** This routine will fail with SQLITE_LOCKED if there are any open
+** cursors on the table.
+**
+** If AUTOVACUUM is enabled and the page at iTable is not the last
+** root page in the database file, then the last root page
+** in the database file is moved into the slot formerly occupied by
+** iTable and that last slot formerly occupied by the last root page
+** is added to the freelist instead of iTable. In this say, all
+** root pages are kept at the beginning of the database file, which
+** is necessary for AUTOVACUUM to work right. *piMoved is set to the
+** page number that used to be the last root page in the file before
+** the move. If no page gets moved, *piMoved is set to 0.
+** The last root page is recorded in meta[3] and the value of
+** meta[3] is updated by this procedure.
+*/
+static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
+ int rc;
+ MemPage *pPage = 0;
+ BtShared *pBt = p->pBt;
+
+ assert( sqlite3BtreeHoldsMutex(p) );
+ assert( p->inTrans==TRANS_WRITE );
+
+ /* It is illegal to drop a table if any cursors are open on the
+ ** database. This is because in auto-vacuum mode the backend may
+ ** need to move another root-page to fill a gap left by the deleted
+ ** root page. If an open cursor was using this page a problem would
+ ** occur.
+ **
+ ** This error is caught long before control reaches this point.
+ */
+ if( NEVER(pBt->pCursor) ){
+ sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
+ return SQLITE_LOCKED_SHAREDCACHE;
+ }
+
+ rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
+ if( rc ) return rc;
+ rc = sqlite3BtreeClearTable(p, iTable, 0);
+ if( rc ){
+ releasePage(pPage);
+ return rc;
+ }
+
+ *piMoved = 0;
+
+ if( iTable>1 ){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ freePage(pPage, &rc);
+ releasePage(pPage);
+#else
+ if( pBt->autoVacuum ){
+ Pgno maxRootPgno;
+ sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
+
+ if( iTable==maxRootPgno ){
+ /* If the table being dropped is the table with the largest root-page
+ ** number in the database, put the root page on the free list.
+ */
+ freePage(pPage, &rc);
+ releasePage(pPage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }else{
+ /* The table being dropped does not have the largest root-page
+ ** number in the database. So move the page that does into the
+ ** gap left by the deleted root-page.
+ */
+ MemPage *pMove;
+ releasePage(pPage);
+ rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
+ releasePage(pMove);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pMove = 0;
+ rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
+ freePage(pMove, &rc);
+ releasePage(pMove);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ *piMoved = maxRootPgno;
+ }
+
+ /* Set the new 'max-root-page' value in the database header. This
+ ** is the old value less one, less one more if that happens to
+ ** be a root-page number, less one again if that is the
+ ** PENDING_BYTE_PAGE.
+ */
+ maxRootPgno--;
+ while( maxRootPgno==PENDING_BYTE_PAGE(pBt)
+ || PTRMAP_ISPAGE(pBt, maxRootPgno) ){
+ maxRootPgno--;
+ }
+ assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
+
+ rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
+ }else{
+ freePage(pPage, &rc);
+ releasePage(pPage);
+ }
+#endif
+ }else{
+ /* If sqlite3BtreeDropTable was called on page 1.
+ ** This really never should happen except in a corrupt
+ ** database.
+ */
+ zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
+ releasePage(pPage);
+ }
+ return rc;
+}
+SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = btreeDropTable(p, iTable, piMoved);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+
+/*
+** This function may only be called if the b-tree connection already
+** has a read or write transaction open on the database.
+**
+** Read the meta-information out of a database file. Meta[0]
+** is the number of free pages currently in the database. Meta[1]
+** through meta[15] are available for use by higher layers. Meta[0]
+** is read-only, the others are read/write.
+**
+** The schema layer numbers meta values differently. At the schema
+** layer (and the SetCookie and ReadCookie opcodes) the number of
+** free pages is not visible. So Cookie[0] is the same as Meta[1].
+*/
+SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
+ BtShared *pBt = p->pBt;
+
+ sqlite3BtreeEnter(p);
+ assert( p->inTrans>TRANS_NONE );
+ assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
+ assert( pBt->pPage1 );
+ assert( idx>=0 && idx<=15 );
+
+ *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
+
+ /* If auto-vacuum is disabled in this build and this is an auto-vacuum
+ ** database, mark the database as read-only. */
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
+ pBt->btsFlags |= BTS_READ_ONLY;
+ }
+#endif
+
+ sqlite3BtreeLeave(p);
+}
+
+/*
+** Write meta-information back into the database. Meta[0] is
+** read-only and may not be written.
+*/
+SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
+ BtShared *pBt = p->pBt;
+ unsigned char *pP1;
+ int rc;
+ assert( idx>=1 && idx<=15 );
+ sqlite3BtreeEnter(p);
+ assert( p->inTrans==TRANS_WRITE );
+ assert( pBt->pPage1!=0 );
+ pP1 = pBt->pPage1->aData;
+ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ if( rc==SQLITE_OK ){
+ put4byte(&pP1[36 + idx*4], iMeta);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( idx==BTREE_INCR_VACUUM ){
+ assert( pBt->autoVacuum || iMeta==0 );
+ assert( iMeta==0 || iMeta==1 );
+ pBt->incrVacuum = (u8)iMeta;
+ }
+#endif
+ }
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_BTREECOUNT
+/*
+** The first argument, pCur, is a cursor opened on some b-tree. Count the
+** number of entries in the b-tree and write the result to *pnEntry.
+**
+** SQLITE_OK is returned if the operation is successfully executed.
+** Otherwise, if an error is encountered (i.e. an IO error or database
+** corruption) an SQLite error code is returned.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
+ i64 nEntry = 0; /* Value to return in *pnEntry */
+ int rc; /* Return code */
+
+ if( pCur->pgnoRoot==0 ){
+ *pnEntry = 0;
+ return SQLITE_OK;
+ }
+ rc = moveToRoot(pCur);
+
+ /* Unless an error occurs, the following loop runs one iteration for each
+ ** page in the B-Tree structure (not including overflow pages).
+ */
+ while( rc==SQLITE_OK ){
+ int iIdx; /* Index of child node in parent */
+ MemPage *pPage; /* Current page of the b-tree */
+
+ /* If this is a leaf page or the tree is not an int-key tree, then
+ ** this page contains countable entries. Increment the entry counter
+ ** accordingly.
+ */
+ pPage = pCur->apPage[pCur->iPage];
+ if( pPage->leaf || !pPage->intKey ){
+ nEntry += pPage->nCell;
+ }
+
+ /* pPage is a leaf node. This loop navigates the cursor so that it
+ ** points to the first interior cell that it points to the parent of
+ ** the next page in the tree that has not yet been visited. The
+ ** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
+ ** of the page, or to the number of cells in the page if the next page
+ ** to visit is the right-child of its parent.
+ **
+ ** If all pages in the tree have been visited, return SQLITE_OK to the
+ ** caller.
+ */
+ if( pPage->leaf ){
+ do {
+ if( pCur->iPage==0 ){
+ /* All pages of the b-tree have been visited. Return successfully. */
+ *pnEntry = nEntry;
+ return SQLITE_OK;
+ }
+ moveToParent(pCur);
+ }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
+
+ pCur->aiIdx[pCur->iPage]++;
+ pPage = pCur->apPage[pCur->iPage];
+ }
+
+ /* Descend to the child node of the cell that the cursor currently
+ ** points at. This is the right-child if (iIdx==pPage->nCell).
+ */
+ iIdx = pCur->aiIdx[pCur->iPage];
+ if( iIdx==pPage->nCell ){
+ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
+ }else{
+ rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx)));
+ }
+ }
+
+ /* An error has occurred. Return an error code. */
+ return rc;
+}
+#endif
+
+/*
+** Return the pager associated with a BTree. This routine is used for
+** testing and debugging only.
+*/
+SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){
+ return p->pBt->pPager;
+}
+
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
+/*
+** Append a message to the error message string.
+*/
+static void checkAppendMsg(
+ IntegrityCk *pCheck,
+ char *zMsg1,
+ const char *zFormat,
+ ...
+){
+ va_list ap;
+ if( !pCheck->mxErr ) return;
+ pCheck->mxErr--;
+ pCheck->nErr++;
+ va_start(ap, zFormat);
+ if( pCheck->errMsg.nChar ){
+ sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
+ }
+ if( zMsg1 ){
+ sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1);
+ }
+ sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
+ va_end(ap);
+ if( pCheck->errMsg.mallocFailed ){
+ pCheck->mallocFailed = 1;
+ }
+}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
+
+/*
+** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that
+** corresponds to page iPg is already set.
+*/
+static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){
+ assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
+ return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07)));
+}
+
+/*
+** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg.
+*/
+static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){
+ assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
+ pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07));
+}
+
+
+/*
+** Add 1 to the reference count for page iPage. If this is the second
+** reference to the page, add an error message to pCheck->zErrMsg.
+** Return 1 if there are 2 ore more references to the page and 0 if
+** if this is the first reference to the page.
+**
+** Also check that the page number is in bounds.
+*/
+static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){
+ if( iPage==0 ) return 1;
+ if( iPage>pCheck->nPage ){
+ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage);
+ return 1;
+ }
+ if( getPageReferenced(pCheck, iPage) ){
+ checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage);
+ return 1;
+ }
+ setPageReferenced(pCheck, iPage);
+ return 0;
+}
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Check that the entry in the pointer-map for page iChild maps to
+** page iParent, pointer type ptrType. If not, append an error message
+** to pCheck.
+*/
+static void checkPtrmap(
+ IntegrityCk *pCheck, /* Integrity check context */
+ Pgno iChild, /* Child page number */
+ u8 eType, /* Expected pointer map type */
+ Pgno iParent, /* Expected pointer map parent page number */
+ char *zContext /* Context description (used for error msg) */
+){
+ int rc;
+ u8 ePtrmapType;
+ Pgno iPtrmapParent;
+
+ rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
+ checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild);
+ return;
+ }
+
+ if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
+ checkAppendMsg(pCheck, zContext,
+ "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
+ iChild, eType, iParent, ePtrmapType, iPtrmapParent);
+ }
+}
+#endif
+
+/*
+** Check the integrity of the freelist or of an overflow page list.
+** Verify that the number of pages on the list is N.
+*/
+static void checkList(
+ IntegrityCk *pCheck, /* Integrity checking context */
+ int isFreeList, /* True for a freelist. False for overflow page list */
+ int iPage, /* Page number for first page in the list */
+ int N, /* Expected number of pages in the list */
+ char *zContext /* Context for error messages */
+){
+ int i;
+ int expected = N;
+ int iFirst = iPage;
+ while( N-- > 0 && pCheck->mxErr ){
+ DbPage *pOvflPage;
+ unsigned char *pOvflData;
+ if( iPage<1 ){
+ checkAppendMsg(pCheck, zContext,
+ "%d of %d pages missing from overflow list starting at %d",
+ N+1, expected, iFirst);
+ break;
+ }
+ if( checkRef(pCheck, iPage, zContext) ) break;
+ if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){
+ checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage);
+ break;
+ }
+ pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
+ if( isFreeList ){
+ int n = get4byte(&pOvflData[4]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pCheck->pBt->autoVacuum ){
+ checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext);
+ }
+#endif
+ if( n>(int)pCheck->pBt->usableSize/4-2 ){
+ checkAppendMsg(pCheck, zContext,
+ "freelist leaf count too big on page %d", iPage);
+ N--;
+ }else{
+ for(i=0; i<n; i++){
+ Pgno iFreePage = get4byte(&pOvflData[8+i*4]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pCheck->pBt->autoVacuum ){
+ checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext);
+ }
+#endif
+ checkRef(pCheck, iFreePage, zContext);
+ }
+ N -= n;
+ }
+ }
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ else{
+ /* If this database supports auto-vacuum and iPage is not the last
+ ** page in this overflow list, check that the pointer-map entry for
+ ** the following page matches iPage.
+ */
+ if( pCheck->pBt->autoVacuum && N>0 ){
+ i = get4byte(pOvflData);
+ checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext);
+ }
+ }
+#endif
+ iPage = get4byte(pOvflData);
+ sqlite3PagerUnref(pOvflPage);
+ }
+}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
+/*
+** Do various sanity checks on a single page of a tree. Return
+** the tree depth. Root pages return 0. Parents of root pages
+** return 1, and so forth.
+**
+** These checks are done:
+**
+** 1. Make sure that cells and freeblocks do not overlap
+** but combine to completely cover the page.
+** NO 2. Make sure cell keys are in order.
+** NO 3. Make sure no key is less than or equal to zLowerBound.
+** NO 4. Make sure no key is greater than or equal to zUpperBound.
+** 5. Check the integrity of overflow pages.
+** 6. Recursively call checkTreePage on all children.
+** 7. Verify that the depth of all children is the same.
+** 8. Make sure this page is at least 33% full or else it is
+** the root of the tree.
+*/
+static int checkTreePage(
+ IntegrityCk *pCheck, /* Context for the sanity check */
+ int iPage, /* Page number of the page to check */
+ char *zParentContext, /* Parent context */
+ i64 *pnParentMinKey,
+ i64 *pnParentMaxKey
+){
+ MemPage *pPage;
+ int i, rc, depth, d2, pgno, cnt;
+ int hdr, cellStart;
+ int nCell;
+ u8 *data;
+ BtShared *pBt;
+ int usableSize;
+ char zContext[100];
+ char *hit = 0;
+ i64 nMinKey = 0;
+ i64 nMaxKey = 0;
+
+ sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
+
+ /* Check that the page exists
+ */
+ pBt = pCheck->pBt;
+ usableSize = pBt->usableSize;
+ if( iPage==0 ) return 0;
+ if( checkRef(pCheck, iPage, zParentContext) ) return 0;
+ if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
+ checkAppendMsg(pCheck, zContext,
+ "unable to get the page. error code=%d", rc);
+ return 0;
+ }
+
+ /* Clear MemPage.isInit to make sure the corruption detection code in
+ ** btreeInitPage() is executed. */
+ pPage->isInit = 0;
+ if( (rc = btreeInitPage(pPage))!=0 ){
+ assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */
+ checkAppendMsg(pCheck, zContext,
+ "btreeInitPage() returns error code %d", rc);
+ releasePage(pPage);
+ return 0;
+ }
+
+ /* Check out all the cells.
+ */
+ depth = 0;
+ for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
+ u8 *pCell;
+ u32 sz;
+ CellInfo info;
+
+ /* Check payload overflow pages
+ */
+ sqlite3_snprintf(sizeof(zContext), zContext,
+ "On tree page %d cell %d: ", iPage, i);
+ pCell = findCell(pPage,i);
+ btreeParseCellPtr(pPage, pCell, &info);
+ sz = info.nData;
+ if( !pPage->intKey ) sz += (int)info.nKey;
+ /* For intKey pages, check that the keys are in order.
+ */
+ else if( i==0 ) nMinKey = nMaxKey = info.nKey;
+ else{
+ if( info.nKey <= nMaxKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
+ }
+ nMaxKey = info.nKey;
+ }
+ assert( sz==info.nPayload );
+ if( (sz>info.nLocal)
+ && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
+ ){
+ int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
+ Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext);
+ }
+#endif
+ checkList(pCheck, 0, pgnoOvfl, nPage, zContext);
+ }
+
+ /* Check sanity of left child page.
+ */
+ if( !pPage->leaf ){
+ pgno = get4byte(pCell);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
+ }
+#endif
+ d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
+ if( i>0 && d2!=depth ){
+ checkAppendMsg(pCheck, zContext, "Child page depth differs");
+ }
+ depth = d2;
+ }
+ }
+
+ if( !pPage->leaf ){
+ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ sqlite3_snprintf(sizeof(zContext), zContext,
+ "On page %d at right child: ", iPage);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
+ }
+#endif
+ checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
+ }
+
+ /* For intKey leaf pages, check that the min/max keys are in order
+ ** with any left/parent/right pages.
+ */
+ if( pPage->leaf && pPage->intKey ){
+ /* if we are a left child page */
+ if( pnParentMinKey ){
+ /* if we are the left most child page */
+ if( !pnParentMaxKey ){
+ if( nMaxKey > *pnParentMinKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (max larger than parent min of %lld)",
+ nMaxKey, *pnParentMinKey);
+ }
+ }else{
+ if( nMinKey <= *pnParentMinKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (min less than parent min of %lld)",
+ nMinKey, *pnParentMinKey);
+ }
+ if( nMaxKey > *pnParentMaxKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (max larger than parent max of %lld)",
+ nMaxKey, *pnParentMaxKey);
+ }
+ *pnParentMinKey = nMaxKey;
+ }
+ /* else if we're a right child page */
+ } else if( pnParentMaxKey ){
+ if( nMinKey <= *pnParentMaxKey ){
+ checkAppendMsg(pCheck, zContext,
+ "Rowid %lld out of order (min less than parent max of %lld)",
+ nMinKey, *pnParentMaxKey);
+ }
+ }
+ }
+
+ /* Check for complete coverage of the page
+ */
+ data = pPage->aData;
+ hdr = pPage->hdrOffset;
+ hit = sqlite3PageMalloc( pBt->pageSize );
+ if( hit==0 ){
+ pCheck->mallocFailed = 1;
+ }else{
+ int contentOffset = get2byteNotZero(&data[hdr+5]);
+ assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
+ memset(hit+contentOffset, 0, usableSize-contentOffset);
+ memset(hit, 1, contentOffset);
+ nCell = get2byte(&data[hdr+3]);
+ cellStart = hdr + 12 - 4*pPage->leaf;
+ for(i=0; i<nCell; i++){
+ int pc = get2byte(&data[cellStart+i*2]);
+ u32 size = 65536;
+ int j;
+ if( pc<=usableSize-4 ){
+ size = cellSizePtr(pPage, &data[pc]);
+ }
+ if( (int)(pc+size-1)>=usableSize ){
+ checkAppendMsg(pCheck, 0,
+ "Corruption detected in cell %d on page %d",i,iPage);
+ }else{
+ for(j=pc+size-1; j>=pc; j--) hit[j]++;
+ }
+ }
+ i = get2byte(&data[hdr+1]);
+ while( i>0 ){
+ int size, j;
+ assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */
+ size = get2byte(&data[i+2]);
+ assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */
+ for(j=i+size-1; j>=i; j--) hit[j]++;
+ j = get2byte(&data[i]);
+ assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */
+ assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
+ i = j;
+ }
+ for(i=cnt=0; i<usableSize; i++){
+ if( hit[i]==0 ){
+ cnt++;
+ }else if( hit[i]>1 ){
+ checkAppendMsg(pCheck, 0,
+ "Multiple uses for byte %d of page %d", i, iPage);
+ break;
+ }
+ }
+ if( cnt!=data[hdr+7] ){
+ checkAppendMsg(pCheck, 0,
+ "Fragmentation of %d bytes reported as %d on page %d",
+ cnt, data[hdr+7], iPage);
+ }
+ }
+ sqlite3PageFree(hit);
+ releasePage(pPage);
+ return depth+1;
+}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
+/*
+** This routine does a complete check of the given BTree file. aRoot[] is
+** an array of pages numbers were each page number is the root page of
+** a table. nRoot is the number of entries in aRoot.
+**
+** A read-only or read-write transaction must be opened before calling
+** this function.
+**
+** Write the number of error seen in *pnErr. Except for some memory
+** allocation errors, an error message held in memory obtained from
+** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
+** returned. If a memory allocation error occurs, NULL is returned.
+*/
+SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
+ Btree *p, /* The btree to be checked */
+ int *aRoot, /* An array of root pages numbers for individual trees */
+ int nRoot, /* Number of entries in aRoot[] */
+ int mxErr, /* Stop reporting errors after this many */
+ int *pnErr /* Write number of errors seen to this variable */
+){
+ Pgno i;
+ int nRef;
+ IntegrityCk sCheck;
+ BtShared *pBt = p->pBt;
+ char zErr[100];
+
+ sqlite3BtreeEnter(p);
+ assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
+ nRef = sqlite3PagerRefcount(pBt->pPager);
+ sCheck.pBt = pBt;
+ sCheck.pPager = pBt->pPager;
+ sCheck.nPage = btreePagecount(sCheck.pBt);
+ sCheck.mxErr = mxErr;
+ sCheck.nErr = 0;
+ sCheck.mallocFailed = 0;
+ *pnErr = 0;
+ if( sCheck.nPage==0 ){
+ sqlite3BtreeLeave(p);
+ return 0;
+ }
+
+ sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
+ if( !sCheck.aPgRef ){
+ *pnErr = 1;
+ sqlite3BtreeLeave(p);
+ return 0;
+ }
+ i = PENDING_BYTE_PAGE(pBt);
+ if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
+ sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
+ sCheck.errMsg.useMalloc = 2;
+
+ /* Check the integrity of the freelist
+ */
+ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
+ get4byte(&pBt->pPage1->aData[36]), "Main freelist: ");
+
+ /* Check all the tables.
+ */
+ for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
+ if( aRoot[i]==0 ) continue;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum && aRoot[i]>1 ){
+ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
+ }
+#endif
+ checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
+ }
+
+ /* Make sure every page in the file is referenced
+ */
+ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ if( getPageReferenced(&sCheck, i)==0 ){
+ checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
+ }
+#else
+ /* If the database supports auto-vacuum, make sure no tables contain
+ ** references to pointer-map pages.
+ */
+ if( getPageReferenced(&sCheck, i)==0 &&
+ (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
+ }
+ if( getPageReferenced(&sCheck, i)!=0 &&
+ (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i);
+ }
+#endif
+ }
+
+ /* Make sure this analysis did not leave any unref() pages.
+ ** This is an internal consistency check; an integrity check
+ ** of the integrity check.
+ */
+ if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
+ checkAppendMsg(&sCheck, 0,
+ "Outstanding page count goes from %d to %d during this analysis",
+ nRef, sqlite3PagerRefcount(pBt->pPager)
+ );
+ }
+
+ /* Clean up and report errors.
+ */
+ sqlite3BtreeLeave(p);
+ sqlite3_free(sCheck.aPgRef);
+ if( sCheck.mallocFailed ){
+ sqlite3StrAccumReset(&sCheck.errMsg);
+ *pnErr = sCheck.nErr+1;
+ return 0;
+ }
+ *pnErr = sCheck.nErr;
+ if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
+ return sqlite3StrAccumFinish(&sCheck.errMsg);
+}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+/*
+** Return the full pathname of the underlying database file. Return
+** an empty string if the database is in-memory or a TEMP database.
+**
+** The pager filename is invariant as long as the pager is
+** open so it is safe to access without the BtShared mutex.
+*/
+SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *p){
+ assert( p->pBt->pPager!=0 );
+ return sqlite3PagerFilename(p->pBt->pPager, 1);
+}
+
+/*
+** Return the pathname of the journal file for this database. The return
+** value of this routine is the same regardless of whether the journal file
+** has been created or not.
+**
+** The pager journal filename is invariant as long as the pager is
+** open so it is safe to access without the BtShared mutex.
+*/
+SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){
+ assert( p->pBt->pPager!=0 );
+ return sqlite3PagerJournalname(p->pBt->pPager);
+}
+
+/*
+** Return non-zero if a transaction is active.
+*/
+SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree *p){
+ assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
+ return (p && (p->inTrans==TRANS_WRITE));
+}
+
+#ifndef SQLITE_OMIT_WAL
+/*
+** Run a checkpoint on the Btree passed as the first argument.
+**
+** Return SQLITE_LOCKED if this or any other connection has an open
+** transaction on the shared-cache the argument Btree is connected to.
+**
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
+ int rc = SQLITE_OK;
+ if( p ){
+ BtShared *pBt = p->pBt;
+ sqlite3BtreeEnter(p);
+ if( pBt->inTransaction!=TRANS_NONE ){
+ rc = SQLITE_LOCKED;
+ }else{
+ rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
+ }
+ sqlite3BtreeLeave(p);
+ }
+ return rc;
+}
+#endif
+
+/*
+** Return non-zero if a read (or write) transaction is active.
+*/
+SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree *p){
+ assert( p );
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ return p->inTrans!=TRANS_NONE;
+}
+
+SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){
+ assert( p );
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ return p->nBackup!=0;
+}
+
+/*
+** This function returns a pointer to a blob of memory associated with
+** a single shared-btree. The memory is used by client code for its own
+** purposes (for example, to store a high-level schema associated with
+** the shared-btree). The btree layer manages reference counting issues.
+**
+** The first time this is called on a shared-btree, nBytes bytes of memory
+** are allocated, zeroed, and returned to the caller. For each subsequent
+** call the nBytes parameter is ignored and a pointer to the same blob
+** of memory returned.
+**
+** If the nBytes parameter is 0 and the blob of memory has not yet been
+** allocated, a null pointer is returned. If the blob has already been
+** allocated, it is returned as normal.
+**
+** Just before the shared-btree is closed, the function passed as the
+** xFree argument when the memory allocation was made is invoked on the
+** blob of allocated memory. The xFree function should not call sqlite3_free()
+** on the memory, the btree layer does that.
+*/
+SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
+ BtShared *pBt = p->pBt;
+ sqlite3BtreeEnter(p);
+ if( !pBt->pSchema && nBytes ){
+ pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
+ pBt->xFreeSchema = xFree;
+ }
+ sqlite3BtreeLeave(p);
+ return pBt->pSchema;
+}
+
+/*
+** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
+** btree as the argument handle holds an exclusive lock on the
+** sqlite_master table. Otherwise SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){
+ int rc;
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ sqlite3BtreeEnter(p);
+ rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
+ assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE );
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/*
+** Obtain a lock on the table whose root page is iTab. The
+** lock is a write lock if isWritelock is true or a read lock
+** if it is false.
+*/
+SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
+ int rc = SQLITE_OK;
+ assert( p->inTrans!=TRANS_NONE );
+ if( p->sharable ){
+ u8 lockType = READ_LOCK + isWriteLock;
+ assert( READ_LOCK+1==WRITE_LOCK );
+ assert( isWriteLock==0 || isWriteLock==1 );
+
+ sqlite3BtreeEnter(p);
+ rc = querySharedCacheTableLock(p, iTab, lockType);
+ if( rc==SQLITE_OK ){
+ rc = setSharedCacheTableLock(p, iTab, lockType);
+ }
+ sqlite3BtreeLeave(p);
+ }
+ return rc;
+}
+#endif
+
+#ifndef SQLITE_OMIT_INCRBLOB
+/*
+** Argument pCsr must be a cursor opened for writing on an
+** INTKEY table currently pointing at a valid table entry.
+** This function modifies the data stored as part of that entry.
+**
+** Only the data content may only be modified, it is not possible to
+** change the length of the data stored. If this function is called with
+** parameters that attempt to write past the end of the existing data,
+** no modifications are made and SQLITE_CORRUPT is returned.
+*/
+SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
+ int rc;
+ assert( cursorHoldsMutex(pCsr) );
+ assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
+ assert( pCsr->isIncrblobHandle );
+
+ rc = restoreCursorPosition(pCsr);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ assert( pCsr->eState!=CURSOR_REQUIRESEEK );
+ if( pCsr->eState!=CURSOR_VALID ){
+ return SQLITE_ABORT;
+ }
+
+ /* Check some assumptions:
+ ** (a) the cursor is open for writing,
+ ** (b) there is a read/write transaction open,
+ ** (c) the connection holds a write-lock on the table (if required),
+ ** (d) there are no conflicting read-locks, and
+ ** (e) the cursor points at a valid row of an intKey table.
+ */
+ if( !pCsr->wrFlag ){
+ return SQLITE_READONLY;
+ }
+ assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
+ && pCsr->pBt->inTransaction==TRANS_WRITE );
+ assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
+ assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
+ assert( pCsr->apPage[pCsr->iPage]->intKey );
+
+ return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
+}
+
+/*
+** Set a flag on this cursor to cache the locations of pages from the
+** overflow list for the current row. This is used by cursors opened
+** for incremental blob IO only.
+**
+** This function sets a flag only. The actual page location cache
+** (stored in BtCursor.aOverflow[]) is allocated and used by function
+** accessPayload() (the worker function for sqlite3BtreeData() and
+** sqlite3BtreePutData()).
+*/
+SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+ invalidateOverflowCache(pCur);
+ pCur->isIncrblobHandle = 1;
+}
+#endif
+
+/*
+** Set both the "read version" (single byte at byte offset 18) and
+** "write version" (single byte at byte offset 19) fields in the database
+** header to iVersion.
+*/
+SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
+ BtShared *pBt = pBtree->pBt;
+ int rc; /* Return code */
+
+ assert( iVersion==1 || iVersion==2 );
+
+ /* If setting the version fields to 1, do not automatically open the
+ ** WAL connection, even if the version fields are currently set to 2.
+ */
+ pBt->btsFlags &= ~BTS_NO_WAL;
+ if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
+
+ rc = sqlite3BtreeBeginTrans(pBtree, 0);
+ if( rc==SQLITE_OK ){
+ u8 *aData = pBt->pPage1->aData;
+ if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
+ rc = sqlite3BtreeBeginTrans(pBtree, 2);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ if( rc==SQLITE_OK ){
+ aData[18] = (u8)iVersion;
+ aData[19] = (u8)iVersion;
+ }
+ }
+ }
+ }
+
+ pBt->btsFlags &= ~BTS_NO_WAL;
+ return rc;
+}
+
+/*
+** set the mask of hint flags for cursor pCsr. Currently the only valid
+** values are 0 and BTREE_BULKLOAD.
+*/
+SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
+ assert( mask==BTREE_BULKLOAD || mask==0 );
+ pCsr->hints = mask;
+}
+
+/************** End of btree.c ***********************************************/
+/************** Begin file backup.c ******************************************/
+/*
+** 2009 January 28
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the implementation of the sqlite3_backup_XXX()
+** API functions and the related features.
+*/
+
+/* Macro to find the minimum of two numeric values.
+*/
+#ifndef MIN
+# define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+/*
+** Structure allocated for each backup operation.
+*/
+struct sqlite3_backup {
+ sqlite3* pDestDb; /* Destination database handle */
+ Btree *pDest; /* Destination b-tree file */
+ u32 iDestSchema; /* Original schema cookie in destination */
+ int bDestLocked; /* True once a write-transaction is open on pDest */
+
+ Pgno iNext; /* Page number of the next source page to copy */
+ sqlite3* pSrcDb; /* Source database handle */
+ Btree *pSrc; /* Source b-tree file */
+
+ int rc; /* Backup process error code */
+
+ /* These two variables are set by every call to backup_step(). They are
+ ** read by calls to backup_remaining() and backup_pagecount().
+ */
+ Pgno nRemaining; /* Number of pages left to copy */
+ Pgno nPagecount; /* Total number of pages to copy */
+
+ int isAttached; /* True once backup has been registered with pager */
+ sqlite3_backup *pNext; /* Next backup associated with source pager */
+};
+
+/*
+** THREAD SAFETY NOTES:
+**
+** Once it has been created using backup_init(), a single sqlite3_backup
+** structure may be accessed via two groups of thread-safe entry points:
+**
+** * Via the sqlite3_backup_XXX() API function backup_step() and
+** backup_finish(). Both these functions obtain the source database
+** handle mutex and the mutex associated with the source BtShared
+** structure, in that order.
+**
+** * Via the BackupUpdate() and BackupRestart() functions, which are
+** invoked by the pager layer to report various state changes in
+** the page cache associated with the source database. The mutex
+** associated with the source database BtShared structure will always
+** be held when either of these functions are invoked.
+**
+** The other sqlite3_backup_XXX() API functions, backup_remaining() and
+** backup_pagecount() are not thread-safe functions. If they are called
+** while some other thread is calling backup_step() or backup_finish(),
+** the values returned may be invalid. There is no way for a call to
+** BackupUpdate() or BackupRestart() to interfere with backup_remaining()
+** or backup_pagecount().
+**
+** Depending on the SQLite configuration, the database handles and/or
+** the Btree objects may have their own mutexes that require locking.
+** Non-sharable Btrees (in-memory databases for example), do not have
+** associated mutexes.
+*/
+
+/*
+** Return a pointer corresponding to database zDb (i.e. "main", "temp")
+** in connection handle pDb. If such a database cannot be found, return
+** a NULL pointer and write an error message to pErrorDb.
+**
+** If the "temp" database is requested, it may need to be opened by this
+** function. If an error occurs while doing so, return 0 and write an
+** error message to pErrorDb.
+*/
+static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
+ int i = sqlite3FindDbName(pDb, zDb);
+
+ if( i==1 ){
+ Parse *pParse;
+ int rc = 0;
+ pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse));
+ if( pParse==0 ){
+ sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory");
+ rc = SQLITE_NOMEM;
+ }else{
+ pParse->db = pDb;
+ if( sqlite3OpenTempDatabase(pParse) ){
+ sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
+ rc = SQLITE_ERROR;
+ }
+ sqlite3DbFree(pErrorDb, pParse->zErrMsg);
+ sqlite3StackFree(pErrorDb, pParse);
+ }
+ if( rc ){
+ return 0;
+ }
+ }
+
+ if( i<0 ){
+ sqlite3Error(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb);
+ return 0;
+ }
+
+ return pDb->aDb[i].pBt;
+}
+
+/*
+** Attempt to set the page size of the destination to match the page size
+** of the source.
+*/
+static int setDestPgsz(sqlite3_backup *p){
+ int rc;
+ rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
+ return rc;
+}
+
+/*
+** Create an sqlite3_backup process to copy the contents of zSrcDb from
+** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
+** a pointer to the new sqlite3_backup object.
+**
+** If an error occurs, NULL is returned and an error code and error message
+** stored in database handle pDestDb.
+*/
+SQLITE_API sqlite3_backup *sqlite3_backup_init(
+ sqlite3* pDestDb, /* Database to write to */
+ const char *zDestDb, /* Name of database within pDestDb */
+ sqlite3* pSrcDb, /* Database connection to read from */
+ const char *zSrcDb /* Name of database within pSrcDb */
+){
+ sqlite3_backup *p; /* Value to return */
+
+ /* Lock the source database handle. The destination database
+ ** handle is not locked in this routine, but it is locked in
+ ** sqlite3_backup_step(). The user is required to ensure that no
+ ** other thread accesses the destination handle for the duration
+ ** of the backup operation. Any attempt to use the destination
+ ** database connection while a backup is in progress may cause
+ ** a malfunction or a deadlock.
+ */
+ sqlite3_mutex_enter(pSrcDb->mutex);
+ sqlite3_mutex_enter(pDestDb->mutex);
+
+ if( pSrcDb==pDestDb ){
+ sqlite3Error(
+ pDestDb, SQLITE_ERROR, "source and destination must be distinct"
+ );
+ p = 0;
+ }else {
+ /* Allocate space for a new sqlite3_backup object...
+ ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
+ ** call to sqlite3_backup_init() and is destroyed by a call to
+ ** sqlite3_backup_finish(). */
+ p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
+ if( !p ){
+ sqlite3Error(pDestDb, SQLITE_NOMEM, 0);
+ }
+ }
+
+ /* If the allocation succeeded, populate the new object. */
+ if( p ){
+ p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
+ p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
+ p->pDestDb = pDestDb;
+ p->pSrcDb = pSrcDb;
+ p->iNext = 1;
+ p->isAttached = 0;
+
+ if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){
+ /* One (or both) of the named databases did not exist or an OOM
+ ** error was hit. The error has already been written into the
+ ** pDestDb handle. All that is left to do here is free the
+ ** sqlite3_backup structure.
+ */
+ sqlite3_free(p);
+ p = 0;
+ }
+ }
+ if( p ){
+ p->pSrc->nBackup++;
+ }
+
+ sqlite3_mutex_leave(pDestDb->mutex);
+ sqlite3_mutex_leave(pSrcDb->mutex);
+ return p;
+}
+
+/*
+** Argument rc is an SQLite error code. Return true if this error is
+** considered fatal if encountered during a backup operation. All errors
+** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED.
+*/
+static int isFatalError(int rc){
+ return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED));
+}
+
+/*
+** Parameter zSrcData points to a buffer containing the data for
+** page iSrcPg from the source database. Copy this data into the
+** destination database.
+*/
+static int backupOnePage(
+ sqlite3_backup *p, /* Backup handle */
+ Pgno iSrcPg, /* Source database page to backup */
+ const u8 *zSrcData, /* Source database page data */
+ int bUpdate /* True for an update, false otherwise */
+){
+ Pager * const pDestPager = sqlite3BtreePager(p->pDest);
+ const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
+ int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
+ const int nCopy = MIN(nSrcPgsz, nDestPgsz);
+ const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
+#ifdef SQLITE_HAS_CODEC
+ /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
+ ** guaranteed that the shared-mutex is held by this thread, handle
+ ** p->pSrc may not actually be the owner. */
+ int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
+ int nDestReserve = sqlite3BtreeGetReserve(p->pDest);
+#endif
+ int rc = SQLITE_OK;
+ i64 iOff;
+
+ assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
+ assert( p->bDestLocked );
+ assert( !isFatalError(p->rc) );
+ assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
+ assert( zSrcData );
+
+ /* Catch the case where the destination is an in-memory database and the
+ ** page sizes of the source and destination differ.
+ */
+ if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
+ rc = SQLITE_READONLY;
+ }
+
+#ifdef SQLITE_HAS_CODEC
+ /* Backup is not possible if the page size of the destination is changing
+ ** and a codec is in use.
+ */
+ if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
+ rc = SQLITE_READONLY;
+ }
+
+ /* Backup is not possible if the number of bytes of reserve space differ
+ ** between source and destination. If there is a difference, try to
+ ** fix the destination to agree with the source. If that is not possible,
+ ** then the backup cannot proceed.
+ */
+ if( nSrcReserve!=nDestReserve ){
+ u32 newPgsz = nSrcPgsz;
+ rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve);
+ if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY;
+ }
+#endif
+
+ /* This loop runs once for each destination page spanned by the source
+ ** page. For each iteration, variable iOff is set to the byte offset
+ ** of the destination page.
+ */
+ for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
+ DbPage *pDestPg = 0;
+ Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
+ if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
+ if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg))
+ && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
+ ){
+ const u8 *zIn = &zSrcData[iOff%nSrcPgsz];
+ u8 *zDestData = sqlite3PagerGetData(pDestPg);
+ u8 *zOut = &zDestData[iOff%nDestPgsz];
+
+ /* Copy the data from the source page into the destination page.
+ ** Then clear the Btree layer MemPage.isInit flag. Both this module
+ ** and the pager code use this trick (clearing the first byte
+ ** of the page 'extra' space to invalidate the Btree layers
+ ** cached parse of the page). MemPage.isInit is marked
+ ** "MUST BE FIRST" for this purpose.
+ */
+ memcpy(zOut, zIn, nCopy);
+ ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
+ if( iOff==0 && bUpdate==0 ){
+ sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
+ }
+ }
+ sqlite3PagerUnref(pDestPg);
+ }
+
+ return rc;
+}
+
+/*
+** If pFile is currently larger than iSize bytes, then truncate it to
+** exactly iSize bytes. If pFile is not larger than iSize bytes, then
+** this function is a no-op.
+**
+** Return SQLITE_OK if everything is successful, or an SQLite error
+** code if an error occurs.
+*/
+static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
+ i64 iCurrent;
+ int rc = sqlite3OsFileSize(pFile, &iCurrent);
+ if( rc==SQLITE_OK && iCurrent>iSize ){
+ rc = sqlite3OsTruncate(pFile, iSize);
+ }
+ return rc;
+}
+
+/*
+** Register this backup object with the associated source pager for
+** callbacks when pages are changed or the cache invalidated.
+*/
+static void attachBackupObject(sqlite3_backup *p){
+ sqlite3_backup **pp;
+ assert( sqlite3BtreeHoldsMutex(p->pSrc) );
+ pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
+ p->pNext = *pp;
+ *pp = p;
+ p->isAttached = 1;
+}
+
+/*
+** Copy nPage pages from the source b-tree to the destination.
+*/
+SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
+ int rc;
+ int destMode; /* Destination journal mode */
+ int pgszSrc = 0; /* Source page size */
+ int pgszDest = 0; /* Destination page size */
+
+ sqlite3_mutex_enter(p->pSrcDb->mutex);
+ sqlite3BtreeEnter(p->pSrc);
+ if( p->pDestDb ){
+ sqlite3_mutex_enter(p->pDestDb->mutex);
+ }
+
+ rc = p->rc;
+ if( !isFatalError(rc) ){
+ Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
+ Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
+ int ii; /* Iterator variable */
+ int nSrcPage = -1; /* Size of source db in pages */
+ int bCloseTrans = 0; /* True if src db requires unlocking */
+
+ /* If the source pager is currently in a write-transaction, return
+ ** SQLITE_BUSY immediately.
+ */
+ if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
+ rc = SQLITE_BUSY;
+ }else{
+ rc = SQLITE_OK;
+ }
+
+ /* Lock the destination database, if it is not locked already. */
+ if( SQLITE_OK==rc && p->bDestLocked==0
+ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
+ ){
+ p->bDestLocked = 1;
+ sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
+ }
+
+ /* If there is no open read-transaction on the source database, open
+ ** one now. If a transaction is opened here, then it will be closed
+ ** before this function exits.
+ */
+ if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
+ rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
+ bCloseTrans = 1;
+ }
+
+ /* Do not allow backup if the destination database is in WAL mode
+ ** and the page sizes are different between source and destination */
+ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
+ pgszDest = sqlite3BtreeGetPageSize(p->pDest);
+ destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
+ if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
+ rc = SQLITE_READONLY;
+ }
+
+ /* Now that there is a read-lock on the source database, query the
+ ** source pager for the number of pages in the database.
+ */
+ nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
+ assert( nSrcPage>=0 );
+ for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
+ const Pgno iSrcPg = p->iNext; /* Source page number */
+ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
+ DbPage *pSrcPg; /* Source page object */
+ rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
+ if( rc==SQLITE_OK ){
+ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
+ sqlite3PagerUnref(pSrcPg);
+ }
+ }
+ p->iNext++;
+ }
+ if( rc==SQLITE_OK ){
+ p->nPagecount = nSrcPage;
+ p->nRemaining = nSrcPage+1-p->iNext;
+ if( p->iNext>(Pgno)nSrcPage ){
+ rc = SQLITE_DONE;
+ }else if( !p->isAttached ){
+ attachBackupObject(p);
+ }
+ }
+
+ /* Update the schema version field in the destination database. This
+ ** is to make sure that the schema-version really does change in
+ ** the case where the source and destination databases have the
+ ** same schema version.
+ */
+ if( rc==SQLITE_DONE ){
+ if( nSrcPage==0 ){
+ rc = sqlite3BtreeNewDb(p->pDest);
+ nSrcPage = 1;
+ }
+ if( rc==SQLITE_OK || rc==SQLITE_DONE ){
+ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+ }
+ if( rc==SQLITE_OK ){
+ if( p->pDestDb ){
+ sqlite3ResetAllSchemasOfConnection(p->pDestDb);
+ }
+ if( destMode==PAGER_JOURNALMODE_WAL ){
+ rc = sqlite3BtreeSetVersion(p->pDest, 2);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ int nDestTruncate;
+ /* Set nDestTruncate to the final number of pages in the destination
+ ** database. The complication here is that the destination page
+ ** size may be different to the source page size.
+ **
+ ** If the source page size is smaller than the destination page size,
+ ** round up. In this case the call to sqlite3OsTruncate() below will
+ ** fix the size of the file. However it is important to call
+ ** sqlite3PagerTruncateImage() here so that any pages in the
+ ** destination file that lie beyond the nDestTruncate page mark are
+ ** journalled by PagerCommitPhaseOne() before they are destroyed
+ ** by the file truncation.
+ */
+ assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
+ assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
+ if( pgszSrc<pgszDest ){
+ int ratio = pgszDest/pgszSrc;
+ nDestTruncate = (nSrcPage+ratio-1)/ratio;
+ if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
+ nDestTruncate--;
+ }
+ }else{
+ nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
+ }
+ assert( nDestTruncate>0 );
+
+ if( pgszSrc<pgszDest ){
+ /* If the source page-size is smaller than the destination page-size,
+ ** two extra things may need to happen:
+ **
+ ** * The destination may need to be truncated, and
+ **
+ ** * Data stored on the pages immediately following the
+ ** pending-byte page in the source database may need to be
+ ** copied into the destination database.
+ */
+ const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
+ sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
+ Pgno iPg;
+ int nDstPage;
+ i64 iOff;
+ i64 iEnd;
+
+ assert( pFile );
+ assert( nDestTruncate==0
+ || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
+ nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
+ && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
+ ));
+
+ /* This block ensures that all data required to recreate the original
+ ** database has been stored in the journal for pDestPager and the
+ ** journal synced to disk. So at this point we may safely modify
+ ** the database file in any way, knowing that if a power failure
+ ** occurs, the original database will be reconstructed from the
+ ** journal file. */
+ sqlite3PagerPagecount(pDestPager, &nDstPage);
+ for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
+ if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
+ DbPage *pPg;
+ rc = sqlite3PagerGet(pDestPager, iPg, &pPg);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pPg);
+ sqlite3PagerUnref(pPg);
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+ }
+
+ /* Write the extra pages and truncate the database file as required */
+ iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
+ for(
+ iOff=PENDING_BYTE+pgszSrc;
+ rc==SQLITE_OK && iOff<iEnd;
+ iOff+=pgszSrc
+ ){
+ PgHdr *pSrcPg = 0;
+ const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
+ rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
+ if( rc==SQLITE_OK ){
+ u8 *zData = sqlite3PagerGetData(pSrcPg);
+ rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
+ }
+ sqlite3PagerUnref(pSrcPg);
+ }
+ if( rc==SQLITE_OK ){
+ rc = backupTruncateFile(pFile, iSize);
+ }
+
+ /* Sync the database file to disk. */
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSync(pDestPager);
+ }
+ }else{
+ sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
+ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
+ }
+
+ /* Finish committing the transaction to the destination database. */
+ if( SQLITE_OK==rc
+ && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
+ ){
+ rc = SQLITE_DONE;
+ }
+ }
+ }
+
+ /* If bCloseTrans is true, then this function opened a read transaction
+ ** on the source database. Close the read transaction here. There is
+ ** no need to check the return values of the btree methods here, as
+ ** "committing" a read-only transaction cannot fail.
+ */
+ if( bCloseTrans ){
+ TESTONLY( int rc2 );
+ TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
+ TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
+ assert( rc2==SQLITE_OK );
+ }
+
+ if( rc==SQLITE_IOERR_NOMEM ){
+ rc = SQLITE_NOMEM;
+ }
+ p->rc = rc;
+ }
+ if( p->pDestDb ){
+ sqlite3_mutex_leave(p->pDestDb->mutex);
+ }
+ sqlite3BtreeLeave(p->pSrc);
+ sqlite3_mutex_leave(p->pSrcDb->mutex);
+ return rc;
+}
+
+/*
+** Release all resources associated with an sqlite3_backup* handle.
+*/
+SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
+ sqlite3_backup **pp; /* Ptr to head of pagers backup list */
+ sqlite3 *pSrcDb; /* Source database connection */
+ int rc; /* Value to return */
+
+ /* Enter the mutexes */
+ if( p==0 ) return SQLITE_OK;
+ pSrcDb = p->pSrcDb;
+ sqlite3_mutex_enter(pSrcDb->mutex);
+ sqlite3BtreeEnter(p->pSrc);
+ if( p->pDestDb ){
+ sqlite3_mutex_enter(p->pDestDb->mutex);
+ }
+
+ /* Detach this backup from the source pager. */
+ if( p->pDestDb ){
+ p->pSrc->nBackup--;
+ }
+ if( p->isAttached ){
+ pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
+ while( *pp!=p ){
+ pp = &(*pp)->pNext;
+ }
+ *pp = p->pNext;
+ }
+
+ /* If a transaction is still open on the Btree, roll it back. */
+ sqlite3BtreeRollback(p->pDest, SQLITE_OK);
+
+ /* Set the error code of the destination database handle. */
+ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
+ sqlite3Error(p->pDestDb, rc, 0);
+
+ /* Exit the mutexes and free the backup context structure. */
+ if( p->pDestDb ){
+ sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
+ }
+ sqlite3BtreeLeave(p->pSrc);
+ if( p->pDestDb ){
+ /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
+ ** call to sqlite3_backup_init() and is destroyed by a call to
+ ** sqlite3_backup_finish(). */
+ sqlite3_free(p);
+ }
+ sqlite3LeaveMutexAndCloseZombie(pSrcDb);
+ return rc;
+}
+
+/*
+** Return the number of pages still to be backed up as of the most recent
+** call to sqlite3_backup_step().
+*/
+SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){
+ return p->nRemaining;
+}
+
+/*
+** Return the total number of pages in the source database as of the most
+** recent call to sqlite3_backup_step().
+*/
+SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){
+ return p->nPagecount;
+}
+
+/*
+** This function is called after the contents of page iPage of the
+** source database have been modified. If page iPage has already been
+** copied into the destination database, then the data written to the
+** destination is now invalidated. The destination copy of iPage needs
+** to be updated with the new data before the backup operation is
+** complete.
+**
+** It is assumed that the mutex associated with the BtShared object
+** corresponding to the source database is held when this function is
+** called.
+*/
+SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
+ sqlite3_backup *p; /* Iterator variable */
+ for(p=pBackup; p; p=p->pNext){
+ assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
+ if( !isFatalError(p->rc) && iPage<p->iNext ){
+ /* The backup process p has already copied page iPage. But now it
+ ** has been modified by a transaction on the source pager. Copy
+ ** the new data into the backup.
+ */
+ int rc;
+ assert( p->pDestDb );
+ sqlite3_mutex_enter(p->pDestDb->mutex);
+ rc = backupOnePage(p, iPage, aData, 1);
+ sqlite3_mutex_leave(p->pDestDb->mutex);
+ assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
+ if( rc!=SQLITE_OK ){
+ p->rc = rc;
+ }
+ }
+ }
+}
+
+/*
+** Restart the backup process. This is called when the pager layer
+** detects that the database has been modified by an external database
+** connection. In this case there is no way of knowing which of the
+** pages that have been copied into the destination database are still
+** valid and which are not, so the entire process needs to be restarted.
+**
+** It is assumed that the mutex associated with the BtShared object
+** corresponding to the source database is held when this function is
+** called.
+*/
+SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *pBackup){
+ sqlite3_backup *p; /* Iterator variable */
+ for(p=pBackup; p; p=p->pNext){
+ assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
+ p->iNext = 1;
+ }
+}
+
+#ifndef SQLITE_OMIT_VACUUM
+/*
+** Copy the complete content of pBtFrom into pBtTo. A transaction
+** must be active for both files.
+**
+** The size of file pTo may be reduced by this operation. If anything
+** goes wrong, the transaction on pTo is rolled back. If successful, the
+** transaction is committed before returning.
+*/
+SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
+ int rc;
+ sqlite3_file *pFd; /* File descriptor for database pTo */
+ sqlite3_backup b;
+ sqlite3BtreeEnter(pTo);
+ sqlite3BtreeEnter(pFrom);
+
+ assert( sqlite3BtreeIsInTrans(pTo) );
+ pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
+ if( pFd->pMethods ){
+ i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
+ rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte);
+ if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
+ if( rc ) goto copy_finished;
+ }
+
+ /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set
+ ** to 0. This is used by the implementations of sqlite3_backup_step()
+ ** and sqlite3_backup_finish() to detect that they are being called
+ ** from this function, not directly by the user.
+ */
+ memset(&b, 0, sizeof(b));
+ b.pSrcDb = pFrom->db;
+ b.pSrc = pFrom;
+ b.pDest = pTo;
+ b.iNext = 1;
+
+ /* 0x7FFFFFFF is the hard limit for the number of pages in a database
+ ** file. By passing this as the number of pages to copy to
+ ** sqlite3_backup_step(), we can guarantee that the copy finishes
+ ** within a single call (unless an error occurs). The assert() statement
+ ** checks this assumption - (p->rc) should be set to either SQLITE_DONE
+ ** or an error code.
+ */
+ sqlite3_backup_step(&b, 0x7FFFFFFF);
+ assert( b.rc!=SQLITE_OK );
+ rc = sqlite3_backup_finish(&b);
+ if( rc==SQLITE_OK ){
+ pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
+ }else{
+ sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
+ }
+
+ assert( sqlite3BtreeIsInTrans(pTo)==0 );
+copy_finished:
+ sqlite3BtreeLeave(pFrom);
+ sqlite3BtreeLeave(pTo);
+ return rc;
+}
+#endif /* SQLITE_OMIT_VACUUM */
+
+/************** End of backup.c **********************************************/
+/************** Begin file vdbemem.c *****************************************/
+/*
+** 2004 May 26
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code use to manipulate "Mem" structure. A "Mem"
+** stores a single value in the VDBE. Mem is an opaque structure visible
+** only within the VDBE. Interface routines refer to a Mem using the
+** name sqlite_value
+*/
+
+/*
+** If pMem is an object with a valid string representation, this routine
+** ensures the internal encoding for the string representation is
+** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
+**
+** If pMem is not a string object, or the encoding of the string
+** representation is already stored using the requested encoding, then this
+** routine is a no-op.
+**
+** SQLITE_OK is returned if the conversion is successful (or not required).
+** SQLITE_NOMEM may be returned if a malloc() fails during conversion
+** between formats.
+*/
+SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
+#ifndef SQLITE_OMIT_UTF16
+ int rc;
+#endif
+ assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
+ || desiredEnc==SQLITE_UTF16BE );
+ if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
+ return SQLITE_OK;
+ }
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+#ifdef SQLITE_OMIT_UTF16
+ return SQLITE_ERROR;
+#else
+
+ /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
+ ** then the encoding of the value may not have changed.
+ */
+ rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc);
+ assert(rc==SQLITE_OK || rc==SQLITE_NOMEM);
+ assert(rc==SQLITE_OK || pMem->enc!=desiredEnc);
+ assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
+ return rc;
+#endif
+}
+
+/*
+** Make sure pMem->z points to a writable allocation of at least
+** n bytes.
+**
+** If the third argument passed to this function is true, then memory
+** cell pMem must contain a string or blob. In this case the content is
+** preserved. Otherwise, if the third parameter to this function is false,
+** any current string or blob value may be discarded.
+**
+** This function sets the MEM_Dyn flag and clears any xDel callback.
+** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
+** not set, Mem.n is zeroed.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
+ assert( 1 >=
+ ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
+ (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
+ ((pMem->flags&MEM_Ephem) ? 1 : 0) +
+ ((pMem->flags&MEM_Static) ? 1 : 0)
+ );
+ assert( (pMem->flags&MEM_RowSet)==0 );
+
+ /* If the preserve flag is set to true, then the memory cell must already
+ ** contain a valid string or blob value. */
+ assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
+
+ if( n<32 ) n = 32;
+ if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
+ if( preserve && pMem->z==pMem->zMalloc ){
+ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
+ preserve = 0;
+ }else{
+ sqlite3DbFree(pMem->db, pMem->zMalloc);
+ pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
+ }
+ }
+
+ if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
+ memcpy(pMem->zMalloc, pMem->z, pMem->n);
+ }
+ if( pMem->flags&MEM_Dyn && pMem->xDel ){
+ assert( pMem->xDel!=SQLITE_DYNAMIC );
+ pMem->xDel((void *)(pMem->z));
+ }
+
+ pMem->z = pMem->zMalloc;
+ if( pMem->z==0 ){
+ pMem->flags = MEM_Null;
+ }else{
+ pMem->flags &= ~(MEM_Ephem|MEM_Static);
+ }
+ pMem->xDel = 0;
+ return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
+}
+
+/*
+** Make the given Mem object MEM_Dyn. In other words, make it so
+** that any TEXT or BLOB content is stored in memory obtained from
+** malloc(). In this way, we know that the memory is safe to be
+** overwritten or altered.
+**
+** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
+ int f;
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( (pMem->flags&MEM_RowSet)==0 );
+ ExpandBlob(pMem);
+ f = pMem->flags;
+ if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){
+ if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
+ return SQLITE_NOMEM;
+ }
+ pMem->z[pMem->n] = 0;
+ pMem->z[pMem->n+1] = 0;
+ pMem->flags |= MEM_Term;
+#ifdef SQLITE_DEBUG
+ pMem->pScopyFrom = 0;
+#endif
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** If the given Mem* has a zero-filled tail, turn it into an ordinary
+** blob stored in dynamically allocated space.
+*/
+#ifndef SQLITE_OMIT_INCRBLOB
+SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
+ if( pMem->flags & MEM_Zero ){
+ int nByte;
+ assert( pMem->flags&MEM_Blob );
+ assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+
+ /* Set nByte to the number of bytes required to store the expanded blob. */
+ nByte = pMem->n + pMem->u.nZero;
+ if( nByte<=0 ){
+ nByte = 1;
+ }
+ if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
+ return SQLITE_NOMEM;
+ }
+
+ memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
+ pMem->n += pMem->u.nZero;
+ pMem->flags &= ~(MEM_Zero|MEM_Term);
+ }
+ return SQLITE_OK;
+}
+#endif
+
+
+/*
+** Make sure the given Mem is \u0000 terminated.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
+ return SQLITE_OK; /* Nothing to do */
+ }
+ if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
+ return SQLITE_NOMEM;
+ }
+ pMem->z[pMem->n] = 0;
+ pMem->z[pMem->n+1] = 0;
+ pMem->flags |= MEM_Term;
+ return SQLITE_OK;
+}
+
+/*
+** Add MEM_Str to the set of representations for the given Mem. Numbers
+** are converted using sqlite3_snprintf(). Converting a BLOB to a string
+** is a no-op.
+**
+** Existing representations MEM_Int and MEM_Real are *not* invalidated.
+**
+** A MEM_Null value will never be passed to this function. This function is
+** used for converting values to text for returning to the user (i.e. via
+** sqlite3_value_text()), or for ensuring that values to be used as btree
+** keys are strings. In the former case a NULL pointer is returned the
+** user and the later is an internal programming error.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, int enc){
+ int rc = SQLITE_OK;
+ int fg = pMem->flags;
+ const int nByte = 32;
+
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( !(fg&MEM_Zero) );
+ assert( !(fg&(MEM_Str|MEM_Blob)) );
+ assert( fg&(MEM_Int|MEM_Real) );
+ assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( EIGHT_BYTE_ALIGNMENT(pMem) );
+
+
+ if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
+ return SQLITE_NOMEM;
+ }
+
+ /* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8
+ ** string representation of the value. Then, if the required encoding
+ ** is UTF-16le or UTF-16be do a translation.
+ **
+ ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
+ */
+ if( fg & MEM_Int ){
+ sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
+ }else{
+ assert( fg & MEM_Real );
+ sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r);
+ }
+ pMem->n = sqlite3Strlen30(pMem->z);
+ pMem->enc = SQLITE_UTF8;
+ pMem->flags |= MEM_Str|MEM_Term;
+ sqlite3VdbeChangeEncoding(pMem, enc);
+ return rc;
+}
+
+/*
+** Memory cell pMem contains the context of an aggregate function.
+** This routine calls the finalize method for that function. The
+** result of the aggregate is stored back into pMem.
+**
+** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK
+** otherwise.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
+ int rc = SQLITE_OK;
+ if( ALWAYS(pFunc && pFunc->xFinalize) ){
+ sqlite3_context ctx;
+ assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.s.flags = MEM_Null;
+ ctx.s.db = pMem->db;
+ ctx.pMem = pMem;
+ ctx.pFunc = pFunc;
+ pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
+ assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
+ sqlite3DbFree(pMem->db, pMem->zMalloc);
+ memcpy(pMem, &ctx.s, sizeof(ctx.s));
+ rc = ctx.isError;
+ }
+ return rc;
+}
+
+/*
+** If the memory cell contains a string value that must be freed by
+** invoking an external callback, free it now. Calling this function
+** does not free any Mem.zMalloc buffer.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
+ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
+ if( p->flags&MEM_Agg ){
+ sqlite3VdbeMemFinalize(p, p->u.pDef);
+ assert( (p->flags & MEM_Agg)==0 );
+ sqlite3VdbeMemRelease(p);
+ }else if( p->flags&MEM_Dyn && p->xDel ){
+ assert( (p->flags&MEM_RowSet)==0 );
+ assert( p->xDel!=SQLITE_DYNAMIC );
+ p->xDel((void *)p->z);
+ p->xDel = 0;
+ }else if( p->flags&MEM_RowSet ){
+ sqlite3RowSetClear(p->u.pRowSet);
+ }else if( p->flags&MEM_Frame ){
+ sqlite3VdbeMemSetNull(p);
+ }
+}
+
+/*
+** Release any memory held by the Mem. This may leave the Mem in an
+** inconsistent state, for example with (Mem.z==0) and
+** (Mem.type==SQLITE_TEXT).
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
+ VdbeMemRelease(p);
+ sqlite3DbFree(p->db, p->zMalloc);
+ p->z = 0;
+ p->zMalloc = 0;
+ p->xDel = 0;
+}
+
+/*
+** Convert a 64-bit IEEE double into a 64-bit signed integer.
+** If the double is too large, return 0x8000000000000000.
+**
+** Most systems appear to do this simply by assigning
+** variables and without the extra range tests. But
+** there are reports that windows throws an expection
+** if the floating point value is out of range. (See ticket #2880.)
+** Because we do not completely understand the problem, we will
+** take the conservative approach and always do range tests
+** before attempting the conversion.
+*/
+static i64 doubleToInt64(double r){
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ /* When floating-point is omitted, double and int64 are the same thing */
+ return r;
+#else
+ /*
+ ** Many compilers we encounter do not define constants for the
+ ** minimum and maximum 64-bit integers, or they define them
+ ** inconsistently. And many do not understand the "LL" notation.
+ ** So we define our own static constants here using nothing
+ ** larger than a 32-bit integer constant.
+ */
+ static const i64 maxInt = LARGEST_INT64;
+ static const i64 minInt = SMALLEST_INT64;
+
+ if( r<(double)minInt ){
+ return minInt;
+ }else if( r>(double)maxInt ){
+ /* minInt is correct here - not maxInt. It turns out that assigning
+ ** a very large positive number to an integer results in a very large
+ ** negative integer. This makes no sense, but it is what x86 hardware
+ ** does so for compatibility we will do the same in software. */
+ return minInt;
+ }else{
+ return (i64)r;
+ }
+#endif
+}
+
+/*
+** Return some kind of integer value which is the best we can do
+** at representing the value that *pMem describes as an integer.
+** If pMem is an integer, then the value is exact. If pMem is
+** a floating-point then the value returned is the integer part.
+** If pMem is a string or blob, then we make an attempt to convert
+** it into a integer and return that. If pMem represents an
+** an SQL-NULL value, return 0.
+**
+** If pMem represents a string value, its encoding might be changed.
+*/
+SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
+ int flags;
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( EIGHT_BYTE_ALIGNMENT(pMem) );
+ flags = pMem->flags;
+ if( flags & MEM_Int ){
+ return pMem->u.i;
+ }else if( flags & MEM_Real ){
+ return doubleToInt64(pMem->r);
+ }else if( flags & (MEM_Str|MEM_Blob) ){
+ i64 value = 0;
+ assert( pMem->z || pMem->n==0 );
+ testcase( pMem->z==0 );
+ sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
+ return value;
+ }else{
+ return 0;
+ }
+}
+
+/*
+** Return the best representation of pMem that we can get into a
+** double. If pMem is already a double or an integer, return its
+** value. If it is a string or blob, try to convert it to a double.
+** If it is a NULL, return 0.0.
+*/
+SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( EIGHT_BYTE_ALIGNMENT(pMem) );
+ if( pMem->flags & MEM_Real ){
+ return pMem->r;
+ }else if( pMem->flags & MEM_Int ){
+ return (double)pMem->u.i;
+ }else if( pMem->flags & (MEM_Str|MEM_Blob) ){
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ double val = (double)0;
+ sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
+ return val;
+ }else{
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ return (double)0;
+ }
+}
+
+/*
+** The MEM structure is already a MEM_Real. Try to also make it a
+** MEM_Int if we can.
+*/
+SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
+ assert( pMem->flags & MEM_Real );
+ assert( (pMem->flags & MEM_RowSet)==0 );
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( EIGHT_BYTE_ALIGNMENT(pMem) );
+
+ pMem->u.i = doubleToInt64(pMem->r);
+
+ /* Only mark the value as an integer if
+ **
+ ** (1) the round-trip conversion real->int->real is a no-op, and
+ ** (2) The integer is neither the largest nor the smallest
+ ** possible integer (ticket #3922)
+ **
+ ** The second and third terms in the following conditional enforces
+ ** the second condition under the assumption that addition overflow causes
+ ** values to wrap around. On x86 hardware, the third term is always
+ ** true and could be omitted. But we leave it in because other
+ ** architectures might behave differently.
+ */
+ if( pMem->r==(double)pMem->u.i
+ && pMem->u.i>SMALLEST_INT64
+#if defined(__i486__) || defined(__x86_64__)
+ && ALWAYS(pMem->u.i<LARGEST_INT64)
+#else
+ && pMem->u.i<LARGEST_INT64
+#endif
+ ){
+ pMem->flags |= MEM_Int;
+ }
+}
+
+/*
+** Convert pMem to type integer. Invalidate any prior representations.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( (pMem->flags & MEM_RowSet)==0 );
+ assert( EIGHT_BYTE_ALIGNMENT(pMem) );
+
+ pMem->u.i = sqlite3VdbeIntValue(pMem);
+ MemSetTypeFlag(pMem, MEM_Int);
+ return SQLITE_OK;
+}
+
+/*
+** Convert pMem so that it is of type MEM_Real.
+** Invalidate any prior representations.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( EIGHT_BYTE_ALIGNMENT(pMem) );
+
+ pMem->r = sqlite3VdbeRealValue(pMem);
+ MemSetTypeFlag(pMem, MEM_Real);
+ return SQLITE_OK;
+}
+
+/*
+** Convert pMem so that it has types MEM_Real or MEM_Int or both.
+** Invalidate any prior representations.
+**
+** Every effort is made to force the conversion, even if the input
+** is a string that does not look completely like a number. Convert
+** as much of the string as we can and ignore the rest.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
+ if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
+ assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
+ MemSetTypeFlag(pMem, MEM_Int);
+ }else{
+ pMem->r = sqlite3VdbeRealValue(pMem);
+ MemSetTypeFlag(pMem, MEM_Real);
+ sqlite3VdbeIntegerAffinity(pMem);
+ }
+ }
+ assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
+ pMem->flags &= ~(MEM_Str|MEM_Blob);
+ return SQLITE_OK;
+}
+
+/*
+** Delete any previous value and set the value stored in *pMem to NULL.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
+ if( pMem->flags & MEM_Frame ){
+ VdbeFrame *pFrame = pMem->u.pFrame;
+ pFrame->pParent = pFrame->v->pDelFrame;
+ pFrame->v->pDelFrame = pFrame;
+ }
+ if( pMem->flags & MEM_RowSet ){
+ sqlite3RowSetClear(pMem->u.pRowSet);
+ }
+ MemSetTypeFlag(pMem, MEM_Null);
+ pMem->type = SQLITE_NULL;
+}
+
+/*
+** Delete any previous value and set the value to be a BLOB of length
+** n containing all zeros.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
+ sqlite3VdbeMemRelease(pMem);
+ pMem->flags = MEM_Blob|MEM_Zero;
+ pMem->type = SQLITE_BLOB;
+ pMem->n = 0;
+ if( n<0 ) n = 0;
+ pMem->u.nZero = n;
+ pMem->enc = SQLITE_UTF8;
+
+#ifdef SQLITE_OMIT_INCRBLOB
+ sqlite3VdbeMemGrow(pMem, n, 0);
+ if( pMem->z ){
+ pMem->n = n;
+ memset(pMem->z, 0, n);
+ }
+#endif
+}
+
+/*
+** Delete any previous value and set the value stored in *pMem to val,
+** manifest type INTEGER.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
+ sqlite3VdbeMemRelease(pMem);
+ pMem->u.i = val;
+ pMem->flags = MEM_Int;
+ pMem->type = SQLITE_INTEGER;
+}
+
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/*
+** Delete any previous value and set the value stored in *pMem to val,
+** manifest type REAL.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
+ if( sqlite3IsNaN(val) ){
+ sqlite3VdbeMemSetNull(pMem);
+ }else{
+ sqlite3VdbeMemRelease(pMem);
+ pMem->r = val;
+ pMem->flags = MEM_Real;
+ pMem->type = SQLITE_FLOAT;
+ }
+}
+#endif
+
+/*
+** Delete any previous value and set the value of pMem to be an
+** empty boolean index.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){
+ sqlite3 *db = pMem->db;
+ assert( db!=0 );
+ assert( (pMem->flags & MEM_RowSet)==0 );
+ sqlite3VdbeMemRelease(pMem);
+ pMem->zMalloc = sqlite3DbMallocRaw(db, 64);
+ if( db->mallocFailed ){
+ pMem->flags = MEM_Null;
+ }else{
+ assert( pMem->zMalloc );
+ pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
+ sqlite3DbMallocSize(db, pMem->zMalloc));
+ assert( pMem->u.pRowSet!=0 );
+ pMem->flags = MEM_RowSet;
+ }
+}
+
+/*
+** Return true if the Mem object contains a TEXT or BLOB that is
+** too large - whose size exceeds SQLITE_MAX_LENGTH.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
+ assert( p->db!=0 );
+ if( p->flags & (MEM_Str|MEM_Blob) ){
+ int n = p->n;
+ if( p->flags & MEM_Zero ){
+ n += p->u.nZero;
+ }
+ return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
+ }
+ return 0;
+}
+
+#ifdef SQLITE_DEBUG
+/*
+** This routine prepares a memory cell for modication by breaking
+** its link to a shallow copy and by marking any current shallow
+** copies of this cell as invalid.
+**
+** This is used for testing and debugging only - to make sure shallow
+** copies are not misused.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
+ int i;
+ Mem *pX;
+ for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
+ if( pX->pScopyFrom==pMem ){
+ pX->flags |= MEM_Invalid;
+ pX->pScopyFrom = 0;
+ }
+ }
+ pMem->pScopyFrom = 0;
+}
+#endif /* SQLITE_DEBUG */
+
+/*
+** Size of struct Mem not including the Mem.zMalloc member.
+*/
+#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
+
+/*
+** Make an shallow copy of pFrom into pTo. Prior contents of
+** pTo are freed. The pFrom->z field is not duplicated. If
+** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
+** and flags gets srcType (either MEM_Ephem or MEM_Static).
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
+ assert( (pFrom->flags & MEM_RowSet)==0 );
+ VdbeMemRelease(pTo);
+ memcpy(pTo, pFrom, MEMCELLSIZE);
+ pTo->xDel = 0;
+ if( (pFrom->flags&MEM_Static)==0 ){
+ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
+ assert( srcType==MEM_Ephem || srcType==MEM_Static );
+ pTo->flags |= srcType;
+ }
+}
+
+/*
+** Make a full copy of pFrom into pTo. Prior contents of pTo are
+** freed before the copy is made.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
+ int rc = SQLITE_OK;
+
+ assert( (pFrom->flags & MEM_RowSet)==0 );
+ VdbeMemRelease(pTo);
+ memcpy(pTo, pFrom, MEMCELLSIZE);
+ pTo->flags &= ~MEM_Dyn;
+
+ if( pTo->flags&(MEM_Str|MEM_Blob) ){
+ if( 0==(pFrom->flags&MEM_Static) ){
+ pTo->flags |= MEM_Ephem;
+ rc = sqlite3VdbeMemMakeWriteable(pTo);
+ }
+ }
+
+ return rc;
+}
+
+/*
+** Transfer the contents of pFrom to pTo. Any existing value in pTo is
+** freed. If pFrom contains ephemeral data, a copy is made.
+**
+** pFrom contains an SQL NULL when this routine returns.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
+ assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) );
+ assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) );
+ assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db );
+
+ sqlite3VdbeMemRelease(pTo);
+ memcpy(pTo, pFrom, sizeof(Mem));
+ pFrom->flags = MEM_Null;
+ pFrom->xDel = 0;
+ pFrom->zMalloc = 0;
+}
+
+/*
+** Change the value of a Mem to be a string or a BLOB.
+**
+** The memory management strategy depends on the value of the xDel
+** parameter. If the value passed is SQLITE_TRANSIENT, then the
+** string is copied into a (possibly existing) buffer managed by the
+** Mem structure. Otherwise, any existing buffer is freed and the
+** pointer copied.
+**
+** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
+** size limit) then no memory allocation occurs. If the string can be
+** stored without allocating memory, then it is. If a memory allocation
+** is required to store the string, then value of pMem is unchanged. In
+** either case, SQLITE_TOOBIG is returned.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
+ Mem *pMem, /* Memory cell to set to string value */
+ const char *z, /* String pointer */
+ int n, /* Bytes in string, or negative */
+ u8 enc, /* Encoding of z. 0 for BLOBs */
+ void (*xDel)(void*) /* Destructor function */
+){
+ int nByte = n; /* New value for pMem->n */
+ int iLimit; /* Maximum allowed string or blob size */
+ u16 flags = 0; /* New value for pMem->flags */
+
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( (pMem->flags & MEM_RowSet)==0 );
+
+ /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
+ if( !z ){
+ sqlite3VdbeMemSetNull(pMem);
+ return SQLITE_OK;
+ }
+
+ if( pMem->db ){
+ iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH];
+ }else{
+ iLimit = SQLITE_MAX_LENGTH;
+ }
+ flags = (enc==0?MEM_Blob:MEM_Str);
+ if( nByte<0 ){
+ assert( enc!=0 );
+ if( enc==SQLITE_UTF8 ){
+ for(nByte=0; nByte<=iLimit && z[nByte]; nByte++){}
+ }else{
+ for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
+ }
+ flags |= MEM_Term;
+ }
+
+ /* The following block sets the new values of Mem.z and Mem.xDel. It
+ ** also sets a flag in local variable "flags" to indicate the memory
+ ** management (one of MEM_Dyn or MEM_Static).
+ */
+ if( xDel==SQLITE_TRANSIENT ){
+ int nAlloc = nByte;
+ if( flags&MEM_Term ){
+ nAlloc += (enc==SQLITE_UTF8?1:2);
+ }
+ if( nByte>iLimit ){
+ return SQLITE_TOOBIG;
+ }
+ if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){
+ return SQLITE_NOMEM;
+ }
+ memcpy(pMem->z, z, nAlloc);
+ }else if( xDel==SQLITE_DYNAMIC ){
+ sqlite3VdbeMemRelease(pMem);
+ pMem->zMalloc = pMem->z = (char *)z;
+ pMem->xDel = 0;
+ }else{
+ sqlite3VdbeMemRelease(pMem);
+ pMem->z = (char *)z;
+ pMem->xDel = xDel;
+ flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
+ }
+
+ pMem->n = nByte;
+ pMem->flags = flags;
+ pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
+ pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT);
+
+#ifndef SQLITE_OMIT_UTF16
+ if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
+ return SQLITE_NOMEM;
+ }
+#endif
+
+ if( nByte>iLimit ){
+ return SQLITE_TOOBIG;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Compare the values contained by the two memory cells, returning
+** negative, zero or positive if pMem1 is less than, equal to, or greater
+** than pMem2. Sorting order is NULL's first, followed by numbers (integers
+** and reals) sorted numerically, followed by text ordered by the collating
+** sequence pColl and finally blob's ordered by memcmp().
+**
+** Two NULL values are considered equal by this function.
+*/
+SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
+ int rc;
+ int f1, f2;
+ int combined_flags;
+
+ f1 = pMem1->flags;
+ f2 = pMem2->flags;
+ combined_flags = f1|f2;
+ assert( (combined_flags & MEM_RowSet)==0 );
+
+ /* If one value is NULL, it is less than the other. If both values
+ ** are NULL, return 0.
+ */
+ if( combined_flags&MEM_Null ){
+ return (f2&MEM_Null) - (f1&MEM_Null);
+ }
+
+ /* If one value is a number and the other is not, the number is less.
+ ** If both are numbers, compare as reals if one is a real, or as integers
+ ** if both values are integers.
+ */
+ if( combined_flags&(MEM_Int|MEM_Real) ){
+ if( !(f1&(MEM_Int|MEM_Real)) ){
+ return 1;
+ }
+ if( !(f2&(MEM_Int|MEM_Real)) ){
+ return -1;
+ }
+ if( (f1 & f2 & MEM_Int)==0 ){
+ double r1, r2;
+ if( (f1&MEM_Real)==0 ){
+ r1 = (double)pMem1->u.i;
+ }else{
+ r1 = pMem1->r;
+ }
+ if( (f2&MEM_Real)==0 ){
+ r2 = (double)pMem2->u.i;
+ }else{
+ r2 = pMem2->r;
+ }
+ if( r1<r2 ) return -1;
+ if( r1>r2 ) return 1;
+ return 0;
+ }else{
+ assert( f1&MEM_Int );
+ assert( f2&MEM_Int );
+ if( pMem1->u.i < pMem2->u.i ) return -1;
+ if( pMem1->u.i > pMem2->u.i ) return 1;
+ return 0;
+ }
+ }
+
+ /* If one value is a string and the other is a blob, the string is less.
+ ** If both are strings, compare using the collating functions.
+ */
+ if( combined_flags&MEM_Str ){
+ if( (f1 & MEM_Str)==0 ){
+ return 1;
+ }
+ if( (f2 & MEM_Str)==0 ){
+ return -1;
+ }
+
+ assert( pMem1->enc==pMem2->enc );
+ assert( pMem1->enc==SQLITE_UTF8 ||
+ pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
+
+ /* The collation sequence must be defined at this point, even if
+ ** the user deletes the collation sequence after the vdbe program is
+ ** compiled (this was not always the case).
+ */
+ assert( !pColl || pColl->xCmp );
+
+ if( pColl ){
+ if( pMem1->enc==pColl->enc ){
+ /* The strings are already in the correct encoding. Call the
+ ** comparison function directly */
+ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
+ }else{
+ const void *v1, *v2;
+ int n1, n2;
+ Mem c1;
+ Mem c2;
+ memset(&c1, 0, sizeof(c1));
+ memset(&c2, 0, sizeof(c2));
+ sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
+ sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
+ v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
+ n1 = v1==0 ? 0 : c1.n;
+ v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
+ n2 = v2==0 ? 0 : c2.n;
+ rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
+ sqlite3VdbeMemRelease(&c1);
+ sqlite3VdbeMemRelease(&c2);
+ return rc;
+ }
+ }
+ /* If a NULL pointer was passed as the collate function, fall through
+ ** to the blob case and use memcmp(). */
+ }
+
+ /* Both values must be blobs. Compare using memcmp(). */
+ rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
+ if( rc==0 ){
+ rc = pMem1->n - pMem2->n;
+ }
+ return rc;
+}
+
+/*
+** Move data out of a btree key or data field and into a Mem structure.
+** The data or key is taken from the entry that pCur is currently pointing
+** to. offset and amt determine what portion of the data or key to retrieve.
+** key is true to get the key or false to get data. The result is written
+** into the pMem element.
+**
+** The pMem structure is assumed to be uninitialized. Any prior content
+** is overwritten without being freed.
+**
+** If this routine fails for any reason (malloc returns NULL or unable
+** to read from the disk) then the pMem is left in an inconsistent state.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
+ BtCursor *pCur, /* Cursor pointing at record to retrieve. */
+ int offset, /* Offset from the start of data to return bytes from. */
+ int amt, /* Number of bytes to return. */
+ int key, /* If true, retrieve from the btree key, not data. */
+ Mem *pMem /* OUT: Return data in this Mem structure. */
+){
+ char *zData; /* Data from the btree layer */
+ int available = 0; /* Number of bytes available on the local btree page */
+ int rc = SQLITE_OK; /* Return code */
+
+ assert( sqlite3BtreeCursorIsValid(pCur) );
+
+ /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
+ ** that both the BtShared and database handle mutexes are held. */
+ assert( (pMem->flags & MEM_RowSet)==0 );
+ if( key ){
+ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);
+ }else{
+ zData = (char *)sqlite3BtreeDataFetch(pCur, &available);
+ }
+ assert( zData!=0 );
+
+ if( offset+amt<=available && (pMem->flags&MEM_Dyn)==0 ){
+ sqlite3VdbeMemRelease(pMem);
+ pMem->z = &zData[offset];
+ pMem->flags = MEM_Blob|MEM_Ephem;
+ }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
+ pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
+ pMem->enc = 0;
+ pMem->type = SQLITE_BLOB;
+ if( key ){
+ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
+ }else{
+ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
+ }
+ pMem->z[amt] = 0;
+ pMem->z[amt+1] = 0;
+ if( rc!=SQLITE_OK ){
+ sqlite3VdbeMemRelease(pMem);
+ }
+ }
+ pMem->n = amt;
+
+ return rc;
+}
+
+/* This function is only available internally, it is not part of the
+** external API. It works in a similar way to sqlite3_value_text(),
+** except the data returned is in the encoding specified by the second
+** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or
+** SQLITE_UTF8.
+**
+** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED.
+** If that is the case, then the result must be aligned on an even byte
+** boundary.
+*/
+SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
+ if( !pVal ) return 0;
+
+ assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
+ assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
+ assert( (pVal->flags & MEM_RowSet)==0 );
+
+ if( pVal->flags&MEM_Null ){
+ return 0;
+ }
+ assert( (MEM_Blob>>3) == MEM_Str );
+ pVal->flags |= (pVal->flags & MEM_Blob)>>3;
+ ExpandBlob(pVal);
+ if( pVal->flags&MEM_Str ){
+ sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
+ if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){
+ assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
+ if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
+ return 0;
+ }
+ }
+ sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */
+ }else{
+ assert( (pVal->flags&MEM_Blob)==0 );
+ sqlite3VdbeMemStringify(pVal, enc);
+ assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) );
+ }
+ assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
+ || pVal->db->mallocFailed );
+ if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
+ return pVal->z;
+ }else{
+ return 0;
+ }
+}
+
+/*
+** Create a new sqlite3_value object.
+*/
+SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
+ Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
+ if( p ){
+ p->flags = MEM_Null;
+ p->type = SQLITE_NULL;
+ p->db = db;
+ }
+ return p;
+}
+
+/*
+** Create a new sqlite3_value object, containing the value of pExpr.
+**
+** This only works for very simple expressions that consist of one constant
+** token (i.e. "5", "5.1", "'a string'"). If the expression can
+** be converted directly into a value, then the value is allocated and
+** a pointer written to *ppVal. The caller is responsible for deallocating
+** the value by passing it to sqlite3ValueFree() later on. If the expression
+** cannot be converted to a value, then *ppVal is set to NULL.
+*/
+SQLITE_PRIVATE int sqlite3ValueFromExpr(
+ sqlite3 *db, /* The database connection */
+ Expr *pExpr, /* The expression to evaluate */
+ u8 enc, /* Encoding to use */
+ u8 affinity, /* Affinity to use */
+ sqlite3_value **ppVal /* Write the new value here */
+){
+ int op;
+ char *zVal = 0;
+ sqlite3_value *pVal = 0;
+ int negInt = 1;
+ const char *zNeg = "";
+
+ if( !pExpr ){
+ *ppVal = 0;
+ return SQLITE_OK;
+ }
+ op = pExpr->op;
+
+ /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3.
+ ** The ifdef here is to enable us to achieve 100% branch test coverage even
+ ** when SQLITE_ENABLE_STAT3 is omitted.
+ */
+#ifdef SQLITE_ENABLE_STAT3
+ if( op==TK_REGISTER ) op = pExpr->op2;
+#else
+ if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
+#endif
+
+ /* Handle negative integers in a single step. This is needed in the
+ ** case when the value is -9223372036854775808.
+ */
+ if( op==TK_UMINUS
+ && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
+ pExpr = pExpr->pLeft;
+ op = pExpr->op;
+ negInt = -1;
+ zNeg = "-";
+ }
+
+ if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
+ pVal = sqlite3ValueNew(db);
+ if( pVal==0 ) goto no_mem;
+ if( ExprHasProperty(pExpr, EP_IntValue) ){
+ sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
+ }else{
+ zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
+ if( zVal==0 ) goto no_mem;
+ sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
+ if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
+ }
+ if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
+ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
+ }else{
+ sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
+ }
+ if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
+ if( enc!=SQLITE_UTF8 ){
+ sqlite3VdbeChangeEncoding(pVal, enc);
+ }
+ }else if( op==TK_UMINUS ) {
+ /* This branch happens for multiple negative signs. Ex: -(-5) */
+ if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
+ sqlite3VdbeMemNumerify(pVal);
+ if( pVal->u.i==SMALLEST_INT64 ){
+ pVal->flags &= MEM_Int;
+ pVal->flags |= MEM_Real;
+ pVal->r = (double)LARGEST_INT64;
+ }else{
+ pVal->u.i = -pVal->u.i;
+ }
+ pVal->r = -pVal->r;
+ sqlite3ValueApplyAffinity(pVal, affinity, enc);
+ }
+ }else if( op==TK_NULL ){
+ pVal = sqlite3ValueNew(db);
+ if( pVal==0 ) goto no_mem;
+ }
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+ else if( op==TK_BLOB ){
+ int nVal;
+ assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
+ assert( pExpr->u.zToken[1]=='\'' );
+ pVal = sqlite3ValueNew(db);
+ if( !pVal ) goto no_mem;
+ zVal = &pExpr->u.zToken[2];
+ nVal = sqlite3Strlen30(zVal)-1;
+ assert( zVal[nVal]=='\'' );
+ sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
+ 0, SQLITE_DYNAMIC);
+ }
+#endif
+
+ if( pVal ){
+ sqlite3VdbeMemStoreType(pVal);
+ }
+ *ppVal = pVal;
+ return SQLITE_OK;
+
+no_mem:
+ db->mallocFailed = 1;
+ sqlite3DbFree(db, zVal);
+ sqlite3ValueFree(pVal);
+ *ppVal = 0;
+ return SQLITE_NOMEM;
+}
+
+/*
+** Change the string value of an sqlite3_value object
+*/
+SQLITE_PRIVATE void sqlite3ValueSetStr(
+ sqlite3_value *v, /* Value to be set */
+ int n, /* Length of string z */
+ const void *z, /* Text of the new string */
+ u8 enc, /* Encoding to use */
+ void (*xDel)(void*) /* Destructor for the string */
+){
+ if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel);
+}
+
+/*
+** Free an sqlite3_value object
+*/
+SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){
+ if( !v ) return;
+ sqlite3VdbeMemRelease((Mem *)v);
+ sqlite3DbFree(((Mem*)v)->db, v);
+}
+
+/*
+** Return the number of bytes in the sqlite3_value object assuming
+** that it uses the encoding "enc"
+*/
+SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
+ Mem *p = (Mem*)pVal;
+ if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){
+ if( p->flags & MEM_Zero ){
+ return p->n + p->u.nZero;
+ }else{
+ return p->n;
+ }
+ }
+ return 0;
+}
+
+/************** End of vdbemem.c *********************************************/
+/************** Begin file vdbeaux.c *****************************************/
+/*
+** 2003 September 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used for creating, destroying, and populating
+** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior
+** to version 2.8.7, all this code was combined into the vdbe.c source file.
+** But that file was getting too big so this subroutines were split out.
+*/
+
+/*
+** Create a new virtual database engine.
+*/
+SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
+ Vdbe *p;
+ p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
+ if( p==0 ) return 0;
+ p->db = db;
+ if( db->pVdbe ){
+ db->pVdbe->pPrev = p;
+ }
+ p->pNext = db->pVdbe;
+ p->pPrev = 0;
+ db->pVdbe = p;
+ p->magic = VDBE_MAGIC_INIT;
+ return p;
+}
+
+/*
+** Remember the SQL string for a prepared statement.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
+ assert( isPrepareV2==1 || isPrepareV2==0 );
+ if( p==0 ) return;
+#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
+ if( !isPrepareV2 ) return;
+#endif
+ assert( p->zSql==0 );
+ p->zSql = sqlite3DbStrNDup(p->db, z, n);
+ p->isPrepareV2 = (u8)isPrepareV2;
+}
+
+/*
+** Return the SQL associated with a prepared statement
+*/
+SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){
+ Vdbe *p = (Vdbe *)pStmt;
+ return (p && p->isPrepareV2) ? p->zSql : 0;
+}
+
+/*
+** Swap all content between two VDBE structures.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
+ Vdbe tmp, *pTmp;
+ char *zTmp;
+ tmp = *pA;
+ *pA = *pB;
+ *pB = tmp;
+ pTmp = pA->pNext;
+ pA->pNext = pB->pNext;
+ pB->pNext = pTmp;
+ pTmp = pA->pPrev;
+ pA->pPrev = pB->pPrev;
+ pB->pPrev = pTmp;
+ zTmp = pA->zSql;
+ pA->zSql = pB->zSql;
+ pB->zSql = zTmp;
+ pB->isPrepareV2 = pA->isPrepareV2;
+}
+
+#ifdef SQLITE_DEBUG
+/*
+** Turn tracing on or off
+*/
+SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
+ p->trace = trace;
+}
+#endif
+
+/*
+** Resize the Vdbe.aOp array so that it is at least one op larger than
+** it was.
+**
+** If an out-of-memory error occurs while resizing the array, return
+** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
+** unchanged (this is so that any opcodes already allocated can be
+** correctly deallocated along with the rest of the Vdbe).
+*/
+static int growOpArray(Vdbe *p){
+ VdbeOp *pNew;
+ int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
+ pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op));
+ if( pNew ){
+ p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
+ p->aOp = pNew;
+ }
+ return (pNew ? SQLITE_OK : SQLITE_NOMEM);
+}
+
+/*
+** Add a new instruction to the list of instructions current in the
+** VDBE. Return the address of the new instruction.
+**
+** Parameters:
+**
+** p Pointer to the VDBE
+**
+** op The opcode for this instruction
+**
+** p1, p2, p3 Operands
+**
+** Use the sqlite3VdbeResolveLabel() function to fix an address and
+** the sqlite3VdbeChangeP4() function to change the value of the P4
+** operand.
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
+ int i;
+ VdbeOp *pOp;
+
+ i = p->nOp;
+ assert( p->magic==VDBE_MAGIC_INIT );
+ assert( op>0 && op<0xff );
+ if( p->nOpAlloc<=i ){
+ if( growOpArray(p) ){
+ return 1;
+ }
+ }
+ p->nOp++;
+ pOp = &p->aOp[i];
+ pOp->opcode = (u8)op;
+ pOp->p5 = 0;
+ pOp->p1 = p1;
+ pOp->p2 = p2;
+ pOp->p3 = p3;
+ pOp->p4.p = 0;
+ pOp->p4type = P4_NOTUSED;
+#ifdef SQLITE_DEBUG
+ pOp->zComment = 0;
+ if( p->db->flags & SQLITE_VdbeAddopTrace ){
+ sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+ }
+#endif
+#ifdef VDBE_PROFILE
+ pOp->cycles = 0;
+ pOp->cnt = 0;
+#endif
+ return i;
+}
+SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){
+ return sqlite3VdbeAddOp3(p, op, 0, 0, 0);
+}
+SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){
+ return sqlite3VdbeAddOp3(p, op, p1, 0, 0);
+}
+SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){
+ return sqlite3VdbeAddOp3(p, op, p1, p2, 0);
+}
+
+
+/*
+** Add an opcode that includes the p4 value as a pointer.
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddOp4(
+ Vdbe *p, /* Add the opcode to this VM */
+ int op, /* The new opcode */
+ int p1, /* The P1 operand */
+ int p2, /* The P2 operand */
+ int p3, /* The P3 operand */
+ const char *zP4, /* The P4 operand */
+ int p4type /* P4 operand type */
+){
+ int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
+ sqlite3VdbeChangeP4(p, addr, zP4, p4type);
+ return addr;
+}
+
+/*
+** Add an OP_ParseSchema opcode. This routine is broken out from
+** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
+** as having been used.
+**
+** The zWhere string must have been obtained from sqlite3_malloc().
+** This routine will take ownership of the allocated memory.
+*/
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
+ int j;
+ int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
+ sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
+ for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
+}
+
+/*
+** Add an opcode that includes the p4 value as an integer.
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
+ Vdbe *p, /* Add the opcode to this VM */
+ int op, /* The new opcode */
+ int p1, /* The P1 operand */
+ int p2, /* The P2 operand */
+ int p3, /* The P3 operand */
+ int p4 /* The P4 operand as an integer */
+){
+ int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
+ sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32);
+ return addr;
+}
+
+/*
+** Create a new symbolic label for an instruction that has yet to be
+** coded. The symbolic label is really just a negative number. The
+** label can be used as the P2 value of an operation. Later, when
+** the label is resolved to a specific address, the VDBE will scan
+** through its operation list and change all values of P2 which match
+** the label into the resolved address.
+**
+** The VDBE knows that a P2 value is a label because labels are
+** always negative and P2 values are suppose to be non-negative.
+** Hence, a negative P2 value is a label that has yet to be resolved.
+**
+** Zero is returned if a malloc() fails.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
+ int i = p->nLabel++;
+ assert( p->magic==VDBE_MAGIC_INIT );
+ if( (i & (i-1))==0 ){
+ p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
+ (i*2+1)*sizeof(p->aLabel[0]));
+ }
+ if( p->aLabel ){
+ p->aLabel[i] = -1;
+ }
+ return -1-i;
+}
+
+/*
+** Resolve label "x" to be the address of the next instruction to
+** be inserted. The parameter "x" must have been obtained from
+** a prior call to sqlite3VdbeMakeLabel().
+*/
+SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *p, int x){
+ int j = -1-x;
+ assert( p->magic==VDBE_MAGIC_INIT );
+ assert( j>=0 && j<p->nLabel );
+ if( p->aLabel ){
+ p->aLabel[j] = p->nOp;
+ }
+}
+
+/*
+** Mark the VDBE as one that can only be run one time.
+*/
+SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){
+ p->runOnlyOnce = 1;
+}
+
+#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
+
+/*
+** The following type and function are used to iterate through all opcodes
+** in a Vdbe main program and each of the sub-programs (triggers) it may
+** invoke directly or indirectly. It should be used as follows:
+**
+** Op *pOp;
+** VdbeOpIter sIter;
+**
+** memset(&sIter, 0, sizeof(sIter));
+** sIter.v = v; // v is of type Vdbe*
+** while( (pOp = opIterNext(&sIter)) ){
+** // Do something with pOp
+** }
+** sqlite3DbFree(v->db, sIter.apSub);
+**
+*/
+typedef struct VdbeOpIter VdbeOpIter;
+struct VdbeOpIter {
+ Vdbe *v; /* Vdbe to iterate through the opcodes of */
+ SubProgram **apSub; /* Array of subprograms */
+ int nSub; /* Number of entries in apSub */
+ int iAddr; /* Address of next instruction to return */
+ int iSub; /* 0 = main program, 1 = first sub-program etc. */
+};
+static Op *opIterNext(VdbeOpIter *p){
+ Vdbe *v = p->v;
+ Op *pRet = 0;
+ Op *aOp;
+ int nOp;
+
+ if( p->iSub<=p->nSub ){
+
+ if( p->iSub==0 ){
+ aOp = v->aOp;
+ nOp = v->nOp;
+ }else{
+ aOp = p->apSub[p->iSub-1]->aOp;
+ nOp = p->apSub[p->iSub-1]->nOp;
+ }
+ assert( p->iAddr<nOp );
+
+ pRet = &aOp[p->iAddr];
+ p->iAddr++;
+ if( p->iAddr==nOp ){
+ p->iSub++;
+ p->iAddr = 0;
+ }
+
+ if( pRet->p4type==P4_SUBPROGRAM ){
+ int nByte = (p->nSub+1)*sizeof(SubProgram*);
+ int j;
+ for(j=0; j<p->nSub; j++){
+ if( p->apSub[j]==pRet->p4.pProgram ) break;
+ }
+ if( j==p->nSub ){
+ p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte);
+ if( !p->apSub ){
+ pRet = 0;
+ }else{
+ p->apSub[p->nSub++] = pRet->p4.pProgram;
+ }
+ }
+ }
+ }
+
+ return pRet;
+}
+
+/*
+** Check if the program stored in the VM associated with pParse may
+** throw an ABORT exception (causing the statement, but not entire transaction
+** to be rolled back). This condition is true if the main program or any
+** sub-programs contains any of the following:
+**
+** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
+** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
+** * OP_Destroy
+** * OP_VUpdate
+** * OP_VRename
+** * OP_FkCounter with P2==0 (immediate foreign key constraint)
+**
+** Then check that the value of Parse.mayAbort is true if an
+** ABORT may be thrown, or false otherwise. Return true if it does
+** match, or false otherwise. This function is intended to be used as
+** part of an assert statement in the compiler. Similar to:
+**
+** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
+*/
+SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
+ int hasAbort = 0;
+ Op *pOp;
+ VdbeOpIter sIter;
+ memset(&sIter, 0, sizeof(sIter));
+ sIter.v = v;
+
+ while( (pOp = opIterNext(&sIter))!=0 ){
+ int opcode = pOp->opcode;
+ if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
+#endif
+ || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
+ && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+ ){
+ hasAbort = 1;
+ break;
+ }
+ }
+ sqlite3DbFree(v->db, sIter.apSub);
+
+ /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
+ ** If malloc failed, then the while() loop above may not have iterated
+ ** through all opcodes and hasAbort may be set incorrectly. Return
+ ** true for this case to prevent the assert() in the callers frame
+ ** from failing. */
+ return ( v->db->mallocFailed || hasAbort==mayAbort );
+}
+#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
+
+/*
+** Loop through the program looking for P2 values that are negative
+** on jump instructions. Each such value is a label. Resolve the
+** label by setting the P2 value to its correct non-zero value.
+**
+** This routine is called once after all opcodes have been inserted.
+**
+** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
+** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
+** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
+**
+** The Op.opflags field is set on all opcodes.
+*/
+static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
+ int i;
+ int nMaxArgs = *pMaxFuncArgs;
+ Op *pOp;
+ int *aLabel = p->aLabel;
+ p->readOnly = 1;
+ for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
+ u8 opcode = pOp->opcode;
+
+ pOp->opflags = sqlite3OpcodeProperty[opcode];
+ if( opcode==OP_Function || opcode==OP_AggStep ){
+ if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
+ }else if( (opcode==OP_Transaction && pOp->p2!=0) || opcode==OP_Vacuum ){
+ p->readOnly = 0;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ }else if( opcode==OP_VUpdate ){
+ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
+ }else if( opcode==OP_VFilter ){
+ int n;
+ assert( p->nOp - i >= 3 );
+ assert( pOp[-1].opcode==OP_Integer );
+ n = pOp[-1].p1;
+ if( n>nMaxArgs ) nMaxArgs = n;
+#endif
+ }else if( opcode==OP_Next || opcode==OP_SorterNext ){
+ pOp->p4.xAdvance = sqlite3BtreeNext;
+ pOp->p4type = P4_ADVANCE;
+ }else if( opcode==OP_Prev ){
+ pOp->p4.xAdvance = sqlite3BtreePrevious;
+ pOp->p4type = P4_ADVANCE;
+ }
+
+ if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
+ assert( -1-pOp->p2<p->nLabel );
+ pOp->p2 = aLabel[-1-pOp->p2];
+ }
+ }
+ sqlite3DbFree(p->db, p->aLabel);
+ p->aLabel = 0;
+
+ *pMaxFuncArgs = nMaxArgs;
+}
+
+/*
+** Return the address of the next instruction to be inserted.
+*/
+SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
+ assert( p->magic==VDBE_MAGIC_INIT );
+ return p->nOp;
+}
+
+/*
+** This function returns a pointer to the array of opcodes associated with
+** the Vdbe passed as the first argument. It is the callers responsibility
+** to arrange for the returned array to be eventually freed using the
+** vdbeFreeOpArray() function.
+**
+** Before returning, *pnOp is set to the number of entries in the returned
+** array. Also, *pnMaxArg is set to the larger of its current value and
+** the number of entries in the Vdbe.apArg[] array required to execute the
+** returned program.
+*/
+SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
+ VdbeOp *aOp = p->aOp;
+ assert( aOp && !p->db->mallocFailed );
+
+ /* Check that sqlite3VdbeUsesBtree() was not called on this VM */
+ assert( p->btreeMask==0 );
+
+ resolveP2Values(p, pnMaxArg);
+ *pnOp = p->nOp;
+ p->aOp = 0;
+ return aOp;
+}
+
+/*
+** Add a whole list of operations to the operation stack. Return the
+** address of the first operation added.
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
+ int addr;
+ assert( p->magic==VDBE_MAGIC_INIT );
+ if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){
+ return 0;
+ }
+ addr = p->nOp;
+ if( ALWAYS(nOp>0) ){
+ int i;
+ VdbeOpList const *pIn = aOp;
+ for(i=0; i<nOp; i++, pIn++){
+ int p2 = pIn->p2;
+ VdbeOp *pOut = &p->aOp[i+addr];
+ pOut->opcode = pIn->opcode;
+ pOut->p1 = pIn->p1;
+ if( p2<0 && (sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP)!=0 ){
+ pOut->p2 = addr + ADDR(p2);
+ }else{
+ pOut->p2 = p2;
+ }
+ pOut->p3 = pIn->p3;
+ pOut->p4type = P4_NOTUSED;
+ pOut->p4.p = 0;
+ pOut->p5 = 0;
+#ifdef SQLITE_DEBUG
+ pOut->zComment = 0;
+ if( p->db->flags & SQLITE_VdbeAddopTrace ){
+ sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
+ }
+#endif
+ }
+ p->nOp += nOp;
+ }
+ return addr;
+}
+
+/*
+** Change the value of the P1 operand for a specific instruction.
+** This routine is useful when a large program is loaded from a
+** static array using sqlite3VdbeAddOpList but we want to make a
+** few minor changes to the program.
+*/
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
+ assert( p!=0 );
+ if( ((u32)p->nOp)>addr ){
+ p->aOp[addr].p1 = val;
+ }
+}
+
+/*
+** Change the value of the P2 operand for a specific instruction.
+** This routine is useful for setting a jump destination.
+*/
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
+ assert( p!=0 );
+ if( ((u32)p->nOp)>addr ){
+ p->aOp[addr].p2 = val;
+ }
+}
+
+/*
+** Change the value of the P3 operand for a specific instruction.
+*/
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
+ assert( p!=0 );
+ if( ((u32)p->nOp)>addr ){
+ p->aOp[addr].p3 = val;
+ }
+}
+
+/*
+** Change the value of the P5 operand for the most recently
+** added operation.
+*/
+SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
+ assert( p!=0 );
+ if( p->aOp ){
+ assert( p->nOp>0 );
+ p->aOp[p->nOp-1].p5 = val;
+ }
+}
+
+/*
+** Change the P2 operand of instruction addr so that it points to
+** the address of the next instruction to be coded.
+*/
+SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
+ assert( addr>=0 || p->db->mallocFailed );
+ if( addr>=0 ) sqlite3VdbeChangeP2(p, addr, p->nOp);
+}
+
+
+/*
+** If the input FuncDef structure is ephemeral, then free it. If
+** the FuncDef is not ephermal, then do nothing.
+*/
+static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
+ if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
+ sqlite3DbFree(db, pDef);
+ }
+}
+
+static void vdbeFreeOpArray(sqlite3 *, Op *, int);
+
+/*
+** Delete a P4 value if necessary.
+*/
+static void freeP4(sqlite3 *db, int p4type, void *p4){
+ if( p4 ){
+ assert( db );
+ switch( p4type ){
+ case P4_REAL:
+ case P4_INT64:
+ case P4_DYNAMIC:
+ case P4_KEYINFO:
+ case P4_INTARRAY:
+ case P4_KEYINFO_HANDOFF: {
+ sqlite3DbFree(db, p4);
+ break;
+ }
+ case P4_MPRINTF: {
+ if( db->pnBytesFreed==0 ) sqlite3_free(p4);
+ break;
+ }
+ case P4_VDBEFUNC: {
+ VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
+ freeEphemeralFunction(db, pVdbeFunc->pFunc);
+ if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
+ sqlite3DbFree(db, pVdbeFunc);
+ break;
+ }
+ case P4_FUNCDEF: {
+ freeEphemeralFunction(db, (FuncDef*)p4);
+ break;
+ }
+ case P4_MEM: {
+ if( db->pnBytesFreed==0 ){
+ sqlite3ValueFree((sqlite3_value*)p4);
+ }else{
+ Mem *p = (Mem*)p4;
+ sqlite3DbFree(db, p->zMalloc);
+ sqlite3DbFree(db, p);
+ }
+ break;
+ }
+ case P4_VTAB : {
+ if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
+ break;
+ }
+ }
+ }
+}
+
+/*
+** Free the space allocated for aOp and any p4 values allocated for the
+** opcodes contained within. If aOp is not NULL it is assumed to contain
+** nOp entries.
+*/
+static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
+ if( aOp ){
+ Op *pOp;
+ for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
+ freeP4(db, pOp->p4type, pOp->p4.p);
+#ifdef SQLITE_DEBUG
+ sqlite3DbFree(db, pOp->zComment);
+#endif
+ }
+ }
+ sqlite3DbFree(db, aOp);
+}
+
+/*
+** Link the SubProgram object passed as the second argument into the linked
+** list at Vdbe.pSubProgram. This list is used to delete all sub-program
+** objects when the VM is no longer required.
+*/
+SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
+ p->pNext = pVdbe->pProgram;
+ pVdbe->pProgram = p;
+}
+
+/*
+** Change the opcode at addr into OP_Noop
+*/
+SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
+ if( p->aOp ){
+ VdbeOp *pOp = &p->aOp[addr];
+ sqlite3 *db = p->db;
+ freeP4(db, pOp->p4type, pOp->p4.p);
+ memset(pOp, 0, sizeof(pOp[0]));
+ pOp->opcode = OP_Noop;
+ }
+}
+
+/*
+** Change the value of the P4 operand for a specific instruction.
+** This routine is useful when a large program is loaded from a
+** static array using sqlite3VdbeAddOpList but we want to make a
+** few minor changes to the program.
+**
+** If n>=0 then the P4 operand is dynamic, meaning that a copy of
+** the string is made into memory obtained from sqlite3_malloc().
+** A value of n==0 means copy bytes of zP4 up to and including the
+** first null byte. If n>0 then copy n+1 bytes of zP4.
+**
+** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure.
+** A copy is made of the KeyInfo structure into memory obtained from
+** sqlite3_malloc, to be freed when the Vdbe is finalized.
+** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure
+** stored in memory that the caller has obtained from sqlite3_malloc. The
+** caller should not free the allocation, it will be freed when the Vdbe is
+** finalized.
+**
+** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
+** to a string or structure that is guaranteed to exist for the lifetime of
+** the Vdbe. In these cases we can just copy the pointer.
+**
+** If addr<0 then change P4 on the most recently inserted instruction.
+*/
+SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
+ Op *pOp;
+ sqlite3 *db;
+ assert( p!=0 );
+ db = p->db;
+ assert( p->magic==VDBE_MAGIC_INIT );
+ if( p->aOp==0 || db->mallocFailed ){
+ if ( n!=P4_KEYINFO && n!=P4_VTAB ) {
+ freeP4(db, n, (void*)*(char**)&zP4);
+ }
+ return;
+ }
+ assert( p->nOp>0 );
+ assert( addr<p->nOp );
+ if( addr<0 ){
+ addr = p->nOp - 1;
+ }
+ pOp = &p->aOp[addr];
+ assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );
+ freeP4(db, pOp->p4type, pOp->p4.p);
+ pOp->p4.p = 0;
+ if( n==P4_INT32 ){
+ /* Note: this cast is safe, because the origin data point was an int
+ ** that was cast to a (const char *). */
+ pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
+ pOp->p4type = P4_INT32;
+ }else if( zP4==0 ){
+ pOp->p4.p = 0;
+ pOp->p4type = P4_NOTUSED;
+ }else if( n==P4_KEYINFO ){
+ KeyInfo *pKeyInfo;
+ int nField, nByte;
+
+ nField = ((KeyInfo*)zP4)->nField;
+ nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
+ pKeyInfo = sqlite3DbMallocRaw(0, nByte);
+ pOp->p4.pKeyInfo = pKeyInfo;
+ if( pKeyInfo ){
+ u8 *aSortOrder;
+ memcpy((char*)pKeyInfo, zP4, nByte - nField);
+ aSortOrder = pKeyInfo->aSortOrder;
+ assert( aSortOrder!=0 );
+ pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
+ memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
+ pOp->p4type = P4_KEYINFO;
+ }else{
+ p->db->mallocFailed = 1;
+ pOp->p4type = P4_NOTUSED;
+ }
+ }else if( n==P4_KEYINFO_HANDOFF ){
+ pOp->p4.p = (void*)zP4;
+ pOp->p4type = P4_KEYINFO;
+ }else if( n==P4_VTAB ){
+ pOp->p4.p = (void*)zP4;
+ pOp->p4type = P4_VTAB;
+ sqlite3VtabLock((VTable *)zP4);
+ assert( ((VTable *)zP4)->db==p->db );
+ }else if( n<0 ){
+ pOp->p4.p = (void*)zP4;
+ pOp->p4type = (signed char)n;
+ }else{
+ if( n==0 ) n = sqlite3Strlen30(zP4);
+ pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
+ pOp->p4type = P4_DYNAMIC;
+ }
+}
+
+#ifndef NDEBUG
+/*
+** Change the comment on the most recently coded instruction. Or
+** insert a No-op and add the comment to that new instruction. This
+** makes the code easier to read during debugging. None of this happens
+** in a production build.
+*/
+static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
+ assert( p->nOp>0 || p->aOp==0 );
+ assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
+ if( p->nOp ){
+ assert( p->aOp );
+ sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
+ p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap);
+ }
+}
+SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
+ va_list ap;
+ if( p ){
+ va_start(ap, zFormat);
+ vdbeVComment(p, zFormat, ap);
+ va_end(ap);
+ }
+}
+SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
+ va_list ap;
+ if( p ){
+ sqlite3VdbeAddOp0(p, OP_Noop);
+ va_start(ap, zFormat);
+ vdbeVComment(p, zFormat, ap);
+ va_end(ap);
+ }
+}
+#endif /* NDEBUG */
+
+/*
+** Return the opcode for a given address. If the address is -1, then
+** return the most recently inserted opcode.
+**
+** If a memory allocation error has occurred prior to the calling of this
+** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
+** is readable but not writable, though it is cast to a writable value.
+** The return of a dummy opcode allows the call to continue functioning
+** after a OOM fault without having to check to see if the return from
+** this routine is a valid pointer. But because the dummy.opcode is 0,
+** dummy will never be written to. This is verified by code inspection and
+** by running with Valgrind.
+**
+** About the #ifdef SQLITE_OMIT_TRACE: Normally, this routine is never called
+** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE,
+** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as
+** a new VDBE is created. So we are free to set addr to p->nOp-1 without
+** having to double-check to make sure that the result is non-negative. But
+** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
+** check the value of p->nOp-1 before continuing.
+*/
+SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
+ /* C89 specifies that the constant "dummy" will be initialized to all
+ ** zeros, which is correct. MSVC generates a warning, nevertheless. */
+ static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
+ assert( p->magic==VDBE_MAGIC_INIT );
+ if( addr<0 ){
+#ifdef SQLITE_OMIT_TRACE
+ if( p->nOp==0 ) return (VdbeOp*)&dummy;
+#endif
+ addr = p->nOp - 1;
+ }
+ assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
+ if( p->db->mallocFailed ){
+ return (VdbeOp*)&dummy;
+ }else{
+ return &p->aOp[addr];
+ }
+}
+
+#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
+ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+/*
+** Compute a string that describes the P4 parameter for an opcode.
+** Use zTemp for any required temporary buffer space.
+*/
+static char *displayP4(Op *pOp, char *zTemp, int nTemp){
+ char *zP4 = zTemp;
+ assert( nTemp>=20 );
+ switch( pOp->p4type ){
+ case P4_KEYINFO_STATIC:
+ case P4_KEYINFO: {
+ int i, j;
+ KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
+ assert( pKeyInfo->aSortOrder!=0 );
+ sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
+ i = sqlite3Strlen30(zTemp);
+ for(j=0; j<pKeyInfo->nField; j++){
+ CollSeq *pColl = pKeyInfo->aColl[j];
+ const char *zColl = pColl ? pColl->zName : "nil";
+ int n = sqlite3Strlen30(zColl);
+ if( i+n>nTemp-6 ){
+ memcpy(&zTemp[i],",...",4);
+ break;
+ }
+ zTemp[i++] = ',';
+ if( pKeyInfo->aSortOrder[j] ){
+ zTemp[i++] = '-';
+ }
+ memcpy(&zTemp[i], zColl, n+1);
+ i += n;
+ }
+ zTemp[i++] = ')';
+ zTemp[i] = 0;
+ assert( i<nTemp );
+ break;
+ }
+ case P4_COLLSEQ: {
+ CollSeq *pColl = pOp->p4.pColl;
+ sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName);
+ break;
+ }
+ case P4_FUNCDEF: {
+ FuncDef *pDef = pOp->p4.pFunc;
+ sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
+ break;
+ }
+ case P4_INT64: {
+ sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64);
+ break;
+ }
+ case P4_INT32: {
+ sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i);
+ break;
+ }
+ case P4_REAL: {
+ sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal);
+ break;
+ }
+ case P4_MEM: {
+ Mem *pMem = pOp->p4.pMem;
+ if( pMem->flags & MEM_Str ){
+ zP4 = pMem->z;
+ }else if( pMem->flags & MEM_Int ){
+ sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);
+ }else if( pMem->flags & MEM_Real ){
+ sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r);
+ }else if( pMem->flags & MEM_Null ){
+ sqlite3_snprintf(nTemp, zTemp, "NULL");
+ }else{
+ assert( pMem->flags & MEM_Blob );
+ zP4 = "(blob)";
+ }
+ break;
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ case P4_VTAB: {
+ sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab;
+ sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
+ break;
+ }
+#endif
+ case P4_INTARRAY: {
+ sqlite3_snprintf(nTemp, zTemp, "intarray");
+ break;
+ }
+ case P4_SUBPROGRAM: {
+ sqlite3_snprintf(nTemp, zTemp, "program");
+ break;
+ }
+ case P4_ADVANCE: {
+ zTemp[0] = 0;
+ break;
+ }
+ default: {
+ zP4 = pOp->p4.z;
+ if( zP4==0 ){
+ zP4 = zTemp;
+ zTemp[0] = 0;
+ }
+ }
+ }
+ assert( zP4!=0 );
+ return zP4;
+}
+#endif
+
+/*
+** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
+**
+** The prepared statements need to know in advance the complete set of
+** attached databases that will be use. A mask of these databases
+** is maintained in p->btreeMask. The p->lockMask value is the subset of
+** p->btreeMask of databases that will require a lock.
+*/
+SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
+ assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
+ assert( i<(int)sizeof(p->btreeMask)*8 );
+ p->btreeMask |= ((yDbMask)1)<<i;
+ if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
+ p->lockMask |= ((yDbMask)1)<<i;
+ }
+}
+
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
+/*
+** If SQLite is compiled to support shared-cache mode and to be threadsafe,
+** this routine obtains the mutex associated with each BtShared structure
+** that may be accessed by the VM passed as an argument. In doing so it also
+** sets the BtShared.db member of each of the BtShared structures, ensuring
+** that the correct busy-handler callback is invoked if required.
+**
+** If SQLite is not threadsafe but does support shared-cache mode, then
+** sqlite3BtreeEnter() is invoked to set the BtShared.db variables
+** of all of BtShared structures accessible via the database handle
+** associated with the VM.
+**
+** If SQLite is not threadsafe and does not support shared-cache mode, this
+** function is a no-op.
+**
+** The p->btreeMask field is a bitmask of all btrees that the prepared
+** statement p will ever use. Let N be the number of bits in p->btreeMask
+** corresponding to btrees that use shared cache. Then the runtime of
+** this routine is N*N. But as N is rarely more than 1, this should not
+** be a problem.
+*/
+SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){
+ int i;
+ yDbMask mask;
+ sqlite3 *db;
+ Db *aDb;
+ int nDb;
+ if( p->lockMask==0 ) return; /* The common case */
+ db = p->db;
+ aDb = db->aDb;
+ nDb = db->nDb;
+ for(i=0, mask=1; i<nDb; i++, mask += mask){
+ if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
+ sqlite3BtreeEnter(aDb[i].pBt);
+ }
+ }
+}
+#endif
+
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
+/*
+** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
+*/
+SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
+ int i;
+ yDbMask mask;
+ sqlite3 *db;
+ Db *aDb;
+ int nDb;
+ if( p->lockMask==0 ) return; /* The common case */
+ db = p->db;
+ aDb = db->aDb;
+ nDb = db->nDb;
+ for(i=0, mask=1; i<nDb; i++, mask += mask){
+ if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
+ sqlite3BtreeLeave(aDb[i].pBt);
+ }
+ }
+}
+#endif
+
+#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+/*
+** Print a single opcode. This routine is used for debugging only.
+*/
+SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
+ char *zP4;
+ char zPtr[50];
+ static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
+ if( pOut==0 ) pOut = stdout;
+ zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
+ fprintf(pOut, zFormat1, pc,
+ sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
+#ifdef SQLITE_DEBUG
+ pOp->zComment ? pOp->zComment : ""
+#else
+ ""
+#endif
+ );
+ fflush(pOut);
+}
+#endif
+
+/*
+** Release an array of N Mem elements
+*/
+static void releaseMemArray(Mem *p, int N){
+ if( p && N ){
+ Mem *pEnd;
+ sqlite3 *db = p->db;
+ u8 malloc_failed = db->mallocFailed;
+ if( db->pnBytesFreed ){
+ for(pEnd=&p[N]; p<pEnd; p++){
+ sqlite3DbFree(db, p->zMalloc);
+ }
+ return;
+ }
+ for(pEnd=&p[N]; p<pEnd; p++){
+ assert( (&p[1])==pEnd || p[0].db==p[1].db );
+
+ /* This block is really an inlined version of sqlite3VdbeMemRelease()
+ ** that takes advantage of the fact that the memory cell value is
+ ** being set to NULL after releasing any dynamic resources.
+ **
+ ** The justification for duplicating code is that according to
+ ** callgrind, this causes a certain test case to hit the CPU 4.7
+ ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
+ ** sqlite3MemRelease() were called from here. With -O2, this jumps
+ ** to 6.6 percent. The test case is inserting 1000 rows into a table
+ ** with no indexes using a single prepared INSERT statement, bind()
+ ** and reset(). Inserts are grouped into a transaction.
+ */
+ if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
+ sqlite3VdbeMemRelease(p);
+ }else if( p->zMalloc ){
+ sqlite3DbFree(db, p->zMalloc);
+ p->zMalloc = 0;
+ }
+
+ p->flags = MEM_Invalid;
+ }
+ db->mallocFailed = malloc_failed;
+ }
+}
+
+/*
+** Delete a VdbeFrame object and its contents. VdbeFrame objects are
+** allocated by the OP_Program opcode in sqlite3VdbeExec().
+*/
+SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){
+ int i;
+ Mem *aMem = VdbeFrameMem(p);
+ VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
+ for(i=0; i<p->nChildCsr; i++){
+ sqlite3VdbeFreeCursor(p->v, apCsr[i]);
+ }
+ releaseMemArray(aMem, p->nChildMem);
+ sqlite3DbFree(p->v->db, p);
+}
+
+#ifndef SQLITE_OMIT_EXPLAIN
+/*
+** Give a listing of the program in the virtual machine.
+**
+** The interface is the same as sqlite3VdbeExec(). But instead of
+** running the code, it invokes the callback once for each instruction.
+** This feature is used to implement "EXPLAIN".
+**
+** When p->explain==1, each instruction is listed. When
+** p->explain==2, only OP_Explain instructions are listed and these
+** are shown in a different format. p->explain==2 is used to implement
+** EXPLAIN QUERY PLAN.
+**
+** When p->explain==1, first the main program is listed, then each of
+** the trigger subprograms are listed one by one.
+*/
+SQLITE_PRIVATE int sqlite3VdbeList(
+ Vdbe *p /* The VDBE */
+){
+ int nRow; /* Stop when row count reaches this */
+ int nSub = 0; /* Number of sub-vdbes seen so far */
+ SubProgram **apSub = 0; /* Array of sub-vdbes */
+ Mem *pSub = 0; /* Memory cell hold array of subprogs */
+ sqlite3 *db = p->db; /* The database connection */
+ int i; /* Loop counter */
+ int rc = SQLITE_OK; /* Return code */
+ Mem *pMem = &p->aMem[1]; /* First Mem of result set */
+
+ assert( p->explain );
+ assert( p->magic==VDBE_MAGIC_RUN );
+ assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
+
+ /* Even though this opcode does not use dynamic strings for
+ ** the result, result columns may become dynamic if the user calls
+ ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
+ */
+ releaseMemArray(pMem, 8);
+ p->pResultSet = 0;
+
+ if( p->rc==SQLITE_NOMEM ){
+ /* This happens if a malloc() inside a call to sqlite3_column_text() or
+ ** sqlite3_column_text16() failed. */
+ db->mallocFailed = 1;
+ return SQLITE_ERROR;
+ }
+
+ /* When the number of output rows reaches nRow, that means the
+ ** listing has finished and sqlite3_step() should return SQLITE_DONE.
+ ** nRow is the sum of the number of rows in the main program, plus
+ ** the sum of the number of rows in all trigger subprograms encountered
+ ** so far. The nRow value will increase as new trigger subprograms are
+ ** encountered, but p->pc will eventually catch up to nRow.
+ */
+ nRow = p->nOp;
+ if( p->explain==1 ){
+ /* The first 8 memory cells are used for the result set. So we will
+ ** commandeer the 9th cell to use as storage for an array of pointers
+ ** to trigger subprograms. The VDBE is guaranteed to have at least 9
+ ** cells. */
+ assert( p->nMem>9 );
+ pSub = &p->aMem[9];
+ if( pSub->flags&MEM_Blob ){
+ /* On the first call to sqlite3_step(), pSub will hold a NULL. It is
+ ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
+ nSub = pSub->n/sizeof(Vdbe*);
+ apSub = (SubProgram **)pSub->z;
+ }
+ for(i=0; i<nSub; i++){
+ nRow += apSub[i]->nOp;
+ }
+ }
+
+ do{
+ i = p->pc++;
+ }while( i<nRow && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
+ if( i>=nRow ){
+ p->rc = SQLITE_OK;
+ rc = SQLITE_DONE;
+ }else if( db->u1.isInterrupted ){
+ p->rc = SQLITE_INTERRUPT;
+ rc = SQLITE_ERROR;
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc));
+ }else{
+ char *z;
+ Op *pOp;
+ if( i<p->nOp ){
+ /* The output line number is small enough that we are still in the
+ ** main program. */
+ pOp = &p->aOp[i];
+ }else{
+ /* We are currently listing subprograms. Figure out which one and
+ ** pick up the appropriate opcode. */
+ int j;
+ i -= p->nOp;
+ for(j=0; i>=apSub[j]->nOp; j++){
+ i -= apSub[j]->nOp;
+ }
+ pOp = &apSub[j]->aOp[i];
+ }
+ if( p->explain==1 ){
+ pMem->flags = MEM_Int;
+ pMem->type = SQLITE_INTEGER;
+ pMem->u.i = i; /* Program counter */
+ pMem++;
+
+ pMem->flags = MEM_Static|MEM_Str|MEM_Term;
+ pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
+ assert( pMem->z!=0 );
+ pMem->n = sqlite3Strlen30(pMem->z);
+ pMem->type = SQLITE_TEXT;
+ pMem->enc = SQLITE_UTF8;
+ pMem++;
+
+ /* When an OP_Program opcode is encounter (the only opcode that has
+ ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
+ ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
+ ** has not already been seen.
+ */
+ if( pOp->p4type==P4_SUBPROGRAM ){
+ int nByte = (nSub+1)*sizeof(SubProgram*);
+ int j;
+ for(j=0; j<nSub; j++){
+ if( apSub[j]==pOp->p4.pProgram ) break;
+ }
+ if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){
+ apSub = (SubProgram **)pSub->z;
+ apSub[nSub++] = pOp->p4.pProgram;
+ pSub->flags |= MEM_Blob;
+ pSub->n = nSub*sizeof(SubProgram*);
+ }
+ }
+ }
+
+ pMem->flags = MEM_Int;
+ pMem->u.i = pOp->p1; /* P1 */
+ pMem->type = SQLITE_INTEGER;
+ pMem++;
+
+ pMem->flags = MEM_Int;
+ pMem->u.i = pOp->p2; /* P2 */
+ pMem->type = SQLITE_INTEGER;
+ pMem++;
+
+ pMem->flags = MEM_Int;
+ pMem->u.i = pOp->p3; /* P3 */
+ pMem->type = SQLITE_INTEGER;
+ pMem++;
+
+ if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
+ assert( p->db->mallocFailed );
+ return SQLITE_ERROR;
+ }
+ pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ z = displayP4(pOp, pMem->z, 32);
+ if( z!=pMem->z ){
+ sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0);
+ }else{
+ assert( pMem->z!=0 );
+ pMem->n = sqlite3Strlen30(pMem->z);
+ pMem->enc = SQLITE_UTF8;
+ }
+ pMem->type = SQLITE_TEXT;
+ pMem++;
+
+ if( p->explain==1 ){
+ if( sqlite3VdbeMemGrow(pMem, 4, 0) ){
+ assert( p->db->mallocFailed );
+ return SQLITE_ERROR;
+ }
+ pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ pMem->n = 2;
+ sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
+ pMem->type = SQLITE_TEXT;
+ pMem->enc = SQLITE_UTF8;
+ pMem++;
+
+#ifdef SQLITE_DEBUG
+ if( pOp->zComment ){
+ pMem->flags = MEM_Str|MEM_Term;
+ pMem->z = pOp->zComment;
+ pMem->n = sqlite3Strlen30(pMem->z);
+ pMem->enc = SQLITE_UTF8;
+ pMem->type = SQLITE_TEXT;
+ }else
+#endif
+ {
+ pMem->flags = MEM_Null; /* Comment */
+ pMem->type = SQLITE_NULL;
+ }
+ }
+
+ p->nResColumn = 8 - 4*(p->explain-1);
+ p->pResultSet = &p->aMem[1];
+ p->rc = SQLITE_OK;
+ rc = SQLITE_ROW;
+ }
+ return rc;
+}
+#endif /* SQLITE_OMIT_EXPLAIN */
+
+#ifdef SQLITE_DEBUG
+/*
+** Print the SQL that was used to generate a VDBE program.
+*/
+SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){
+ int nOp = p->nOp;
+ VdbeOp *pOp;
+ if( nOp<1 ) return;
+ pOp = &p->aOp[0];
+ if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
+ const char *z = pOp->p4.z;
+ while( sqlite3Isspace(*z) ) z++;
+ printf("SQL: [%s]\n", z);
+ }
+}
+#endif
+
+#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
+/*
+** Print an IOTRACE message showing SQL content.
+*/
+SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){
+ int nOp = p->nOp;
+ VdbeOp *pOp;
+ if( sqlite3IoTrace==0 ) return;
+ if( nOp<1 ) return;
+ pOp = &p->aOp[0];
+ if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
+ int i, j;
+ char z[1000];
+ sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z);
+ for(i=0; sqlite3Isspace(z[i]); i++){}
+ for(j=0; z[i]; i++){
+ if( sqlite3Isspace(z[i]) ){
+ if( z[i-1]!=' ' ){
+ z[j++] = ' ';
+ }
+ }else{
+ z[j++] = z[i];
+ }
+ }
+ z[j] = 0;
+ sqlite3IoTrace("SQL %s\n", z);
+ }
+}
+#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
+
+/*
+** Allocate space from a fixed size buffer and return a pointer to
+** that space. If insufficient space is available, return NULL.
+**
+** The pBuf parameter is the initial value of a pointer which will
+** receive the new memory. pBuf is normally NULL. If pBuf is not
+** NULL, it means that memory space has already been allocated and that
+** this routine should not allocate any new memory. When pBuf is not
+** NULL simply return pBuf. Only allocate new memory space when pBuf
+** is NULL.
+**
+** nByte is the number of bytes of space needed.
+**
+** *ppFrom points to available space and pEnd points to the end of the
+** available space. When space is allocated, *ppFrom is advanced past
+** the end of the allocated space.
+**
+** *pnByte is a counter of the number of bytes of space that have failed
+** to allocate. If there is insufficient space in *ppFrom to satisfy the
+** request, then increment *pnByte by the amount of the request.
+*/
+static void *allocSpace(
+ void *pBuf, /* Where return pointer will be stored */
+ int nByte, /* Number of bytes to allocate */
+ u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */
+ u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */
+ int *pnByte /* If allocation cannot be made, increment *pnByte */
+){
+ assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) );
+ if( pBuf ) return pBuf;
+ nByte = ROUND8(nByte);
+ if( &(*ppFrom)[nByte] <= pEnd ){
+ pBuf = (void*)*ppFrom;
+ *ppFrom += nByte;
+ }else{
+ *pnByte += nByte;
+ }
+ return pBuf;
+}
+
+/*
+** Rewind the VDBE back to the beginning in preparation for
+** running it.
+*/
+SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+ int i;
+#endif
+ assert( p!=0 );
+ assert( p->magic==VDBE_MAGIC_INIT );
+
+ /* There should be at least one opcode.
+ */
+ assert( p->nOp>0 );
+
+ /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
+ p->magic = VDBE_MAGIC_RUN;
+
+#ifdef SQLITE_DEBUG
+ for(i=1; i<p->nMem; i++){
+ assert( p->aMem[i].db==p->db );
+ }
+#endif
+ p->pc = -1;
+ p->rc = SQLITE_OK;
+ p->errorAction = OE_Abort;
+ p->magic = VDBE_MAGIC_RUN;
+ p->nChange = 0;
+ p->cacheCtr = 1;
+ p->minWriteFileFormat = 255;
+ p->iStatement = 0;
+ p->nFkConstraint = 0;
+#ifdef VDBE_PROFILE
+ for(i=0; i<p->nOp; i++){
+ p->aOp[i].cnt = 0;
+ p->aOp[i].cycles = 0;
+ }
+#endif
+}
+
+/*
+** Prepare a virtual machine for execution for the first time after
+** creating the virtual machine. This involves things such
+** as allocating stack space and initializing the program counter.
+** After the VDBE has be prepped, it can be executed by one or more
+** calls to sqlite3VdbeExec().
+**
+** This function may be called exact once on a each virtual machine.
+** After this routine is called the VM has been "packaged" and is ready
+** to run. After this routine is called, futher calls to
+** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
+** the Vdbe from the Parse object that helped generate it so that the
+** the Vdbe becomes an independent entity and the Parse object can be
+** destroyed.
+**
+** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back
+** to its initial state after it has been run.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMakeReady(
+ Vdbe *p, /* The VDBE */
+ Parse *pParse /* Parsing context */
+){
+ sqlite3 *db; /* The database connection */
+ int nVar; /* Number of parameters */
+ int nMem; /* Number of VM memory registers */
+ int nCursor; /* Number of cursors required */
+ int nArg; /* Number of arguments in subprograms */
+ int nOnce; /* Number of OP_Once instructions */
+ int n; /* Loop counter */
+ u8 *zCsr; /* Memory available for allocation */
+ u8 *zEnd; /* First byte past allocated memory */
+ int nByte; /* How much extra memory is needed */
+
+ assert( p!=0 );
+ assert( p->nOp>0 );
+ assert( pParse!=0 );
+ assert( p->magic==VDBE_MAGIC_INIT );
+ db = p->db;
+ assert( db->mallocFailed==0 );
+ nVar = pParse->nVar;
+ nMem = pParse->nMem;
+ nCursor = pParse->nTab;
+ nArg = pParse->nMaxArg;
+ nOnce = pParse->nOnce;
+ if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */
+
+ /* For each cursor required, also allocate a memory cell. Memory
+ ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
+ ** the vdbe program. Instead they are used to allocate space for
+ ** VdbeCursor/BtCursor structures. The blob of memory associated with
+ ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
+ ** stores the blob of memory associated with cursor 1, etc.
+ **
+ ** See also: allocateCursor().
+ */
+ nMem += nCursor;
+
+ /* Allocate space for memory registers, SQL variables, VDBE cursors and
+ ** an array to marshal SQL function arguments in.
+ */
+ zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
+ zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */
+
+ resolveP2Values(p, &nArg);
+ p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
+ if( pParse->explain && nMem<10 ){
+ nMem = 10;
+ }
+ memset(zCsr, 0, zEnd-zCsr);
+ zCsr += (zCsr - (u8*)0)&7;
+ assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
+ p->expired = 0;
+
+ /* Memory for registers, parameters, cursor, etc, is allocated in two
+ ** passes. On the first pass, we try to reuse unused space at the
+ ** end of the opcode array. If we are unable to satisfy all memory
+ ** requirements by reusing the opcode array tail, then the second
+ ** pass will fill in the rest using a fresh allocation.
+ **
+ ** This two-pass approach that reuses as much memory as possible from
+ ** the leftover space at the end of the opcode array can significantly
+ ** reduce the amount of memory held by a prepared statement.
+ */
+ do {
+ nByte = 0;
+ p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
+ p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
+ p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
+ p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
+ p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
+ &zCsr, zEnd, &nByte);
+ p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte);
+ if( nByte ){
+ p->pFree = sqlite3DbMallocZero(db, nByte);
+ }
+ zCsr = p->pFree;
+ zEnd = &zCsr[nByte];
+ }while( nByte && !db->mallocFailed );
+
+ p->nCursor = nCursor;
+ p->nOnceFlag = nOnce;
+ if( p->aVar ){
+ p->nVar = (ynVar)nVar;
+ for(n=0; n<nVar; n++){
+ p->aVar[n].flags = MEM_Null;
+ p->aVar[n].db = db;
+ }
+ }
+ if( p->azVar ){
+ p->nzVar = pParse->nzVar;
+ memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
+ memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
+ }
+ if( p->aMem ){
+ p->aMem--; /* aMem[] goes from 1..nMem */
+ p->nMem = nMem; /* not from 0..nMem-1 */
+ for(n=1; n<=nMem; n++){
+ p->aMem[n].flags = MEM_Invalid;
+ p->aMem[n].db = db;
+ }
+ }
+ p->explain = pParse->explain;
+ sqlite3VdbeRewind(p);
+}
+
+/*
+** Close a VDBE cursor and release all the resources that cursor
+** happens to hold.
+*/
+SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
+ if( pCx==0 ){
+ return;
+ }
+ sqlite3VdbeSorterClose(p->db, pCx);
+ if( pCx->pBt ){
+ sqlite3BtreeClose(pCx->pBt);
+ /* The pCx->pCursor will be close automatically, if it exists, by
+ ** the call above. */
+ }else if( pCx->pCursor ){
+ sqlite3BtreeCloseCursor(pCx->pCursor);
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pCx->pVtabCursor ){
+ sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
+ const sqlite3_module *pModule = pCx->pModule;
+ p->inVtabMethod = 1;
+ pModule->xClose(pVtabCursor);
+ p->inVtabMethod = 0;
+ }
+#endif
+}
+
+/*
+** Copy the values stored in the VdbeFrame structure to its Vdbe. This
+** is used, for example, when a trigger sub-program is halted to restore
+** control to the main program.
+*/
+SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
+ Vdbe *v = pFrame->v;
+ v->aOnceFlag = pFrame->aOnceFlag;
+ v->nOnceFlag = pFrame->nOnceFlag;
+ v->aOp = pFrame->aOp;
+ v->nOp = pFrame->nOp;
+ v->aMem = pFrame->aMem;
+ v->nMem = pFrame->nMem;
+ v->apCsr = pFrame->apCsr;
+ v->nCursor = pFrame->nCursor;
+ v->db->lastRowid = pFrame->lastRowid;
+ v->nChange = pFrame->nChange;
+ return pFrame->pc;
+}
+
+/*
+** Close all cursors.
+**
+** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
+** cell array. This is necessary as the memory cell array may contain
+** pointers to VdbeFrame objects, which may in turn contain pointers to
+** open cursors.
+*/
+static void closeAllCursors(Vdbe *p){
+ if( p->pFrame ){
+ VdbeFrame *pFrame;
+ for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
+ sqlite3VdbeFrameRestore(pFrame);
+ }
+ p->pFrame = 0;
+ p->nFrame = 0;
+
+ if( p->apCsr ){
+ int i;
+ for(i=0; i<p->nCursor; i++){
+ VdbeCursor *pC = p->apCsr[i];
+ if( pC ){
+ sqlite3VdbeFreeCursor(p, pC);
+ p->apCsr[i] = 0;
+ }
+ }
+ }
+ if( p->aMem ){
+ releaseMemArray(&p->aMem[1], p->nMem);
+ }
+ while( p->pDelFrame ){
+ VdbeFrame *pDel = p->pDelFrame;
+ p->pDelFrame = pDel->pParent;
+ sqlite3VdbeFrameDelete(pDel);
+ }
+}
+
+/*
+** Clean up the VM after execution.
+**
+** This routine will automatically close any cursors, lists, and/or
+** sorters that were left open. It also deletes the values of
+** variables in the aVar[] array.
+*/
+static void Cleanup(Vdbe *p){
+ sqlite3 *db = p->db;
+
+#ifdef SQLITE_DEBUG
+ /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
+ ** Vdbe.aMem[] arrays have already been cleaned up. */
+ int i;
+ if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
+ if( p->aMem ){
+ for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
+ }
+#endif
+
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
+ p->pResultSet = 0;
+}
+
+/*
+** Set the number of result columns that will be returned by this SQL
+** statement. This is now set at compile time, rather than during
+** execution of the vdbe program so that sqlite3_column_count() can
+** be called on an SQL statement before sqlite3_step().
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
+ Mem *pColName;
+ int n;
+ sqlite3 *db = p->db;
+
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ sqlite3DbFree(db, p->aColName);
+ n = nResColumn*COLNAME_N;
+ p->nResColumn = (u16)nResColumn;
+ p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n );
+ if( p->aColName==0 ) return;
+ while( n-- > 0 ){
+ pColName->flags = MEM_Null;
+ pColName->db = p->db;
+ pColName++;
+ }
+}
+
+/*
+** Set the name of the idx'th column to be returned by the SQL statement.
+** zName must be a pointer to a nul terminated string.
+**
+** This call must be made after a call to sqlite3VdbeSetNumCols().
+**
+** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC
+** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed
+** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed.
+*/
+SQLITE_PRIVATE int sqlite3VdbeSetColName(
+ Vdbe *p, /* Vdbe being configured */
+ int idx, /* Index of column zName applies to */
+ int var, /* One of the COLNAME_* constants */
+ const char *zName, /* Pointer to buffer containing name */
+ void (*xDel)(void*) /* Memory management strategy for zName */
+){
+ int rc;
+ Mem *pColName;
+ assert( idx<p->nResColumn );
+ assert( var<COLNAME_N );
+ if( p->db->mallocFailed ){
+ assert( !zName || xDel!=SQLITE_DYNAMIC );
+ return SQLITE_NOMEM;
+ }
+ assert( p->aColName!=0 );
+ pColName = &(p->aColName[idx+var*p->nResColumn]);
+ rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel);
+ assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
+ return rc;
+}
+
+/*
+** A read or write transaction may or may not be active on database handle
+** db. If a transaction is active, commit it. If there is a
+** write-transaction spanning more than one database file, this routine
+** takes care of the master journal trickery.
+*/
+static int vdbeCommit(sqlite3 *db, Vdbe *p){
+ int i;
+ int nTrans = 0; /* Number of databases with an active write-transaction */
+ int rc = SQLITE_OK;
+ int needXcommit = 0;
+
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+ /* With this option, sqlite3VtabSync() is defined to be simply
+ ** SQLITE_OK so p is not used.
+ */
+ UNUSED_PARAMETER(p);
+#endif
+
+ /* Before doing anything else, call the xSync() callback for any
+ ** virtual module tables written in this transaction. This has to
+ ** be done before determining whether a master journal file is
+ ** required, as an xSync() callback may add an attached database
+ ** to the transaction.
+ */
+ rc = sqlite3VtabSync(db, &p->zErrMsg);
+
+ /* This loop determines (a) if the commit hook should be invoked and
+ ** (b) how many database files have open write transactions, not
+ ** including the temp database. (b) is important because if more than
+ ** one database file has an open write transaction, a master journal
+ ** file is required for an atomic commit.
+ */
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( sqlite3BtreeIsInTrans(pBt) ){
+ needXcommit = 1;
+ if( i!=1 ) nTrans++;
+ sqlite3BtreeEnter(pBt);
+ rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
+ sqlite3BtreeLeave(pBt);
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* If there are any write-transactions at all, invoke the commit hook */
+ if( needXcommit && db->xCommitCallback ){
+ rc = db->xCommitCallback(db->pCommitArg);
+ if( rc ){
+ return SQLITE_CONSTRAINT_COMMITHOOK;
+ }
+ }
+
+ /* The simple case - no more than one database file (not counting the
+ ** TEMP database) has a transaction active. There is no need for the
+ ** master-journal.
+ **
+ ** If the return value of sqlite3BtreeGetFilename() is a zero length
+ ** string, it means the main database is :memory: or a temp file. In
+ ** that case we do not support atomic multi-file commits, so use the
+ ** simple case then too.
+ */
+ if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
+ || nTrans<=1
+ ){
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
+ }
+ }
+
+ /* Do the commit only if all databases successfully complete phase 1.
+ ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an
+ ** IO error while deleting or truncating a journal file. It is unlikely,
+ ** but could happen. In this case abandon processing and return the error.
+ */
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ rc = sqlite3BtreeCommitPhaseTwo(pBt, 0);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3VtabCommit(db);
+ }
+ }
+
+ /* The complex case - There is a multi-file write-transaction active.
+ ** This requires a master journal file to ensure the transaction is
+ ** committed atomicly.
+ */
+#ifndef SQLITE_OMIT_DISKIO
+ else{
+ sqlite3_vfs *pVfs = db->pVfs;
+ int needSync = 0;
+ char *zMaster = 0; /* File-name for the master journal */
+ char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
+ sqlite3_file *pMaster = 0;
+ i64 offset = 0;
+ int res;
+ int retryCount = 0;
+ int nMainFile;
+
+ /* Select a master journal file name */
+ nMainFile = sqlite3Strlen30(zMainFile);
+ zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile);
+ if( zMaster==0 ) return SQLITE_NOMEM;
+ do {
+ u32 iRandom;
+ if( retryCount ){
+ if( retryCount>100 ){
+ sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
+ sqlite3OsDelete(pVfs, zMaster, 0);
+ break;
+ }else if( retryCount==1 ){
+ sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster);
+ }
+ }
+ retryCount++;
+ sqlite3_randomness(sizeof(iRandom), &iRandom);
+ sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
+ (iRandom>>8)&0xffffff, iRandom&0xff);
+ /* The antipenultimate character of the master journal name must
+ ** be "9" to avoid name collisions when using 8+3 filenames. */
+ assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
+ sqlite3FileSuffix3(zMainFile, zMaster);
+ rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
+ }while( rc==SQLITE_OK && res );
+ if( rc==SQLITE_OK ){
+ /* Open the master journal. */
+ rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
+ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
+ SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
+ );
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, zMaster);
+ return rc;
+ }
+
+ /* Write the name of each database file in the transaction into the new
+ ** master journal file. If an error occurs at this point close
+ ** and delete the master journal file. All the individual journal files
+ ** still have 'null' as the master journal pointer, so they will roll
+ ** back independently if a failure occurs.
+ */
+ for(i=0; i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( sqlite3BtreeIsInTrans(pBt) ){
+ char const *zFile = sqlite3BtreeGetJournalname(pBt);
+ if( zFile==0 ){
+ continue; /* Ignore TEMP and :memory: databases */
+ }
+ assert( zFile[0]!=0 );
+ if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
+ needSync = 1;
+ }
+ rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
+ offset += sqlite3Strlen30(zFile)+1;
+ if( rc!=SQLITE_OK ){
+ sqlite3OsCloseFree(pMaster);
+ sqlite3OsDelete(pVfs, zMaster, 0);
+ sqlite3DbFree(db, zMaster);
+ return rc;
+ }
+ }
+ }
+
+ /* Sync the master journal file. If the IOCAP_SEQUENTIAL device
+ ** flag is set this is not required.
+ */
+ if( needSync
+ && 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
+ && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
+ ){
+ sqlite3OsCloseFree(pMaster);
+ sqlite3OsDelete(pVfs, zMaster, 0);
+ sqlite3DbFree(db, zMaster);
+ return rc;
+ }
+
+ /* Sync all the db files involved in the transaction. The same call
+ ** sets the master journal pointer in each individual journal. If
+ ** an error occurs here, do not delete the master journal file.
+ **
+ ** If the error occurs during the first call to
+ ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the
+ ** master journal file will be orphaned. But we cannot delete it,
+ ** in case the master journal file name was written into the journal
+ ** file before the failure occurred.
+ */
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
+ }
+ }
+ sqlite3OsCloseFree(pMaster);
+ assert( rc!=SQLITE_BUSY );
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, zMaster);
+ return rc;
+ }
+
+ /* Delete the master journal file. This commits the transaction. After
+ ** doing this the directory is synced again before any individual
+ ** transaction files are deleted.
+ */
+ rc = sqlite3OsDelete(pVfs, zMaster, 1);
+ sqlite3DbFree(db, zMaster);
+ zMaster = 0;
+ if( rc ){
+ return rc;
+ }
+
+ /* All files and directories have already been synced, so the following
+ ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
+ ** deleting or truncating journals. If something goes wrong while
+ ** this is happening we don't really care. The integrity of the
+ ** transaction is already guaranteed, but some stray 'cold' journals
+ ** may be lying around. Returning an error code won't help matters.
+ */
+ disable_simulated_io_errors();
+ sqlite3BeginBenignMalloc();
+ for(i=0; i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ sqlite3BtreeCommitPhaseTwo(pBt, 1);
+ }
+ }
+ sqlite3EndBenignMalloc();
+ enable_simulated_io_errors();
+
+ sqlite3VtabCommit(db);
+ }
+#endif
+
+ return rc;
+}
+
+/*
+** This routine checks that the sqlite3.activeVdbeCnt count variable
+** matches the number of vdbe's in the list sqlite3.pVdbe that are
+** currently active. An assertion fails if the two counts do not match.
+** This is an internal self-check only - it is not an essential processing
+** step.
+**
+** This is a no-op if NDEBUG is defined.
+*/
+#ifndef NDEBUG
+static void checkActiveVdbeCnt(sqlite3 *db){
+ Vdbe *p;
+ int cnt = 0;
+ int nWrite = 0;
+ p = db->pVdbe;
+ while( p ){
+ if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
+ cnt++;
+ if( p->readOnly==0 ) nWrite++;
+ }
+ p = p->pNext;
+ }
+ assert( cnt==db->activeVdbeCnt );
+ assert( nWrite==db->writeVdbeCnt );
+}
+#else
+#define checkActiveVdbeCnt(x)
+#endif
+
+/*
+** If the Vdbe passed as the first argument opened a statement-transaction,
+** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
+** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
+** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
+** statement transaction is commtted.
+**
+** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
+** Otherwise SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
+ sqlite3 *const db = p->db;
+ int rc = SQLITE_OK;
+
+ /* If p->iStatement is greater than zero, then this Vdbe opened a
+ ** statement transaction that should be closed here. The only exception
+ ** is that an IO error may have occurred, causing an emergency rollback.
+ ** In this case (db->nStatement==0), and there is nothing to do.
+ */
+ if( db->nStatement && p->iStatement ){
+ int i;
+ const int iSavepoint = p->iStatement-1;
+
+ assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
+ assert( db->nStatement>0 );
+ assert( p->iStatement==(db->nStatement+db->nSavepoint) );
+
+ for(i=0; i<db->nDb; i++){
+ int rc2 = SQLITE_OK;
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ if( eOp==SAVEPOINT_ROLLBACK ){
+ rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
+ }
+ if( rc2==SQLITE_OK ){
+ rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
+ }
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+ }
+ db->nStatement--;
+ p->iStatement = 0;
+
+ if( rc==SQLITE_OK ){
+ if( eOp==SAVEPOINT_ROLLBACK ){
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
+ }
+ }
+
+ /* If the statement transaction is being rolled back, also restore the
+ ** database handles deferred constraint counter to the value it had when
+ ** the statement transaction was opened. */
+ if( eOp==SAVEPOINT_ROLLBACK ){
+ db->nDeferredCons = p->nStmtDefCons;
+ }
+ }
+ return rc;
+}
+
+/*
+** This function is called when a transaction opened by the database
+** handle associated with the VM passed as an argument is about to be
+** committed. If there are outstanding deferred foreign key constraint
+** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
+**
+** If there are outstanding FK violations and this function returns
+** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
+** and write an error message to it. Then return SQLITE_ERROR.
+*/
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
+ sqlite3 *db = p->db;
+ if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
+ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
+ p->errorAction = OE_Abort;
+ sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+#endif
+
+/*
+** This routine is called the when a VDBE tries to halt. If the VDBE
+** has made changes and is in autocommit mode, then commit those
+** changes. If a rollback is needed, then do the rollback.
+**
+** This routine is the only way to move the state of a VM from
+** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to
+** call this on a VM that is in the SQLITE_MAGIC_HALT state.
+**
+** Return an error code. If the commit could not complete because of
+** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
+** means the close did not happen and needs to be repeated.
+*/
+SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
+ int rc; /* Used to store transient return codes */
+ sqlite3 *db = p->db;
+
+ /* This function contains the logic that determines if a statement or
+ ** transaction will be committed or rolled back as a result of the
+ ** execution of this virtual machine.
+ **
+ ** If any of the following errors occur:
+ **
+ ** SQLITE_NOMEM
+ ** SQLITE_IOERR
+ ** SQLITE_FULL
+ ** SQLITE_INTERRUPT
+ **
+ ** Then the internal cache might have been left in an inconsistent
+ ** state. We need to rollback the statement transaction, if there is
+ ** one, or the complete transaction if there is no statement transaction.
+ */
+
+ if( p->db->mallocFailed ){
+ p->rc = SQLITE_NOMEM;
+ }
+ if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
+ closeAllCursors(p);
+ if( p->magic!=VDBE_MAGIC_RUN ){
+ return SQLITE_OK;
+ }
+ checkActiveVdbeCnt(db);
+
+ /* No commit or rollback needed if the program never started */
+ if( p->pc>=0 ){
+ int mrc; /* Primary error code from p->rc */
+ int eStatementOp = 0;
+ int isSpecialError; /* Set to true if a 'special' error */
+
+ /* Lock all btrees used by the statement */
+ sqlite3VdbeEnter(p);
+
+ /* Check for one of the special errors */
+ mrc = p->rc & 0xff;
+ assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */
+ isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
+ || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
+ if( isSpecialError ){
+ /* If the query was read-only and the error code is SQLITE_INTERRUPT,
+ ** no rollback is necessary. Otherwise, at least a savepoint
+ ** transaction must be rolled back to restore the database to a
+ ** consistent state.
+ **
+ ** Even if the statement is read-only, it is important to perform
+ ** a statement or transaction rollback operation. If the error
+ ** occurred while writing to the journal, sub-journal or database
+ ** file as part of an effort to free up cache space (see function
+ ** pagerStress() in pager.c), the rollback is required to restore
+ ** the pager to a consistent state.
+ */
+ if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
+ if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){
+ eStatementOp = SAVEPOINT_ROLLBACK;
+ }else{
+ /* We are forced to roll back the active transaction. Before doing
+ ** so, abort any other statements this handle currently has active.
+ */
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
+ sqlite3CloseSavepoints(db);
+ db->autoCommit = 1;
+ }
+ }
+ }
+
+ /* Check for immediate foreign key violations. */
+ if( p->rc==SQLITE_OK ){
+ sqlite3VdbeCheckFk(p, 0);
+ }
+
+ /* If the auto-commit flag is set and this is the only active writer
+ ** VM, then we do either a commit or rollback of the current transaction.
+ **
+ ** Note: This block also runs if one of the special errors handled
+ ** above has occurred.
+ */
+ if( !sqlite3VtabInSync(db)
+ && db->autoCommit
+ && db->writeVdbeCnt==(p->readOnly==0)
+ ){
+ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
+ rc = sqlite3VdbeCheckFk(p, 1);
+ if( rc!=SQLITE_OK ){
+ if( NEVER(p->readOnly) ){
+ sqlite3VdbeLeave(p);
+ return SQLITE_ERROR;
+ }
+ rc = SQLITE_CONSTRAINT_FOREIGNKEY;
+ }else{
+ /* The auto-commit flag is true, the vdbe program was successful
+ ** or hit an 'OR FAIL' constraint and there are no deferred foreign
+ ** key constraints to hold up the transaction. This means a commit
+ ** is required. */
+ rc = vdbeCommit(db, p);
+ }
+ if( rc==SQLITE_BUSY && p->readOnly ){
+ sqlite3VdbeLeave(p);
+ return SQLITE_BUSY;
+ }else if( rc!=SQLITE_OK ){
+ p->rc = rc;
+ sqlite3RollbackAll(db, SQLITE_OK);
+ }else{
+ db->nDeferredCons = 0;
+ sqlite3CommitInternalChanges(db);
+ }
+ }else{
+ sqlite3RollbackAll(db, SQLITE_OK);
+ }
+ db->nStatement = 0;
+ }else if( eStatementOp==0 ){
+ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
+ eStatementOp = SAVEPOINT_RELEASE;
+ }else if( p->errorAction==OE_Abort ){
+ eStatementOp = SAVEPOINT_ROLLBACK;
+ }else{
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
+ sqlite3CloseSavepoints(db);
+ db->autoCommit = 1;
+ }
+ }
+
+ /* If eStatementOp is non-zero, then a statement transaction needs to
+ ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
+ ** do so. If this operation returns an error, and the current statement
+ ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
+ ** current statement error code.
+ */
+ if( eStatementOp ){
+ rc = sqlite3VdbeCloseStatement(p, eStatementOp);
+ if( rc ){
+ if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
+ p->rc = rc;
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
+ }
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
+ sqlite3CloseSavepoints(db);
+ db->autoCommit = 1;
+ }
+ }
+
+ /* If this was an INSERT, UPDATE or DELETE and no statement transaction
+ ** has been rolled back, update the database connection change-counter.
+ */
+ if( p->changeCntOn ){
+ if( eStatementOp!=SAVEPOINT_ROLLBACK ){
+ sqlite3VdbeSetChanges(db, p->nChange);
+ }else{
+ sqlite3VdbeSetChanges(db, 0);
+ }
+ p->nChange = 0;
+ }
+
+ /* Release the locks */
+ sqlite3VdbeLeave(p);
+ }
+
+ /* We have successfully halted and closed the VM. Record this fact. */
+ if( p->pc>=0 ){
+ db->activeVdbeCnt--;
+ if( !p->readOnly ){
+ db->writeVdbeCnt--;
+ }
+ assert( db->activeVdbeCnt>=db->writeVdbeCnt );
+ }
+ p->magic = VDBE_MAGIC_HALT;
+ checkActiveVdbeCnt(db);
+ if( p->db->mallocFailed ){
+ p->rc = SQLITE_NOMEM;
+ }
+
+ /* If the auto-commit flag is set to true, then any locks that were held
+ ** by connection db have now been released. Call sqlite3ConnectionUnlocked()
+ ** to invoke any required unlock-notify callbacks.
+ */
+ if( db->autoCommit ){
+ sqlite3ConnectionUnlocked(db);
+ }
+
+ assert( db->activeVdbeCnt>0 || db->autoCommit==0 || db->nStatement==0 );
+ return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK);
+}
+
+
+/*
+** Each VDBE holds the result of the most recent sqlite3_step() call
+** in p->rc. This routine sets that result back to SQLITE_OK.
+*/
+SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){
+ p->rc = SQLITE_OK;
+}
+
+/*
+** Copy the error code and error message belonging to the VDBE passed
+** as the first argument to its database handle (so that they will be
+** returned by calls to sqlite3_errcode() and sqlite3_errmsg()).
+**
+** This function does not clear the VDBE error code or message, just
+** copies them to the database handle.
+*/
+SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
+ sqlite3 *db = p->db;
+ int rc = p->rc;
+ if( p->zErrMsg ){
+ u8 mallocFailed = db->mallocFailed;
+ sqlite3BeginBenignMalloc();
+ sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
+ sqlite3EndBenignMalloc();
+ db->mallocFailed = mallocFailed;
+ db->errCode = rc;
+ }else{
+ sqlite3Error(db, rc, 0);
+ }
+ return rc;
+}
+
+#ifdef SQLITE_ENABLE_SQLLOG
+/*
+** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
+** invoke it.
+*/
+static void vdbeInvokeSqllog(Vdbe *v){
+ if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){
+ char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql);
+ assert( v->db->init.busy==0 );
+ if( zExpanded ){
+ sqlite3GlobalConfig.xSqllog(
+ sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1
+ );
+ sqlite3DbFree(v->db, zExpanded);
+ }
+ }
+}
+#else
+# define vdbeInvokeSqllog(x)
+#endif
+
+/*
+** Clean up a VDBE after execution but do not delete the VDBE just yet.
+** Write any error messages into *pzErrMsg. Return the result code.
+**
+** After this routine is run, the VDBE should be ready to be executed
+** again.
+**
+** To look at it another way, this routine resets the state of the
+** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
+** VDBE_MAGIC_INIT.
+*/
+SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
+ sqlite3 *db;
+ db = p->db;
+
+ /* If the VM did not run to completion or if it encountered an
+ ** error, then it might not have been halted properly. So halt
+ ** it now.
+ */
+ sqlite3VdbeHalt(p);
+
+ /* If the VDBE has be run even partially, then transfer the error code
+ ** and error message from the VDBE into the main database structure. But
+ ** if the VDBE has just been set to run but has not actually executed any
+ ** instructions yet, leave the main database error information unchanged.
+ */
+ if( p->pc>=0 ){
+ vdbeInvokeSqllog(p);
+ sqlite3VdbeTransferError(p);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
+ if( p->runOnlyOnce ) p->expired = 1;
+ }else if( p->rc && p->expired ){
+ /* The expired flag was set on the VDBE before the first call
+ ** to sqlite3_step(). For consistency (since sqlite3_step() was
+ ** called), set the database error in this case as well.
+ */
+ sqlite3Error(db, p->rc, 0);
+ sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
+ }
+
+ /* Reclaim all memory used by the VDBE
+ */
+ Cleanup(p);
+
+ /* Save profiling information from this VDBE run.
+ */
+#ifdef VDBE_PROFILE
+ {
+ FILE *out = fopen("vdbe_profile.out", "a");
+ if( out ){
+ int i;
+ fprintf(out, "---- ");
+ for(i=0; i<p->nOp; i++){
+ fprintf(out, "%02x", p->aOp[i].opcode);
+ }
+ fprintf(out, "\n");
+ for(i=0; i<p->nOp; i++){
+ fprintf(out, "%6d %10lld %8lld ",
+ p->aOp[i].cnt,
+ p->aOp[i].cycles,
+ p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
+ );
+ sqlite3VdbePrintOp(out, i, &p->aOp[i]);
+ }
+ fclose(out);
+ }
+ }
+#endif
+ p->magic = VDBE_MAGIC_INIT;
+ return p->rc & db->errMask;
+}
+
+/*
+** Clean up and delete a VDBE after execution. Return an integer which is
+** the result code. Write any error message text into *pzErrMsg.
+*/
+SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
+ int rc = SQLITE_OK;
+ if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
+ rc = sqlite3VdbeReset(p);
+ assert( (rc & p->db->errMask)==rc );
+ }
+ sqlite3VdbeDelete(p);
+ return rc;
+}
+
+/*
+** Call the destructor for each auxdata entry in pVdbeFunc for which
+** the corresponding bit in mask is clear. Auxdata entries beyond 31
+** are always destroyed. To destroy all auxdata entries, call this
+** routine with mask==0.
+*/
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
+ int i;
+ for(i=0; i<pVdbeFunc->nAux; i++){
+ struct AuxData *pAux = &pVdbeFunc->apAux[i];
+ if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
+ if( pAux->xDelete ){
+ pAux->xDelete(pAux->pAux);
+ }
+ pAux->pAux = 0;
+ }
+ }
+}
+
+/*
+** Free all memory associated with the Vdbe passed as the second argument,
+** except for object itself, which is preserved.
+**
+** The difference between this function and sqlite3VdbeDelete() is that
+** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
+** the database connection and frees the object itself.
+*/
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
+ SubProgram *pSub, *pNext;
+ int i;
+ assert( p->db==0 || p->db==db );
+ releaseMemArray(p->aVar, p->nVar);
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ for(pSub=p->pProgram; pSub; pSub=pNext){
+ pNext = pSub->pNext;
+ vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
+ sqlite3DbFree(db, pSub);
+ }
+ for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
+ vdbeFreeOpArray(db, p->aOp, p->nOp);
+ sqlite3DbFree(db, p->aLabel);
+ sqlite3DbFree(db, p->aColName);
+ sqlite3DbFree(db, p->zSql);
+ sqlite3DbFree(db, p->pFree);
+#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
+ sqlite3DbFree(db, p->zExplain);
+ sqlite3DbFree(db, p->pExplain);
+#endif
+}
+
+/*
+** Delete an entire VDBE.
+*/
+SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
+ sqlite3 *db;
+
+ if( NEVER(p==0) ) return;
+ db = p->db;
+ assert( sqlite3_mutex_held(db->mutex) );
+ sqlite3VdbeClearObject(db, p);
+ if( p->pPrev ){
+ p->pPrev->pNext = p->pNext;
+ }else{
+ assert( db->pVdbe==p );
+ db->pVdbe = p->pNext;
+ }
+ if( p->pNext ){
+ p->pNext->pPrev = p->pPrev;
+ }
+ p->magic = VDBE_MAGIC_DEAD;
+ p->db = 0;
+ sqlite3DbFree(db, p);
+}
+
+/*
+** Make sure the cursor p is ready to read or write the row to which it
+** was last positioned. Return an error code if an OOM fault or I/O error
+** prevents us from positioning the cursor to its correct position.
+**
+** If a MoveTo operation is pending on the given cursor, then do that
+** MoveTo now. If no move is pending, check to see if the row has been
+** deleted out from under the cursor and if it has, mark the row as
+** a NULL row.
+**
+** If the cursor is already pointing to the correct row and that row has
+** not been deleted out from under the cursor, then this routine is a no-op.
+*/
+SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
+ if( p->deferredMoveto ){
+ int res, rc;
+#ifdef SQLITE_TEST
+ extern int sqlite3_search_count;
+#endif
+ assert( p->isTable );
+ rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
+ if( rc ) return rc;
+ p->lastRowid = p->movetoTarget;
+ if( res!=0 ) return SQLITE_CORRUPT_BKPT;
+ p->rowidIsValid = 1;
+#ifdef SQLITE_TEST
+ sqlite3_search_count++;
+#endif
+ p->deferredMoveto = 0;
+ p->cacheStatus = CACHE_STALE;
+ }else if( ALWAYS(p->pCursor) ){
+ int hasMoved;
+ int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
+ if( rc ) return rc;
+ if( hasMoved ){
+ p->cacheStatus = CACHE_STALE;
+ p->nullRow = 1;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** The following functions:
+**
+** sqlite3VdbeSerialType()
+** sqlite3VdbeSerialTypeLen()
+** sqlite3VdbeSerialLen()
+** sqlite3VdbeSerialPut()
+** sqlite3VdbeSerialGet()
+**
+** encapsulate the code that serializes values for storage in SQLite
+** data and index records. Each serialized value consists of a
+** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
+** integer, stored as a varint.
+**
+** In an SQLite index record, the serial type is stored directly before
+** the blob of data that it corresponds to. In a table record, all serial
+** types are stored at the start of the record, and the blobs of data at
+** the end. Hence these functions allow the caller to handle the
+** serial-type and data blob separately.
+**
+** The following table describes the various storage classes for data:
+**
+** serial type bytes of data type
+** -------------- --------------- ---------------
+** 0 0 NULL
+** 1 1 signed integer
+** 2 2 signed integer
+** 3 3 signed integer
+** 4 4 signed integer
+** 5 6 signed integer
+** 6 8 signed integer
+** 7 8 IEEE float
+** 8 0 Integer constant 0
+** 9 0 Integer constant 1
+** 10,11 reserved for expansion
+** N>=12 and even (N-12)/2 BLOB
+** N>=13 and odd (N-13)/2 text
+**
+** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions
+** of SQLite will not understand those serial types.
+*/
+
+/*
+** Return the serial-type for the value stored in pMem.
+*/
+SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
+ int flags = pMem->flags;
+ int n;
+
+ if( flags&MEM_Null ){
+ return 0;
+ }
+ if( flags&MEM_Int ){
+ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
+# define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
+ i64 i = pMem->u.i;
+ u64 u;
+ if( i<0 ){
+ if( i<(-MAX_6BYTE) ) return 6;
+ /* Previous test prevents: u = -(-9223372036854775808) */
+ u = -i;
+ }else{
+ u = i;
+ }
+ if( u<=127 ){
+ return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1;
+ }
+ if( u<=32767 ) return 2;
+ if( u<=8388607 ) return 3;
+ if( u<=2147483647 ) return 4;
+ if( u<=MAX_6BYTE ) return 5;
+ return 6;
+ }
+ if( flags&MEM_Real ){
+ return 7;
+ }
+ assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
+ n = pMem->n;
+ if( flags & MEM_Zero ){
+ n += pMem->u.nZero;
+ }
+ assert( n>=0 );
+ return ((n*2) + 12 + ((flags&MEM_Str)!=0));
+}
+
+/*
+** Return the length of the data corresponding to the supplied serial-type.
+*/
+SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
+ if( serial_type>=12 ){
+ return (serial_type-12)/2;
+ }else{
+ static const u8 aSize[] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 };
+ return aSize[serial_type];
+ }
+}
+
+/*
+** If we are on an architecture with mixed-endian floating
+** points (ex: ARM7) then swap the lower 4 bytes with the
+** upper 4 bytes. Return the result.
+**
+** For most architectures, this is a no-op.
+**
+** (later): It is reported to me that the mixed-endian problem
+** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems
+** that early versions of GCC stored the two words of a 64-bit
+** float in the wrong order. And that error has been propagated
+** ever since. The blame is not necessarily with GCC, though.
+** GCC might have just copying the problem from a prior compiler.
+** I am also told that newer versions of GCC that follow a different
+** ABI get the byte order right.
+**
+** Developers using SQLite on an ARM7 should compile and run their
+** application using -DSQLITE_DEBUG=1 at least once. With DEBUG
+** enabled, some asserts below will ensure that the byte order of
+** floating point values is correct.
+**
+** (2007-08-30) Frank van Vugt has studied this problem closely
+** and has send his findings to the SQLite developers. Frank
+** writes that some Linux kernels offer floating point hardware
+** emulation that uses only 32-bit mantissas instead of a full
+** 48-bits as required by the IEEE standard. (This is the
+** CONFIG_FPE_FASTFPE option.) On such systems, floating point
+** byte swapping becomes very complicated. To avoid problems,
+** the necessary byte swapping is carried out using a 64-bit integer
+** rather than a 64-bit float. Frank assures us that the code here
+** works for him. We, the developers, have no way to independently
+** verify this, but Frank seems to know what he is talking about
+** so we trust him.
+*/
+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+static u64 floatSwap(u64 in){
+ union {
+ u64 r;
+ u32 i[2];
+ } u;
+ u32 t;
+
+ u.r = in;
+ t = u.i[0];
+ u.i[0] = u.i[1];
+ u.i[1] = t;
+ return u.r;
+}
+# define swapMixedEndianFloat(X) X = floatSwap(X)
+#else
+# define swapMixedEndianFloat(X)
+#endif
+
+/*
+** Write the serialized data blob for the value stored in pMem into
+** buf. It is assumed that the caller has allocated sufficient space.
+** Return the number of bytes written.
+**
+** nBuf is the amount of space left in buf[]. nBuf must always be
+** large enough to hold the entire field. Except, if the field is
+** a blob with a zero-filled tail, then buf[] might be just the right
+** size to hold everything except for the zero-filled tail. If buf[]
+** is only big enough to hold the non-zero prefix, then only write that
+** prefix into buf[]. But if buf[] is large enough to hold both the
+** prefix and the tail then write the prefix and set the tail to all
+** zeros.
+**
+** Return the number of bytes actually written into buf[]. The number
+** of bytes in the zero-filled tail is included in the return value only
+** if those bytes were zeroed in buf[].
+*/
+SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
+ u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
+ u32 len;
+
+ /* Integer and Real */
+ if( serial_type<=7 && serial_type>0 ){
+ u64 v;
+ u32 i;
+ if( serial_type==7 ){
+ assert( sizeof(v)==sizeof(pMem->r) );
+ memcpy(&v, &pMem->r, sizeof(v));
+ swapMixedEndianFloat(v);
+ }else{
+ v = pMem->u.i;
+ }
+ len = i = sqlite3VdbeSerialTypeLen(serial_type);
+ assert( len<=(u32)nBuf );
+ while( i-- ){
+ buf[i] = (u8)(v&0xFF);
+ v >>= 8;
+ }
+ return len;
+ }
+
+ /* String or blob */
+ if( serial_type>=12 ){
+ assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
+ == (int)sqlite3VdbeSerialTypeLen(serial_type) );
+ assert( pMem->n<=nBuf );
+ len = pMem->n;
+ memcpy(buf, pMem->z, len);
+ if( pMem->flags & MEM_Zero ){
+ len += pMem->u.nZero;
+ assert( nBuf>=0 );
+ if( len > (u32)nBuf ){
+ len = (u32)nBuf;
+ }
+ memset(&buf[pMem->n], 0, len-pMem->n);
+ }
+ return len;
+ }
+
+ /* NULL or constants 0 or 1 */
+ return 0;
+}
+
+/*
+** Deserialize the data blob pointed to by buf as serial type serial_type
+** and store the result in pMem. Return the number of bytes read.
+*/
+SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
+ const unsigned char *buf, /* Buffer to deserialize from */
+ u32 serial_type, /* Serial type to deserialize */
+ Mem *pMem /* Memory cell to write value into */
+){
+ switch( serial_type ){
+ case 10: /* Reserved for future use */
+ case 11: /* Reserved for future use */
+ case 0: { /* NULL */
+ pMem->flags = MEM_Null;
+ break;
+ }
+ case 1: { /* 1-byte signed integer */
+ pMem->u.i = (signed char)buf[0];
+ pMem->flags = MEM_Int;
+ return 1;
+ }
+ case 2: { /* 2-byte signed integer */
+ pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
+ pMem->flags = MEM_Int;
+ return 2;
+ }
+ case 3: { /* 3-byte signed integer */
+ pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
+ pMem->flags = MEM_Int;
+ return 3;
+ }
+ case 4: { /* 4-byte signed integer */
+ pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
+ pMem->flags = MEM_Int;
+ return 4;
+ }
+ case 5: { /* 6-byte signed integer */
+ u64 x = (((signed char)buf[0])<<8) | buf[1];
+ u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
+ x = (x<<32) | y;
+ pMem->u.i = *(i64*)&x;
+ pMem->flags = MEM_Int;
+ return 6;
+ }
+ case 6: /* 8-byte signed integer */
+ case 7: { /* IEEE floating point */
+ u64 x;
+ u32 y;
+#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
+ /* Verify that integers and floating point values use the same
+ ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
+ ** defined that 64-bit floating point values really are mixed
+ ** endian.
+ */
+ static const u64 t1 = ((u64)0x3ff00000)<<32;
+ static const double r1 = 1.0;
+ u64 t2 = t1;
+ swapMixedEndianFloat(t2);
+ assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
+#endif
+
+ x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
+ y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
+ x = (x<<32) | y;
+ if( serial_type==6 ){
+ pMem->u.i = *(i64*)&x;
+ pMem->flags = MEM_Int;
+ }else{
+ assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
+ swapMixedEndianFloat(x);
+ memcpy(&pMem->r, &x, sizeof(x));
+ pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real;
+ }
+ return 8;
+ }
+ case 8: /* Integer 0 */
+ case 9: { /* Integer 1 */
+ pMem->u.i = serial_type-8;
+ pMem->flags = MEM_Int;
+ return 0;
+ }
+ default: {
+ u32 len = (serial_type-12)/2;
+ pMem->z = (char *)buf;
+ pMem->n = len;
+ pMem->xDel = 0;
+ if( serial_type&0x01 ){
+ pMem->flags = MEM_Str | MEM_Ephem;
+ }else{
+ pMem->flags = MEM_Blob | MEM_Ephem;
+ }
+ return len;
+ }
+ }
+ return 0;
+}
+
+/*
+** This routine is used to allocate sufficient space for an UnpackedRecord
+** structure large enough to be used with sqlite3VdbeRecordUnpack() if
+** the first argument is a pointer to KeyInfo structure pKeyInfo.
+**
+** The space is either allocated using sqlite3DbMallocRaw() or from within
+** the unaligned buffer passed via the second and third arguments (presumably
+** stack space). If the former, then *ppFree is set to a pointer that should
+** be eventually freed by the caller using sqlite3DbFree(). Or, if the
+** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
+** before returning.
+**
+** If an OOM error occurs, NULL is returned.
+*/
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
+ KeyInfo *pKeyInfo, /* Description of the record */
+ char *pSpace, /* Unaligned space available */
+ int szSpace, /* Size of pSpace[] in bytes */
+ char **ppFree /* OUT: Caller should free this pointer */
+){
+ UnpackedRecord *p; /* Unpacked record to return */
+ int nOff; /* Increment pSpace by nOff to align it */
+ int nByte; /* Number of bytes required for *p */
+
+ /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
+ ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
+ ** it by. If pSpace is already 8-byte aligned, nOff should be zero.
+ */
+ nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
+ nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
+ if( nByte>szSpace+nOff ){
+ p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
+ *ppFree = (char *)p;
+ if( !p ) return 0;
+ }else{
+ p = (UnpackedRecord*)&pSpace[nOff];
+ *ppFree = 0;
+ }
+
+ p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
+ assert( pKeyInfo->aSortOrder!=0 );
+ p->pKeyInfo = pKeyInfo;
+ p->nField = pKeyInfo->nField + 1;
+ return p;
+}
+
+/*
+** Given the nKey-byte encoding of a record in pKey[], populate the
+** UnpackedRecord structure indicated by the fourth argument with the
+** contents of the decoded record.
+*/
+SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
+ KeyInfo *pKeyInfo, /* Information about the record format */
+ int nKey, /* Size of the binary record */
+ const void *pKey, /* The binary record */
+ UnpackedRecord *p /* Populate this structure before returning. */
+){
+ const unsigned char *aKey = (const unsigned char *)pKey;
+ int d;
+ u32 idx; /* Offset in aKey[] to read from */
+ u16 u; /* Unsigned loop counter */
+ u32 szHdr;
+ Mem *pMem = p->aMem;
+
+ p->flags = 0;
+ assert( EIGHT_BYTE_ALIGNMENT(pMem) );
+ idx = getVarint32(aKey, szHdr);
+ d = szHdr;
+ u = 0;
+ while( idx<szHdr && u<p->nField && d<=nKey ){
+ u32 serial_type;
+
+ idx += getVarint32(&aKey[idx], serial_type);
+ pMem->enc = pKeyInfo->enc;
+ pMem->db = pKeyInfo->db;
+ /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
+ pMem->zMalloc = 0;
+ d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
+ pMem++;
+ u++;
+ }
+ assert( u<=pKeyInfo->nField + 1 );
+ p->nField = u;
+}
+
+/*
+** This function compares the two table rows or index records
+** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
+** or positive integer if key1 is less than, equal to or
+** greater than key2. The {nKey1, pKey1} key must be a blob
+** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
+** key must be a parsed key such as obtained from
+** sqlite3VdbeParseRecord.
+**
+** Key1 and Key2 do not have to contain the same number of fields.
+** The key with fewer fields is usually compares less than the
+** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
+** and the common prefixes are equal, then key1 is less than key2.
+** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
+** equal, then the keys are considered to be equal and
+** the parts beyond the common prefix are ignored.
+*/
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
+ int nKey1, const void *pKey1, /* Left key */
+ UnpackedRecord *pPKey2 /* Right key */
+){
+ int d1; /* Offset into aKey[] of next data element */
+ u32 idx1; /* Offset into aKey[] of next header element */
+ u32 szHdr1; /* Number of bytes in header */
+ int i = 0;
+ int nField;
+ int rc = 0;
+ const unsigned char *aKey1 = (const unsigned char *)pKey1;
+ KeyInfo *pKeyInfo;
+ Mem mem1;
+
+ pKeyInfo = pPKey2->pKeyInfo;
+ mem1.enc = pKeyInfo->enc;
+ mem1.db = pKeyInfo->db;
+ /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
+ VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
+
+ /* Compilers may complain that mem1.u.i is potentially uninitialized.
+ ** We could initialize it, as shown here, to silence those complaints.
+ ** But in fact, mem1.u.i will never actually be used uninitialized, and doing
+ ** the unnecessary initialization has a measurable negative performance
+ ** impact, since this routine is a very high runner. And so, we choose
+ ** to ignore the compiler warnings and leave this variable uninitialized.
+ */
+ /* mem1.u.i = 0; // not needed, here to silence compiler warning */
+
+ idx1 = getVarint32(aKey1, szHdr1);
+ d1 = szHdr1;
+ nField = pKeyInfo->nField;
+ assert( pKeyInfo->aSortOrder!=0 );
+ while( idx1<szHdr1 && i<pPKey2->nField ){
+ u32 serial_type1;
+
+ /* Read the serial types for the next element in each key. */
+ idx1 += getVarint32( aKey1+idx1, serial_type1 );
+ if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
+
+ /* Extract the values to be compared.
+ */
+ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
+
+ /* Do the comparison
+ */
+ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
+ i<nField ? pKeyInfo->aColl[i] : 0);
+ if( rc!=0 ){
+ assert( mem1.zMalloc==0 ); /* See comment below */
+
+ /* Invert the result if we are using DESC sort order. */
+ if( i<nField && pKeyInfo->aSortOrder[i] ){
+ rc = -rc;
+ }
+
+ /* If the PREFIX_SEARCH flag is set and all fields except the final
+ ** rowid field were equal, then clear the PREFIX_SEARCH flag and set
+ ** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1).
+ ** This is used by the OP_IsUnique opcode.
+ */
+ if( (pPKey2->flags & UNPACKED_PREFIX_SEARCH) && i==(pPKey2->nField-1) ){
+ assert( idx1==szHdr1 && rc );
+ assert( mem1.flags & MEM_Int );
+ pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH;
+ pPKey2->rowid = mem1.u.i;
+ }
+
+ return rc;
+ }
+ i++;
+ }
+
+ /* No memory allocation is ever used on mem1. Prove this using
+ ** the following assert(). If the assert() fails, it indicates a
+ ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
+ */
+ assert( mem1.zMalloc==0 );
+
+ /* rc==0 here means that one of the keys ran out of fields and
+ ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
+ ** flag is set, then break the tie by treating key2 as larger.
+ ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
+ ** are considered to be equal. Otherwise, the longer key is the
+ ** larger. As it happens, the pPKey2 will always be the longer
+ ** if there is a difference.
+ */
+ assert( rc==0 );
+ if( pPKey2->flags & UNPACKED_INCRKEY ){
+ rc = -1;
+ }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
+ /* Leave rc==0 */
+ }else if( idx1<szHdr1 ){
+ rc = 1;
+ }
+ return rc;
+}
+
+
+/*
+** pCur points at an index entry created using the OP_MakeRecord opcode.
+** Read the rowid (the last field in the record) and store it in *rowid.
+** Return SQLITE_OK if everything works, or an error code otherwise.
+**
+** pCur might be pointing to text obtained from a corrupt database file.
+** So the content cannot be trusted. Do appropriate checks on the content.
+*/
+SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
+ i64 nCellKey = 0;
+ int rc;
+ u32 szHdr; /* Size of the header */
+ u32 typeRowid; /* Serial type of the rowid */
+ u32 lenRowid; /* Size of the rowid */
+ Mem m, v;
+
+ UNUSED_PARAMETER(db);
+
+ /* Get the size of the index entry. Only indices entries of less
+ ** than 2GiB are support - anything large must be database corruption.
+ ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
+ ** this code can safely assume that nCellKey is 32-bits
+ */
+ assert( sqlite3BtreeCursorIsValid(pCur) );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
+ assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
+ assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
+
+ /* Read in the complete content of the index entry */
+ memset(&m, 0, sizeof(m));
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m);
+ if( rc ){
+ return rc;
+ }
+
+ /* The index entry must begin with a header size */
+ (void)getVarint32((u8*)m.z, szHdr);
+ testcase( szHdr==3 );
+ testcase( szHdr==m.n );
+ if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
+ goto idx_rowid_corruption;
+ }
+
+ /* The last field of the index should be an integer - the ROWID.
+ ** Verify that the last entry really is an integer. */
+ (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
+ testcase( typeRowid==1 );
+ testcase( typeRowid==2 );
+ testcase( typeRowid==3 );
+ testcase( typeRowid==4 );
+ testcase( typeRowid==5 );
+ testcase( typeRowid==6 );
+ testcase( typeRowid==8 );
+ testcase( typeRowid==9 );
+ if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){
+ goto idx_rowid_corruption;
+ }
+ lenRowid = sqlite3VdbeSerialTypeLen(typeRowid);
+ testcase( (u32)m.n==szHdr+lenRowid );
+ if( unlikely((u32)m.n<szHdr+lenRowid) ){
+ goto idx_rowid_corruption;
+ }
+
+ /* Fetch the integer off the end of the index record */
+ sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
+ *rowid = v.u.i;
+ sqlite3VdbeMemRelease(&m);
+ return SQLITE_OK;
+
+ /* Jump here if database corruption is detected after m has been
+ ** allocated. Free the m object and return SQLITE_CORRUPT. */
+idx_rowid_corruption:
+ testcase( m.zMalloc!=0 );
+ sqlite3VdbeMemRelease(&m);
+ return SQLITE_CORRUPT_BKPT;
+}
+
+/*
+** Compare the key of the index entry that cursor pC is pointing to against
+** the key string in pUnpacked. Write into *pRes a number
+** that is negative, zero, or positive if pC is less than, equal to,
+** or greater than pUnpacked. Return SQLITE_OK on success.
+**
+** pUnpacked is either created without a rowid or is truncated so that it
+** omits the rowid at the end. The rowid at the end of the index entry
+** is ignored as well. Hence, this routine only compares the prefixes
+** of the keys prior to the final rowid, not the entire key.
+*/
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
+ VdbeCursor *pC, /* The cursor to compare against */
+ UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */
+ int *res /* Write the comparison result here */
+){
+ i64 nCellKey = 0;
+ int rc;
+ BtCursor *pCur = pC->pCursor;
+ Mem m;
+
+ assert( sqlite3BtreeCursorIsValid(pCur) );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
+ assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
+ /* nCellKey will always be between 0 and 0xffffffff because of the say
+ ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
+ if( nCellKey<=0 || nCellKey>0x7fffffff ){
+ *res = 0;
+ return SQLITE_CORRUPT_BKPT;
+ }
+ memset(&m, 0, sizeof(m));
+ rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
+ if( rc ){
+ return rc;
+ }
+ assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH );
+ *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
+ sqlite3VdbeMemRelease(&m);
+ return SQLITE_OK;
+}
+
+/*
+** This routine sets the value to be returned by subsequent calls to
+** sqlite3_changes() on the database handle 'db'.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
+ assert( sqlite3_mutex_held(db->mutex) );
+ db->nChange = nChange;
+ db->nTotalChange += nChange;
+}
+
+/*
+** Set a flag in the vdbe to update the change counter when it is finalised
+** or reset.
+*/
+SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){
+ v->changeCntOn = 1;
+}
+
+/*
+** Mark every prepared statement associated with a database connection
+** as expired.
+**
+** An expired statement means that recompilation of the statement is
+** recommend. Statements expire when things happen that make their
+** programs obsolete. Removing user-defined functions or collating
+** sequences, or changing an authorization function are the types of
+** things that make prepared statements obsolete.
+*/
+SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){
+ Vdbe *p;
+ for(p = db->pVdbe; p; p=p->pNext){
+ p->expired = 1;
+ }
+}
+
+/*
+** Return the database associated with the Vdbe.
+*/
+SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
+ return v->db;
+}
+
+/*
+** Return a pointer to an sqlite3_value structure containing the value bound
+** parameter iVar of VM v. Except, if the value is an SQL NULL, return
+** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_*
+** constants) to the value before returning it.
+**
+** The returned value must be freed by the caller using sqlite3ValueFree().
+*/
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe *v, int iVar, u8 aff){
+ assert( iVar>0 );
+ if( v ){
+ Mem *pMem = &v->aVar[iVar-1];
+ if( 0==(pMem->flags & MEM_Null) ){
+ sqlite3_value *pRet = sqlite3ValueNew(v->db);
+ if( pRet ){
+ sqlite3VdbeMemCopy((Mem *)pRet, pMem);
+ sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
+ sqlite3VdbeMemStoreType((Mem *)pRet);
+ }
+ return pRet;
+ }
+ }
+ return 0;
+}
+
+/*
+** Configure SQL variable iVar so that binding a new value to it signals
+** to sqlite3_reoptimize() that re-preparing the statement may result
+** in a better query plan.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
+ assert( iVar>0 );
+ if( iVar>32 ){
+ v->expmask = 0xffffffff;
+ }else{
+ v->expmask |= ((u32)1 << (iVar-1));
+ }
+}
+
+/************** End of vdbeaux.c *********************************************/
+/************** Begin file vdbeapi.c *****************************************/
+/*
+** 2004 May 26
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code use to implement APIs that are part of the
+** VDBE.
+*/
+
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** Return TRUE (non-zero) of the statement supplied as an argument needs
+** to be recompiled. A statement needs to be recompiled whenever the
+** execution environment changes in a way that would alter the program
+** that sqlite3_prepare() generates. For example, if new functions or
+** collating sequences are registered or if an authorizer function is
+** added or changed.
+*/
+SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){
+ Vdbe *p = (Vdbe*)pStmt;
+ return p==0 || p->expired;
+}
+#endif
+
+/*
+** Check on a Vdbe to make sure it has not been finalized. Log
+** an error and return true if it has been finalized (or is otherwise
+** invalid). Return false if it is ok.
+*/
+static int vdbeSafety(Vdbe *p){
+ if( p->db==0 ){
+ sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
+ return 1;
+ }else{
+ return 0;
+ }
+}
+static int vdbeSafetyNotNull(Vdbe *p){
+ if( p==0 ){
+ sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
+ return 1;
+ }else{
+ return vdbeSafety(p);
+ }
+}
+
+/*
+** The following routine destroys a virtual machine that is created by
+** the sqlite3_compile() routine. The integer returned is an SQLITE_
+** success/failure code that describes the result of executing the virtual
+** machine.
+**
+** This routine sets the error code and string returned by
+** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
+*/
+SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
+ int rc;
+ if( pStmt==0 ){
+ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL
+ ** pointer is a harmless no-op. */
+ rc = SQLITE_OK;
+ }else{
+ Vdbe *v = (Vdbe*)pStmt;
+ sqlite3 *db = v->db;
+ if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
+ sqlite3_mutex_enter(db->mutex);
+ rc = sqlite3VdbeFinalize(v);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3LeaveMutexAndCloseZombie(db);
+ }
+ return rc;
+}
+
+/*
+** Terminate the current execution of an SQL statement and reset it
+** back to its starting state so that it can be reused. A success code from
+** the prior execution is returned.
+**
+** This routine sets the error code and string returned by
+** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
+*/
+SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){
+ int rc;
+ if( pStmt==0 ){
+ rc = SQLITE_OK;
+ }else{
+ Vdbe *v = (Vdbe*)pStmt;
+ sqlite3_mutex_enter(v->db->mutex);
+ rc = sqlite3VdbeReset(v);
+ sqlite3VdbeRewind(v);
+ assert( (rc & (v->db->errMask))==rc );
+ rc = sqlite3ApiExit(v->db, rc);
+ sqlite3_mutex_leave(v->db->mutex);
+ }
+ return rc;
+}
+
+/*
+** Set all the parameters in the compiled SQL statement to NULL.
+*/
+SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
+ int i;
+ int rc = SQLITE_OK;
+ Vdbe *p = (Vdbe*)pStmt;
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
+#endif
+ sqlite3_mutex_enter(mutex);
+ for(i=0; i<p->nVar; i++){
+ sqlite3VdbeMemRelease(&p->aVar[i]);
+ p->aVar[i].flags = MEM_Null;
+ }
+ if( p->isPrepareV2 && p->expmask ){
+ p->expired = 1;
+ }
+ sqlite3_mutex_leave(mutex);
+ return rc;
+}
+
+
+/**************************** sqlite3_value_ *******************************
+** The following routines extract information from a Mem or sqlite3_value
+** structure.
+*/
+SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
+ Mem *p = (Mem*)pVal;
+ if( p->flags & (MEM_Blob|MEM_Str) ){
+ sqlite3VdbeMemExpandBlob(p);
+ p->flags &= ~MEM_Str;
+ p->flags |= MEM_Blob;
+ return p->n ? p->z : 0;
+ }else{
+ return sqlite3_value_text(pVal);
+ }
+}
+SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){
+ return sqlite3ValueBytes(pVal, SQLITE_UTF8);
+}
+SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){
+ return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE);
+}
+SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){
+ return sqlite3VdbeRealValue((Mem*)pVal);
+}
+SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){
+ return (int)sqlite3VdbeIntValue((Mem*)pVal);
+}
+SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
+ return sqlite3VdbeIntValue((Mem*)pVal);
+}
+SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
+ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){
+ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
+}
+SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){
+ return sqlite3ValueText(pVal, SQLITE_UTF16BE);
+}
+SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
+ return sqlite3ValueText(pVal, SQLITE_UTF16LE);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
+ return pVal->type;
+}
+
+/**************************** sqlite3_result_ *******************************
+** The following routines are used by user-defined functions to specify
+** the function result.
+**
+** The setStrOrError() funtion calls sqlite3VdbeMemSetStr() to store the
+** result as a string or blob but if the string or blob is too large, it
+** then sets the error code to SQLITE_TOOBIG
+*/
+static void setResultStrOrError(
+ sqlite3_context *pCtx, /* Function context */
+ const char *z, /* String pointer */
+ int n, /* Bytes in string, or negative */
+ u8 enc, /* Encoding of z. 0 for BLOBs */
+ void (*xDel)(void*) /* Destructor function */
+){
+ if( sqlite3VdbeMemSetStr(&pCtx->s, z, n, enc, xDel)==SQLITE_TOOBIG ){
+ sqlite3_result_error_toobig(pCtx);
+ }
+}
+SQLITE_API void sqlite3_result_blob(
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
+ void (*xDel)(void *)
+){
+ assert( n>=0 );
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ setResultStrOrError(pCtx, z, n, 0, xDel);
+}
+SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ sqlite3VdbeMemSetDouble(&pCtx->s, rVal);
+}
+SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ pCtx->isError = SQLITE_ERROR;
+ sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ pCtx->isError = SQLITE_ERROR;
+ sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
+}
+#endif
+SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal);
+}
+SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ sqlite3VdbeMemSetInt64(&pCtx->s, iVal);
+}
+SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ sqlite3VdbeMemSetNull(&pCtx->s);
+}
+SQLITE_API void sqlite3_result_text(
+ sqlite3_context *pCtx,
+ const char *z,
+ int n,
+ void (*xDel)(void *)
+){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API void sqlite3_result_text16(
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
+ void (*xDel)(void *)
+){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
+}
+SQLITE_API void sqlite3_result_text16be(
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
+ void (*xDel)(void *)
+){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
+}
+SQLITE_API void sqlite3_result_text16le(
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
+ void (*xDel)(void *)
+){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ sqlite3VdbeMemCopy(&pCtx->s, pValue);
+}
+SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ sqlite3VdbeMemSetZeroBlob(&pCtx->s, n);
+}
+SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
+ pCtx->isError = errCode;
+ if( pCtx->s.flags & MEM_Null ){
+ sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
+ SQLITE_UTF8, SQLITE_STATIC);
+ }
+}
+
+/* Force an SQLITE_TOOBIG error. */
+SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ pCtx->isError = SQLITE_TOOBIG;
+ sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
+ SQLITE_UTF8, SQLITE_STATIC);
+}
+
+/* An SQLITE_NOMEM error. */
+SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ sqlite3VdbeMemSetNull(&pCtx->s);
+ pCtx->isError = SQLITE_NOMEM;
+ pCtx->s.db->mallocFailed = 1;
+}
+
+/*
+** This function is called after a transaction has been committed. It
+** invokes callbacks registered with sqlite3_wal_hook() as required.
+*/
+static int doWalCallbacks(sqlite3 *db){
+ int rc = SQLITE_OK;
+#ifndef SQLITE_OMIT_WAL
+ int i;
+ for(i=0; i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
+ if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
+ rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
+ }
+ }
+ }
+#endif
+ return rc;
+}
+
+/*
+** Execute the statement pStmt, either until a row of data is ready, the
+** statement is completely executed or an error occurs.
+**
+** This routine implements the bulk of the logic behind the sqlite_step()
+** API. The only thing omitted is the automatic recompile if a
+** schema change has occurred. That detail is handled by the
+** outer sqlite3_step() wrapper procedure.
+*/
+static int sqlite3Step(Vdbe *p){
+ sqlite3 *db;
+ int rc;
+
+ assert(p);
+ if( p->magic!=VDBE_MAGIC_RUN ){
+ /* We used to require that sqlite3_reset() be called before retrying
+ ** sqlite3_step() after any error or after SQLITE_DONE. But beginning
+ ** with version 3.7.0, we changed this so that sqlite3_reset() would
+ ** be called automatically instead of throwing the SQLITE_MISUSE error.
+ ** This "automatic-reset" change is not technically an incompatibility,
+ ** since any application that receives an SQLITE_MISUSE is broken by
+ ** definition.
+ **
+ ** Nevertheless, some published applications that were originally written
+ ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
+ ** returns, and those were broken by the automatic-reset change. As a
+ ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
+ ** legacy behavior of returning SQLITE_MISUSE for cases where the
+ ** previous sqlite3_step() returned something other than a SQLITE_LOCKED
+ ** or SQLITE_BUSY error.
+ */
+#ifdef SQLITE_OMIT_AUTORESET
+ if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){
+ sqlite3_reset((sqlite3_stmt*)p);
+ }else{
+ return SQLITE_MISUSE_BKPT;
+ }
+#else
+ sqlite3_reset((sqlite3_stmt*)p);
+#endif
+ }
+
+ /* Check that malloc() has not failed. If it has, return early. */
+ db = p->db;
+ if( db->mallocFailed ){
+ p->rc = SQLITE_NOMEM;
+ return SQLITE_NOMEM;
+ }
+
+ if( p->pc<=0 && p->expired ){
+ p->rc = SQLITE_SCHEMA;
+ rc = SQLITE_ERROR;
+ goto end_of_step;
+ }
+ if( p->pc<0 ){
+ /* If there are no other statements currently running, then
+ ** reset the interrupt flag. This prevents a call to sqlite3_interrupt
+ ** from interrupting a statement that has not yet started.
+ */
+ if( db->activeVdbeCnt==0 ){
+ db->u1.isInterrupted = 0;
+ }
+
+ assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 );
+
+#ifndef SQLITE_OMIT_TRACE
+ if( db->xProfile && !db->init.busy ){
+ sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
+ }
+#endif
+
+ db->activeVdbeCnt++;
+ if( p->readOnly==0 ) db->writeVdbeCnt++;
+ p->pc = 0;
+ }
+#ifndef SQLITE_OMIT_EXPLAIN
+ if( p->explain ){
+ rc = sqlite3VdbeList(p);
+ }else
+#endif /* SQLITE_OMIT_EXPLAIN */
+ {
+ db->vdbeExecCnt++;
+ rc = sqlite3VdbeExec(p);
+ db->vdbeExecCnt--;
+ }
+
+#ifndef SQLITE_OMIT_TRACE
+ /* Invoke the profile callback if there is one
+ */
+ if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){
+ sqlite3_int64 iNow;
+ sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
+ db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000);
+ }
+#endif
+
+ if( rc==SQLITE_DONE ){
+ assert( p->rc==SQLITE_OK );
+ p->rc = doWalCallbacks(db);
+ if( p->rc!=SQLITE_OK ){
+ rc = SQLITE_ERROR;
+ }
+ }
+
+ db->errCode = rc;
+ if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
+ p->rc = SQLITE_NOMEM;
+ }
+end_of_step:
+ /* At this point local variable rc holds the value that should be
+ ** returned if this statement was compiled using the legacy
+ ** sqlite3_prepare() interface. According to the docs, this can only
+ ** be one of the values in the first assert() below. Variable p->rc
+ ** contains the value that would be returned if sqlite3_finalize()
+ ** were called on statement p.
+ */
+ assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
+ || rc==SQLITE_BUSY || rc==SQLITE_MISUSE
+ );
+ assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
+ if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
+ /* If this statement was prepared using sqlite3_prepare_v2(), and an
+ ** error has occurred, then return the error code in p->rc to the
+ ** caller. Set the error code in the database handle to the same value.
+ */
+ rc = sqlite3VdbeTransferError(p);
+ }
+ return (rc&db->errMask);
+}
+
+/*
+** The maximum number of times that a statement will try to reparse
+** itself before giving up and returning SQLITE_SCHEMA.
+*/
+#ifndef SQLITE_MAX_SCHEMA_RETRY
+# define SQLITE_MAX_SCHEMA_RETRY 5
+#endif
+
+/*
+** This is the top-level implementation of sqlite3_step(). Call
+** sqlite3Step() to do most of the work. If a schema error occurs,
+** call sqlite3Reprepare() and try again.
+*/
+SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
+ int rc = SQLITE_OK; /* Result from sqlite3Step() */
+ int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
+ Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
+ int cnt = 0; /* Counter to prevent infinite loop of reprepares */
+ sqlite3 *db; /* The database connection */
+
+ if( vdbeSafetyNotNull(v) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ db = v->db;
+ sqlite3_mutex_enter(db->mutex);
+ v->doingRerun = 0;
+ while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
+ && cnt++ < SQLITE_MAX_SCHEMA_RETRY
+ && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
+ sqlite3_reset(pStmt);
+ v->doingRerun = 1;
+ assert( v->expired==0 );
+ }
+ if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
+ /* This case occurs after failing to recompile an sql statement.
+ ** The error message from the SQL compiler has already been loaded
+ ** into the database handle. This block copies the error message
+ ** from the database handle into the statement and sets the statement
+ ** program counter to 0 to ensure that when the statement is
+ ** finalized or reset the parser error message is available via
+ ** sqlite3_errmsg() and sqlite3_errcode().
+ */
+ const char *zErr = (const char *)sqlite3_value_text(db->pErr);
+ sqlite3DbFree(db, v->zErrMsg);
+ if( !db->mallocFailed ){
+ v->zErrMsg = sqlite3DbStrDup(db, zErr);
+ v->rc = rc2;
+ } else {
+ v->zErrMsg = 0;
+ v->rc = rc = SQLITE_NOMEM;
+ }
+ }
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** Extract the user data from a sqlite3_context structure and return a
+** pointer to it.
+*/
+SQLITE_API void *sqlite3_user_data(sqlite3_context *p){
+ assert( p && p->pFunc );
+ return p->pFunc->pUserData;
+}
+
+/*
+** Extract the user data from a sqlite3_context structure and return a
+** pointer to it.
+**
+** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface
+** returns a copy of the pointer to the database connection (the 1st
+** parameter) of the sqlite3_create_function() and
+** sqlite3_create_function16() routines that originally registered the
+** application defined function.
+*/
+SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
+ assert( p && p->pFunc );
+ return p->s.db;
+}
+
+/*
+** The following is the implementation of an SQL function that always
+** fails with an error message stating that the function is used in the
+** wrong context. The sqlite3_overload_function() API might construct
+** SQL function that use this routine so that the functions will exist
+** for name resolution but are actually overloaded by the xFindFunction
+** method of virtual tables.
+*/
+SQLITE_PRIVATE void sqlite3InvalidFunction(
+ sqlite3_context *context, /* The function calling context */
+ int NotUsed, /* Number of arguments to the function */
+ sqlite3_value **NotUsed2 /* Value of each argument */
+){
+ const char *zName = context->pFunc->zName;
+ char *zErr;
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ zErr = sqlite3_mprintf(
+ "unable to use function %s in the requested context", zName);
+ sqlite3_result_error(context, zErr, -1);
+ sqlite3_free(zErr);
+}
+
+/*
+** Allocate or return the aggregate context for a user function. A new
+** context is allocated on the first call. Subsequent calls return the
+** same context that was returned on prior calls.
+*/
+SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
+ Mem *pMem;
+ assert( p && p->pFunc && p->pFunc->xStep );
+ assert( sqlite3_mutex_held(p->s.db->mutex) );
+ pMem = p->pMem;
+ testcase( nByte<0 );
+ if( (pMem->flags & MEM_Agg)==0 ){
+ if( nByte<=0 ){
+ sqlite3VdbeMemReleaseExternal(pMem);
+ pMem->flags = MEM_Null;
+ pMem->z = 0;
+ }else{
+ sqlite3VdbeMemGrow(pMem, nByte, 0);
+ pMem->flags = MEM_Agg;
+ pMem->u.pDef = p->pFunc;
+ if( pMem->z ){
+ memset(pMem->z, 0, nByte);
+ }
+ }
+ }
+ return (void*)pMem->z;
+}
+
+/*
+** Return the auxilary data pointer, if any, for the iArg'th argument to
+** the user-function defined by pCtx.
+*/
+SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
+ VdbeFunc *pVdbeFunc;
+
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ pVdbeFunc = pCtx->pVdbeFunc;
+ if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
+ return 0;
+ }
+ return pVdbeFunc->apAux[iArg].pAux;
+}
+
+/*
+** Set the auxilary data pointer and delete function, for the iArg'th
+** argument to the user-function defined by pCtx. Any previous value is
+** deleted by calling the delete function specified when it was set.
+*/
+SQLITE_API void sqlite3_set_auxdata(
+ sqlite3_context *pCtx,
+ int iArg,
+ void *pAux,
+ void (*xDelete)(void*)
+){
+ struct AuxData *pAuxData;
+ VdbeFunc *pVdbeFunc;
+ if( iArg<0 ) goto failed;
+
+ assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
+ pVdbeFunc = pCtx->pVdbeFunc;
+ if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
+ int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0);
+ int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
+ pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc);
+ if( !pVdbeFunc ){
+ goto failed;
+ }
+ pCtx->pVdbeFunc = pVdbeFunc;
+ memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux));
+ pVdbeFunc->nAux = iArg+1;
+ pVdbeFunc->pFunc = pCtx->pFunc;
+ }
+
+ pAuxData = &pVdbeFunc->apAux[iArg];
+ if( pAuxData->pAux && pAuxData->xDelete ){
+ pAuxData->xDelete(pAuxData->pAux);
+ }
+ pAuxData->pAux = pAux;
+ pAuxData->xDelete = xDelete;
+ return;
+
+failed:
+ if( xDelete ){
+ xDelete(pAux);
+ }
+}
+
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** Return the number of times the Step function of a aggregate has been
+** called.
+**
+** This function is deprecated. Do not use it for new code. It is
+** provide only to avoid breaking legacy code. New aggregate function
+** implementations should keep their own counts within their aggregate
+** context.
+*/
+SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){
+ assert( p && p->pMem && p->pFunc && p->pFunc->xStep );
+ return p->pMem->n;
+}
+#endif
+
+/*
+** Return the number of columns in the result set for the statement pStmt.
+*/
+SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){
+ Vdbe *pVm = (Vdbe *)pStmt;
+ return pVm ? pVm->nResColumn : 0;
+}
+
+/*
+** Return the number of values available from the current row of the
+** currently executing statement pStmt.
+*/
+SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){
+ Vdbe *pVm = (Vdbe *)pStmt;
+ if( pVm==0 || pVm->pResultSet==0 ) return 0;
+ return pVm->nResColumn;
+}
+
+
+/*
+** Check to see if column iCol of the given statement is valid. If
+** it is, return a pointer to the Mem for the value of that column.
+** If iCol is not valid, return a pointer to a Mem which has a value
+** of NULL.
+*/
+static Mem *columnMem(sqlite3_stmt *pStmt, int i){
+ Vdbe *pVm;
+ Mem *pOut;
+
+ pVm = (Vdbe *)pStmt;
+ if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
+ sqlite3_mutex_enter(pVm->db->mutex);
+ pOut = &pVm->pResultSet[i];
+ }else{
+ /* If the value passed as the second argument is out of range, return
+ ** a pointer to the following static Mem object which contains the
+ ** value SQL NULL. Even though the Mem structure contains an element
+ ** of type i64, on certain architectures (x86) with certain compiler
+ ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
+ ** instead of an 8-byte one. This all works fine, except that when
+ ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
+ ** that a Mem structure is located on an 8-byte boundary. To prevent
+ ** these assert()s from failing, when building with SQLITE_DEBUG defined
+ ** using gcc, we force nullMem to be 8-byte aligned using the magical
+ ** __attribute__((aligned(8))) macro. */
+ static const Mem nullMem
+#if defined(SQLITE_DEBUG) && defined(__GNUC__)
+ __attribute__((aligned(8)))
+#endif
+ = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
+#ifdef SQLITE_DEBUG
+ 0, 0, /* pScopyFrom, pFiller */
+#endif
+ 0, 0 };
+
+ if( pVm && ALWAYS(pVm->db) ){
+ sqlite3_mutex_enter(pVm->db->mutex);
+ sqlite3Error(pVm->db, SQLITE_RANGE, 0);
+ }
+ pOut = (Mem*)&nullMem;
+ }
+ return pOut;
+}
+
+/*
+** This function is called after invoking an sqlite3_value_XXX function on a
+** column value (i.e. a value returned by evaluating an SQL expression in the
+** select list of a SELECT statement) that may cause a malloc() failure. If
+** malloc() has failed, the threads mallocFailed flag is cleared and the result
+** code of statement pStmt set to SQLITE_NOMEM.
+**
+** Specifically, this is called from within:
+**
+** sqlite3_column_int()
+** sqlite3_column_int64()
+** sqlite3_column_text()
+** sqlite3_column_text16()
+** sqlite3_column_real()
+** sqlite3_column_bytes()
+** sqlite3_column_bytes16()
+** sqiite3_column_blob()
+*/
+static void columnMallocFailure(sqlite3_stmt *pStmt)
+{
+ /* If malloc() failed during an encoding conversion within an
+ ** sqlite3_column_XXX API, then set the return code of the statement to
+ ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR
+ ** and _finalize() will return NOMEM.
+ */
+ Vdbe *p = (Vdbe *)pStmt;
+ if( p ){
+ p->rc = sqlite3ApiExit(p->db, p->rc);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+}
+
+/**************************** sqlite3_column_ *******************************
+** The following routines are used to access elements of the current row
+** in the result set.
+*/
+SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
+ const void *val;
+ val = sqlite3_value_blob( columnMem(pStmt,i) );
+ /* Even though there is no encoding conversion, value_blob() might
+ ** need to call malloc() to expand the result of a zeroblob()
+ ** expression.
+ */
+ columnMallocFailure(pStmt);
+ return val;
+}
+SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){
+ int val = sqlite3_value_bytes( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return val;
+}
+SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){
+ int val = sqlite3_value_bytes16( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return val;
+}
+SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){
+ double val = sqlite3_value_double( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return val;
+}
+SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){
+ int val = sqlite3_value_int( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return val;
+}
+SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
+ sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return val;
+}
+SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
+ const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return val;
+}
+SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
+ Mem *pOut = columnMem(pStmt, i);
+ if( pOut->flags&MEM_Static ){
+ pOut->flags &= ~MEM_Static;
+ pOut->flags |= MEM_Ephem;
+ }
+ columnMallocFailure(pStmt);
+ return (sqlite3_value *)pOut;
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
+ const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return val;
+}
+#endif /* SQLITE_OMIT_UTF16 */
+SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
+ int iType = sqlite3_value_type( columnMem(pStmt,i) );
+ columnMallocFailure(pStmt);
+ return iType;
+}
+
+/* The following function is experimental and subject to change or
+** removal */
+/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){
+** return sqlite3_value_numeric_type( columnMem(pStmt,i) );
+**}
+*/
+
+/*
+** Convert the N-th element of pStmt->pColName[] into a string using
+** xFunc() then return that string. If N is out of range, return 0.
+**
+** There are up to 5 names for each column. useType determines which
+** name is returned. Here are the names:
+**
+** 0 The column name as it should be displayed for output
+** 1 The datatype name for the column
+** 2 The name of the database that the column derives from
+** 3 The name of the table that the column derives from
+** 4 The name of the table column that the result column derives from
+**
+** If the result is not a simple column reference (if it is an expression
+** or a constant) then useTypes 2, 3, and 4 return NULL.
+*/
+static const void *columnName(
+ sqlite3_stmt *pStmt,
+ int N,
+ const void *(*xFunc)(Mem*),
+ int useType
+){
+ const void *ret = 0;
+ Vdbe *p = (Vdbe *)pStmt;
+ int n;
+ sqlite3 *db = p->db;
+
+ assert( db!=0 );
+ n = sqlite3_column_count(pStmt);
+ if( N<n && N>=0 ){
+ N += useType*n;
+ sqlite3_mutex_enter(db->mutex);
+ assert( db->mallocFailed==0 );
+ ret = xFunc(&p->aColName[N]);
+ /* A malloc may have failed inside of the xFunc() call. If this
+ ** is the case, clear the mallocFailed flag and return NULL.
+ */
+ if( db->mallocFailed ){
+ db->mallocFailed = 0;
+ ret = 0;
+ }
+ sqlite3_mutex_leave(db->mutex);
+ }
+ return ret;
+}
+
+/*
+** Return the name of the Nth column of the result set returned by SQL
+** statement pStmt.
+*/
+SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
+}
+#endif
+
+/*
+** Constraint: If you have ENABLE_COLUMN_METADATA then you must
+** not define OMIT_DECLTYPE.
+*/
+#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA)
+# error "Must not define both SQLITE_OMIT_DECLTYPE \
+ and SQLITE_ENABLE_COLUMN_METADATA"
+#endif
+
+#ifndef SQLITE_OMIT_DECLTYPE
+/*
+** Return the column declaration type (if applicable) of the 'i'th column
+** of the result set of SQL statement pStmt.
+*/
+SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+#endif /* SQLITE_OMIT_DECLTYPE */
+
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+/*
+** Return the name of the database from which a result column derives.
+** NULL is returned if the result column is an expression or constant or
+** anything else which is not an unabiguous reference to a database column.
+*/
+SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+
+/*
+** Return the name of the table from which a result column derives.
+** NULL is returned if the result column is an expression or constant or
+** anything else which is not an unabiguous reference to a database column.
+*/
+SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+
+/*
+** Return the name of the table column from which a result column derives.
+** NULL is returned if the result column is an expression or constant or
+** anything else which is not an unabiguous reference to a database column.
+*/
+SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
+ return columnName(
+ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+#endif /* SQLITE_ENABLE_COLUMN_METADATA */
+
+
+/******************************* sqlite3_bind_ ***************************
+**
+** Routines used to attach values to wildcards in a compiled SQL statement.
+*/
+/*
+** Unbind the value bound to variable i in virtual machine p. This is the
+** the same as binding a NULL value to the column. If the "i" parameter is
+** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
+**
+** A successful evaluation of this routine acquires the mutex on p.
+** the mutex is released if any kind of error occurs.
+**
+** The error code stored in database p->db is overwritten with the return
+** value in any case.
+*/
+static int vdbeUnbind(Vdbe *p, int i){
+ Mem *pVar;
+ if( vdbeSafetyNotNull(p) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ sqlite3_mutex_enter(p->db->mutex);
+ if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
+ sqlite3Error(p->db, SQLITE_MISUSE, 0);
+ sqlite3_mutex_leave(p->db->mutex);
+ sqlite3_log(SQLITE_MISUSE,
+ "bind on a busy prepared statement: [%s]", p->zSql);
+ return SQLITE_MISUSE_BKPT;
+ }
+ if( i<1 || i>p->nVar ){
+ sqlite3Error(p->db, SQLITE_RANGE, 0);
+ sqlite3_mutex_leave(p->db->mutex);
+ return SQLITE_RANGE;
+ }
+ i--;
+ pVar = &p->aVar[i];
+ sqlite3VdbeMemRelease(pVar);
+ pVar->flags = MEM_Null;
+ sqlite3Error(p->db, SQLITE_OK, 0);
+
+ /* If the bit corresponding to this variable in Vdbe.expmask is set, then
+ ** binding a new value to this variable invalidates the current query plan.
+ **
+ ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
+ ** parameter in the WHERE clause might influence the choice of query plan
+ ** for a statement, then the statement will be automatically recompiled,
+ ** as if there had been a schema change, on the first sqlite3_step() call
+ ** following any change to the bindings of that parameter.
+ */
+ if( p->isPrepareV2 &&
+ ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff)
+ ){
+ p->expired = 1;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Bind a text or BLOB value.
+*/
+static int bindText(
+ sqlite3_stmt *pStmt, /* The statement to bind against */
+ int i, /* Index of the parameter to bind */
+ const void *zData, /* Pointer to the data to be bound */
+ int nData, /* Number of bytes of data to be bound */
+ void (*xDel)(void*), /* Destructor for the data */
+ u8 encoding /* Encoding for the data */
+){
+ Vdbe *p = (Vdbe *)pStmt;
+ Mem *pVar;
+ int rc;
+
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ if( zData!=0 ){
+ pVar = &p->aVar[i-1];
+ rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
+ if( rc==SQLITE_OK && encoding!=0 ){
+ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
+ }
+ sqlite3Error(p->db, rc, 0);
+ rc = sqlite3ApiExit(p->db, rc);
+ }
+ sqlite3_mutex_leave(p->db->mutex);
+ }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
+ xDel((void*)zData);
+ }
+ return rc;
+}
+
+
+/*
+** Bind a blob value to an SQL statement variable.
+*/
+SQLITE_API int sqlite3_bind_blob(
+ sqlite3_stmt *pStmt,
+ int i,
+ const void *zData,
+ int nData,
+ void (*xDel)(void*)
+){
+ return bindText(pStmt, i, zData, nData, xDel, 0);
+}
+SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
+ int rc;
+ Vdbe *p = (Vdbe *)pStmt;
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return rc;
+}
+SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
+ return sqlite3_bind_int64(p, i, (i64)iValue);
+}
+SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
+ int rc;
+ Vdbe *p = (Vdbe *)pStmt;
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return rc;
+}
+SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
+ int rc;
+ Vdbe *p = (Vdbe*)pStmt;
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return rc;
+}
+SQLITE_API int sqlite3_bind_text(
+ sqlite3_stmt *pStmt,
+ int i,
+ const char *zData,
+ int nData,
+ void (*xDel)(void*)
+){
+ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
+}
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API int sqlite3_bind_text16(
+ sqlite3_stmt *pStmt,
+ int i,
+ const void *zData,
+ int nData,
+ void (*xDel)(void*)
+){
+ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
+ int rc;
+ switch( pValue->type ){
+ case SQLITE_INTEGER: {
+ rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
+ break;
+ }
+ case SQLITE_FLOAT: {
+ rc = sqlite3_bind_double(pStmt, i, pValue->r);
+ break;
+ }
+ case SQLITE_BLOB: {
+ if( pValue->flags & MEM_Zero ){
+ rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
+ }else{
+ rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
+ }
+ break;
+ }
+ case SQLITE_TEXT: {
+ rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT,
+ pValue->enc);
+ break;
+ }
+ default: {
+ rc = sqlite3_bind_null(pStmt, i);
+ break;
+ }
+ }
+ return rc;
+}
+SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
+ int rc;
+ Vdbe *p = (Vdbe *)pStmt;
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return rc;
+}
+
+/*
+** Return the number of wildcards that can be potentially bound to.
+** This routine is added to support DBD::SQLite.
+*/
+SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
+ Vdbe *p = (Vdbe*)pStmt;
+ return p ? p->nVar : 0;
+}
+
+/*
+** Return the name of a wildcard parameter. Return NULL if the index
+** is out of range or if the wildcard is unnamed.
+**
+** The result is always UTF-8.
+*/
+SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
+ Vdbe *p = (Vdbe*)pStmt;
+ if( p==0 || i<1 || i>p->nzVar ){
+ return 0;
+ }
+ return p->azVar[i-1];
+}
+
+/*
+** Given a wildcard parameter name, return the index of the variable
+** with that name. If there is no variable with the given name,
+** return 0.
+*/
+SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
+ int i;
+ if( p==0 ){
+ return 0;
+ }
+ if( zName ){
+ for(i=0; i<p->nzVar; i++){
+ const char *z = p->azVar[i];
+ if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
+ return i+1;
+ }
+ }
+ }
+ return 0;
+}
+SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
+ return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
+}
+
+/*
+** Transfer all bindings from the first statement over to the second.
+*/
+SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+ Vdbe *pFrom = (Vdbe*)pFromStmt;
+ Vdbe *pTo = (Vdbe*)pToStmt;
+ int i;
+ assert( pTo->db==pFrom->db );
+ assert( pTo->nVar==pFrom->nVar );
+ sqlite3_mutex_enter(pTo->db->mutex);
+ for(i=0; i<pFrom->nVar; i++){
+ sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
+ }
+ sqlite3_mutex_leave(pTo->db->mutex);
+ return SQLITE_OK;
+}
+
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** Deprecated external interface. Internal/core SQLite code
+** should call sqlite3TransferBindings.
+**
+** Is is misuse to call this routine with statements from different
+** database connections. But as this is a deprecated interface, we
+** will not bother to check for that condition.
+**
+** If the two statements contain a different number of bindings, then
+** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise
+** SQLITE_OK is returned.
+*/
+SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+ Vdbe *pFrom = (Vdbe*)pFromStmt;
+ Vdbe *pTo = (Vdbe*)pToStmt;
+ if( pFrom->nVar!=pTo->nVar ){
+ return SQLITE_ERROR;
+ }
+ if( pTo->isPrepareV2 && pTo->expmask ){
+ pTo->expired = 1;
+ }
+ if( pFrom->isPrepareV2 && pFrom->expmask ){
+ pFrom->expired = 1;
+ }
+ return sqlite3TransferBindings(pFromStmt, pToStmt);
+}
+#endif
+
+/*
+** Return the sqlite3* database handle to which the prepared statement given
+** in the argument belongs. This is the same database handle that was
+** the first argument to the sqlite3_prepare() that was used to create
+** the statement in the first place.
+*/
+SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
+ return pStmt ? ((Vdbe*)pStmt)->db : 0;
+}
+
+/*
+** Return true if the prepared statement is guaranteed to not modify the
+** database.
+*/
+SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
+ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
+}
+
+/*
+** Return true if the prepared statement is in need of being reset.
+*/
+SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
+ Vdbe *v = (Vdbe*)pStmt;
+ return v!=0 && v->pc>0 && v->magic==VDBE_MAGIC_RUN;
+}
+
+/*
+** Return a pointer to the next prepared statement after pStmt associated
+** with database connection pDb. If pStmt is NULL, return the first
+** prepared statement for the database connection. Return NULL if there
+** are no more.
+*/
+SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
+ sqlite3_stmt *pNext;
+ sqlite3_mutex_enter(pDb->mutex);
+ if( pStmt==0 ){
+ pNext = (sqlite3_stmt*)pDb->pVdbe;
+ }else{
+ pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext;
+ }
+ sqlite3_mutex_leave(pDb->mutex);
+ return pNext;
+}
+
+/*
+** Return the value of a status counter for a prepared statement
+*/
+SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
+ Vdbe *pVdbe = (Vdbe*)pStmt;
+ int v = pVdbe->aCounter[op-1];
+ if( resetFlag ) pVdbe->aCounter[op-1] = 0;
+ return v;
+}
+
+/************** End of vdbeapi.c *********************************************/
+/************** Begin file vdbetrace.c ***************************************/
+/*
+** 2009 November 25
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code used to insert the values of host parameters
+** (aka "wildcards") into the SQL text output by sqlite3_trace().
+**
+** The Vdbe parse-tree explainer is also found here.
+*/
+
+#ifndef SQLITE_OMIT_TRACE
+
+/*
+** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of
+** bytes in this text up to but excluding the first character in
+** a host parameter. If the text contains no host parameters, return
+** the total number of bytes in the text.
+*/
+static int findNextHostParameter(const char *zSql, int *pnToken){
+ int tokenType;
+ int nTotal = 0;
+ int n;
+
+ *pnToken = 0;
+ while( zSql[0] ){
+ n = sqlite3GetToken((u8*)zSql, &tokenType);
+ assert( n>0 && tokenType!=TK_ILLEGAL );
+ if( tokenType==TK_VARIABLE ){
+ *pnToken = n;
+ break;
+ }
+ nTotal += n;
+ zSql += n;
+ }
+ return nTotal;
+}
+
+/*
+** This function returns a pointer to a nul-terminated string in memory
+** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
+** string contains a copy of zRawSql but with host parameters expanded to
+** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1,
+** then the returned string holds a copy of zRawSql with "-- " prepended
+** to each line of text.
+**
+** The calling function is responsible for making sure the memory returned
+** is eventually freed.
+**
+** ALGORITHM: Scan the input string looking for host parameters in any of
+** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within
+** string literals, quoted identifier names, and comments. For text forms,
+** the host parameter index is found by scanning the perpared
+** statement for the corresponding OP_Variable opcode. Once the host
+** parameter index is known, locate the value in p->aVar[]. Then render
+** the value as a literal in place of the host parameter name.
+*/
+SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
+ Vdbe *p, /* The prepared statement being evaluated */
+ const char *zRawSql /* Raw text of the SQL statement */
+){
+ sqlite3 *db; /* The database connection */
+ int idx = 0; /* Index of a host parameter */
+ int nextIndex = 1; /* Index of next ? host parameter */
+ int n; /* Length of a token prefix */
+ int nToken; /* Length of the parameter token */
+ int i; /* Loop counter */
+ Mem *pVar; /* Value of a host parameter */
+ StrAccum out; /* Accumulate the output here */
+ char zBase[100]; /* Initial working space */
+
+ db = p->db;
+ sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
+ db->aLimit[SQLITE_LIMIT_LENGTH]);
+ out.db = db;
+ if( db->vdbeExecCnt>1 ){
+ while( *zRawSql ){
+ const char *zStart = zRawSql;
+ while( *(zRawSql++)!='\n' && *zRawSql );
+ sqlite3StrAccumAppend(&out, "-- ", 3);
+ sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
+ }
+ }else{
+ while( zRawSql[0] ){
+ n = findNextHostParameter(zRawSql, &nToken);
+ assert( n>0 );
+ sqlite3StrAccumAppend(&out, zRawSql, n);
+ zRawSql += n;
+ assert( zRawSql[0] || nToken==0 );
+ if( nToken==0 ) break;
+ if( zRawSql[0]=='?' ){
+ if( nToken>1 ){
+ assert( sqlite3Isdigit(zRawSql[1]) );
+ sqlite3GetInt32(&zRawSql[1], &idx);
+ }else{
+ idx = nextIndex;
+ }
+ }else{
+ assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
+ testcase( zRawSql[0]==':' );
+ testcase( zRawSql[0]=='$' );
+ testcase( zRawSql[0]=='@' );
+ idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
+ assert( idx>0 );
+ }
+ zRawSql += nToken;
+ nextIndex = idx + 1;
+ assert( idx>0 && idx<=p->nVar );
+ pVar = &p->aVar[idx-1];
+ if( pVar->flags & MEM_Null ){
+ sqlite3StrAccumAppend(&out, "NULL", 4);
+ }else if( pVar->flags & MEM_Int ){
+ sqlite3XPrintf(&out, "%lld", pVar->u.i);
+ }else if( pVar->flags & MEM_Real ){
+ sqlite3XPrintf(&out, "%!.15g", pVar->r);
+ }else if( pVar->flags & MEM_Str ){
+#ifndef SQLITE_OMIT_UTF16
+ u8 enc = ENC(db);
+ if( enc!=SQLITE_UTF8 ){
+ Mem utf8;
+ memset(&utf8, 0, sizeof(utf8));
+ utf8.db = db;
+ sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
+ sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
+ sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z);
+ sqlite3VdbeMemRelease(&utf8);
+ }else
+#endif
+ {
+ sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);
+ }
+ }else if( pVar->flags & MEM_Zero ){
+ sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
+ }else{
+ assert( pVar->flags & MEM_Blob );
+ sqlite3StrAccumAppend(&out, "x'", 2);
+ for(i=0; i<pVar->n; i++){
+ sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
+ }
+ sqlite3StrAccumAppend(&out, "'", 1);
+ }
+ }
+ }
+ return sqlite3StrAccumFinish(&out);
+}
+
+#endif /* #ifndef SQLITE_OMIT_TRACE */
+
+/*****************************************************************************
+** The following code implements the data-structure explaining logic
+** for the Vdbe.
+*/
+
+#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
+
+/*
+** Allocate a new Explain object
+*/
+SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe *pVdbe){
+ if( pVdbe ){
+ Explain *p;
+ sqlite3BeginBenignMalloc();
+ p = (Explain *)sqlite3MallocZero( sizeof(Explain) );
+ if( p ){
+ p->pVdbe = pVdbe;
+ sqlite3_free(pVdbe->pExplain);
+ pVdbe->pExplain = p;
+ sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase),
+ SQLITE_MAX_LENGTH);
+ p->str.useMalloc = 2;
+ }else{
+ sqlite3EndBenignMalloc();
+ }
+ }
+}
+
+/*
+** Return true if the Explain ends with a new-line.
+*/
+static int endsWithNL(Explain *p){
+ return p && p->str.zText && p->str.nChar
+ && p->str.zText[p->str.nChar-1]=='\n';
+}
+
+/*
+** Append text to the indentation
+*/
+SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
+ Explain *p;
+ if( pVdbe && (p = pVdbe->pExplain)!=0 ){
+ va_list ap;
+ if( p->nIndent && endsWithNL(p) ){
+ int n = p->nIndent;
+ if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent);
+ sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
+ }
+ va_start(ap, zFormat);
+ sqlite3VXPrintf(&p->str, 1, zFormat, ap);
+ va_end(ap);
+ }
+}
+
+/*
+** Append a '\n' if there is not already one.
+*/
+SQLITE_PRIVATE void sqlite3ExplainNL(Vdbe *pVdbe){
+ Explain *p;
+ if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){
+ sqlite3StrAccumAppend(&p->str, "\n", 1);
+ }
+}
+
+/*
+** Push a new indentation level. Subsequent lines will be indented
+** so that they begin at the current cursor position.
+*/
+SQLITE_PRIVATE void sqlite3ExplainPush(Vdbe *pVdbe){
+ Explain *p;
+ if( pVdbe && (p = pVdbe->pExplain)!=0 ){
+ if( p->str.zText && p->nIndent<ArraySize(p->aIndent) ){
+ const char *z = p->str.zText;
+ int i = p->str.nChar-1;
+ int x;
+ while( i>=0 && z[i]!='\n' ){ i--; }
+ x = (p->str.nChar - 1) - i;
+ if( p->nIndent && x<p->aIndent[p->nIndent-1] ){
+ x = p->aIndent[p->nIndent-1];
+ }
+ p->aIndent[p->nIndent] = x;
+ }
+ p->nIndent++;
+ }
+}
+
+/*
+** Pop the indentation stack by one level.
+*/
+SQLITE_PRIVATE void sqlite3ExplainPop(Vdbe *p){
+ if( p && p->pExplain ) p->pExplain->nIndent--;
+}
+
+/*
+** Free the indentation structure
+*/
+SQLITE_PRIVATE void sqlite3ExplainFinish(Vdbe *pVdbe){
+ if( pVdbe && pVdbe->pExplain ){
+ sqlite3_free(pVdbe->zExplain);
+ sqlite3ExplainNL(pVdbe);
+ pVdbe->zExplain = sqlite3StrAccumFinish(&pVdbe->pExplain->str);
+ sqlite3_free(pVdbe->pExplain);
+ pVdbe->pExplain = 0;
+ sqlite3EndBenignMalloc();
+ }
+}
+
+/*
+** Return the explanation of a virtual machine.
+*/
+SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){
+ return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0;
+}
+#endif /* defined(SQLITE_DEBUG) */
+
+/************** End of vdbetrace.c *******************************************/
+/************** Begin file vdbe.c ********************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** The code in this file implements execution method of the
+** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")
+** handles housekeeping details such as creating and deleting
+** VDBE instances. This file is solely interested in executing
+** the VDBE program.
+**
+** In the external interface, an "sqlite3_stmt*" is an opaque pointer
+** to a VDBE.
+**
+** The SQL parser generates a program which is then executed by
+** the VDBE to do the work of the SQL statement. VDBE programs are
+** similar in form to assembly language. The program consists of
+** a linear sequence of operations. Each operation has an opcode
+** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4
+** is a null-terminated string. Operand P5 is an unsigned character.
+** Few opcodes use all 5 operands.
+**
+** Computation results are stored on a set of registers numbered beginning
+** with 1 and going up to Vdbe.nMem. Each register can store
+** either an integer, a null-terminated string, a floating point
+** number, or the SQL "NULL" value. An implicit conversion from one
+** type to the other occurs as necessary.
+**
+** Most of the code in this file is taken up by the sqlite3VdbeExec()
+** function which does the work of interpreting a VDBE program.
+** But other routines are also provided to help in building up
+** a program instruction by instruction.
+**
+** Various scripts scan this source file in order to generate HTML
+** documentation, headers files, or other derived files. The formatting
+** of the code in this file is, therefore, important. See other comments
+** in this file for details. If in doubt, do not deviate from existing
+** commenting and indentation practices when changing or adding code.
+*/
+
+/*
+** Invoke this macro on memory cells just prior to changing the
+** value of the cell. This macro verifies that shallow copies are
+** not misused.
+*/
+#ifdef SQLITE_DEBUG
+# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
+#else
+# define memAboutToChange(P,M)
+#endif
+
+/*
+** The following global variable is incremented every time a cursor
+** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
+** procedures use this information to make sure that indices are
+** working correctly. This variable has no function other than to
+** help verify the correct operation of the library.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_search_count = 0;
+#endif
+
+/*
+** When this global variable is positive, it gets decremented once before
+** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted
+** field of the sqlite3 structure is set in order to simulate an interrupt.
+**
+** This facility is used for testing purposes only. It does not function
+** in an ordinary build.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_interrupt_count = 0;
+#endif
+
+/*
+** The next global variable is incremented each type the OP_Sort opcode
+** is executed. The test procedures use this information to make sure that
+** sorting is occurring or not occurring at appropriate times. This variable
+** has no function other than to help verify the correct operation of the
+** library.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_sort_count = 0;
+#endif
+
+/*
+** The next global variable records the size of the largest MEM_Blob
+** or MEM_Str that has been used by a VDBE opcode. The test procedures
+** use this information to make sure that the zero-blob functionality
+** is working correctly. This variable has no function other than to
+** help verify the correct operation of the library.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_max_blobsize = 0;
+static void updateMaxBlobsize(Mem *p){
+ if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){
+ sqlite3_max_blobsize = p->n;
+ }
+}
+#endif
+
+/*
+** The next global variable is incremented each type the OP_Found opcode
+** is executed. This is used to test whether or not the foreign key
+** operation implemented using OP_FkIsZero is working. This variable
+** has no function other than to help verify the correct operation of the
+** library.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_found_count = 0;
+#endif
+
+/*
+** Test a register to see if it exceeds the current maximum blob size.
+** If it does, record the new maximum blob size.
+*/
+#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST)
+# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P)
+#else
+# define UPDATE_MAX_BLOBSIZE(P)
+#endif
+
+/*
+** Convert the given register into a string if it isn't one
+** already. Return non-zero if a malloc() fails.
+*/
+#define Stringify(P, enc) \
+ if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \
+ { goto no_mem; }
+
+/*
+** An ephemeral string value (signified by the MEM_Ephem flag) contains
+** a pointer to a dynamically allocated string where some other entity
+** is responsible for deallocating that string. Because the register
+** does not control the string, it might be deleted without the register
+** knowing it.
+**
+** This routine converts an ephemeral string into a dynamically allocated
+** string that the register itself controls. In other words, it
+** converts an MEM_Ephem string into an MEM_Dyn string.
+*/
+#define Deephemeralize(P) \
+ if( ((P)->flags&MEM_Ephem)!=0 \
+ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
+
+/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
+# define isSorter(x) ((x)->pSorter!=0)
+
+/*
+** Argument pMem points at a register that will be passed to a
+** user-defined function or returned to the user as the result of a query.
+** This routine sets the pMem->type variable used by the sqlite3_value_*()
+** routines.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){
+ int flags = pMem->flags;
+ if( flags & MEM_Null ){
+ pMem->type = SQLITE_NULL;
+ }
+ else if( flags & MEM_Int ){
+ pMem->type = SQLITE_INTEGER;
+ }
+ else if( flags & MEM_Real ){
+ pMem->type = SQLITE_FLOAT;
+ }
+ else if( flags & MEM_Str ){
+ pMem->type = SQLITE_TEXT;
+ }else{
+ pMem->type = SQLITE_BLOB;
+ }
+}
+
+/*
+** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
+** if we run out of memory.
+*/
+static VdbeCursor *allocateCursor(
+ Vdbe *p, /* The virtual machine */
+ int iCur, /* Index of the new VdbeCursor */
+ int nField, /* Number of fields in the table or index */
+ int iDb, /* Database the cursor belongs to, or -1 */
+ int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */
+){
+ /* Find the memory cell that will be used to store the blob of memory
+ ** required for this VdbeCursor structure. It is convenient to use a
+ ** vdbe memory cell to manage the memory allocation required for a
+ ** VdbeCursor structure for the following reasons:
+ **
+ ** * Sometimes cursor numbers are used for a couple of different
+ ** purposes in a vdbe program. The different uses might require
+ ** different sized allocations. Memory cells provide growable
+ ** allocations.
+ **
+ ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can
+ ** be freed lazily via the sqlite3_release_memory() API. This
+ ** minimizes the number of malloc calls made by the system.
+ **
+ ** Memory cells for cursors are allocated at the top of the address
+ ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for
+ ** cursor 1 is managed by memory cell (p->nMem-1), etc.
+ */
+ Mem *pMem = &p->aMem[p->nMem-iCur];
+
+ int nByte;
+ VdbeCursor *pCx = 0;
+ nByte =
+ ROUND8(sizeof(VdbeCursor)) +
+ (isBtreeCursor?sqlite3BtreeCursorSize():0) +
+ 2*nField*sizeof(u32);
+
+ assert( iCur<p->nCursor );
+ if( p->apCsr[iCur] ){
+ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
+ p->apCsr[iCur] = 0;
+ }
+ if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){
+ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
+ memset(pCx, 0, sizeof(VdbeCursor));
+ pCx->iDb = iDb;
+ pCx->nField = nField;
+ if( nField ){
+ pCx->aType = (u32 *)&pMem->z[ROUND8(sizeof(VdbeCursor))];
+ }
+ if( isBtreeCursor ){
+ pCx->pCursor = (BtCursor*)
+ &pMem->z[ROUND8(sizeof(VdbeCursor))+2*nField*sizeof(u32)];
+ sqlite3BtreeCursorZero(pCx->pCursor);
+ }
+ }
+ return pCx;
+}
+
+/*
+** Try to convert a value into a numeric representation if we can
+** do so without loss of information. In other words, if the string
+** looks like a number, convert it into a number. If it does not
+** look like a number, leave it alone.
+*/
+static void applyNumericAffinity(Mem *pRec){
+ if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
+ double rValue;
+ i64 iValue;
+ u8 enc = pRec->enc;
+ if( (pRec->flags&MEM_Str)==0 ) return;
+ if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
+ if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
+ pRec->u.i = iValue;
+ pRec->flags |= MEM_Int;
+ }else{
+ pRec->r = rValue;
+ pRec->flags |= MEM_Real;
+ }
+ }
+}
+
+/*
+** Processing is determine by the affinity parameter:
+**
+** SQLITE_AFF_INTEGER:
+** SQLITE_AFF_REAL:
+** SQLITE_AFF_NUMERIC:
+** Try to convert pRec to an integer representation or a
+** floating-point representation if an integer representation
+** is not possible. Note that the integer representation is
+** always preferred, even if the affinity is REAL, because
+** an integer representation is more space efficient on disk.
+**
+** SQLITE_AFF_TEXT:
+** Convert pRec to a text representation.
+**
+** SQLITE_AFF_NONE:
+** No-op. pRec is unchanged.
+*/
+static void applyAffinity(
+ Mem *pRec, /* The value to apply affinity to */
+ char affinity, /* The affinity to be applied */
+ u8 enc /* Use this text encoding */
+){
+ if( affinity==SQLITE_AFF_TEXT ){
+ /* Only attempt the conversion to TEXT if there is an integer or real
+ ** representation (blob and NULL do not get converted) but no string
+ ** representation.
+ */
+ if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
+ sqlite3VdbeMemStringify(pRec, enc);
+ }
+ pRec->flags &= ~(MEM_Real|MEM_Int);
+ }else if( affinity!=SQLITE_AFF_NONE ){
+ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
+ || affinity==SQLITE_AFF_NUMERIC );
+ applyNumericAffinity(pRec);
+ if( pRec->flags & MEM_Real ){
+ sqlite3VdbeIntegerAffinity(pRec);
+ }
+ }
+}
+
+/*
+** Try to convert the type of a function argument or a result column
+** into a numeric representation. Use either INTEGER or REAL whichever
+** is appropriate. But only do the conversion if it is possible without
+** loss of information and return the revised type of the argument.
+*/
+SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
+ Mem *pMem = (Mem*)pVal;
+ if( pMem->type==SQLITE_TEXT ){
+ applyNumericAffinity(pMem);
+ sqlite3VdbeMemStoreType(pMem);
+ }
+ return pMem->type;
+}
+
+/*
+** Exported version of applyAffinity(). This one works on sqlite3_value*,
+** not the internal Mem* type.
+*/
+SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
+ sqlite3_value *pVal,
+ u8 affinity,
+ u8 enc
+){
+ applyAffinity((Mem *)pVal, affinity, enc);
+}
+
+#ifdef SQLITE_DEBUG
+/*
+** Write a nice string representation of the contents of cell pMem
+** into buffer zBuf, length nBuf.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
+ char *zCsr = zBuf;
+ int f = pMem->flags;
+
+ static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};
+
+ if( f&MEM_Blob ){
+ int i;
+ char c;
+ if( f & MEM_Dyn ){
+ c = 'z';
+ assert( (f & (MEM_Static|MEM_Ephem))==0 );
+ }else if( f & MEM_Static ){
+ c = 't';
+ assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
+ }else if( f & MEM_Ephem ){
+ c = 'e';
+ assert( (f & (MEM_Static|MEM_Dyn))==0 );
+ }else{
+ c = 's';
+ }
+
+ sqlite3_snprintf(100, zCsr, "%c", c);
+ zCsr += sqlite3Strlen30(zCsr);
+ sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
+ zCsr += sqlite3Strlen30(zCsr);
+ for(i=0; i<16 && i<pMem->n; i++){
+ sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
+ zCsr += sqlite3Strlen30(zCsr);
+ }
+ for(i=0; i<16 && i<pMem->n; i++){
+ char z = pMem->z[i];
+ if( z<32 || z>126 ) *zCsr++ = '.';
+ else *zCsr++ = z;
+ }
+
+ sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]);
+ zCsr += sqlite3Strlen30(zCsr);
+ if( f & MEM_Zero ){
+ sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
+ zCsr += sqlite3Strlen30(zCsr);
+ }
+ *zCsr = '\0';
+ }else if( f & MEM_Str ){
+ int j, k;
+ zBuf[0] = ' ';
+ if( f & MEM_Dyn ){
+ zBuf[1] = 'z';
+ assert( (f & (MEM_Static|MEM_Ephem))==0 );
+ }else if( f & MEM_Static ){
+ zBuf[1] = 't';
+ assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
+ }else if( f & MEM_Ephem ){
+ zBuf[1] = 'e';
+ assert( (f & (MEM_Static|MEM_Dyn))==0 );
+ }else{
+ zBuf[1] = 's';
+ }
+ k = 2;
+ sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
+ k += sqlite3Strlen30(&zBuf[k]);
+ zBuf[k++] = '[';
+ for(j=0; j<15 && j<pMem->n; j++){
+ u8 c = pMem->z[j];
+ if( c>=0x20 && c<0x7f ){
+ zBuf[k++] = c;
+ }else{
+ zBuf[k++] = '.';
+ }
+ }
+ zBuf[k++] = ']';
+ sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
+ k += sqlite3Strlen30(&zBuf[k]);
+ zBuf[k++] = 0;
+ }
+}
+#endif
+
+#ifdef SQLITE_DEBUG
+/*
+** Print the value of a register for tracing purposes:
+*/
+static void memTracePrint(FILE *out, Mem *p){
+ if( p->flags & MEM_Invalid ){
+ fprintf(out, " undefined");
+ }else if( p->flags & MEM_Null ){
+ fprintf(out, " NULL");
+ }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
+ fprintf(out, " si:%lld", p->u.i);
+ }else if( p->flags & MEM_Int ){
+ fprintf(out, " i:%lld", p->u.i);
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ }else if( p->flags & MEM_Real ){
+ fprintf(out, " r:%g", p->r);
+#endif
+ }else if( p->flags & MEM_RowSet ){
+ fprintf(out, " (rowset)");
+ }else{
+ char zBuf[200];
+ sqlite3VdbeMemPrettyPrint(p, zBuf);
+ fprintf(out, " ");
+ fprintf(out, "%s", zBuf);
+ }
+}
+static void registerTrace(FILE *out, int iReg, Mem *p){
+ fprintf(out, "REG[%d] = ", iReg);
+ memTracePrint(out, p);
+ fprintf(out, "\n");
+}
+#endif
+
+#ifdef SQLITE_DEBUG
+# define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M)
+#else
+# define REGISTER_TRACE(R,M)
+#endif
+
+
+#ifdef VDBE_PROFILE
+
+/*
+** hwtime.h contains inline assembler code for implementing
+** high-performance timing routines.
+*/
+/************** Include hwtime.h in the middle of vdbe.c *********************/
+/************** Begin file hwtime.h ******************************************/
+/*
+** 2008 May 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains inline asm code for retrieving "high-performance"
+** counters for x86 class CPUs.
+*/
+#ifndef _HWTIME_H_
+#define _HWTIME_H_
+
+/*
+** The following routine only works on pentium-class (or newer) processors.
+** It uses the RDTSC opcode to read the cycle count value out of the
+** processor and returns that value. This can be used for high-res
+** profiling.
+*/
+#if (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
+
+ #if defined(__GNUC__)
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+ #elif defined(_MSC_VER)
+
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+ __asm {
+ rdtsc
+ ret ; return value at EDX:EAX
+ }
+ }
+
+ #endif
+
+#elif (defined(__GNUC__) && defined(__x86_64__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long val;
+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
+ return val;
+ }
+
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
+ }
+
+#else
+
+ #error Need implementation of sqlite3Hwtime() for your platform.
+
+ /*
+ ** To compile without implementing sqlite3Hwtime() for your platform,
+ ** you can remove the above #error and use the following
+ ** stub function. You will lose timing support for many
+ ** of the debugging and testing utilities, but it should at
+ ** least compile and run.
+ */
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+
+#endif
+
+#endif /* !defined(_HWTIME_H_) */
+
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in vdbe.c ***********************/
+
+#endif
+
+/*
+** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
+** sqlite3_interrupt() routine has been called. If it has been, then
+** processing of the VDBE program is interrupted.
+**
+** This macro added to every instruction that does a jump in order to
+** implement a loop. This test used to be on every single instruction,
+** but that meant we more testing than we needed. By only testing the
+** flag on jump instructions, we get a (small) speed improvement.
+*/
+#define CHECK_FOR_INTERRUPT \
+ if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
+
+
+#ifndef NDEBUG
+/*
+** This function is only called from within an assert() expression. It
+** checks that the sqlite3.nTransaction variable is correctly set to
+** the number of non-transaction savepoints currently in the
+** linked list starting at sqlite3.pSavepoint.
+**
+** Usage:
+**
+** assert( checkSavepointCount(db) );
+*/
+static int checkSavepointCount(sqlite3 *db){
+ int n = 0;
+ Savepoint *p;
+ for(p=db->pSavepoint; p; p=p->pNext) n++;
+ assert( n==(db->nSavepoint + db->isTransactionSavepoint) );
+ return 1;
+}
+#endif
+
+/*
+** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
+** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
+** in memory obtained from sqlite3DbMalloc).
+*/
+static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
+ sqlite3 *db = p->db;
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
+ sqlite3_free(pVtab->zErrMsg);
+ pVtab->zErrMsg = 0;
+}
+
+
+/*
+** Execute as much of a VDBE program as we can then return.
+**
+** sqlite3VdbeMakeReady() must be called before this routine in order to
+** close the program with a final OP_Halt and to set up the callbacks
+** and the error message pointer.
+**
+** Whenever a row or result data is available, this routine will either
+** invoke the result callback (if there is one) or return with
+** SQLITE_ROW.
+**
+** If an attempt is made to open a locked database, then this routine
+** will either invoke the busy callback (if there is one) or it will
+** return SQLITE_BUSY.
+**
+** If an error occurs, an error message is written to memory obtained
+** from sqlite3_malloc() and p->zErrMsg is made to point to that memory.
+** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
+**
+** If the callback ever returns non-zero, then the program exits
+** immediately. There will be no error message but the p->rc field is
+** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.
+**
+** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this
+** routine to return SQLITE_ERROR.
+**
+** Other fatal errors return SQLITE_ERROR.
+**
+** After this routine has finished, sqlite3VdbeFinalize() should be
+** used to clean up the mess that was left behind.
+*/
+SQLITE_PRIVATE int sqlite3VdbeExec(
+ Vdbe *p /* The VDBE */
+){
+ int pc=0; /* The program counter */
+ Op *aOp = p->aOp; /* Copy of p->aOp */
+ Op *pOp; /* Current operation */
+ int rc = SQLITE_OK; /* Value to return */
+ sqlite3 *db = p->db; /* The database */
+ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
+ u8 encoding = ENC(db); /* The database encoding */
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ int checkProgress; /* True if progress callbacks are enabled */
+ int nProgressOps = 0; /* Opcodes executed since progress callback. */
+#endif
+ Mem *aMem = p->aMem; /* Copy of p->aMem */
+ Mem *pIn1 = 0; /* 1st input operand */
+ Mem *pIn2 = 0; /* 2nd input operand */
+ Mem *pIn3 = 0; /* 3rd input operand */
+ Mem *pOut = 0; /* Output operand */
+ int iCompare = 0; /* Result of last OP_Compare operation */
+ int *aPermute = 0; /* Permutation of columns for OP_Compare */
+ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
+#ifdef VDBE_PROFILE
+ u64 start; /* CPU clock count at start of opcode */
+ int origPc; /* Program counter at start of opcode */
+#endif
+ /********************************************************************
+ ** Automatically generated code
+ **
+ ** The following union is automatically generated by the
+ ** vdbe-compress.tcl script. The purpose of this union is to
+ ** reduce the amount of stack space required by this function.
+ ** See comments in the vdbe-compress.tcl script for details.
+ */
+ union vdbeExecUnion {
+ struct OP_Yield_stack_vars {
+ int pcDest;
+ } aa;
+ struct OP_Null_stack_vars {
+ int cnt;
+ u16 nullFlag;
+ } ab;
+ struct OP_Variable_stack_vars {
+ Mem *pVar; /* Value being transferred */
+ } ac;
+ struct OP_Move_stack_vars {
+ char *zMalloc; /* Holding variable for allocated memory */
+ int n; /* Number of registers left to copy */
+ int p1; /* Register to copy from */
+ int p2; /* Register to copy to */
+ } ad;
+ struct OP_Copy_stack_vars {
+ int n;
+ } ae;
+ struct OP_ResultRow_stack_vars {
+ Mem *pMem;
+ int i;
+ } af;
+ struct OP_Concat_stack_vars {
+ i64 nByte;
+ } ag;
+ struct OP_Remainder_stack_vars {
+ char bIntint; /* Started out as two integer operands */
+ int flags; /* Combined MEM_* flags from both inputs */
+ i64 iA; /* Integer value of left operand */
+ i64 iB; /* Integer value of right operand */
+ double rA; /* Real value of left operand */
+ double rB; /* Real value of right operand */
+ } ah;
+ struct OP_Function_stack_vars {
+ int i;
+ Mem *pArg;
+ sqlite3_context ctx;
+ sqlite3_value **apVal;
+ int n;
+ } ai;
+ struct OP_ShiftRight_stack_vars {
+ i64 iA;
+ u64 uA;
+ i64 iB;
+ u8 op;
+ } aj;
+ struct OP_Ge_stack_vars {
+ int res; /* Result of the comparison of pIn1 against pIn3 */
+ char affinity; /* Affinity to use for comparison */
+ u16 flags1; /* Copy of initial value of pIn1->flags */
+ u16 flags3; /* Copy of initial value of pIn3->flags */
+ } ak;
+ struct OP_Compare_stack_vars {
+ int n;
+ int i;
+ int p1;
+ int p2;
+ const KeyInfo *pKeyInfo;
+ int idx;
+ CollSeq *pColl; /* Collating sequence to use on this term */
+ int bRev; /* True for DESCENDING sort order */
+ } al;
+ struct OP_Or_stack_vars {
+ int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
+ int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
+ } am;
+ struct OP_IfNot_stack_vars {
+ int c;
+ } an;
+ struct OP_Column_stack_vars {
+ u32 payloadSize; /* Number of bytes in the record */
+ i64 payloadSize64; /* Number of bytes in the record */
+ int p1; /* P1 value of the opcode */
+ int p2; /* column number to retrieve */
+ VdbeCursor *pC; /* The VDBE cursor */
+ char *zRec; /* Pointer to complete record-data */
+ BtCursor *pCrsr; /* The BTree cursor */
+ u32 *aType; /* aType[i] holds the numeric type of the i-th column */
+ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
+ int nField; /* number of fields in the record */
+ int len; /* The length of the serialized data for the column */
+ int i; /* Loop counter */
+ char *zData; /* Part of the record being decoded */
+ Mem *pDest; /* Where to write the extracted value */
+ Mem sMem; /* For storing the record being decoded */
+ u8 *zIdx; /* Index into header */
+ u8 *zEndHdr; /* Pointer to first byte after the header */
+ u32 offset; /* Offset into the data */
+ u32 szField; /* Number of bytes in the content of a field */
+ int szHdr; /* Size of the header size field at start of record */
+ int avail; /* Number of bytes of available data */
+ u32 t; /* A type code from the record header */
+ Mem *pReg; /* PseudoTable input register */
+ } ao;
+ struct OP_Affinity_stack_vars {
+ const char *zAffinity; /* The affinity to be applied */
+ char cAff; /* A single character of affinity */
+ } ap;
+ struct OP_MakeRecord_stack_vars {
+ u8 *zNewRecord; /* A buffer to hold the data for the new record */
+ Mem *pRec; /* The new record */
+ u64 nData; /* Number of bytes of data space */
+ int nHdr; /* Number of bytes of header space */
+ i64 nByte; /* Data space required for this record */
+ int nZero; /* Number of zero bytes at the end of the record */
+ int nVarint; /* Number of bytes in a varint */
+ u32 serial_type; /* Type field */
+ Mem *pData0; /* First field to be combined into the record */
+ Mem *pLast; /* Last field of the record */
+ int nField; /* Number of fields in the record */
+ char *zAffinity; /* The affinity string for the record */
+ int file_format; /* File format to use for encoding */
+ int i; /* Space used in zNewRecord[] */
+ int len; /* Length of a field */
+ } aq;
+ struct OP_Count_stack_vars {
+ i64 nEntry;
+ BtCursor *pCrsr;
+ } ar;
+ struct OP_Savepoint_stack_vars {
+ int p1; /* Value of P1 operand */
+ char *zName; /* Name of savepoint */
+ int nName;
+ Savepoint *pNew;
+ Savepoint *pSavepoint;
+ Savepoint *pTmp;
+ int iSavepoint;
+ int ii;
+ } as;
+ struct OP_AutoCommit_stack_vars {
+ int desiredAutoCommit;
+ int iRollback;
+ int turnOnAC;
+ } at;
+ struct OP_Transaction_stack_vars {
+ Btree *pBt;
+ } au;
+ struct OP_ReadCookie_stack_vars {
+ int iMeta;
+ int iDb;
+ int iCookie;
+ } av;
+ struct OP_SetCookie_stack_vars {
+ Db *pDb;
+ } aw;
+ struct OP_VerifyCookie_stack_vars {
+ int iMeta;
+ int iGen;
+ Btree *pBt;
+ } ax;
+ struct OP_OpenWrite_stack_vars {
+ int nField;
+ KeyInfo *pKeyInfo;
+ int p2;
+ int iDb;
+ int wrFlag;
+ Btree *pX;
+ VdbeCursor *pCur;
+ Db *pDb;
+ } ay;
+ struct OP_OpenEphemeral_stack_vars {
+ VdbeCursor *pCx;
+ } az;
+ struct OP_SorterOpen_stack_vars {
+ VdbeCursor *pCx;
+ } ba;
+ struct OP_OpenPseudo_stack_vars {
+ VdbeCursor *pCx;
+ } bb;
+ struct OP_SeekGt_stack_vars {
+ int res;
+ int oc;
+ VdbeCursor *pC;
+ UnpackedRecord r;
+ int nField;
+ i64 iKey; /* The rowid we are to seek to */
+ } bc;
+ struct OP_Seek_stack_vars {
+ VdbeCursor *pC;
+ } bd;
+ struct OP_Found_stack_vars {
+ int alreadyExists;
+ VdbeCursor *pC;
+ int res;
+ char *pFree;
+ UnpackedRecord *pIdxKey;
+ UnpackedRecord r;
+ char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
+ } be;
+ struct OP_IsUnique_stack_vars {
+ u16 ii;
+ VdbeCursor *pCx;
+ BtCursor *pCrsr;
+ u16 nField;
+ Mem *aMx;
+ UnpackedRecord r; /* B-Tree index search key */
+ i64 R; /* Rowid stored in register P3 */
+ } bf;
+ struct OP_NotExists_stack_vars {
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ u64 iKey;
+ } bg;
+ struct OP_NewRowid_stack_vars {
+ i64 v; /* The new rowid */
+ VdbeCursor *pC; /* Cursor of table to get the new rowid */
+ int res; /* Result of an sqlite3BtreeLast() */
+ int cnt; /* Counter to limit the number of searches */
+ Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
+ VdbeFrame *pFrame; /* Root frame of VDBE */
+ } bh;
+ struct OP_InsertInt_stack_vars {
+ Mem *pData; /* MEM cell holding data for the record to be inserted */
+ Mem *pKey; /* MEM cell holding key for the record */
+ i64 iKey; /* The integer ROWID or key for the record to be inserted */
+ VdbeCursor *pC; /* Cursor to table into which insert is written */
+ int nZero; /* Number of zero-bytes to append */
+ int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
+ const char *zDb; /* database name - used by the update hook */
+ const char *zTbl; /* Table name - used by the opdate hook */
+ int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
+ } bi;
+ struct OP_Delete_stack_vars {
+ i64 iKey;
+ VdbeCursor *pC;
+ } bj;
+ struct OP_SorterCompare_stack_vars {
+ VdbeCursor *pC;
+ int res;
+ } bk;
+ struct OP_SorterData_stack_vars {
+ VdbeCursor *pC;
+ } bl;
+ struct OP_RowData_stack_vars {
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ u32 n;
+ i64 n64;
+ } bm;
+ struct OP_Rowid_stack_vars {
+ VdbeCursor *pC;
+ i64 v;
+ sqlite3_vtab *pVtab;
+ const sqlite3_module *pModule;
+ } bn;
+ struct OP_NullRow_stack_vars {
+ VdbeCursor *pC;
+ } bo;
+ struct OP_Last_stack_vars {
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ } bp;
+ struct OP_Rewind_stack_vars {
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ } bq;
+ struct OP_Next_stack_vars {
+ VdbeCursor *pC;
+ int res;
+ } br;
+ struct OP_IdxInsert_stack_vars {
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int nKey;
+ const char *zKey;
+ } bs;
+ struct OP_IdxDelete_stack_vars {
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ UnpackedRecord r;
+ } bt;
+ struct OP_IdxRowid_stack_vars {
+ BtCursor *pCrsr;
+ VdbeCursor *pC;
+ i64 rowid;
+ } bu;
+ struct OP_IdxGE_stack_vars {
+ VdbeCursor *pC;
+ int res;
+ UnpackedRecord r;
+ } bv;
+ struct OP_Destroy_stack_vars {
+ int iMoved;
+ int iCnt;
+ Vdbe *pVdbe;
+ int iDb;
+ } bw;
+ struct OP_Clear_stack_vars {
+ int nChange;
+ } bx;
+ struct OP_CreateTable_stack_vars {
+ int pgno;
+ int flags;
+ Db *pDb;
+ } by;
+ struct OP_ParseSchema_stack_vars {
+ int iDb;
+ const char *zMaster;
+ char *zSql;
+ InitData initData;
+ } bz;
+ struct OP_IntegrityCk_stack_vars {
+ int nRoot; /* Number of tables to check. (Number of root pages.) */
+ int *aRoot; /* Array of rootpage numbers for tables to be checked */
+ int j; /* Loop counter */
+ int nErr; /* Number of errors reported */
+ char *z; /* Text of the error report */
+ Mem *pnErr; /* Register keeping track of errors remaining */
+ } ca;
+ struct OP_RowSetRead_stack_vars {
+ i64 val;
+ } cb;
+ struct OP_RowSetTest_stack_vars {
+ int iSet;
+ int exists;
+ } cc;
+ struct OP_Program_stack_vars {
+ int nMem; /* Number of memory registers for sub-program */
+ int nByte; /* Bytes of runtime space required for sub-program */
+ Mem *pRt; /* Register to allocate runtime space */
+ Mem *pMem; /* Used to iterate through memory cells */
+ Mem *pEnd; /* Last memory cell in new array */
+ VdbeFrame *pFrame; /* New vdbe frame to execute in */
+ SubProgram *pProgram; /* Sub-program to execute */
+ void *t; /* Token identifying trigger */
+ } cd;
+ struct OP_Param_stack_vars {
+ VdbeFrame *pFrame;
+ Mem *pIn;
+ } ce;
+ struct OP_MemMax_stack_vars {
+ Mem *pIn1;
+ VdbeFrame *pFrame;
+ } cf;
+ struct OP_AggStep_stack_vars {
+ int n;
+ int i;
+ Mem *pMem;
+ Mem *pRec;
+ sqlite3_context ctx;
+ sqlite3_value **apVal;
+ } cg;
+ struct OP_AggFinal_stack_vars {
+ Mem *pMem;
+ } ch;
+ struct OP_Checkpoint_stack_vars {
+ int i; /* Loop counter */
+ int aRes[3]; /* Results */
+ Mem *pMem; /* Write results here */
+ } ci;
+ struct OP_JournalMode_stack_vars {
+ Btree *pBt; /* Btree to change journal mode of */
+ Pager *pPager; /* Pager associated with pBt */
+ int eNew; /* New journal mode */
+ int eOld; /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
+ const char *zFilename; /* Name of database file for pPager */
+#endif
+ } cj;
+ struct OP_IncrVacuum_stack_vars {
+ Btree *pBt;
+ } ck;
+ struct OP_VBegin_stack_vars {
+ VTable *pVTab;
+ } cl;
+ struct OP_VOpen_stack_vars {
+ VdbeCursor *pCur;
+ sqlite3_vtab_cursor *pVtabCursor;
+ sqlite3_vtab *pVtab;
+ sqlite3_module *pModule;
+ } cm;
+ struct OP_VFilter_stack_vars {
+ int nArg;
+ int iQuery;
+ const sqlite3_module *pModule;
+ Mem *pQuery;
+ Mem *pArgc;
+ sqlite3_vtab_cursor *pVtabCursor;
+ sqlite3_vtab *pVtab;
+ VdbeCursor *pCur;
+ int res;
+ int i;
+ Mem **apArg;
+ } cn;
+ struct OP_VColumn_stack_vars {
+ sqlite3_vtab *pVtab;
+ const sqlite3_module *pModule;
+ Mem *pDest;
+ sqlite3_context sContext;
+ } co;
+ struct OP_VNext_stack_vars {
+ sqlite3_vtab *pVtab;
+ const sqlite3_module *pModule;
+ int res;
+ VdbeCursor *pCur;
+ } cp;
+ struct OP_VRename_stack_vars {
+ sqlite3_vtab *pVtab;
+ Mem *pName;
+ } cq;
+ struct OP_VUpdate_stack_vars {
+ sqlite3_vtab *pVtab;
+ sqlite3_module *pModule;
+ int nArg;
+ int i;
+ sqlite_int64 rowid;
+ Mem **apArg;
+ Mem *pX;
+ } cr;
+ struct OP_Trace_stack_vars {
+ char *zTrace;
+ char *z;
+ } cs;
+ } u;
+ /* End automatically generated code
+ ********************************************************************/
+
+ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
+ sqlite3VdbeEnter(p);
+ if( p->rc==SQLITE_NOMEM ){
+ /* This happens if a malloc() inside a call to sqlite3_column_text() or
+ ** sqlite3_column_text16() failed. */
+ goto no_mem;
+ }
+ assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
+ p->rc = SQLITE_OK;
+ assert( p->explain==0 );
+ p->pResultSet = 0;
+ db->busyHandler.nBusy = 0;
+ CHECK_FOR_INTERRUPT;
+ sqlite3VdbeIOTraceSql(p);
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ checkProgress = db->xProgress!=0;
+#endif
+#ifdef SQLITE_DEBUG
+ sqlite3BeginBenignMalloc();
+ if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){
+ int i;
+ printf("VDBE Program Listing:\n");
+ sqlite3VdbePrintSql(p);
+ for(i=0; i<p->nOp; i++){
+ sqlite3VdbePrintOp(stdout, i, &aOp[i]);
+ }
+ }
+ sqlite3EndBenignMalloc();
+#endif
+ for(pc=p->pc; rc==SQLITE_OK; pc++){
+ assert( pc>=0 && pc<p->nOp );
+ if( db->mallocFailed ) goto no_mem;
+#ifdef VDBE_PROFILE
+ origPc = pc;
+ start = sqlite3Hwtime();
+#endif
+ pOp = &aOp[pc];
+
+ /* Only allow tracing if SQLITE_DEBUG is defined.
+ */
+#ifdef SQLITE_DEBUG
+ if( p->trace ){
+ if( pc==0 ){
+ printf("VDBE Execution Trace:\n");
+ sqlite3VdbePrintSql(p);
+ }
+ sqlite3VdbePrintOp(p->trace, pc, pOp);
+ }
+#endif
+
+
+ /* Check to see if we need to simulate an interrupt. This only happens
+ ** if we have a special test build.
+ */
+#ifdef SQLITE_TEST
+ if( sqlite3_interrupt_count>0 ){
+ sqlite3_interrupt_count--;
+ if( sqlite3_interrupt_count==0 ){
+ sqlite3_interrupt(db);
+ }
+ }
+#endif
+
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ /* Call the progress callback if it is configured and the required number
+ ** of VDBE ops have been executed (either since this invocation of
+ ** sqlite3VdbeExec() or since last time the progress callback was called).
+ ** If the progress callback returns non-zero, exit the virtual machine with
+ ** a return code SQLITE_ABORT.
+ */
+ if( checkProgress ){
+ if( db->nProgressOps==nProgressOps ){
+ int prc;
+ prc = db->xProgress(db->pProgressArg);
+ if( prc!=0 ){
+ rc = SQLITE_INTERRUPT;
+ goto vdbe_error_halt;
+ }
+ nProgressOps = 0;
+ }
+ nProgressOps++;
+ }
+#endif
+
+ /* On any opcode with the "out2-prerelease" tag, free any
+ ** external allocations out of mem[p2] and set mem[p2] to be
+ ** an undefined integer. Opcodes will either fill in the integer
+ ** value or convert mem[p2] to a different type.
+ */
+ assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
+ if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
+ assert( pOp->p2>0 );
+ assert( pOp->p2<=p->nMem );
+ pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
+ VdbeMemRelease(pOut);
+ pOut->flags = MEM_Int;
+ }
+
+ /* Sanity checking on other operands */
+#ifdef SQLITE_DEBUG
+ if( (pOp->opflags & OPFLG_IN1)!=0 ){
+ assert( pOp->p1>0 );
+ assert( pOp->p1<=p->nMem );
+ assert( memIsValid(&aMem[pOp->p1]) );
+ REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
+ }
+ if( (pOp->opflags & OPFLG_IN2)!=0 ){
+ assert( pOp->p2>0 );
+ assert( pOp->p2<=p->nMem );
+ assert( memIsValid(&aMem[pOp->p2]) );
+ REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
+ }
+ if( (pOp->opflags & OPFLG_IN3)!=0 ){
+ assert( pOp->p3>0 );
+ assert( pOp->p3<=p->nMem );
+ assert( memIsValid(&aMem[pOp->p3]) );
+ REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
+ }
+ if( (pOp->opflags & OPFLG_OUT2)!=0 ){
+ assert( pOp->p2>0 );
+ assert( pOp->p2<=p->nMem );
+ memAboutToChange(p, &aMem[pOp->p2]);
+ }
+ if( (pOp->opflags & OPFLG_OUT3)!=0 ){
+ assert( pOp->p3>0 );
+ assert( pOp->p3<=p->nMem );
+ memAboutToChange(p, &aMem[pOp->p3]);
+ }
+#endif
+
+ switch( pOp->opcode ){
+
+/*****************************************************************************
+** What follows is a massive switch statement where each case implements a
+** separate instruction in the virtual machine. If we follow the usual
+** indentation conventions, each case should be indented by 6 spaces. But
+** that is a lot of wasted space on the left margin. So the code within
+** the switch statement will break with convention and be flush-left. Another
+** big comment (similar to this one) will mark the point in the code where
+** we transition back to normal indentation.
+**
+** The formatting of each case is important. The makefile for SQLite
+** generates two C files "opcodes.h" and "opcodes.c" by scanning this
+** file looking for lines that begin with "case OP_". The opcodes.h files
+** will be filled with #defines that give unique integer values to each
+** opcode and the opcodes.c file is filled with an array of strings where
+** each string is the symbolic name for the corresponding opcode. If the
+** case statement is followed by a comment of the form "/# same as ... #/"
+** that comment is used to determine the particular value of the opcode.
+**
+** Other keywords in the comment that follows each case are used to
+** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[].
+** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See
+** the mkopcodeh.awk script for additional information.
+**
+** Documentation about VDBE opcodes is generated by scanning this file
+** for lines of that contain "Opcode:". That line and all subsequent
+** comment lines are used in the generation of the opcode.html documentation
+** file.
+**
+** SUMMARY:
+**
+** Formatting is important to scripts that scan this file.
+** Do not deviate from the formatting style currently in use.
+**
+*****************************************************************************/
+
+/* Opcode: Goto * P2 * * *
+**
+** An unconditional jump to address P2.
+** The next instruction executed will be
+** the one at index P2 from the beginning of
+** the program.
+*/
+case OP_Goto: { /* jump */
+ CHECK_FOR_INTERRUPT;
+ pc = pOp->p2 - 1;
+ break;
+}
+
+/* Opcode: Gosub P1 P2 * * *
+**
+** Write the current address onto register P1
+** and then jump to address P2.
+*/
+case OP_Gosub: { /* jump */
+ assert( pOp->p1>0 && pOp->p1<=p->nMem );
+ pIn1 = &aMem[pOp->p1];
+ assert( (pIn1->flags & MEM_Dyn)==0 );
+ memAboutToChange(p, pIn1);
+ pIn1->flags = MEM_Int;
+ pIn1->u.i = pc;
+ REGISTER_TRACE(pOp->p1, pIn1);
+ pc = pOp->p2 - 1;
+ break;
+}
+
+/* Opcode: Return P1 * * * *
+**
+** Jump to the next instruction after the address in register P1.
+*/
+case OP_Return: { /* in1 */
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags & MEM_Int );
+ pc = (int)pIn1->u.i;
+ break;
+}
+
+/* Opcode: Yield P1 * * * *
+**
+** Swap the program counter with the value in register P1.
+*/
+case OP_Yield: { /* in1 */
+#if 0 /* local variables moved into u.aa */
+ int pcDest;
+#endif /* local variables moved into u.aa */
+ pIn1 = &aMem[pOp->p1];
+ assert( (pIn1->flags & MEM_Dyn)==0 );
+ pIn1->flags = MEM_Int;
+ u.aa.pcDest = (int)pIn1->u.i;
+ pIn1->u.i = pc;
+ REGISTER_TRACE(pOp->p1, pIn1);
+ pc = u.aa.pcDest;
+ break;
+}
+
+/* Opcode: HaltIfNull P1 P2 P3 P4 *
+**
+** Check the value in register P3. If it is NULL then Halt using
+** parameter P1, P2, and P4 as if this were a Halt instruction. If the
+** value in register P3 is not NULL, then this routine is a no-op.
+*/
+case OP_HaltIfNull: { /* in3 */
+ pIn3 = &aMem[pOp->p3];
+ if( (pIn3->flags & MEM_Null)==0 ) break;
+ /* Fall through into OP_Halt */
+}
+
+/* Opcode: Halt P1 P2 * P4 *
+**
+** Exit immediately. All open cursors, etc are closed
+** automatically.
+**
+** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
+** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0).
+** For errors, it can be some other value. If P1!=0 then P2 will determine
+** whether or not to rollback the current transaction. Do not rollback
+** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
+** then back out all changes that have occurred during this execution of the
+** VDBE, but do not rollback the transaction.
+**
+** If P4 is not null then it is an error message string.
+**
+** There is an implied "Halt 0 0 0" instruction inserted at the very end of
+** every program. So a jump past the last instruction of the program
+** is the same as executing Halt.
+*/
+case OP_Halt: {
+ if( pOp->p1==SQLITE_OK && p->pFrame ){
+ /* Halt the sub-program. Return control to the parent frame. */
+ VdbeFrame *pFrame = p->pFrame;
+ p->pFrame = pFrame->pParent;
+ p->nFrame--;
+ sqlite3VdbeSetChanges(db, p->nChange);
+ pc = sqlite3VdbeFrameRestore(pFrame);
+ lastRowid = db->lastRowid;
+ if( pOp->p2==OE_Ignore ){
+ /* Instruction pc is the OP_Program that invoked the sub-program
+ ** currently being halted. If the p2 instruction of this OP_Halt
+ ** instruction is set to OE_Ignore, then the sub-program is throwing
+ ** an IGNORE exception. In this case jump to the address specified
+ ** as the p2 of the calling OP_Program. */
+ pc = p->aOp[pc].p2-1;
+ }
+ aOp = p->aOp;
+ aMem = p->aMem;
+ break;
+ }
+
+ p->rc = pOp->p1;
+ p->errorAction = (u8)pOp->p2;
+ p->pc = pc;
+ if( pOp->p4.z ){
+ assert( p->rc!=SQLITE_OK );
+ sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
+ }else if( p->rc ){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
+ }
+ rc = sqlite3VdbeHalt(p);
+ assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
+ if( rc==SQLITE_BUSY ){
+ p->rc = rc = SQLITE_BUSY;
+ }else{
+ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
+ assert( rc==SQLITE_OK || db->nDeferredCons>0 );
+ rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
+ }
+ goto vdbe_return;
+}
+
+/* Opcode: Integer P1 P2 * * *
+**
+** The 32-bit integer value P1 is written into register P2.
+*/
+case OP_Integer: { /* out2-prerelease */
+ pOut->u.i = pOp->p1;
+ break;
+}
+
+/* Opcode: Int64 * P2 * P4 *
+**
+** P4 is a pointer to a 64-bit integer value.
+** Write that value into register P2.
+*/
+case OP_Int64: { /* out2-prerelease */
+ assert( pOp->p4.pI64!=0 );
+ pOut->u.i = *pOp->p4.pI64;
+ break;
+}
+
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/* Opcode: Real * P2 * P4 *
+**
+** P4 is a pointer to a 64-bit floating point value.
+** Write that value into register P2.
+*/
+case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
+ pOut->flags = MEM_Real;
+ assert( !sqlite3IsNaN(*pOp->p4.pReal) );
+ pOut->r = *pOp->p4.pReal;
+ break;
+}
+#endif
+
+/* Opcode: String8 * P2 * P4 *
+**
+** P4 points to a nul terminated UTF-8 string. This opcode is transformed
+** into an OP_String before it is executed for the first time.
+*/
+case OP_String8: { /* same as TK_STRING, out2-prerelease */
+ assert( pOp->p4.z!=0 );
+ pOp->opcode = OP_String;
+ pOp->p1 = sqlite3Strlen30(pOp->p4.z);
+
+#ifndef SQLITE_OMIT_UTF16
+ if( encoding!=SQLITE_UTF8 ){
+ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
+ if( rc==SQLITE_TOOBIG ) goto too_big;
+ if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
+ assert( pOut->zMalloc==pOut->z );
+ assert( pOut->flags & MEM_Dyn );
+ pOut->zMalloc = 0;
+ pOut->flags |= MEM_Static;
+ pOut->flags &= ~MEM_Dyn;
+ if( pOp->p4type==P4_DYNAMIC ){
+ sqlite3DbFree(db, pOp->p4.z);
+ }
+ pOp->p4type = P4_DYNAMIC;
+ pOp->p4.z = pOut->z;
+ pOp->p1 = pOut->n;
+ }
+#endif
+ if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+ /* Fall through to the next case, OP_String */
+}
+
+/* Opcode: String P1 P2 * P4 *
+**
+** The string value P4 of length P1 (bytes) is stored in register P2.
+*/
+case OP_String: { /* out2-prerelease */
+ assert( pOp->p4.z!=0 );
+ pOut->flags = MEM_Str|MEM_Static|MEM_Term;
+ pOut->z = pOp->p4.z;
+ pOut->n = pOp->p1;
+ pOut->enc = encoding;
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: Null P1 P2 P3 * *
+**
+** Write a NULL into registers P2. If P3 greater than P2, then also write
+** NULL into register P3 and every register in between P2 and P3. If P3
+** is less than P2 (typically P3 is zero) then only register P2 is
+** set to NULL.
+**
+** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
+** NULL values will not compare equal even if SQLITE_NULLEQ is set on
+** OP_Ne or OP_Eq.
+*/
+case OP_Null: { /* out2-prerelease */
+#if 0 /* local variables moved into u.ab */
+ int cnt;
+ u16 nullFlag;
+#endif /* local variables moved into u.ab */
+ u.ab.cnt = pOp->p3-pOp->p2;
+ assert( pOp->p3<=p->nMem );
+ pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
+ while( u.ab.cnt>0 ){
+ pOut++;
+ memAboutToChange(p, pOut);
+ VdbeMemRelease(pOut);
+ pOut->flags = u.ab.nullFlag;
+ u.ab.cnt--;
+ }
+ break;
+}
+
+
+/* Opcode: Blob P1 P2 * P4
+**
+** P4 points to a blob of data P1 bytes long. Store this
+** blob in register P2.
+*/
+case OP_Blob: { /* out2-prerelease */
+ assert( pOp->p1 <= SQLITE_MAX_LENGTH );
+ sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
+ pOut->enc = encoding;
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: Variable P1 P2 * P4 *
+**
+** Transfer the values of bound parameter P1 into register P2
+**
+** If the parameter is named, then its name appears in P4 and P3==1.
+** The P4 value is used by sqlite3_bind_parameter_name().
+*/
+case OP_Variable: { /* out2-prerelease */
+#if 0 /* local variables moved into u.ac */
+ Mem *pVar; /* Value being transferred */
+#endif /* local variables moved into u.ac */
+
+ assert( pOp->p1>0 && pOp->p1<=p->nVar );
+ assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
+ u.ac.pVar = &p->aVar[pOp->p1 - 1];
+ if( sqlite3VdbeMemTooBig(u.ac.pVar) ){
+ goto too_big;
+ }
+ sqlite3VdbeMemShallowCopy(pOut, u.ac.pVar, MEM_Static);
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: Move P1 P2 P3 * *
+**
+** Move the values in register P1..P1+P3 over into
+** registers P2..P2+P3. Registers P1..P1+P3 are
+** left holding a NULL. It is an error for register ranges
+** P1..P1+P3 and P2..P2+P3 to overlap.
+*/
+case OP_Move: {
+#if 0 /* local variables moved into u.ad */
+ char *zMalloc; /* Holding variable for allocated memory */
+ int n; /* Number of registers left to copy */
+ int p1; /* Register to copy from */
+ int p2; /* Register to copy to */
+#endif /* local variables moved into u.ad */
+
+ u.ad.n = pOp->p3 + 1;
+ u.ad.p1 = pOp->p1;
+ u.ad.p2 = pOp->p2;
+ assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
+ assert( u.ad.p1+u.ad.n<=u.ad.p2 || u.ad.p2+u.ad.n<=u.ad.p1 );
+
+ pIn1 = &aMem[u.ad.p1];
+ pOut = &aMem[u.ad.p2];
+ while( u.ad.n-- ){
+ assert( pOut<=&aMem[p->nMem] );
+ assert( pIn1<=&aMem[p->nMem] );
+ assert( memIsValid(pIn1) );
+ memAboutToChange(p, pOut);
+ u.ad.zMalloc = pOut->zMalloc;
+ pOut->zMalloc = 0;
+ sqlite3VdbeMemMove(pOut, pIn1);
+#ifdef SQLITE_DEBUG
+ if( pOut->pScopyFrom>=&aMem[u.ad.p1] && pOut->pScopyFrom<&aMem[u.ad.p1+pOp->p3] ){
+ pOut->pScopyFrom += u.ad.p1 - pOp->p2;
+ }
+#endif
+ pIn1->zMalloc = u.ad.zMalloc;
+ REGISTER_TRACE(u.ad.p2++, pOut);
+ pIn1++;
+ pOut++;
+ }
+ break;
+}
+
+/* Opcode: Copy P1 P2 P3 * *
+**
+** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
+**
+** This instruction makes a deep copy of the value. A duplicate
+** is made of any string or blob constant. See also OP_SCopy.
+*/
+case OP_Copy: {
+#if 0 /* local variables moved into u.ae */
+ int n;
+#endif /* local variables moved into u.ae */
+
+ u.ae.n = pOp->p3;
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
+ assert( pOut!=pIn1 );
+ while( 1 ){
+ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+ Deephemeralize(pOut);
+#ifdef SQLITE_DEBUG
+ pOut->pScopyFrom = 0;
+#endif
+ REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
+ if( (u.ae.n--)==0 ) break;
+ pOut++;
+ pIn1++;
+ }
+ break;
+}
+
+/* Opcode: SCopy P1 P2 * * *
+**
+** Make a shallow copy of register P1 into register P2.
+**
+** This instruction makes a shallow copy of the value. If the value
+** is a string or blob, then the copy is only a pointer to the
+** original and hence if the original changes so will the copy.
+** Worse, if the original is deallocated, the copy becomes invalid.
+** Thus the program must guarantee that the original will not change
+** during the lifetime of the copy. Use OP_Copy to make a complete
+** copy.
+*/
+case OP_SCopy: { /* in1, out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
+ assert( pOut!=pIn1 );
+ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+#ifdef SQLITE_DEBUG
+ if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
+#endif
+ REGISTER_TRACE(pOp->p2, pOut);
+ break;
+}
+
+/* Opcode: ResultRow P1 P2 * * *
+**
+** The registers P1 through P1+P2-1 contain a single row of
+** results. This opcode causes the sqlite3_step() call to terminate
+** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
+** structure to provide access to the top P1 values as the result
+** row.
+*/
+case OP_ResultRow: {
+#if 0 /* local variables moved into u.af */
+ Mem *pMem;
+ int i;
+#endif /* local variables moved into u.af */
+ assert( p->nResColumn==pOp->p2 );
+ assert( pOp->p1>0 );
+ assert( pOp->p1+pOp->p2<=p->nMem+1 );
+
+ /* If this statement has violated immediate foreign key constraints, do
+ ** not return the number of rows modified. And do not RELEASE the statement
+ ** transaction. It needs to be rolled back. */
+ if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
+ assert( db->flags&SQLITE_CountRows );
+ assert( p->usesStmtJournal );
+ break;
+ }
+
+ /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
+ ** DML statements invoke this opcode to return the number of rows
+ ** modified to the user. This is the only way that a VM that
+ ** opens a statement transaction may invoke this opcode.
+ **
+ ** In case this is such a statement, close any statement transaction
+ ** opened by this VM before returning control to the user. This is to
+ ** ensure that statement-transactions are always nested, not overlapping.
+ ** If the open statement-transaction is not closed here, then the user
+ ** may step another VM that opens its own statement transaction. This
+ ** may lead to overlapping statement transactions.
+ **
+ ** The statement transaction is never a top-level transaction. Hence
+ ** the RELEASE call below can never fail.
+ */
+ assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
+ rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
+ if( NEVER(rc!=SQLITE_OK) ){
+ break;
+ }
+
+ /* Invalidate all ephemeral cursor row caches */
+ p->cacheCtr = (p->cacheCtr + 2)|1;
+
+ /* Make sure the results of the current row are \000 terminated
+ ** and have an assigned type. The results are de-ephemeralized as
+ ** a side effect.
+ */
+ u.af.pMem = p->pResultSet = &aMem[pOp->p1];
+ for(u.af.i=0; u.af.i<pOp->p2; u.af.i++){
+ assert( memIsValid(&u.af.pMem[u.af.i]) );
+ Deephemeralize(&u.af.pMem[u.af.i]);
+ assert( (u.af.pMem[u.af.i].flags & MEM_Ephem)==0
+ || (u.af.pMem[u.af.i].flags & (MEM_Str|MEM_Blob))==0 );
+ sqlite3VdbeMemNulTerminate(&u.af.pMem[u.af.i]);
+ sqlite3VdbeMemStoreType(&u.af.pMem[u.af.i]);
+ REGISTER_TRACE(pOp->p1+u.af.i, &u.af.pMem[u.af.i]);
+ }
+ if( db->mallocFailed ) goto no_mem;
+
+ /* Return SQLITE_ROW
+ */
+ p->pc = pc + 1;
+ rc = SQLITE_ROW;
+ goto vdbe_return;
+}
+
+/* Opcode: Concat P1 P2 P3 * *
+**
+** Add the text in register P1 onto the end of the text in
+** register P2 and store the result in register P3.
+** If either the P1 or P2 text are NULL then store NULL in P3.
+**
+** P3 = P2 || P1
+**
+** It is illegal for P1 and P3 to be the same register. Sometimes,
+** if P3 is the same register as P2, the implementation is able
+** to avoid a memcpy().
+*/
+case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
+#if 0 /* local variables moved into u.ag */
+ i64 nByte;
+#endif /* local variables moved into u.ag */
+
+ pIn1 = &aMem[pOp->p1];
+ pIn2 = &aMem[pOp->p2];
+ pOut = &aMem[pOp->p3];
+ assert( pIn1!=pOut );
+ if( (pIn1->flags | pIn2->flags) & MEM_Null ){
+ sqlite3VdbeMemSetNull(pOut);
+ break;
+ }
+ if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
+ Stringify(pIn1, encoding);
+ Stringify(pIn2, encoding);
+ u.ag.nByte = pIn1->n + pIn2->n;
+ if( u.ag.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+ MemSetTypeFlag(pOut, MEM_Str);
+ if( sqlite3VdbeMemGrow(pOut, (int)u.ag.nByte+2, pOut==pIn2) ){
+ goto no_mem;
+ }
+ if( pOut!=pIn2 ){
+ memcpy(pOut->z, pIn2->z, pIn2->n);
+ }
+ memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
+ pOut->z[u.ag.nByte] = 0;
+ pOut->z[u.ag.nByte+1] = 0;
+ pOut->flags |= MEM_Term;
+ pOut->n = (int)u.ag.nByte;
+ pOut->enc = encoding;
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: Add P1 P2 P3 * *
+**
+** Add the value in register P1 to the value in register P2
+** and store the result in register P3.
+** If either input is NULL, the result is NULL.
+*/
+/* Opcode: Multiply P1 P2 P3 * *
+**
+**
+** Multiply the value in register P1 by the value in register P2
+** and store the result in register P3.
+** If either input is NULL, the result is NULL.
+*/
+/* Opcode: Subtract P1 P2 P3 * *
+**
+** Subtract the value in register P1 from the value in register P2
+** and store the result in register P3.
+** If either input is NULL, the result is NULL.
+*/
+/* Opcode: Divide P1 P2 P3 * *
+**
+** Divide the value in register P1 by the value in register P2
+** and store the result in register P3 (P3=P2/P1). If the value in
+** register P1 is zero, then the result is NULL. If either input is
+** NULL, the result is NULL.
+*/
+/* Opcode: Remainder P1 P2 P3 * *
+**
+** Compute the remainder after integer division of the value in
+** register P1 by the value in register P2 and store the result in P3.
+** If the value in register P2 is zero the result is NULL.
+** If either operand is NULL, the result is NULL.
+*/
+case OP_Add: /* same as TK_PLUS, in1, in2, out3 */
+case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
+case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
+case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
+case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
+#if 0 /* local variables moved into u.ah */
+ char bIntint; /* Started out as two integer operands */
+ int flags; /* Combined MEM_* flags from both inputs */
+ i64 iA; /* Integer value of left operand */
+ i64 iB; /* Integer value of right operand */
+ double rA; /* Real value of left operand */
+ double rB; /* Real value of right operand */
+#endif /* local variables moved into u.ah */
+
+ pIn1 = &aMem[pOp->p1];
+ applyNumericAffinity(pIn1);
+ pIn2 = &aMem[pOp->p2];
+ applyNumericAffinity(pIn2);
+ pOut = &aMem[pOp->p3];
+ u.ah.flags = pIn1->flags | pIn2->flags;
+ if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
+ if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
+ u.ah.iA = pIn1->u.i;
+ u.ah.iB = pIn2->u.i;
+ u.ah.bIntint = 1;
+ switch( pOp->opcode ){
+ case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
+ case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
+ case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
+ case OP_Divide: {
+ if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math;
+ u.ah.iB /= u.ah.iA;
+ break;
+ }
+ default: {
+ if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ah.iA==-1 ) u.ah.iA = 1;
+ u.ah.iB %= u.ah.iA;
+ break;
+ }
+ }
+ pOut->u.i = u.ah.iB;
+ MemSetTypeFlag(pOut, MEM_Int);
+ }else{
+ u.ah.bIntint = 0;
+fp_math:
+ u.ah.rA = sqlite3VdbeRealValue(pIn1);
+ u.ah.rB = sqlite3VdbeRealValue(pIn2);
+ switch( pOp->opcode ){
+ case OP_Add: u.ah.rB += u.ah.rA; break;
+ case OP_Subtract: u.ah.rB -= u.ah.rA; break;
+ case OP_Multiply: u.ah.rB *= u.ah.rA; break;
+ case OP_Divide: {
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ if( u.ah.rA==(double)0 ) goto arithmetic_result_is_null;
+ u.ah.rB /= u.ah.rA;
+ break;
+ }
+ default: {
+ u.ah.iA = (i64)u.ah.rA;
+ u.ah.iB = (i64)u.ah.rB;
+ if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ah.iA==-1 ) u.ah.iA = 1;
+ u.ah.rB = (double)(u.ah.iB % u.ah.iA);
+ break;
+ }
+ }
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ pOut->u.i = u.ah.rB;
+ MemSetTypeFlag(pOut, MEM_Int);
+#else
+ if( sqlite3IsNaN(u.ah.rB) ){
+ goto arithmetic_result_is_null;
+ }
+ pOut->r = u.ah.rB;
+ MemSetTypeFlag(pOut, MEM_Real);
+ if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
+ sqlite3VdbeIntegerAffinity(pOut);
+ }
+#endif
+ }
+ break;
+
+arithmetic_result_is_null:
+ sqlite3VdbeMemSetNull(pOut);
+ break;
+}
+
+/* Opcode: CollSeq P1 * * P4
+**
+** P4 is a pointer to a CollSeq struct. If the next call to a user function
+** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
+** be returned. This is used by the built-in min(), max() and nullif()
+** functions.
+**
+** If P1 is not zero, then it is a register that a subsequent min() or
+** max() aggregate will set to 1 if the current row is not the minimum or
+** maximum. The P1 register is initialized to 0 by this instruction.
+**
+** The interface used by the implementation of the aforementioned functions
+** to retrieve the collation sequence set by this opcode is not available
+** publicly, only to user functions defined in func.c.
+*/
+case OP_CollSeq: {
+ assert( pOp->p4type==P4_COLLSEQ );
+ if( pOp->p1 ){
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0);
+ }
+ break;
+}
+
+/* Opcode: Function P1 P2 P3 P4 P5
+**
+** Invoke a user function (P4 is a pointer to a Function structure that
+** defines the function) with P5 arguments taken from register P2 and
+** successors. The result of the function is stored in register P3.
+** Register P3 must not be one of the function inputs.
+**
+** P1 is a 32-bit bitmask indicating whether or not each argument to the
+** function was determined to be constant at compile time. If the first
+** argument was constant then bit 0 of P1 is set. This is used to determine
+** whether meta data associated with a user function argument using the
+** sqlite3_set_auxdata() API may be safely retained until the next
+** invocation of this opcode.
+**
+** See also: AggStep and AggFinal
+*/
+case OP_Function: {
+#if 0 /* local variables moved into u.ai */
+ int i;
+ Mem *pArg;
+ sqlite3_context ctx;
+ sqlite3_value **apVal;
+ int n;
+#endif /* local variables moved into u.ai */
+
+ u.ai.n = pOp->p5;
+ u.ai.apVal = p->apArg;
+ assert( u.ai.apVal || u.ai.n==0 );
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ pOut = &aMem[pOp->p3];
+ memAboutToChange(p, pOut);
+
+ assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) );
+ assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ai.n );
+ u.ai.pArg = &aMem[pOp->p2];
+ for(u.ai.i=0; u.ai.i<u.ai.n; u.ai.i++, u.ai.pArg++){
+ assert( memIsValid(u.ai.pArg) );
+ u.ai.apVal[u.ai.i] = u.ai.pArg;
+ Deephemeralize(u.ai.pArg);
+ sqlite3VdbeMemStoreType(u.ai.pArg);
+ REGISTER_TRACE(pOp->p2+u.ai.i, u.ai.pArg);
+ }
+
+ assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
+ if( pOp->p4type==P4_FUNCDEF ){
+ u.ai.ctx.pFunc = pOp->p4.pFunc;
+ u.ai.ctx.pVdbeFunc = 0;
+ }else{
+ u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
+ u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
+ }
+
+ u.ai.ctx.s.flags = MEM_Null;
+ u.ai.ctx.s.db = db;
+ u.ai.ctx.s.xDel = 0;
+ u.ai.ctx.s.zMalloc = 0;
+
+ /* The output cell may already have a buffer allocated. Move
+ ** the pointer to u.ai.ctx.s so in case the user-function can use
+ ** the already allocated buffer instead of allocating a new one.
+ */
+ sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
+ MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);
+
+ u.ai.ctx.isError = 0;
+ if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ assert( pOp>aOp );
+ assert( pOp[-1].p4type==P4_COLLSEQ );
+ assert( pOp[-1].opcode==OP_CollSeq );
+ u.ai.ctx.pColl = pOp[-1].p4.pColl;
+ }
+ db->lastRowid = lastRowid;
+ (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
+ lastRowid = db->lastRowid;
+
+ /* If any auxiliary data functions have been called by this user function,
+ ** immediately call the destructor for any non-static values.
+ */
+ if( u.ai.ctx.pVdbeFunc ){
+ sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
+ pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
+ pOp->p4type = P4_VDBEFUNC;
+ }
+
+ if( db->mallocFailed ){
+ /* Even though a malloc() has failed, the implementation of the
+ ** user function may have called an sqlite3_result_XXX() function
+ ** to return a value. The following call releases any resources
+ ** associated with such a value.
+ */
+ sqlite3VdbeMemRelease(&u.ai.ctx.s);
+ goto no_mem;
+ }
+
+ /* If the function returned an error, throw an exception */
+ if( u.ai.ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
+ rc = u.ai.ctx.isError;
+ }
+
+ /* Copy the result of the function into register P3 */
+ sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding);
+ sqlite3VdbeMemMove(pOut, &u.ai.ctx.s);
+ if( sqlite3VdbeMemTooBig(pOut) ){
+ goto too_big;
+ }
+
+#if 0
+ /* The app-defined function has done something that as caused this
+ ** statement to expire. (Perhaps the function called sqlite3_exec()
+ ** with a CREATE TABLE statement.)
+ */
+ if( p->expired ) rc = SQLITE_ABORT;
+#endif
+
+ REGISTER_TRACE(pOp->p3, pOut);
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: BitAnd P1 P2 P3 * *
+**
+** Take the bit-wise AND of the values in register P1 and P2 and
+** store the result in register P3.
+** If either input is NULL, the result is NULL.
+*/
+/* Opcode: BitOr P1 P2 P3 * *
+**
+** Take the bit-wise OR of the values in register P1 and P2 and
+** store the result in register P3.
+** If either input is NULL, the result is NULL.
+*/
+/* Opcode: ShiftLeft P1 P2 P3 * *
+**
+** Shift the integer value in register P2 to the left by the
+** number of bits specified by the integer in register P1.
+** Store the result in register P3.
+** If either input is NULL, the result is NULL.
+*/
+/* Opcode: ShiftRight P1 P2 P3 * *
+**
+** Shift the integer value in register P2 to the right by the
+** number of bits specified by the integer in register P1.
+** Store the result in register P3.
+** If either input is NULL, the result is NULL.
+*/
+case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
+case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
+case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
+case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
+#if 0 /* local variables moved into u.aj */
+ i64 iA;
+ u64 uA;
+ i64 iB;
+ u8 op;
+#endif /* local variables moved into u.aj */
+
+ pIn1 = &aMem[pOp->p1];
+ pIn2 = &aMem[pOp->p2];
+ pOut = &aMem[pOp->p3];
+ if( (pIn1->flags | pIn2->flags) & MEM_Null ){
+ sqlite3VdbeMemSetNull(pOut);
+ break;
+ }
+ u.aj.iA = sqlite3VdbeIntValue(pIn2);
+ u.aj.iB = sqlite3VdbeIntValue(pIn1);
+ u.aj.op = pOp->opcode;
+ if( u.aj.op==OP_BitAnd ){
+ u.aj.iA &= u.aj.iB;
+ }else if( u.aj.op==OP_BitOr ){
+ u.aj.iA |= u.aj.iB;
+ }else if( u.aj.iB!=0 ){
+ assert( u.aj.op==OP_ShiftRight || u.aj.op==OP_ShiftLeft );
+
+ /* If shifting by a negative amount, shift in the other direction */
+ if( u.aj.iB<0 ){
+ assert( OP_ShiftRight==OP_ShiftLeft+1 );
+ u.aj.op = 2*OP_ShiftLeft + 1 - u.aj.op;
+ u.aj.iB = u.aj.iB>(-64) ? -u.aj.iB : 64;
+ }
+
+ if( u.aj.iB>=64 ){
+ u.aj.iA = (u.aj.iA>=0 || u.aj.op==OP_ShiftLeft) ? 0 : -1;
+ }else{
+ memcpy(&u.aj.uA, &u.aj.iA, sizeof(u.aj.uA));
+ if( u.aj.op==OP_ShiftLeft ){
+ u.aj.uA <<= u.aj.iB;
+ }else{
+ u.aj.uA >>= u.aj.iB;
+ /* Sign-extend on a right shift of a negative number */
+ if( u.aj.iA<0 ) u.aj.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.aj.iB);
+ }
+ memcpy(&u.aj.iA, &u.aj.uA, sizeof(u.aj.iA));
+ }
+ }
+ pOut->u.i = u.aj.iA;
+ MemSetTypeFlag(pOut, MEM_Int);
+ break;
+}
+
+/* Opcode: AddImm P1 P2 * * *
+**
+** Add the constant P2 to the value in register P1.
+** The result is always an integer.
+**
+** To force any register to be an integer, just add 0.
+*/
+case OP_AddImm: { /* in1 */
+ pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
+ sqlite3VdbeMemIntegerify(pIn1);
+ pIn1->u.i += pOp->p2;
+ break;
+}
+
+/* Opcode: MustBeInt P1 P2 * * *
+**
+** Force the value in register P1 to be an integer. If the value
+** in P1 is not an integer and cannot be converted into an integer
+** without data loss, then jump immediately to P2, or if P2==0
+** raise an SQLITE_MISMATCH exception.
+*/
+case OP_MustBeInt: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
+ if( (pIn1->flags & MEM_Int)==0 ){
+ if( pOp->p2==0 ){
+ rc = SQLITE_MISMATCH;
+ goto abort_due_to_error;
+ }else{
+ pc = pOp->p2 - 1;
+ }
+ }else{
+ MemSetTypeFlag(pIn1, MEM_Int);
+ }
+ break;
+}
+
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/* Opcode: RealAffinity P1 * * * *
+**
+** If register P1 holds an integer convert it to a real value.
+**
+** This opcode is used when extracting information from a column that
+** has REAL affinity. Such column values may still be stored as
+** integers, for space efficiency, but after extraction we want them
+** to have only a real value.
+*/
+case OP_RealAffinity: { /* in1 */
+ pIn1 = &aMem[pOp->p1];
+ if( pIn1->flags & MEM_Int ){
+ sqlite3VdbeMemRealify(pIn1);
+ }
+ break;
+}
+#endif
+
+#ifndef SQLITE_OMIT_CAST
+/* Opcode: ToText P1 * * * *
+**
+** Force the value in register P1 to be text.
+** If the value is numeric, convert it to a string using the
+** equivalent of printf(). Blob values are unchanged and
+** are afterwards simply interpreted as text.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToText: { /* same as TK_TO_TEXT, in1 */
+ pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
+ if( pIn1->flags & MEM_Null ) break;
+ assert( MEM_Str==(MEM_Blob>>3) );
+ pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
+ applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
+ rc = ExpandBlob(pIn1);
+ assert( pIn1->flags & MEM_Str || db->mallocFailed );
+ pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero);
+ UPDATE_MAX_BLOBSIZE(pIn1);
+ break;
+}
+
+/* Opcode: ToBlob P1 * * * *
+**
+** Force the value in register P1 to be a BLOB.
+** If the value is numeric, convert it to a string first.
+** Strings are simply reinterpreted as blobs with no change
+** to the underlying data.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
+ pIn1 = &aMem[pOp->p1];
+ if( pIn1->flags & MEM_Null ) break;
+ if( (pIn1->flags & MEM_Blob)==0 ){
+ applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
+ assert( pIn1->flags & MEM_Str || db->mallocFailed );
+ MemSetTypeFlag(pIn1, MEM_Blob);
+ }else{
+ pIn1->flags &= ~(MEM_TypeMask&~MEM_Blob);
+ }
+ UPDATE_MAX_BLOBSIZE(pIn1);
+ break;
+}
+
+/* Opcode: ToNumeric P1 * * * *
+**
+** Force the value in register P1 to be numeric (either an
+** integer or a floating-point number.)
+** If the value is text or blob, try to convert it to an using the
+** equivalent of atoi() or atof() and store 0 if no such conversion
+** is possible.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
+ pIn1 = &aMem[pOp->p1];
+ sqlite3VdbeMemNumerify(pIn1);
+ break;
+}
+#endif /* SQLITE_OMIT_CAST */
+
+/* Opcode: ToInt P1 * * * *
+**
+** Force the value in register P1 to be an integer. If
+** The value is currently a real number, drop its fractional part.
+** If the value is text or blob, try to convert it to an integer using the
+** equivalent of atoi() and store 0 if no such conversion is possible.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToInt: { /* same as TK_TO_INT, in1 */
+ pIn1 = &aMem[pOp->p1];
+ if( (pIn1->flags & MEM_Null)==0 ){
+ sqlite3VdbeMemIntegerify(pIn1);
+ }
+ break;
+}
+
+#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT)
+/* Opcode: ToReal P1 * * * *
+**
+** Force the value in register P1 to be a floating point number.
+** If The value is currently an integer, convert it.
+** If the value is text or blob, try to convert it to an integer using the
+** equivalent of atoi() and store 0.0 if no such conversion is possible.
+**
+** A NULL value is not changed by this routine. It remains NULL.
+*/
+case OP_ToReal: { /* same as TK_TO_REAL, in1 */
+ pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
+ if( (pIn1->flags & MEM_Null)==0 ){
+ sqlite3VdbeMemRealify(pIn1);
+ }
+ break;
+}
+#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
+
+/* Opcode: Lt P1 P2 P3 P4 P5
+**
+** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
+** jump to address P2.
+**
+** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
+** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL
+** bit is clear then fall through if either operand is NULL.
+**
+** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
+** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
+** to coerce both inputs according to this affinity before the
+** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
+** affinity is used. Note that the affinity conversions are stored
+** back into the input registers P1 and P3. So this opcode can cause
+** persistent changes to registers P1 and P3.
+**
+** Once any conversions have taken place, and neither value is NULL,
+** the values are compared. If both values are blobs then memcmp() is
+** used to determine the results of the comparison. If both values
+** are text, then the appropriate collating function specified in
+** P4 is used to do the comparison. If P4 is not specified then
+** memcmp() is used to compare text string. If both values are
+** numeric, then a numeric comparison is used. If the two values
+** are of different types, then numbers are considered less than
+** strings and strings are considered less than blobs.
+**
+** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead,
+** store a boolean result (either 0, or 1, or NULL) in register P2.
+**
+** If the SQLITE_NULLEQ bit is set in P5, then NULL values are considered
+** equal to one another, provided that they do not have their MEM_Cleared
+** bit set.
+*/
+/* Opcode: Ne P1 P2 P3 P4 P5
+**
+** This works just like the Lt opcode except that the jump is taken if
+** the operands in registers P1 and P3 are not equal. See the Lt opcode for
+** additional information.
+**
+** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
+** true or false and is never NULL. If both operands are NULL then the result
+** of comparison is false. If either operand is NULL then the result is true.
+** If neither operand is NULL the result is the same as it would be if
+** the SQLITE_NULLEQ flag were omitted from P5.
+*/
+/* Opcode: Eq P1 P2 P3 P4 P5
+**
+** This works just like the Lt opcode except that the jump is taken if
+** the operands in registers P1 and P3 are equal.
+** See the Lt opcode for additional information.
+**
+** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
+** true or false and is never NULL. If both operands are NULL then the result
+** of comparison is true. If either operand is NULL then the result is false.
+** If neither operand is NULL the result is the same as it would be if
+** the SQLITE_NULLEQ flag were omitted from P5.
+*/
+/* Opcode: Le P1 P2 P3 P4 P5
+**
+** This works just like the Lt opcode except that the jump is taken if
+** the content of register P3 is less than or equal to the content of
+** register P1. See the Lt opcode for additional information.
+*/
+/* Opcode: Gt P1 P2 P3 P4 P5
+**
+** This works just like the Lt opcode except that the jump is taken if
+** the content of register P3 is greater than the content of
+** register P1. See the Lt opcode for additional information.
+*/
+/* Opcode: Ge P1 P2 P3 P4 P5
+**
+** This works just like the Lt opcode except that the jump is taken if
+** the content of register P3 is greater than or equal to the content of
+** register P1. See the Lt opcode for additional information.
+*/
+case OP_Eq: /* same as TK_EQ, jump, in1, in3 */
+case OP_Ne: /* same as TK_NE, jump, in1, in3 */
+case OP_Lt: /* same as TK_LT, jump, in1, in3 */
+case OP_Le: /* same as TK_LE, jump, in1, in3 */
+case OP_Gt: /* same as TK_GT, jump, in1, in3 */
+case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
+#if 0 /* local variables moved into u.ak */
+ int res; /* Result of the comparison of pIn1 against pIn3 */
+ char affinity; /* Affinity to use for comparison */
+ u16 flags1; /* Copy of initial value of pIn1->flags */
+ u16 flags3; /* Copy of initial value of pIn3->flags */
+#endif /* local variables moved into u.ak */
+
+ pIn1 = &aMem[pOp->p1];
+ pIn3 = &aMem[pOp->p3];
+ u.ak.flags1 = pIn1->flags;
+ u.ak.flags3 = pIn3->flags;
+ if( (u.ak.flags1 | u.ak.flags3)&MEM_Null ){
+ /* One or both operands are NULL */
+ if( pOp->p5 & SQLITE_NULLEQ ){
+ /* If SQLITE_NULLEQ is set (which will only happen if the operator is
+ ** OP_Eq or OP_Ne) then take the jump or not depending on whether
+ ** or not both operands are null.
+ */
+ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
+ assert( (u.ak.flags1 & MEM_Cleared)==0 );
+ if( (u.ak.flags1&MEM_Null)!=0
+ && (u.ak.flags3&MEM_Null)!=0
+ && (u.ak.flags3&MEM_Cleared)==0
+ ){
+ u.ak.res = 0; /* Results are equal */
+ }else{
+ u.ak.res = 1; /* Results are not equal */
+ }
+ }else{
+ /* SQLITE_NULLEQ is clear and at least one operand is NULL,
+ ** then the result is always NULL.
+ ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
+ */
+ if( pOp->p5 & SQLITE_STOREP2 ){
+ pOut = &aMem[pOp->p2];
+ MemSetTypeFlag(pOut, MEM_Null);
+ REGISTER_TRACE(pOp->p2, pOut);
+ }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ pc = pOp->p2-1;
+ }
+ break;
+ }
+ }else{
+ /* Neither operand is NULL. Do a comparison. */
+ u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK;
+ if( u.ak.affinity ){
+ applyAffinity(pIn1, u.ak.affinity, encoding);
+ applyAffinity(pIn3, u.ak.affinity, encoding);
+ if( db->mallocFailed ) goto no_mem;
+ }
+
+ assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
+ ExpandBlob(pIn1);
+ ExpandBlob(pIn3);
+ u.ak.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
+ }
+ switch( pOp->opcode ){
+ case OP_Eq: u.ak.res = u.ak.res==0; break;
+ case OP_Ne: u.ak.res = u.ak.res!=0; break;
+ case OP_Lt: u.ak.res = u.ak.res<0; break;
+ case OP_Le: u.ak.res = u.ak.res<=0; break;
+ case OP_Gt: u.ak.res = u.ak.res>0; break;
+ default: u.ak.res = u.ak.res>=0; break;
+ }
+
+ if( pOp->p5 & SQLITE_STOREP2 ){
+ pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
+ MemSetTypeFlag(pOut, MEM_Int);
+ pOut->u.i = u.ak.res;
+ REGISTER_TRACE(pOp->p2, pOut);
+ }else if( u.ak.res ){
+ pc = pOp->p2-1;
+ }
+
+ /* Undo any changes made by applyAffinity() to the input registers. */
+ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ak.flags1&MEM_TypeMask);
+ pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ak.flags3&MEM_TypeMask);
+ break;
+}
+
+/* Opcode: Permutation * * * P4 *
+**
+** Set the permutation used by the OP_Compare operator to be the array
+** of integers in P4.
+**
+** The permutation is only valid until the next OP_Compare that has
+** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
+** occur immediately prior to the OP_Compare.
+*/
+case OP_Permutation: {
+ assert( pOp->p4type==P4_INTARRAY );
+ assert( pOp->p4.ai );
+ aPermute = pOp->p4.ai;
+ break;
+}
+
+/* Opcode: Compare P1 P2 P3 P4 P5
+**
+** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
+** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
+** the comparison for use by the next OP_Jump instruct.
+**
+** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
+** determined by the most recent OP_Permutation operator. If the
+** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
+** order.
+**
+** P4 is a KeyInfo structure that defines collating sequences and sort
+** orders for the comparison. The permutation applies to registers
+** only. The KeyInfo elements are used sequentially.
+**
+** The comparison is a sort comparison, so NULLs compare equal,
+** NULLs are less than numbers, numbers are less than strings,
+** and strings are less than blobs.
+*/
+case OP_Compare: {
+#if 0 /* local variables moved into u.al */
+ int n;
+ int i;
+ int p1;
+ int p2;
+ const KeyInfo *pKeyInfo;
+ int idx;
+ CollSeq *pColl; /* Collating sequence to use on this term */
+ int bRev; /* True for DESCENDING sort order */
+#endif /* local variables moved into u.al */
+
+ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
+ u.al.n = pOp->p3;
+ u.al.pKeyInfo = pOp->p4.pKeyInfo;
+ assert( u.al.n>0 );
+ assert( u.al.pKeyInfo!=0 );
+ u.al.p1 = pOp->p1;
+ u.al.p2 = pOp->p2;
+#if SQLITE_DEBUG
+ if( aPermute ){
+ int k, mx = 0;
+ for(k=0; k<u.al.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
+ assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 );
+ assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 );
+ }else{
+ assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 );
+ assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 );
+ }
+#endif /* SQLITE_DEBUG */
+ for(u.al.i=0; u.al.i<u.al.n; u.al.i++){
+ u.al.idx = aPermute ? aPermute[u.al.i] : u.al.i;
+ assert( memIsValid(&aMem[u.al.p1+u.al.idx]) );
+ assert( memIsValid(&aMem[u.al.p2+u.al.idx]) );
+ REGISTER_TRACE(u.al.p1+u.al.idx, &aMem[u.al.p1+u.al.idx]);
+ REGISTER_TRACE(u.al.p2+u.al.idx, &aMem[u.al.p2+u.al.idx]);
+ assert( u.al.i<u.al.pKeyInfo->nField );
+ u.al.pColl = u.al.pKeyInfo->aColl[u.al.i];
+ u.al.bRev = u.al.pKeyInfo->aSortOrder[u.al.i];
+ iCompare = sqlite3MemCompare(&aMem[u.al.p1+u.al.idx], &aMem[u.al.p2+u.al.idx], u.al.pColl);
+ if( iCompare ){
+ if( u.al.bRev ) iCompare = -iCompare;
+ break;
+ }
+ }
+ aPermute = 0;
+ break;
+}
+
+/* Opcode: Jump P1 P2 P3 * *
+**
+** Jump to the instruction at address P1, P2, or P3 depending on whether
+** in the most recent OP_Compare instruction the P1 vector was less than
+** equal to, or greater than the P2 vector, respectively.
+*/
+case OP_Jump: { /* jump */
+ if( iCompare<0 ){
+ pc = pOp->p1 - 1;
+ }else if( iCompare==0 ){
+ pc = pOp->p2 - 1;
+ }else{
+ pc = pOp->p3 - 1;
+ }
+ break;
+}
+
+/* Opcode: And P1 P2 P3 * *
+**
+** Take the logical AND of the values in registers P1 and P2 and
+** write the result into register P3.
+**
+** If either P1 or P2 is 0 (false) then the result is 0 even if
+** the other input is NULL. A NULL and true or two NULLs give
+** a NULL output.
+*/
+/* Opcode: Or P1 P2 P3 * *
+**
+** Take the logical OR of the values in register P1 and P2 and
+** store the answer in register P3.
+**
+** If either P1 or P2 is nonzero (true) then the result is 1 (true)
+** even if the other input is NULL. A NULL and false or two NULLs
+** give a NULL output.
+*/
+case OP_And: /* same as TK_AND, in1, in2, out3 */
+case OP_Or: { /* same as TK_OR, in1, in2, out3 */
+#if 0 /* local variables moved into u.am */
+ int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
+ int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
+#endif /* local variables moved into u.am */
+
+ pIn1 = &aMem[pOp->p1];
+ if( pIn1->flags & MEM_Null ){
+ u.am.v1 = 2;
+ }else{
+ u.am.v1 = sqlite3VdbeIntValue(pIn1)!=0;
+ }
+ pIn2 = &aMem[pOp->p2];
+ if( pIn2->flags & MEM_Null ){
+ u.am.v2 = 2;
+ }else{
+ u.am.v2 = sqlite3VdbeIntValue(pIn2)!=0;
+ }
+ if( pOp->opcode==OP_And ){
+ static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
+ u.am.v1 = and_logic[u.am.v1*3+u.am.v2];
+ }else{
+ static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
+ u.am.v1 = or_logic[u.am.v1*3+u.am.v2];
+ }
+ pOut = &aMem[pOp->p3];
+ if( u.am.v1==2 ){
+ MemSetTypeFlag(pOut, MEM_Null);
+ }else{
+ pOut->u.i = u.am.v1;
+ MemSetTypeFlag(pOut, MEM_Int);
+ }
+ break;
+}
+
+/* Opcode: Not P1 P2 * * *
+**
+** Interpret the value in register P1 as a boolean value. Store the
+** boolean complement in register P2. If the value in register P1 is
+** NULL, then a NULL is stored in P2.
+*/
+case OP_Not: { /* same as TK_NOT, in1, out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
+ if( pIn1->flags & MEM_Null ){
+ sqlite3VdbeMemSetNull(pOut);
+ }else{
+ sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeIntValue(pIn1));
+ }
+ break;
+}
+
+/* Opcode: BitNot P1 P2 * * *
+**
+** Interpret the content of register P1 as an integer. Store the
+** ones-complement of the P1 value into register P2. If P1 holds
+** a NULL then store a NULL in P2.
+*/
+case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
+ pIn1 = &aMem[pOp->p1];
+ pOut = &aMem[pOp->p2];
+ if( pIn1->flags & MEM_Null ){
+ sqlite3VdbeMemSetNull(pOut);
+ }else{
+ sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
+ }
+ break;
+}
+
+/* Opcode: Once P1 P2 * * *
+**
+** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
+** set the flag and fall through to the next instruction.
+*/
+case OP_Once: { /* jump */
+ assert( pOp->p1<p->nOnceFlag );
+ if( p->aOnceFlag[pOp->p1] ){
+ pc = pOp->p2-1;
+ }else{
+ p->aOnceFlag[pOp->p1] = 1;
+ }
+ break;
+}
+
+/* Opcode: If P1 P2 P3 * *
+**
+** Jump to P2 if the value in register P1 is true. The value
+** is considered true if it is numeric and non-zero. If the value
+** in P1 is NULL then take the jump if P3 is non-zero.
+*/
+/* Opcode: IfNot P1 P2 P3 * *
+**
+** Jump to P2 if the value in register P1 is False. The value
+** is considered false if it has a numeric value of zero. If the value
+** in P1 is NULL then take the jump if P3 is zero.
+*/
+case OP_If: /* jump, in1 */
+case OP_IfNot: { /* jump, in1 */
+#if 0 /* local variables moved into u.an */
+ int c;
+#endif /* local variables moved into u.an */
+ pIn1 = &aMem[pOp->p1];
+ if( pIn1->flags & MEM_Null ){
+ u.an.c = pOp->p3;
+ }else{
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ u.an.c = sqlite3VdbeIntValue(pIn1)!=0;
+#else
+ u.an.c = sqlite3VdbeRealValue(pIn1)!=0.0;
+#endif
+ if( pOp->opcode==OP_IfNot ) u.an.c = !u.an.c;
+ }
+ if( u.an.c ){
+ pc = pOp->p2-1;
+ }
+ break;
+}
+
+/* Opcode: IsNull P1 P2 * * *
+**
+** Jump to P2 if the value in register P1 is NULL.
+*/
+case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ if( (pIn1->flags & MEM_Null)!=0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: NotNull P1 P2 * * *
+**
+** Jump to P2 if the value in register P1 is not NULL.
+*/
+case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ if( (pIn1->flags & MEM_Null)==0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: Column P1 P2 P3 P4 P5
+**
+** Interpret the data that cursor P1 points to as a structure built using
+** the MakeRecord instruction. (See the MakeRecord opcode for additional
+** information about the format of the data.) Extract the P2-th column
+** from this record. If there are less that (P2+1)
+** values in the record, extract a NULL.
+**
+** The value extracted is stored in register P3.
+**
+** If the column contains fewer than P2 fields, then extract a NULL. Or,
+** if the P4 argument is a P4_MEM use the value of the P4 argument as
+** the result.
+**
+** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
+** then the cache of the cursor is reset prior to extracting the column.
+** The first OP_Column against a pseudo-table after the value of the content
+** register has changed should have this bit set.
+**
+** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
+** the result is guaranteed to only be used as the argument of a length()
+** or typeof() function, respectively. The loading of large blobs can be
+** skipped for length() and all content loading can be skipped for typeof().
+*/
+case OP_Column: {
+#if 0 /* local variables moved into u.ao */
+ u32 payloadSize; /* Number of bytes in the record */
+ i64 payloadSize64; /* Number of bytes in the record */
+ int p1; /* P1 value of the opcode */
+ int p2; /* column number to retrieve */
+ VdbeCursor *pC; /* The VDBE cursor */
+ char *zRec; /* Pointer to complete record-data */
+ BtCursor *pCrsr; /* The BTree cursor */
+ u32 *aType; /* aType[i] holds the numeric type of the i-th column */
+ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
+ int nField; /* number of fields in the record */
+ int len; /* The length of the serialized data for the column */
+ int i; /* Loop counter */
+ char *zData; /* Part of the record being decoded */
+ Mem *pDest; /* Where to write the extracted value */
+ Mem sMem; /* For storing the record being decoded */
+ u8 *zIdx; /* Index into header */
+ u8 *zEndHdr; /* Pointer to first byte after the header */
+ u32 offset; /* Offset into the data */
+ u32 szField; /* Number of bytes in the content of a field */
+ int szHdr; /* Size of the header size field at start of record */
+ int avail; /* Number of bytes of available data */
+ u32 t; /* A type code from the record header */
+ Mem *pReg; /* PseudoTable input register */
+#endif /* local variables moved into u.ao */
+
+
+ u.ao.p1 = pOp->p1;
+ u.ao.p2 = pOp->p2;
+ u.ao.pC = 0;
+ memset(&u.ao.sMem, 0, sizeof(u.ao.sMem));
+ assert( u.ao.p1<p->nCursor );
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ u.ao.pDest = &aMem[pOp->p3];
+ memAboutToChange(p, u.ao.pDest);
+ u.ao.zRec = 0;
+
+ /* This block sets the variable u.ao.payloadSize to be the total number of
+ ** bytes in the record.
+ **
+ ** u.ao.zRec is set to be the complete text of the record if it is available.
+ ** The complete record text is always available for pseudo-tables
+ ** If the record is stored in a cursor, the complete record text
+ ** might be available in the u.ao.pC->aRow cache. Or it might not be.
+ ** If the data is unavailable, u.ao.zRec is set to NULL.
+ **
+ ** We also compute the number of columns in the record. For cursors,
+ ** the number of columns is stored in the VdbeCursor.nField element.
+ */
+ u.ao.pC = p->apCsr[u.ao.p1];
+ assert( u.ao.pC!=0 );
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ assert( u.ao.pC->pVtabCursor==0 );
+#endif
+ u.ao.pCrsr = u.ao.pC->pCursor;
+ if( u.ao.pCrsr!=0 ){
+ /* The record is stored in a B-Tree */
+ rc = sqlite3VdbeCursorMoveto(u.ao.pC);
+ if( rc ) goto abort_due_to_error;
+ if( u.ao.pC->nullRow ){
+ u.ao.payloadSize = 0;
+ }else if( u.ao.pC->cacheStatus==p->cacheCtr ){
+ u.ao.payloadSize = u.ao.pC->payloadSize;
+ u.ao.zRec = (char*)u.ao.pC->aRow;
+ }else if( u.ao.pC->isIndex ){
+ assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ao.pCrsr, &u.ao.payloadSize64);
+ assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
+ /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
+ ** payload size, so it is impossible for u.ao.payloadSize64 to be
+ ** larger than 32 bits. */
+ assert( (u.ao.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ao.payloadSize64 );
+ u.ao.payloadSize = (u32)u.ao.payloadSize64;
+ }else{
+ assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize);
+ assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
+ }
+ }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){
+ u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg];
+ if( u.ao.pC->multiPseudo ){
+ sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem);
+ Deephemeralize(u.ao.pDest);
+ goto op_column_out;
+ }
+ assert( u.ao.pReg->flags & MEM_Blob );
+ assert( memIsValid(u.ao.pReg) );
+ u.ao.payloadSize = u.ao.pReg->n;
+ u.ao.zRec = u.ao.pReg->z;
+ u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
+ assert( u.ao.payloadSize==0 || u.ao.zRec!=0 );
+ }else{
+ /* Consider the row to be NULL */
+ u.ao.payloadSize = 0;
+ }
+
+ /* If u.ao.payloadSize is 0, then just store a NULL. This can happen because of
+ ** nullRow or because of a corrupt database. */
+ if( u.ao.payloadSize==0 ){
+ MemSetTypeFlag(u.ao.pDest, MEM_Null);
+ goto op_column_out;
+ }
+ assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
+ if( u.ao.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+
+ u.ao.nField = u.ao.pC->nField;
+ assert( u.ao.p2<u.ao.nField );
+
+ /* Read and parse the table header. Store the results of the parse
+ ** into the record header cache fields of the cursor.
+ */
+ u.ao.aType = u.ao.pC->aType;
+ if( u.ao.pC->cacheStatus==p->cacheCtr ){
+ u.ao.aOffset = u.ao.pC->aOffset;
+ }else{
+ assert(u.ao.aType);
+ u.ao.avail = 0;
+ u.ao.pC->aOffset = u.ao.aOffset = &u.ao.aType[u.ao.nField];
+ u.ao.pC->payloadSize = u.ao.payloadSize;
+ u.ao.pC->cacheStatus = p->cacheCtr;
+
+ /* Figure out how many bytes are in the header */
+ if( u.ao.zRec ){
+ u.ao.zData = u.ao.zRec;
+ }else{
+ if( u.ao.pC->isIndex ){
+ u.ao.zData = (char*)sqlite3BtreeKeyFetch(u.ao.pCrsr, &u.ao.avail);
+ }else{
+ u.ao.zData = (char*)sqlite3BtreeDataFetch(u.ao.pCrsr, &u.ao.avail);
+ }
+ /* If KeyFetch()/DataFetch() managed to get the entire payload,
+ ** save the payload in the u.ao.pC->aRow cache. That will save us from
+ ** having to make additional calls to fetch the content portion of
+ ** the record.
+ */
+ assert( u.ao.avail>=0 );
+ if( u.ao.payloadSize <= (u32)u.ao.avail ){
+ u.ao.zRec = u.ao.zData;
+ u.ao.pC->aRow = (u8*)u.ao.zData;
+ }else{
+ u.ao.pC->aRow = 0;
+ }
+ }
+ /* The following assert is true in all cases except when
+ ** the database file has been corrupted externally.
+ ** assert( u.ao.zRec!=0 || u.ao.avail>=u.ao.payloadSize || u.ao.avail>=9 ); */
+ u.ao.szHdr = getVarint32((u8*)u.ao.zData, u.ao.offset);
+
+ /* Make sure a corrupt database has not given us an oversize header.
+ ** Do this now to avoid an oversize memory allocation.
+ **
+ ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
+ ** types use so much data space that there can only be 4096 and 32 of
+ ** them, respectively. So the maximum header length results from a
+ ** 3-byte type for each of the maximum of 32768 columns plus three
+ ** extra bytes for the header length itself. 32768*3 + 3 = 98307.
+ */
+ if( u.ao.offset > 98307 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto op_column_out;
+ }
+
+ /* Compute in u.ao.len the number of bytes of data we need to read in order
+ ** to get u.ao.nField type values. u.ao.offset is an upper bound on this. But
+ ** u.ao.nField might be significantly less than the true number of columns
+ ** in the table, and in that case, 5*u.ao.nField+3 might be smaller than u.ao.offset.
+ ** We want to minimize u.ao.len in order to limit the size of the memory
+ ** allocation, especially if a corrupt database file has caused u.ao.offset
+ ** to be oversized. Offset is limited to 98307 above. But 98307 might
+ ** still exceed Robson memory allocation limits on some configurations.
+ ** On systems that cannot tolerate large memory allocations, u.ao.nField*5+3
+ ** will likely be much smaller since u.ao.nField will likely be less than
+ ** 20 or so. This insures that Robson memory allocation limits are
+ ** not exceeded even for corrupt database files.
+ */
+ u.ao.len = u.ao.nField*5 + 3;
+ if( u.ao.len > (int)u.ao.offset ) u.ao.len = (int)u.ao.offset;
+
+ /* The KeyFetch() or DataFetch() above are fast and will get the entire
+ ** record header in most cases. But they will fail to get the complete
+ ** record header if the record header does not fit on a single page
+ ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to
+ ** acquire the complete header text.
+ */
+ if( !u.ao.zRec && u.ao.avail<u.ao.len ){
+ u.ao.sMem.flags = 0;
+ u.ao.sMem.db = 0;
+ rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, 0, u.ao.len, u.ao.pC->isIndex, &u.ao.sMem);
+ if( rc!=SQLITE_OK ){
+ goto op_column_out;
+ }
+ u.ao.zData = u.ao.sMem.z;
+ }
+ u.ao.zEndHdr = (u8 *)&u.ao.zData[u.ao.len];
+ u.ao.zIdx = (u8 *)&u.ao.zData[u.ao.szHdr];
+
+ /* Scan the header and use it to fill in the u.ao.aType[] and u.ao.aOffset[]
+ ** arrays. u.ao.aType[u.ao.i] will contain the type integer for the u.ao.i-th
+ ** column and u.ao.aOffset[u.ao.i] will contain the u.ao.offset from the beginning
+ ** of the record to the start of the data for the u.ao.i-th column
+ */
+ for(u.ao.i=0; u.ao.i<u.ao.nField; u.ao.i++){
+ if( u.ao.zIdx<u.ao.zEndHdr ){
+ u.ao.aOffset[u.ao.i] = u.ao.offset;
+ if( u.ao.zIdx[0]<0x80 ){
+ u.ao.t = u.ao.zIdx[0];
+ u.ao.zIdx++;
+ }else{
+ u.ao.zIdx += sqlite3GetVarint32(u.ao.zIdx, &u.ao.t);
+ }
+ u.ao.aType[u.ao.i] = u.ao.t;
+ u.ao.szField = sqlite3VdbeSerialTypeLen(u.ao.t);
+ u.ao.offset += u.ao.szField;
+ if( u.ao.offset<u.ao.szField ){ /* True if u.ao.offset overflows */
+ u.ao.zIdx = &u.ao.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
+ break;
+ }
+ }else{
+ /* If u.ao.i is less that u.ao.nField, then there are fewer fields in this
+ ** record than SetNumColumns indicated there are columns in the
+ ** table. Set the u.ao.offset for any extra columns not present in
+ ** the record to 0. This tells code below to store the default value
+ ** for the column instead of deserializing a value from the record.
+ */
+ u.ao.aOffset[u.ao.i] = 0;
+ }
+ }
+ sqlite3VdbeMemRelease(&u.ao.sMem);
+ u.ao.sMem.flags = MEM_Null;
+
+ /* If we have read more header data than was contained in the header,
+ ** or if the end of the last field appears to be past the end of the
+ ** record, or if the end of the last field appears to be before the end
+ ** of the record (when all fields present), then we must be dealing
+ ** with a corrupt database.
+ */
+ if( (u.ao.zIdx > u.ao.zEndHdr) || (u.ao.offset > u.ao.payloadSize)
+ || (u.ao.zIdx==u.ao.zEndHdr && u.ao.offset!=u.ao.payloadSize) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto op_column_out;
+ }
+ }
+
+ /* Get the column information. If u.ao.aOffset[u.ao.p2] is non-zero, then
+ ** deserialize the value from the record. If u.ao.aOffset[u.ao.p2] is zero,
+ ** then there are not enough fields in the record to satisfy the
+ ** request. In this case, set the value NULL or to P4 if P4 is
+ ** a pointer to a Mem object.
+ */
+ if( u.ao.aOffset[u.ao.p2] ){
+ assert( rc==SQLITE_OK );
+ if( u.ao.zRec ){
+ /* This is the common case where the whole row fits on a single page */
+ VdbeMemRelease(u.ao.pDest);
+ sqlite3VdbeSerialGet((u8 *)&u.ao.zRec[u.ao.aOffset[u.ao.p2]], u.ao.aType[u.ao.p2], u.ao.pDest);
+ }else{
+ /* This branch happens only when the row overflows onto multiple pages */
+ u.ao.t = u.ao.aType[u.ao.p2];
+ if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
+ && ((u.ao.t>=12 && (u.ao.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
+ ){
+ /* Content is irrelevant for the typeof() function and for
+ ** the length(X) function if X is a blob. So we might as well use
+ ** bogus content rather than reading content from disk. NULL works
+ ** for text and blob and whatever is in the u.ao.payloadSize64 variable
+ ** will work for everything else. */
+ u.ao.zData = u.ao.t<12 ? (char*)&u.ao.payloadSize64 : 0;
+ }else{
+ u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.t);
+ sqlite3VdbeMemMove(&u.ao.sMem, u.ao.pDest);
+ rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, u.ao.aOffset[u.ao.p2], u.ao.len, u.ao.pC->isIndex,
+ &u.ao.sMem);
+ if( rc!=SQLITE_OK ){
+ goto op_column_out;
+ }
+ u.ao.zData = u.ao.sMem.z;
+ }
+ sqlite3VdbeSerialGet((u8*)u.ao.zData, u.ao.t, u.ao.pDest);
+ }
+ u.ao.pDest->enc = encoding;
+ }else{
+ if( pOp->p4type==P4_MEM ){
+ sqlite3VdbeMemShallowCopy(u.ao.pDest, pOp->p4.pMem, MEM_Static);
+ }else{
+ MemSetTypeFlag(u.ao.pDest, MEM_Null);
+ }
+ }
+
+ /* If we dynamically allocated space to hold the data (in the
+ ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
+ ** dynamically allocated space over to the u.ao.pDest structure.
+ ** This prevents a memory copy.
+ */
+ if( u.ao.sMem.zMalloc ){
+ assert( u.ao.sMem.z==u.ao.sMem.zMalloc );
+ assert( !(u.ao.pDest->flags & MEM_Dyn) );
+ assert( !(u.ao.pDest->flags & (MEM_Blob|MEM_Str)) || u.ao.pDest->z==u.ao.sMem.z );
+ u.ao.pDest->flags &= ~(MEM_Ephem|MEM_Static);
+ u.ao.pDest->flags |= MEM_Term;
+ u.ao.pDest->z = u.ao.sMem.z;
+ u.ao.pDest->zMalloc = u.ao.sMem.zMalloc;
+ }
+
+ rc = sqlite3VdbeMemMakeWriteable(u.ao.pDest);
+
+op_column_out:
+ UPDATE_MAX_BLOBSIZE(u.ao.pDest);
+ REGISTER_TRACE(pOp->p3, u.ao.pDest);
+ break;
+}
+
+/* Opcode: Affinity P1 P2 * P4 *
+**
+** Apply affinities to a range of P2 registers starting with P1.
+**
+** P4 is a string that is P2 characters long. The nth character of the
+** string indicates the column affinity that should be used for the nth
+** memory cell in the range.
+*/
+case OP_Affinity: {
+#if 0 /* local variables moved into u.ap */
+ const char *zAffinity; /* The affinity to be applied */
+ char cAff; /* A single character of affinity */
+#endif /* local variables moved into u.ap */
+
+ u.ap.zAffinity = pOp->p4.z;
+ assert( u.ap.zAffinity!=0 );
+ assert( u.ap.zAffinity[pOp->p2]==0 );
+ pIn1 = &aMem[pOp->p1];
+ while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){
+ assert( pIn1 <= &p->aMem[p->nMem] );
+ assert( memIsValid(pIn1) );
+ ExpandBlob(pIn1);
+ applyAffinity(pIn1, u.ap.cAff, encoding);
+ pIn1++;
+ }
+ break;
+}
+
+/* Opcode: MakeRecord P1 P2 P3 P4 *
+**
+** Convert P2 registers beginning with P1 into the [record format]
+** use as a data record in a database table or as a key
+** in an index. The OP_Column opcode can decode the record later.
+**
+** P4 may be a string that is P2 characters long. The nth character of the
+** string indicates the column affinity that should be used for the nth
+** field of the index key.
+**
+** The mapping from character to affinity is given by the SQLITE_AFF_
+** macros defined in sqliteInt.h.
+**
+** If P4 is NULL then all index fields have the affinity NONE.
+*/
+case OP_MakeRecord: {
+#if 0 /* local variables moved into u.aq */
+ u8 *zNewRecord; /* A buffer to hold the data for the new record */
+ Mem *pRec; /* The new record */
+ u64 nData; /* Number of bytes of data space */
+ int nHdr; /* Number of bytes of header space */
+ i64 nByte; /* Data space required for this record */
+ int nZero; /* Number of zero bytes at the end of the record */
+ int nVarint; /* Number of bytes in a varint */
+ u32 serial_type; /* Type field */
+ Mem *pData0; /* First field to be combined into the record */
+ Mem *pLast; /* Last field of the record */
+ int nField; /* Number of fields in the record */
+ char *zAffinity; /* The affinity string for the record */
+ int file_format; /* File format to use for encoding */
+ int i; /* Space used in zNewRecord[] */
+ int len; /* Length of a field */
+#endif /* local variables moved into u.aq */
+
+ /* Assuming the record contains N fields, the record format looks
+ ** like this:
+ **
+ ** ------------------------------------------------------------------------
+ ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 |
+ ** ------------------------------------------------------------------------
+ **
+ ** Data(0) is taken from register P1. Data(1) comes from register P1+1
+ ** and so froth.
+ **
+ ** Each type field is a varint representing the serial type of the
+ ** corresponding data element (see sqlite3VdbeSerialType()). The
+ ** hdr-size field is also a varint which is the offset from the beginning
+ ** of the record to data0.
+ */
+ u.aq.nData = 0; /* Number of bytes of data space */
+ u.aq.nHdr = 0; /* Number of bytes of header space */
+ u.aq.nZero = 0; /* Number of zero bytes at the end of the record */
+ u.aq.nField = pOp->p1;
+ u.aq.zAffinity = pOp->p4.z;
+ assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 );
+ u.aq.pData0 = &aMem[u.aq.nField];
+ u.aq.nField = pOp->p2;
+ u.aq.pLast = &u.aq.pData0[u.aq.nField-1];
+ u.aq.file_format = p->minWriteFileFormat;
+
+ /* Identify the output register */
+ assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
+ pOut = &aMem[pOp->p3];
+ memAboutToChange(p, pOut);
+
+ /* Loop through the elements that will make up the record to figure
+ ** out how much space is required for the new record.
+ */
+ for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+ assert( memIsValid(u.aq.pRec) );
+ if( u.aq.zAffinity ){
+ applyAffinity(u.aq.pRec, u.aq.zAffinity[u.aq.pRec-u.aq.pData0], encoding);
+ }
+ if( u.aq.pRec->flags&MEM_Zero && u.aq.pRec->n>0 ){
+ sqlite3VdbeMemExpandBlob(u.aq.pRec);
+ }
+ u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+ u.aq.len = sqlite3VdbeSerialTypeLen(u.aq.serial_type);
+ u.aq.nData += u.aq.len;
+ u.aq.nHdr += sqlite3VarintLen(u.aq.serial_type);
+ if( u.aq.pRec->flags & MEM_Zero ){
+ /* Only pure zero-filled BLOBs can be input to this Opcode.
+ ** We do not allow blobs with a prefix and a zero-filled tail. */
+ u.aq.nZero += u.aq.pRec->u.nZero;
+ }else if( u.aq.len ){
+ u.aq.nZero = 0;
+ }
+ }
+
+ /* Add the initial header varint and total the size */
+ u.aq.nHdr += u.aq.nVarint = sqlite3VarintLen(u.aq.nHdr);
+ if( u.aq.nVarint<sqlite3VarintLen(u.aq.nHdr) ){
+ u.aq.nHdr++;
+ }
+ u.aq.nByte = u.aq.nHdr+u.aq.nData-u.aq.nZero;
+ if( u.aq.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+
+ /* Make sure the output register has a buffer large enough to store
+ ** the new record. The output register (pOp->p3) is not allowed to
+ ** be one of the input registers (because the following call to
+ ** sqlite3VdbeMemGrow() could clobber the value before it is used).
+ */
+ if( sqlite3VdbeMemGrow(pOut, (int)u.aq.nByte, 0) ){
+ goto no_mem;
+ }
+ u.aq.zNewRecord = (u8 *)pOut->z;
+
+ /* Write the record */
+ u.aq.i = putVarint32(u.aq.zNewRecord, u.aq.nHdr);
+ for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+ u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+ u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.serial_type); /* serial type */
+ }
+ for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){ /* serial data */
+ u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), u.aq.pRec,u.aq.file_format);
+ }
+ assert( u.aq.i==u.aq.nByte );
+
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ pOut->n = (int)u.aq.nByte;
+ pOut->flags = MEM_Blob | MEM_Dyn;
+ pOut->xDel = 0;
+ if( u.aq.nZero ){
+ pOut->u.nZero = u.aq.nZero;
+ pOut->flags |= MEM_Zero;
+ }
+ pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
+ REGISTER_TRACE(pOp->p3, pOut);
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: Count P1 P2 * * *
+**
+** Store the number of entries (an integer value) in the table or index
+** opened by cursor P1 in register P2
+*/
+#ifndef SQLITE_OMIT_BTREECOUNT
+case OP_Count: { /* out2-prerelease */
+#if 0 /* local variables moved into u.ar */
+ i64 nEntry;
+ BtCursor *pCrsr;
+#endif /* local variables moved into u.ar */
+
+ u.ar.pCrsr = p->apCsr[pOp->p1]->pCursor;
+ if( ALWAYS(u.ar.pCrsr) ){
+ rc = sqlite3BtreeCount(u.ar.pCrsr, &u.ar.nEntry);
+ }else{
+ u.ar.nEntry = 0;
+ }
+ pOut->u.i = u.ar.nEntry;
+ break;
+}
+#endif
+
+/* Opcode: Savepoint P1 * * P4 *
+**
+** Open, release or rollback the savepoint named by parameter P4, depending
+** on the value of P1. To open a new savepoint, P1==0. To release (commit) an
+** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
+*/
+case OP_Savepoint: {
+#if 0 /* local variables moved into u.as */
+ int p1; /* Value of P1 operand */
+ char *zName; /* Name of savepoint */
+ int nName;
+ Savepoint *pNew;
+ Savepoint *pSavepoint;
+ Savepoint *pTmp;
+ int iSavepoint;
+ int ii;
+#endif /* local variables moved into u.as */
+
+ u.as.p1 = pOp->p1;
+ u.as.zName = pOp->p4.z;
+
+ /* Assert that the u.as.p1 parameter is valid. Also that if there is no open
+ ** transaction, then there cannot be any savepoints.
+ */
+ assert( db->pSavepoint==0 || db->autoCommit==0 );
+ assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
+ assert( db->pSavepoint || db->isTransactionSavepoint==0 );
+ assert( checkSavepointCount(db) );
+
+ if( u.as.p1==SAVEPOINT_BEGIN ){
+ if( db->writeVdbeCnt>0 ){
+ /* A new savepoint cannot be created if there are active write
+ ** statements (i.e. open read/write incremental blob handles).
+ */
+ sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - "
+ "SQL statements in progress");
+ rc = SQLITE_BUSY;
+ }else{
+ u.as.nName = sqlite3Strlen30(u.as.zName);
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* This call is Ok even if this savepoint is actually a transaction
+ ** savepoint (and therefore should not prompt xSavepoint()) callbacks.
+ ** If this is a transaction savepoint being opened, it is guaranteed
+ ** that the db->aVTrans[] array is empty. */
+ assert( db->autoCommit==0 || db->nVTrans==0 );
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN,
+ db->nStatement+db->nSavepoint);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+#endif
+
+ /* Create a new savepoint structure. */
+ u.as.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.as.nName+1);
+ if( u.as.pNew ){
+ u.as.pNew->zName = (char *)&u.as.pNew[1];
+ memcpy(u.as.pNew->zName, u.as.zName, u.as.nName+1);
+
+ /* If there is no open transaction, then mark this as a special
+ ** "transaction savepoint". */
+ if( db->autoCommit ){
+ db->autoCommit = 0;
+ db->isTransactionSavepoint = 1;
+ }else{
+ db->nSavepoint++;
+ }
+
+ /* Link the new savepoint into the database handle's list. */
+ u.as.pNew->pNext = db->pSavepoint;
+ db->pSavepoint = u.as.pNew;
+ u.as.pNew->nDeferredCons = db->nDeferredCons;
+ }
+ }
+ }else{
+ u.as.iSavepoint = 0;
+
+ /* Find the named savepoint. If there is no such savepoint, then an
+ ** an error is returned to the user. */
+ for(
+ u.as.pSavepoint = db->pSavepoint;
+ u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName);
+ u.as.pSavepoint = u.as.pSavepoint->pNext
+ ){
+ u.as.iSavepoint++;
+ }
+ if( !u.as.pSavepoint ){
+ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
+ rc = SQLITE_ERROR;
+ }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){
+ /* It is not possible to release (commit) a savepoint if there are
+ ** active write statements.
+ */
+ sqlite3SetString(&p->zErrMsg, db,
+ "cannot release savepoint - SQL statements in progress"
+ );
+ rc = SQLITE_BUSY;
+ }else{
+
+ /* Determine whether or not this is a transaction savepoint. If so,
+ ** and this is a RELEASE command, then the current transaction
+ ** is committed.
+ */
+ int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint;
+ if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){
+ if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
+ goto vdbe_return;
+ }
+ db->autoCommit = 1;
+ if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
+ p->pc = pc;
+ db->autoCommit = 0;
+ p->rc = rc = SQLITE_BUSY;
+ goto vdbe_return;
+ }
+ db->isTransactionSavepoint = 0;
+ rc = p->rc;
+ }else{
+ u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1;
+ if( u.as.p1==SAVEPOINT_ROLLBACK ){
+ for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
+ sqlite3BtreeTripAllCursors(db->aDb[u.as.ii].pBt, SQLITE_ABORT);
+ }
+ }
+ for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
+ rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ }
+ if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+ sqlite3ExpirePreparedStatements(db);
+ sqlite3ResetAllSchemasOfConnection(db);
+ db->flags = (db->flags | SQLITE_InternChanges);
+ }
+ }
+
+ /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
+ ** savepoints nested inside of the savepoint being operated on. */
+ while( db->pSavepoint!=u.as.pSavepoint ){
+ u.as.pTmp = db->pSavepoint;
+ db->pSavepoint = u.as.pTmp->pNext;
+ sqlite3DbFree(db, u.as.pTmp);
+ db->nSavepoint--;
+ }
+
+ /* If it is a RELEASE, then destroy the savepoint being operated on
+ ** too. If it is a ROLLBACK TO, then set the number of deferred
+ ** constraint violations present in the database to the value stored
+ ** when the savepoint was created. */
+ if( u.as.p1==SAVEPOINT_RELEASE ){
+ assert( u.as.pSavepoint==db->pSavepoint );
+ db->pSavepoint = u.as.pSavepoint->pNext;
+ sqlite3DbFree(db, u.as.pSavepoint);
+ if( !isTransaction ){
+ db->nSavepoint--;
+ }
+ }else{
+ db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
+ }
+
+ if( !isTransaction ){
+ rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ }
+ }
+ }
+
+ break;
+}
+
+/* Opcode: AutoCommit P1 P2 * * *
+**
+** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
+** back any currently active btree transactions. If there are any active
+** VMs (apart from this one), then a ROLLBACK fails. A COMMIT fails if
+** there are active writing VMs or active VMs that use shared cache.
+**
+** This instruction causes the VM to halt.
+*/
+case OP_AutoCommit: {
+#if 0 /* local variables moved into u.at */
+ int desiredAutoCommit;
+ int iRollback;
+ int turnOnAC;
+#endif /* local variables moved into u.at */
+
+ u.at.desiredAutoCommit = pOp->p1;
+ u.at.iRollback = pOp->p2;
+ u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit;
+ assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 );
+ assert( u.at.desiredAutoCommit==1 || u.at.iRollback==0 );
+ assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
+
+#if 0
+ if( u.at.turnOnAC && u.at.iRollback && db->activeVdbeCnt>1 ){
+ /* If this instruction implements a ROLLBACK and other VMs are
+ ** still running, and a transaction is active, return an error indicating
+ ** that the other VMs must complete first.
+ */
+ sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
+ "SQL statements in progress");
+ rc = SQLITE_BUSY;
+ }else
+#endif
+ if( u.at.turnOnAC && !u.at.iRollback && db->writeVdbeCnt>0 ){
+ /* If this instruction implements a COMMIT and other VMs are writing
+ ** return an error indicating that the other VMs must complete first.
+ */
+ sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
+ "SQL statements in progress");
+ rc = SQLITE_BUSY;
+ }else if( u.at.desiredAutoCommit!=db->autoCommit ){
+ if( u.at.iRollback ){
+ assert( u.at.desiredAutoCommit==1 );
+ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
+ db->autoCommit = 1;
+ }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
+ goto vdbe_return;
+ }else{
+ db->autoCommit = (u8)u.at.desiredAutoCommit;
+ if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
+ p->pc = pc;
+ db->autoCommit = (u8)(1-u.at.desiredAutoCommit);
+ p->rc = rc = SQLITE_BUSY;
+ goto vdbe_return;
+ }
+ }
+ assert( db->nStatement==0 );
+ sqlite3CloseSavepoints(db);
+ if( p->rc==SQLITE_OK ){
+ rc = SQLITE_DONE;
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ goto vdbe_return;
+ }else{
+ sqlite3SetString(&p->zErrMsg, db,
+ (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":(
+ (u.at.iRollback)?"cannot rollback - no transaction is active":
+ "cannot commit - no transaction is active"));
+
+ rc = SQLITE_ERROR;
+ }
+ break;
+}
+
+/* Opcode: Transaction P1 P2 * * *
+**
+** Begin a transaction. The transaction ends when a Commit or Rollback
+** opcode is encountered. Depending on the ON CONFLICT setting, the
+** transaction might also be rolled back if an error is encountered.
+**
+** P1 is the index of the database file on which the transaction is
+** started. Index 0 is the main database file and index 1 is the
+** file used for temporary tables. Indices of 2 or more are used for
+** attached databases.
+**
+** If P2 is non-zero, then a write-transaction is started. A RESERVED lock is
+** obtained on the database file when a write-transaction is started. No
+** other process can start another write transaction while this transaction is
+** underway. Starting a write transaction also creates a rollback journal. A
+** write transaction must be started before any changes can be made to the
+** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained
+** on the file.
+**
+** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
+** true (this flag is set if the Vdbe may modify more than one row and may
+** throw an ABORT exception), a statement transaction may also be opened.
+** More specifically, a statement transaction is opened iff the database
+** connection is currently not in autocommit mode, or if there are other
+** active statements. A statement transaction allows the changes made by this
+** VDBE to be rolled back after an error without having to roll back the
+** entire transaction. If no error is encountered, the statement transaction
+** will automatically commit when the VDBE halts.
+**
+** If P2 is zero, then a read-lock is obtained on the database file.
+*/
+case OP_Transaction: {
+#if 0 /* local variables moved into u.au */
+ Btree *pBt;
+#endif /* local variables moved into u.au */
+
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ u.au.pBt = db->aDb[pOp->p1].pBt;
+
+ if( u.au.pBt ){
+ rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
+ if( rc==SQLITE_BUSY ){
+ p->pc = pc;
+ p->rc = rc = SQLITE_BUSY;
+ goto vdbe_return;
+ }
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+
+ if( pOp->p2 && p->usesStmtJournal
+ && (db->autoCommit==0 || db->activeVdbeCnt>1)
+ ){
+ assert( sqlite3BtreeIsInTrans(u.au.pBt) );
+ if( p->iStatement==0 ){
+ assert( db->nStatement>=0 && db->nSavepoint>=0 );
+ db->nStatement++;
+ p->iStatement = db->nSavepoint + db->nStatement;
+ }
+
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
+ }
+
+ /* Store the current value of the database handles deferred constraint
+ ** counter. If the statement transaction needs to be rolled back,
+ ** the value of this counter needs to be restored too. */
+ p->nStmtDefCons = db->nDeferredCons;
+ }
+ }
+ break;
+}
+
+/* Opcode: ReadCookie P1 P2 P3 * *
+**
+** Read cookie number P3 from database P1 and write it into register P2.
+** P3==1 is the schema version. P3==2 is the database format.
+** P3==3 is the recommended pager cache size, and so forth. P1==0 is
+** the main database file and P1==1 is the database file used to store
+** temporary tables.
+**
+** There must be a read-lock on the database (either a transaction
+** must be started or there must be an open cursor) before
+** executing this instruction.
+*/
+case OP_ReadCookie: { /* out2-prerelease */
+#if 0 /* local variables moved into u.av */
+ int iMeta;
+ int iDb;
+ int iCookie;
+#endif /* local variables moved into u.av */
+
+ u.av.iDb = pOp->p1;
+ u.av.iCookie = pOp->p3;
+ assert( pOp->p3<SQLITE_N_BTREE_META );
+ assert( u.av.iDb>=0 && u.av.iDb<db->nDb );
+ assert( db->aDb[u.av.iDb].pBt!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<u.av.iDb))!=0 );
+
+ sqlite3BtreeGetMeta(db->aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta);
+ pOut->u.i = u.av.iMeta;
+ break;
+}
+
+/* Opcode: SetCookie P1 P2 P3 * *
+**
+** Write the content of register P3 (interpreted as an integer)
+** into cookie number P2 of database P1. P2==1 is the schema version.
+** P2==2 is the database format. P2==3 is the recommended pager cache
+** size, and so forth. P1==0 is the main database file and P1==1 is the
+** database file used to store temporary tables.
+**
+** A transaction must be started before executing this opcode.
+*/
+case OP_SetCookie: { /* in3 */
+#if 0 /* local variables moved into u.aw */
+ Db *pDb;
+#endif /* local variables moved into u.aw */
+ assert( pOp->p2<SQLITE_N_BTREE_META );
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ u.aw.pDb = &db->aDb[pOp->p1];
+ assert( u.aw.pDb->pBt!=0 );
+ assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
+ pIn3 = &aMem[pOp->p3];
+ sqlite3VdbeMemIntegerify(pIn3);
+ /* See note about index shifting on OP_ReadCookie */
+ rc = sqlite3BtreeUpdateMeta(u.aw.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+ if( pOp->p2==BTREE_SCHEMA_VERSION ){
+ /* When the schema cookie changes, record the new cookie internally */
+ u.aw.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+ db->flags |= SQLITE_InternChanges;
+ }else if( pOp->p2==BTREE_FILE_FORMAT ){
+ /* Record changes in the file format */
+ u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i;
+ }
+ if( pOp->p1==1 ){
+ /* Invalidate all prepared statements whenever the TEMP database
+ ** schema is changed. Ticket #1644 */
+ sqlite3ExpirePreparedStatements(db);
+ p->expired = 0;
+ }
+ break;
+}
+
+/* Opcode: VerifyCookie P1 P2 P3 * *
+**
+** Check the value of global database parameter number 0 (the
+** schema version) and make sure it is equal to P2 and that the
+** generation counter on the local schema parse equals P3.
+**
+** P1 is the database number which is 0 for the main database file
+** and 1 for the file holding temporary tables and some higher number
+** for auxiliary databases.
+**
+** The cookie changes its value whenever the database schema changes.
+** This operation is used to detect when that the cookie has changed
+** and that the current process needs to reread the schema.
+**
+** Either a transaction needs to have been started or an OP_Open needs
+** to be executed (to establish a read lock) before this opcode is
+** invoked.
+*/
+case OP_VerifyCookie: {
+#if 0 /* local variables moved into u.ax */
+ int iMeta;
+ int iGen;
+ Btree *pBt;
+#endif /* local variables moved into u.ax */
+
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
+ u.ax.pBt = db->aDb[pOp->p1].pBt;
+ if( u.ax.pBt ){
+ sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
+ u.ax.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
+ }else{
+ u.ax.iGen = u.ax.iMeta = 0;
+ }
+ if( u.ax.iMeta!=pOp->p2 || u.ax.iGen!=pOp->p3 ){
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
+ /* If the schema-cookie from the database file matches the cookie
+ ** stored with the in-memory representation of the schema, do
+ ** not reload the schema from the database file.
+ **
+ ** If virtual-tables are in use, this is not just an optimization.
+ ** Often, v-tables store their data in other SQLite tables, which
+ ** are queried from within xNext() and other v-table methods using
+ ** prepared queries. If such a query is out-of-date, we do not want to
+ ** discard the database schema, as the user code implementing the
+ ** v-table would have to be ready for the sqlite3_vtab structure itself
+ ** to be invalidated whenever sqlite3_step() is called from within
+ ** a v-table method.
+ */
+ if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){
+ sqlite3ResetOneSchema(db, pOp->p1);
+ }
+
+ p->expired = 1;
+ rc = SQLITE_SCHEMA;
+ }
+ break;
+}
+
+/* Opcode: OpenRead P1 P2 P3 P4 P5
+**
+** Open a read-only cursor for the database table whose root page is
+** P2 in a database file. The database file is determined by P3.
+** P3==0 means the main database, P3==1 means the database used for
+** temporary tables, and P3>1 means used the corresponding attached
+** database. Give the new cursor an identifier of P1. The P1
+** values need not be contiguous but all P1 values should be small integers.
+** It is an error for P1 to be negative.
+**
+** If P5!=0 then use the content of register P2 as the root page, not
+** the value of P2 itself.
+**
+** There will be a read lock on the database whenever there is an
+** open cursor. If the database was unlocked prior to this instruction
+** then a read lock is acquired as part of this instruction. A read
+** lock allows other processes to read the database but prohibits
+** any other process from modifying the database. The read lock is
+** released when all cursors are closed. If this instruction attempts
+** to get a read lock but fails, the script terminates with an
+** SQLITE_BUSY error code.
+**
+** The P4 value may be either an integer (P4_INT32) or a pointer to
+** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
+** structure, then said structure defines the content and collating
+** sequence of the index being opened. Otherwise, if P4 is an integer
+** value, it is set to the number of columns in the table.
+**
+** See also OpenWrite.
+*/
+/* Opcode: OpenWrite P1 P2 P3 P4 P5
+**
+** Open a read/write cursor named P1 on the table or index whose root
+** page is P2. Or if P5!=0 use the content of register P2 to find the
+** root page.
+**
+** The P4 value may be either an integer (P4_INT32) or a pointer to
+** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
+** structure, then said structure defines the content and collating
+** sequence of the index being opened. Otherwise, if P4 is an integer
+** value, it is set to the number of columns in the table, or to the
+** largest index of any column of the table that is actually used.
+**
+** This instruction works just like OpenRead except that it opens the cursor
+** in read/write mode. For a given table, there can be one or more read-only
+** cursors or a single read/write cursor but not both.
+**
+** See also OpenRead.
+*/
+case OP_OpenRead:
+case OP_OpenWrite: {
+#if 0 /* local variables moved into u.ay */
+ int nField;
+ KeyInfo *pKeyInfo;
+ int p2;
+ int iDb;
+ int wrFlag;
+ Btree *pX;
+ VdbeCursor *pCur;
+ Db *pDb;
+#endif /* local variables moved into u.ay */
+
+ assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
+ assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
+
+ if( p->expired ){
+ rc = SQLITE_ABORT;
+ break;
+ }
+
+ u.ay.nField = 0;
+ u.ay.pKeyInfo = 0;
+ u.ay.p2 = pOp->p2;
+ u.ay.iDb = pOp->p3;
+ assert( u.ay.iDb>=0 && u.ay.iDb<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<u.ay.iDb))!=0 );
+ u.ay.pDb = &db->aDb[u.ay.iDb];
+ u.ay.pX = u.ay.pDb->pBt;
+ assert( u.ay.pX!=0 );
+ if( pOp->opcode==OP_OpenWrite ){
+ u.ay.wrFlag = 1;
+ assert( sqlite3SchemaMutexHeld(db, u.ay.iDb, 0) );
+ if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){
+ p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
+ }
+ }else{
+ u.ay.wrFlag = 0;
+ }
+ if( pOp->p5 & OPFLAG_P2ISREG ){
+ assert( u.ay.p2>0 );
+ assert( u.ay.p2<=p->nMem );
+ pIn2 = &aMem[u.ay.p2];
+ assert( memIsValid(pIn2) );
+ assert( (pIn2->flags & MEM_Int)!=0 );
+ sqlite3VdbeMemIntegerify(pIn2);
+ u.ay.p2 = (int)pIn2->u.i;
+ /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and
+ ** that opcode will always set the u.ay.p2 value to 2 or more or else fail.
+ ** If there were a failure, the prepared statement would have halted
+ ** before reaching this instruction. */
+ if( NEVER(u.ay.p2<2) ) {
+ rc = SQLITE_CORRUPT_BKPT;
+ goto abort_due_to_error;
+ }
+ }
+ if( pOp->p4type==P4_KEYINFO ){
+ u.ay.pKeyInfo = pOp->p4.pKeyInfo;
+ u.ay.pKeyInfo->enc = ENC(p->db);
+ u.ay.nField = u.ay.pKeyInfo->nField+1;
+ }else if( pOp->p4type==P4_INT32 ){
+ u.ay.nField = pOp->p4.i;
+ }
+ assert( pOp->p1>=0 );
+ u.ay.pCur = allocateCursor(p, pOp->p1, u.ay.nField, u.ay.iDb, 1);
+ if( u.ay.pCur==0 ) goto no_mem;
+ u.ay.pCur->nullRow = 1;
+ u.ay.pCur->isOrdered = 1;
+ rc = sqlite3BtreeCursor(u.ay.pX, u.ay.p2, u.ay.wrFlag, u.ay.pKeyInfo, u.ay.pCur->pCursor);
+ u.ay.pCur->pKeyInfo = u.ay.pKeyInfo;
+ assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
+ sqlite3BtreeCursorHints(u.ay.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
+
+ /* Since it performs no memory allocation or IO, the only value that
+ ** sqlite3BtreeCursor() may return is SQLITE_OK. */
+ assert( rc==SQLITE_OK );
+
+ /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
+ ** SQLite used to check if the root-page flags were sane at this point
+ ** and report database corruption if they were not, but this check has
+ ** since moved into the btree layer. */
+ u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO;
+ u.ay.pCur->isIndex = !u.ay.pCur->isTable;
+ break;
+}
+
+/* Opcode: OpenEphemeral P1 P2 * P4 P5
+**
+** Open a new cursor P1 to a transient table.
+** The cursor is always opened read/write even if
+** the main database is read-only. The ephemeral
+** table is deleted automatically when the cursor is closed.
+**
+** P2 is the number of columns in the ephemeral table.
+** The cursor points to a BTree table if P4==0 and to a BTree index
+** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
+** that defines the format of keys in the index.
+**
+** This opcode was once called OpenTemp. But that created
+** confusion because the term "temp table", might refer either
+** to a TEMP table at the SQL level, or to a table opened by
+** this opcode. Then this opcode was call OpenVirtual. But
+** that created confusion with the whole virtual-table idea.
+**
+** The P5 parameter can be a mask of the BTREE_* flags defined
+** in btree.h. These flags control aspects of the operation of
+** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
+** added automatically.
+*/
+/* Opcode: OpenAutoindex P1 P2 * P4 *
+**
+** This opcode works the same as OP_OpenEphemeral. It has a
+** different name to distinguish its use. Tables created using
+** by this opcode will be used for automatically created transient
+** indices in joins.
+*/
+case OP_OpenAutoindex:
+case OP_OpenEphemeral: {
+#if 0 /* local variables moved into u.az */
+ VdbeCursor *pCx;
+#endif /* local variables moved into u.az */
+ static const int vfsFlags =
+ SQLITE_OPEN_READWRITE |
+ SQLITE_OPEN_CREATE |
+ SQLITE_OPEN_EXCLUSIVE |
+ SQLITE_OPEN_DELETEONCLOSE |
+ SQLITE_OPEN_TRANSIENT_DB;
+
+ assert( pOp->p1>=0 );
+ u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( u.az.pCx==0 ) goto no_mem;
+ u.az.pCx->nullRow = 1;
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.az.pCx->pBt,
+ BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1);
+ }
+ if( rc==SQLITE_OK ){
+ /* If a transient index is required, create it by calling
+ ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
+ ** opening it. If a transient table is required, just use the
+ ** automatically created table with root-page 1 (an BLOB_INTKEY table).
+ */
+ if( pOp->p4.pKeyInfo ){
+ int pgno;
+ assert( pOp->p4type==P4_KEYINFO );
+ rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+ if( rc==SQLITE_OK ){
+ assert( pgno==MASTER_ROOT+1 );
+ rc = sqlite3BtreeCursor(u.az.pCx->pBt, pgno, 1,
+ (KeyInfo*)pOp->p4.z, u.az.pCx->pCursor);
+ u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+ u.az.pCx->pKeyInfo->enc = ENC(p->db);
+ }
+ u.az.pCx->isTable = 0;
+ }else{
+ rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor);
+ u.az.pCx->isTable = 1;
+ }
+ }
+ u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ u.az.pCx->isIndex = !u.az.pCx->isTable;
+ break;
+}
+
+/* Opcode: SorterOpen P1 P2 * P4 *
+**
+** This opcode works like OP_OpenEphemeral except that it opens
+** a transient index that is specifically designed to sort large
+** tables using an external merge-sort algorithm.
+*/
+case OP_SorterOpen: {
+#if 0 /* local variables moved into u.ba */
+ VdbeCursor *pCx;
+#endif /* local variables moved into u.ba */
+
+ u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( u.ba.pCx==0 ) goto no_mem;
+ u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+ u.ba.pCx->pKeyInfo->enc = ENC(p->db);
+ u.ba.pCx->isSorter = 1;
+ rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
+ break;
+}
+
+/* Opcode: OpenPseudo P1 P2 P3 * P5
+**
+** Open a new cursor that points to a fake table that contains a single
+** row of data. The content of that one row in the content of memory
+** register P2 when P5==0. In other words, cursor P1 becomes an alias for the
+** MEM_Blob content contained in register P2. When P5==1, then the
+** row is represented by P3 consecutive registers beginning with P2.
+**
+** A pseudo-table created by this opcode is used to hold a single
+** row output from the sorter so that the row can be decomposed into
+** individual columns using the OP_Column opcode. The OP_Column opcode
+** is the only cursor opcode that works with a pseudo-table.
+**
+** P3 is the number of fields in the records that will be stored by
+** the pseudo-table.
+*/
+case OP_OpenPseudo: {
+#if 0 /* local variables moved into u.bb */
+ VdbeCursor *pCx;
+#endif /* local variables moved into u.bb */
+
+ assert( pOp->p1>=0 );
+ u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+ if( u.bb.pCx==0 ) goto no_mem;
+ u.bb.pCx->nullRow = 1;
+ u.bb.pCx->pseudoTableReg = pOp->p2;
+ u.bb.pCx->isTable = 1;
+ u.bb.pCx->isIndex = 0;
+ u.bb.pCx->multiPseudo = pOp->p5;
+ break;
+}
+
+/* Opcode: Close P1 * * * *
+**
+** Close a cursor previously opened as P1. If P1 is not
+** currently open, this instruction is a no-op.
+*/
+case OP_Close: {
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
+ p->apCsr[pOp->p1] = 0;
+ break;
+}
+
+/* Opcode: SeekGe P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as the key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than or equal to the key value. If there are no records
+** greater than or equal to the key and P2 is not zero, then jump to P2.
+**
+** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
+*/
+/* Opcode: SeekGt P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than the key value. If there are no records greater than
+** the key and P2 is not zero, then jump to P2.
+**
+** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
+*/
+/* Opcode: SeekLt P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than the key value. If there are no records less than
+** the key and P2 is not zero, then jump to P2.
+**
+** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
+*/
+/* Opcode: SeekLe P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than or equal to the key value. If there are no records
+** less than or equal to the key and P2 is not zero, then jump to P2.
+**
+** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
+*/
+case OP_SeekLt: /* jump, in3 */
+case OP_SeekLe: /* jump, in3 */
+case OP_SeekGe: /* jump, in3 */
+case OP_SeekGt: { /* jump, in3 */
+#if 0 /* local variables moved into u.bc */
+ int res;
+ int oc;
+ VdbeCursor *pC;
+ UnpackedRecord r;
+ int nField;
+ i64 iKey; /* The rowid we are to seek to */
+#endif /* local variables moved into u.bc */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p2!=0 );
+ u.bc.pC = p->apCsr[pOp->p1];
+ assert( u.bc.pC!=0 );
+ assert( u.bc.pC->pseudoTableReg==0 );
+ assert( OP_SeekLe == OP_SeekLt+1 );
+ assert( OP_SeekGe == OP_SeekLt+2 );
+ assert( OP_SeekGt == OP_SeekLt+3 );
+ assert( u.bc.pC->isOrdered );
+ if( ALWAYS(u.bc.pC->pCursor!=0) ){
+ u.bc.oc = pOp->opcode;
+ u.bc.pC->nullRow = 0;
+ if( u.bc.pC->isTable ){
+ /* The input value in P3 might be of any type: integer, real, string,
+ ** blob, or NULL. But it needs to be an integer before we can do
+ ** the seek, so covert it. */
+ pIn3 = &aMem[pOp->p3];
+ applyNumericAffinity(pIn3);
+ u.bc.iKey = sqlite3VdbeIntValue(pIn3);
+ u.bc.pC->rowidIsValid = 0;
+
+ /* If the P3 value could not be converted into an integer without
+ ** loss of information, then special processing is required... */
+ if( (pIn3->flags & MEM_Int)==0 ){
+ if( (pIn3->flags & MEM_Real)==0 ){
+ /* If the P3 value cannot be converted into any kind of a number,
+ ** then the seek is not possible, so jump to P2 */
+ pc = pOp->p2 - 1;
+ break;
+ }
+ /* If we reach this point, then the P3 value must be a floating
+ ** point number. */
+ assert( (pIn3->flags & MEM_Real)!=0 );
+
+ if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){
+ /* The P3 value is too large in magnitude to be expressed as an
+ ** integer. */
+ u.bc.res = 1;
+ if( pIn3->r<0 ){
+ if( u.bc.oc>=OP_SeekGe ){ assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
+ rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ }
+ }else{
+ if( u.bc.oc<=OP_SeekLe ){ assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
+ rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ }
+ }
+ if( u.bc.res ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+ }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){
+ /* Use the ceiling() function to convert real->int */
+ if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++;
+ }else{
+ /* Use the floor() function to convert real->int */
+ assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt );
+ if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--;
+ }
+ }
+ rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ if( u.bc.res==0 ){
+ u.bc.pC->rowidIsValid = 1;
+ u.bc.pC->lastRowid = u.bc.iKey;
+ }
+ }else{
+ u.bc.nField = pOp->p4.i;
+ assert( pOp->p4type==P4_INT32 );
+ assert( u.bc.nField>0 );
+ u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
+ u.bc.r.nField = (u16)u.bc.nField;
+
+ /* The next line of code computes as follows, only faster:
+ ** if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){
+ ** u.bc.r.flags = UNPACKED_INCRKEY;
+ ** }else{
+ ** u.bc.r.flags = 0;
+ ** }
+ */
+ u.bc.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt)));
+ assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY );
+ assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY );
+ assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 );
+ assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 );
+
+ u.bc.r.aMem = &aMem[pOp->p3];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
+#endif
+ ExpandBlob(u.bc.r.aMem);
+ rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, &u.bc.r, 0, 0, &u.bc.res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ u.bc.pC->rowidIsValid = 0;
+ }
+ u.bc.pC->deferredMoveto = 0;
+ u.bc.pC->cacheStatus = CACHE_STALE;
+#ifdef SQLITE_TEST
+ sqlite3_search_count++;
+#endif
+ if( u.bc.oc>=OP_SeekGe ){ assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
+ if( u.bc.res<0 || (u.bc.res==0 && u.bc.oc==OP_SeekGt) ){
+ rc = sqlite3BtreeNext(u.bc.pC->pCursor, &u.bc.res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ u.bc.pC->rowidIsValid = 0;
+ }else{
+ u.bc.res = 0;
+ }
+ }else{
+ assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
+ if( u.bc.res>0 || (u.bc.res==0 && u.bc.oc==OP_SeekLt) ){
+ rc = sqlite3BtreePrevious(u.bc.pC->pCursor, &u.bc.res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ u.bc.pC->rowidIsValid = 0;
+ }else{
+ /* u.bc.res might be negative because the table is empty. Check to
+ ** see if this is the case.
+ */
+ u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor);
+ }
+ }
+ assert( pOp->p2>0 );
+ if( u.bc.res ){
+ pc = pOp->p2 - 1;
+ }
+ }else{
+ /* This happens when attempting to open the sqlite3_master table
+ ** for read access returns SQLITE_EMPTY. In this case always
+ ** take the jump (since there are no records in the table).
+ */
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: Seek P1 P2 * * *
+**
+** P1 is an open table cursor and P2 is a rowid integer. Arrange
+** for P1 to move so that it points to the rowid given by P2.
+**
+** This is actually a deferred seek. Nothing actually happens until
+** the cursor is used to read a record. That way, if no reads
+** occur, no unnecessary I/O happens.
+*/
+case OP_Seek: { /* in2 */
+#if 0 /* local variables moved into u.bd */
+ VdbeCursor *pC;
+#endif /* local variables moved into u.bd */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bd.pC = p->apCsr[pOp->p1];
+ assert( u.bd.pC!=0 );
+ if( ALWAYS(u.bd.pC->pCursor!=0) ){
+ assert( u.bd.pC->isTable );
+ u.bd.pC->nullRow = 0;
+ pIn2 = &aMem[pOp->p2];
+ u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+ u.bd.pC->rowidIsValid = 0;
+ u.bd.pC->deferredMoveto = 1;
+ }
+ break;
+}
+
+
+/* Opcode: Found P1 P2 P3 P4 *
+**
+** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
+** P4>0 then register P3 is the first of P4 registers that form an unpacked
+** record.
+**
+** Cursor P1 is on an index btree. If the record identified by P3 and P4
+** is a prefix of any entry in P1 then a jump is made to P2 and
+** P1 is left pointing at the matching entry.
+*/
+/* Opcode: NotFound P1 P2 P3 P4 *
+**
+** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
+** P4>0 then register P3 is the first of P4 registers that form an unpacked
+** record.
+**
+** Cursor P1 is on an index btree. If the record identified by P3 and P4
+** is not the prefix of any entry in P1 then a jump is made to P2. If P1
+** does contain an entry whose prefix matches the P3/P4 record then control
+** falls through to the next instruction and P1 is left pointing at the
+** matching entry.
+**
+** See also: Found, NotExists, IsUnique
+*/
+case OP_NotFound: /* jump, in3 */
+case OP_Found: { /* jump, in3 */
+#if 0 /* local variables moved into u.be */
+ int alreadyExists;
+ VdbeCursor *pC;
+ int res;
+ char *pFree;
+ UnpackedRecord *pIdxKey;
+ UnpackedRecord r;
+ char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
+#endif /* local variables moved into u.be */
+
+#ifdef SQLITE_TEST
+ sqlite3_found_count++;
+#endif
+
+ u.be.alreadyExists = 0;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p4type==P4_INT32 );
+ u.be.pC = p->apCsr[pOp->p1];
+ assert( u.be.pC!=0 );
+ pIn3 = &aMem[pOp->p3];
+ if( ALWAYS(u.be.pC->pCursor!=0) ){
+
+ assert( u.be.pC->isTable==0 );
+ if( pOp->p4.i>0 ){
+ u.be.r.pKeyInfo = u.be.pC->pKeyInfo;
+ u.be.r.nField = (u16)pOp->p4.i;
+ u.be.r.aMem = pIn3;
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<u.be.r.nField; i++) assert( memIsValid(&u.be.r.aMem[i]) ); }
+#endif
+ u.be.r.flags = UNPACKED_PREFIX_MATCH;
+ u.be.pIdxKey = &u.be.r;
+ }else{
+ u.be.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+ u.be.pC->pKeyInfo, u.be.aTempRec, sizeof(u.be.aTempRec), &u.be.pFree
+ );
+ if( u.be.pIdxKey==0 ) goto no_mem;
+ assert( pIn3->flags & MEM_Blob );
+ assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
+ sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z, u.be.pIdxKey);
+ u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+ }
+ rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res);
+ if( pOp->p4.i==0 ){
+ sqlite3DbFree(db, u.be.pFree);
+ }
+ if( rc!=SQLITE_OK ){
+ break;
+ }
+ u.be.alreadyExists = (u.be.res==0);
+ u.be.pC->deferredMoveto = 0;
+ u.be.pC->cacheStatus = CACHE_STALE;
+ }
+ if( pOp->opcode==OP_Found ){
+ if( u.be.alreadyExists ) pc = pOp->p2 - 1;
+ }else{
+ if( !u.be.alreadyExists ) pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: IsUnique P1 P2 P3 P4 *
+**
+** Cursor P1 is open on an index b-tree - that is to say, a btree which
+** no data and where the key are records generated by OP_MakeRecord with
+** the list field being the integer ROWID of the entry that the index
+** entry refers to.
+**
+** The P3 register contains an integer record number. Call this record
+** number R. Register P4 is the first in a set of N contiguous registers
+** that make up an unpacked index key that can be used with cursor P1.
+** The value of N can be inferred from the cursor. N includes the rowid
+** value appended to the end of the index record. This rowid value may
+** or may not be the same as R.
+**
+** If any of the N registers beginning with register P4 contains a NULL
+** value, jump immediately to P2.
+**
+** Otherwise, this instruction checks if cursor P1 contains an entry
+** where the first (N-1) fields match but the rowid value at the end
+** of the index entry is not R. If there is no such entry, control jumps
+** to instruction P2. Otherwise, the rowid of the conflicting index
+** entry is copied to register P3 and control falls through to the next
+** instruction.
+**
+** See also: NotFound, NotExists, Found
+*/
+case OP_IsUnique: { /* jump, in3 */
+#if 0 /* local variables moved into u.bf */
+ u16 ii;
+ VdbeCursor *pCx;
+ BtCursor *pCrsr;
+ u16 nField;
+ Mem *aMx;
+ UnpackedRecord r; /* B-Tree index search key */
+ i64 R; /* Rowid stored in register P3 */
+#endif /* local variables moved into u.bf */
+
+ pIn3 = &aMem[pOp->p3];
+ u.bf.aMx = &aMem[pOp->p4.i];
+ /* Assert that the values of parameters P1 and P4 are in range. */
+ assert( pOp->p4type==P4_INT32 );
+ assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+
+ /* Find the index cursor. */
+ u.bf.pCx = p->apCsr[pOp->p1];
+ assert( u.bf.pCx->deferredMoveto==0 );
+ u.bf.pCx->seekResult = 0;
+ u.bf.pCx->cacheStatus = CACHE_STALE;
+ u.bf.pCrsr = u.bf.pCx->pCursor;
+
+ /* If any of the values are NULL, take the jump. */
+ u.bf.nField = u.bf.pCx->pKeyInfo->nField;
+ for(u.bf.ii=0; u.bf.ii<u.bf.nField; u.bf.ii++){
+ if( u.bf.aMx[u.bf.ii].flags & MEM_Null ){
+ pc = pOp->p2 - 1;
+ u.bf.pCrsr = 0;
+ break;
+ }
+ }
+ assert( (u.bf.aMx[u.bf.nField].flags & MEM_Null)==0 );
+
+ if( u.bf.pCrsr!=0 ){
+ /* Populate the index search key. */
+ u.bf.r.pKeyInfo = u.bf.pCx->pKeyInfo;
+ u.bf.r.nField = u.bf.nField + 1;
+ u.bf.r.flags = UNPACKED_PREFIX_SEARCH;
+ u.bf.r.aMem = u.bf.aMx;
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<u.bf.r.nField; i++) assert( memIsValid(&u.bf.r.aMem[i]) ); }
+#endif
+
+ /* Extract the value of u.bf.R from register P3. */
+ sqlite3VdbeMemIntegerify(pIn3);
+ u.bf.R = pIn3->u.i;
+
+ /* Search the B-Tree index. If no conflicting record is found, jump
+ ** to P2. Otherwise, copy the rowid of the conflicting record to
+ ** register P3 and fall through to the next instruction. */
+ rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, &u.bf.r, 0, 0, &u.bf.pCx->seekResult);
+ if( (u.bf.r.flags & UNPACKED_PREFIX_SEARCH) || u.bf.r.rowid==u.bf.R ){
+ pc = pOp->p2 - 1;
+ }else{
+ pIn3->u.i = u.bf.r.rowid;
+ }
+ }
+ break;
+}
+
+/* Opcode: NotExists P1 P2 P3 * *
+**
+** Use the content of register P3 as an integer key. If a record
+** with that key does not exist in table of P1, then jump to P2.
+** If the record does exist, then fall through. The cursor is left
+** pointing to the record if it exists.
+**
+** The difference between this operation and NotFound is that this
+** operation assumes the key is an integer and that P1 is a table whereas
+** NotFound assumes key is a blob constructed from MakeRecord and
+** P1 is an index.
+**
+** See also: Found, NotFound, IsUnique
+*/
+case OP_NotExists: { /* jump, in3 */
+#if 0 /* local variables moved into u.bg */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ u64 iKey;
+#endif /* local variables moved into u.bg */
+
+ pIn3 = &aMem[pOp->p3];
+ assert( pIn3->flags & MEM_Int );
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bg.pC = p->apCsr[pOp->p1];
+ assert( u.bg.pC!=0 );
+ assert( u.bg.pC->isTable );
+ assert( u.bg.pC->pseudoTableReg==0 );
+ u.bg.pCrsr = u.bg.pC->pCursor;
+ if( ALWAYS(u.bg.pCrsr!=0) ){
+ u.bg.res = 0;
+ u.bg.iKey = pIn3->u.i;
+ rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
+ u.bg.pC->lastRowid = pIn3->u.i;
+ u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
+ u.bg.pC->nullRow = 0;
+ u.bg.pC->cacheStatus = CACHE_STALE;
+ u.bg.pC->deferredMoveto = 0;
+ if( u.bg.res!=0 ){
+ pc = pOp->p2 - 1;
+ assert( u.bg.pC->rowidIsValid==0 );
+ }
+ u.bg.pC->seekResult = u.bg.res;
+ }else{
+ /* This happens when an attempt to open a read cursor on the
+ ** sqlite_master table returns SQLITE_EMPTY.
+ */
+ pc = pOp->p2 - 1;
+ assert( u.bg.pC->rowidIsValid==0 );
+ u.bg.pC->seekResult = 0;
+ }
+ break;
+}
+
+/* Opcode: Sequence P1 P2 * * *
+**
+** Find the next available sequence number for cursor P1.
+** Write the sequence number into register P2.
+** The sequence number on the cursor is incremented after this
+** instruction.
+*/
+case OP_Sequence: { /* out2-prerelease */
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( p->apCsr[pOp->p1]!=0 );
+ pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
+ break;
+}
+
+
+/* Opcode: NewRowid P1 P2 P3 * *
+**
+** Get a new integer record number (a.k.a "rowid") used as the key to a table.
+** The record number is not previously used as a key in the database
+** table that cursor P1 points to. The new record number is written
+** written to register P2.
+**
+** If P3>0 then P3 is a register in the root frame of this VDBE that holds
+** the largest previously generated record number. No new record numbers are
+** allowed to be less than this value. When this value reaches its maximum,
+** an SQLITE_FULL error is generated. The P3 register is updated with the '
+** generated record number. This P3 mechanism is used to help implement the
+** AUTOINCREMENT feature.
+*/
+case OP_NewRowid: { /* out2-prerelease */
+#if 0 /* local variables moved into u.bh */
+ i64 v; /* The new rowid */
+ VdbeCursor *pC; /* Cursor of table to get the new rowid */
+ int res; /* Result of an sqlite3BtreeLast() */
+ int cnt; /* Counter to limit the number of searches */
+ Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
+ VdbeFrame *pFrame; /* Root frame of VDBE */
+#endif /* local variables moved into u.bh */
+
+ u.bh.v = 0;
+ u.bh.res = 0;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bh.pC = p->apCsr[pOp->p1];
+ assert( u.bh.pC!=0 );
+ if( NEVER(u.bh.pC->pCursor==0) ){
+ /* The zero initialization above is all that is needed */
+ }else{
+ /* The next rowid or record number (different terms for the same
+ ** thing) is obtained in a two-step algorithm.
+ **
+ ** First we attempt to find the largest existing rowid and add one
+ ** to that. But if the largest existing rowid is already the maximum
+ ** positive integer, we have to fall through to the second
+ ** probabilistic algorithm
+ **
+ ** The second algorithm is to select a rowid at random and see if
+ ** it already exists in the table. If it does not exist, we have
+ ** succeeded. If the random rowid does exist, we select a new one
+ ** and try again, up to 100 times.
+ */
+ assert( u.bh.pC->isTable );
+
+#ifdef SQLITE_32BIT_ROWID
+# define MAX_ROWID 0x7fffffff
+#else
+ /* Some compilers complain about constants of the form 0x7fffffffffffffff.
+ ** Others complain about 0x7ffffffffffffffffLL. The following macro seems
+ ** to provide the constant while making all compilers happy.
+ */
+# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
+#endif
+
+ if( !u.bh.pC->useRandomRowid ){
+ u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor);
+ if( u.bh.v==0 ){
+ rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ if( u.bh.res ){
+ u.bh.v = 1; /* IMP: R-61914-48074 */
+ }else{
+ assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) );
+ rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v);
+ assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
+ if( u.bh.v>=MAX_ROWID ){
+ u.bh.pC->useRandomRowid = 1;
+ }else{
+ u.bh.v++; /* IMP: R-29538-34987 */
+ }
+ }
+ }
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( pOp->p3 ){
+ /* Assert that P3 is a valid memory cell. */
+ assert( pOp->p3>0 );
+ if( p->pFrame ){
+ for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent);
+ /* Assert that P3 is a valid memory cell. */
+ assert( pOp->p3<=u.bh.pFrame->nMem );
+ u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
+ }else{
+ /* Assert that P3 is a valid memory cell. */
+ assert( pOp->p3<=p->nMem );
+ u.bh.pMem = &aMem[pOp->p3];
+ memAboutToChange(p, u.bh.pMem);
+ }
+ assert( memIsValid(u.bh.pMem) );
+
+ REGISTER_TRACE(pOp->p3, u.bh.pMem);
+ sqlite3VdbeMemIntegerify(u.bh.pMem);
+ assert( (u.bh.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
+ if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){
+ rc = SQLITE_FULL; /* IMP: R-12275-61338 */
+ goto abort_due_to_error;
+ }
+ if( u.bh.v<u.bh.pMem->u.i+1 ){
+ u.bh.v = u.bh.pMem->u.i + 1;
+ }
+ u.bh.pMem->u.i = u.bh.v;
+ }
+#endif
+
+ sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.v<MAX_ROWID ? u.bh.v+1 : 0);
+ }
+ if( u.bh.pC->useRandomRowid ){
+ /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
+ ** largest possible integer (9223372036854775807) then the database
+ ** engine starts picking positive candidate ROWIDs at random until
+ ** it finds one that is not previously used. */
+ assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
+ ** an AUTOINCREMENT table. */
+ /* on the first attempt, simply do one more than previous */
+ u.bh.v = lastRowid;
+ u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+ u.bh.v++; /* ensure non-zero */
+ u.bh.cnt = 0;
+ while( ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v,
+ 0, &u.bh.res))==SQLITE_OK)
+ && (u.bh.res==0)
+ && (++u.bh.cnt<100)){
+ /* collision - try another random rowid */
+ sqlite3_randomness(sizeof(u.bh.v), &u.bh.v);
+ if( u.bh.cnt<5 ){
+ /* try "small" random rowids for the initial attempts */
+ u.bh.v &= 0xffffff;
+ }else{
+ u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+ }
+ u.bh.v++; /* ensure non-zero */
+ }
+ if( rc==SQLITE_OK && u.bh.res==0 ){
+ rc = SQLITE_FULL; /* IMP: R-38219-53002 */
+ goto abort_due_to_error;
+ }
+ assert( u.bh.v>0 ); /* EV: R-40812-03570 */
+ }
+ u.bh.pC->rowidIsValid = 0;
+ u.bh.pC->deferredMoveto = 0;
+ u.bh.pC->cacheStatus = CACHE_STALE;
+ }
+ pOut->u.i = u.bh.v;
+ break;
+}
+
+/* Opcode: Insert P1 P2 P3 P4 P5
+**
+** Write an entry into the table of cursor P1. A new entry is
+** created if it doesn't already exist or the data for an existing
+** entry is overwritten. The data is the value MEM_Blob stored in register
+** number P2. The key is stored in register P3. The key must
+** be a MEM_Int.
+**
+** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
+** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set,
+** then rowid is stored for subsequent return by the
+** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
+**
+** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
+** the last seek operation (OP_NotExists) was a success, then this
+** operation will not attempt to find the appropriate row before doing
+** the insert but will instead overwrite the row that the cursor is
+** currently pointing to. Presumably, the prior OP_NotExists opcode
+** has already positioned the cursor correctly. This is an optimization
+** that boosts performance by avoiding redundant seeks.
+**
+** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
+** UPDATE operation. Otherwise (if the flag is clear) then this opcode
+** is part of an INSERT operation. The difference is only important to
+** the update hook.
+**
+** Parameter P4 may point to a string containing the table-name, or
+** may be NULL. If it is not NULL, then the update-hook
+** (sqlite3.xUpdateCallback) is invoked following a successful insert.
+**
+** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
+** allocated, then ownership of P2 is transferred to the pseudo-cursor
+** and register P2 becomes ephemeral. If the cursor is changed, the
+** value of register P2 will then change. Make sure this does not
+** cause any problems.)
+**
+** This instruction only works on tables. The equivalent instruction
+** for indices is OP_IdxInsert.
+*/
+/* Opcode: InsertInt P1 P2 P3 P4 P5
+**
+** This works exactly like OP_Insert except that the key is the
+** integer value P3, not the value of the integer stored in register P3.
+*/
+case OP_Insert:
+case OP_InsertInt: {
+#if 0 /* local variables moved into u.bi */
+ Mem *pData; /* MEM cell holding data for the record to be inserted */
+ Mem *pKey; /* MEM cell holding key for the record */
+ i64 iKey; /* The integer ROWID or key for the record to be inserted */
+ VdbeCursor *pC; /* Cursor to table into which insert is written */
+ int nZero; /* Number of zero-bytes to append */
+ int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
+ const char *zDb; /* database name - used by the update hook */
+ const char *zTbl; /* Table name - used by the opdate hook */
+ int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
+#endif /* local variables moved into u.bi */
+
+ u.bi.pData = &aMem[pOp->p2];
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( memIsValid(u.bi.pData) );
+ u.bi.pC = p->apCsr[pOp->p1];
+ assert( u.bi.pC!=0 );
+ assert( u.bi.pC->pCursor!=0 );
+ assert( u.bi.pC->pseudoTableReg==0 );
+ assert( u.bi.pC->isTable );
+ REGISTER_TRACE(pOp->p2, u.bi.pData);
+
+ if( pOp->opcode==OP_Insert ){
+ u.bi.pKey = &aMem[pOp->p3];
+ assert( u.bi.pKey->flags & MEM_Int );
+ assert( memIsValid(u.bi.pKey) );
+ REGISTER_TRACE(pOp->p3, u.bi.pKey);
+ u.bi.iKey = u.bi.pKey->u.i;
+ }else{
+ assert( pOp->opcode==OP_InsertInt );
+ u.bi.iKey = pOp->p3;
+ }
+
+ if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey;
+ if( u.bi.pData->flags & MEM_Null ){
+ u.bi.pData->z = 0;
+ u.bi.pData->n = 0;
+ }else{
+ assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) );
+ }
+ u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0);
+ if( u.bi.pData->flags & MEM_Zero ){
+ u.bi.nZero = u.bi.pData->u.nZero;
+ }else{
+ u.bi.nZero = 0;
+ }
+ sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
+ rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey,
+ u.bi.pData->z, u.bi.pData->n, u.bi.nZero,
+ pOp->p5 & OPFLAG_APPEND, u.bi.seekResult
+ );
+ u.bi.pC->rowidIsValid = 0;
+ u.bi.pC->deferredMoveto = 0;
+ u.bi.pC->cacheStatus = CACHE_STALE;
+
+ /* Invoke the update-hook if required. */
+ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
+ u.bi.zDb = db->aDb[u.bi.pC->iDb].zName;
+ u.bi.zTbl = pOp->p4.z;
+ u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+ assert( u.bi.pC->isTable );
+ db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey);
+ assert( u.bi.pC->iDb>=0 );
+ }
+ break;
+}
+
+/* Opcode: Delete P1 P2 * P4 *
+**
+** Delete the record at which the P1 cursor is currently pointing.
+**
+** The cursor will be left pointing at either the next or the previous
+** record in the table. If it is left pointing at the next record, then
+** the next Next instruction will be a no-op. Hence it is OK to delete
+** a record from within an Next loop.
+**
+** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
+** incremented (otherwise not).
+**
+** P1 must not be pseudo-table. It has to be a real table with
+** multiple rows.
+**
+** If P4 is not NULL, then it is the name of the table that P1 is
+** pointing to. The update hook will be invoked, if it exists.
+** If P4 is not NULL then the P1 cursor must have been positioned
+** using OP_NotFound prior to invoking this opcode.
+*/
+case OP_Delete: {
+#if 0 /* local variables moved into u.bj */
+ i64 iKey;
+ VdbeCursor *pC;
+#endif /* local variables moved into u.bj */
+
+ u.bj.iKey = 0;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bj.pC = p->apCsr[pOp->p1];
+ assert( u.bj.pC!=0 );
+ assert( u.bj.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
+
+ /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the
+ ** row being deleted.
+ */
+ if( db->xUpdateCallback && pOp->p4.z ){
+ assert( u.bj.pC->isTable );
+ assert( u.bj.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
+ u.bj.iKey = u.bj.pC->lastRowid;
+ }
+
+ /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
+ ** OP_Column on the same table without any intervening operations that
+ ** might move or invalidate the cursor. Hence cursor u.bj.pC is always pointing
+ ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
+ ** below is always a no-op and cannot fail. We will run it anyhow, though,
+ ** to guard against future changes to the code generator.
+ **/
+ assert( u.bj.pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(u.bj.pC);
+ if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
+
+ sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0);
+ rc = sqlite3BtreeDelete(u.bj.pC->pCursor);
+ u.bj.pC->cacheStatus = CACHE_STALE;
+
+ /* Invoke the update-hook if required. */
+ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
+ const char *zDb = db->aDb[u.bj.pC->iDb].zName;
+ const char *zTbl = pOp->p4.z;
+ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey);
+ assert( u.bj.pC->iDb>=0 );
+ }
+ if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
+ break;
+}
+/* Opcode: ResetCount * * * * *
+**
+** The value of the change counter is copied to the database handle
+** change counter (returned by subsequent calls to sqlite3_changes()).
+** Then the VMs internal change counter resets to 0.
+** This is used by trigger programs.
+*/
+case OP_ResetCount: {
+ sqlite3VdbeSetChanges(db, p->nChange);
+ p->nChange = 0;
+ break;
+}
+
+/* Opcode: SorterCompare P1 P2 P3
+**
+** P1 is a sorter cursor. This instruction compares the record blob in
+** register P3 with the entry that the sorter cursor currently points to.
+** If, excluding the rowid fields at the end, the two records are a match,
+** fall through to the next instruction. Otherwise, jump to instruction P2.
+*/
+case OP_SorterCompare: {
+#if 0 /* local variables moved into u.bk */
+ VdbeCursor *pC;
+ int res;
+#endif /* local variables moved into u.bk */
+
+ u.bk.pC = p->apCsr[pOp->p1];
+ assert( isSorter(u.bk.pC) );
+ pIn3 = &aMem[pOp->p3];
+ rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, &u.bk.res);
+ if( u.bk.res ){
+ pc = pOp->p2-1;
+ }
+ break;
+};
+
+/* Opcode: SorterData P1 P2 * * *
+**
+** Write into register P2 the current sorter data for sorter cursor P1.
+*/
+case OP_SorterData: {
+#if 0 /* local variables moved into u.bl */
+ VdbeCursor *pC;
+#endif /* local variables moved into u.bl */
+
+ pOut = &aMem[pOp->p2];
+ u.bl.pC = p->apCsr[pOp->p1];
+ assert( u.bl.pC->isSorter );
+ rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
+ break;
+}
+
+/* Opcode: RowData P1 P2 * * *
+**
+** Write into register P2 the complete row data for cursor P1.
+** There is no interpretation of the data.
+** It is just copied onto the P2 register exactly as
+** it is found in the database file.
+**
+** If the P1 cursor must be pointing to a valid row (not a NULL row)
+** of a real table, not a pseudo-table.
+*/
+/* Opcode: RowKey P1 P2 * * *
+**
+** Write into register P2 the complete row key for cursor P1.
+** There is no interpretation of the data.
+** The key is copied onto the P3 register exactly as
+** it is found in the database file.
+**
+** If the P1 cursor must be pointing to a valid row (not a NULL row)
+** of a real table, not a pseudo-table.
+*/
+case OP_RowKey:
+case OP_RowData: {
+#if 0 /* local variables moved into u.bm */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ u32 n;
+ i64 n64;
+#endif /* local variables moved into u.bm */
+
+ pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
+
+ /* Note that RowKey and RowData are really exactly the same instruction */
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bm.pC = p->apCsr[pOp->p1];
+ assert( u.bm.pC->isSorter==0 );
+ assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData );
+ assert( u.bm.pC->isIndex || pOp->opcode==OP_RowData );
+ assert( u.bm.pC!=0 );
+ assert( u.bm.pC->nullRow==0 );
+ assert( u.bm.pC->pseudoTableReg==0 );
+ assert( u.bm.pC->pCursor!=0 );
+ u.bm.pCrsr = u.bm.pC->pCursor;
+ assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) );
+
+ /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
+ ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
+ ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always
+ ** a no-op and can never fail. But we leave it in place as a safety.
+ */
+ assert( u.bm.pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(u.bm.pC);
+ if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
+
+ if( u.bm.pC->isIndex ){
+ assert( !u.bm.pC->isTable );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64);
+ assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
+ if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+ u.bm.n = (u32)u.bm.n64;
+ }else{
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n);
+ assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
+ if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+ }
+ if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){
+ goto no_mem;
+ }
+ pOut->n = u.bm.n;
+ MemSetTypeFlag(pOut, MEM_Blob);
+ if( u.bm.pC->isIndex ){
+ rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z);
+ }else{
+ rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z);
+ }
+ pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: Rowid P1 P2 * * *
+**
+** Store in register P2 an integer which is the key of the table entry that
+** P1 is currently point to.
+**
+** P1 can be either an ordinary table or a virtual table. There used to
+** be a separate OP_VRowid opcode for use with virtual tables, but this
+** one opcode now works for both table types.
+*/
+case OP_Rowid: { /* out2-prerelease */
+#if 0 /* local variables moved into u.bn */
+ VdbeCursor *pC;
+ i64 v;
+ sqlite3_vtab *pVtab;
+ const sqlite3_module *pModule;
+#endif /* local variables moved into u.bn */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bn.pC = p->apCsr[pOp->p1];
+ assert( u.bn.pC!=0 );
+ assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow );
+ if( u.bn.pC->nullRow ){
+ pOut->flags = MEM_Null;
+ break;
+ }else if( u.bn.pC->deferredMoveto ){
+ u.bn.v = u.bn.pC->movetoTarget;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ }else if( u.bn.pC->pVtabCursor ){
+ u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab;
+ u.bn.pModule = u.bn.pVtab->pModule;
+ assert( u.bn.pModule->xRowid );
+ rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
+ importVtabErrMsg(p, u.bn.pVtab);
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+ }else{
+ assert( u.bn.pC->pCursor!=0 );
+ rc = sqlite3VdbeCursorMoveto(u.bn.pC);
+ if( rc ) goto abort_due_to_error;
+ if( u.bn.pC->rowidIsValid ){
+ u.bn.v = u.bn.pC->lastRowid;
+ }else{
+ rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v);
+ assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */
+ }
+ }
+ pOut->u.i = u.bn.v;
+ break;
+}
+
+/* Opcode: NullRow P1 * * * *
+**
+** Move the cursor P1 to a null row. Any OP_Column operations
+** that occur while the cursor is on the null row will always
+** write a NULL.
+*/
+case OP_NullRow: {
+#if 0 /* local variables moved into u.bo */
+ VdbeCursor *pC;
+#endif /* local variables moved into u.bo */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bo.pC = p->apCsr[pOp->p1];
+ assert( u.bo.pC!=0 );
+ u.bo.pC->nullRow = 1;
+ u.bo.pC->rowidIsValid = 0;
+ assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor );
+ if( u.bo.pC->pCursor ){
+ sqlite3BtreeClearCursor(u.bo.pC->pCursor);
+ }
+ break;
+}
+
+/* Opcode: Last P1 P2 * * *
+**
+** The next use of the Rowid or Column or Next instruction for P1
+** will refer to the last entry in the database table or index.
+** If the table or index is empty and P2>0, then jump immediately to P2.
+** If P2 is 0 or if the table or index is not empty, fall through
+** to the following instruction.
+*/
+case OP_Last: { /* jump */
+#if 0 /* local variables moved into u.bp */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+#endif /* local variables moved into u.bp */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bp.pC = p->apCsr[pOp->p1];
+ assert( u.bp.pC!=0 );
+ u.bp.pCrsr = u.bp.pC->pCursor;
+ u.bp.res = 0;
+ if( ALWAYS(u.bp.pCrsr!=0) ){
+ rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
+ }
+ u.bp.pC->nullRow = (u8)u.bp.res;
+ u.bp.pC->deferredMoveto = 0;
+ u.bp.pC->rowidIsValid = 0;
+ u.bp.pC->cacheStatus = CACHE_STALE;
+ if( pOp->p2>0 && u.bp.res ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+
+/* Opcode: Sort P1 P2 * * *
+**
+** This opcode does exactly the same thing as OP_Rewind except that
+** it increments an undocumented global variable used for testing.
+**
+** Sorting is accomplished by writing records into a sorting index,
+** then rewinding that index and playing it back from beginning to
+** end. We use the OP_Sort opcode instead of OP_Rewind to do the
+** rewinding so that the global variable will be incremented and
+** regression tests can determine whether or not the optimizer is
+** correctly optimizing out sorts.
+*/
+case OP_SorterSort: /* jump */
+case OP_Sort: { /* jump */
+#ifdef SQLITE_TEST
+ sqlite3_sort_count++;
+ sqlite3_search_count--;
+#endif
+ p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
+ /* Fall through into OP_Rewind */
+}
+/* Opcode: Rewind P1 P2 * * *
+**
+** The next use of the Rowid or Column or Next instruction for P1
+** will refer to the first entry in the database table or index.
+** If the table or index is empty and P2>0, then jump immediately to P2.
+** If P2 is 0 or if the table or index is not empty, fall through
+** to the following instruction.
+*/
+case OP_Rewind: { /* jump */
+#if 0 /* local variables moved into u.bq */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+#endif /* local variables moved into u.bq */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bq.pC = p->apCsr[pOp->p1];
+ assert( u.bq.pC!=0 );
+ assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterSort) );
+ u.bq.res = 1;
+ if( isSorter(u.bq.pC) ){
+ rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res);
+ }else{
+ u.bq.pCrsr = u.bq.pC->pCursor;
+ assert( u.bq.pCrsr );
+ rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res);
+ u.bq.pC->atFirst = u.bq.res==0 ?1:0;
+ u.bq.pC->deferredMoveto = 0;
+ u.bq.pC->cacheStatus = CACHE_STALE;
+ u.bq.pC->rowidIsValid = 0;
+ }
+ u.bq.pC->nullRow = (u8)u.bq.res;
+ assert( pOp->p2>0 && pOp->p2<p->nOp );
+ if( u.bq.res ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: Next P1 P2 * P4 P5
+**
+** Advance cursor P1 so that it points to the next key/data pair in its
+** table or index. If there are no more key/value pairs then fall through
+** to the following instruction. But if the cursor advance was successful,
+** jump immediately to P2.
+**
+** The P1 cursor must be for a real table, not a pseudo-table.
+**
+** P4 is always of type P4_ADVANCE. The function pointer points to
+** sqlite3BtreeNext().
+**
+** If P5 is positive and the jump is taken, then event counter
+** number P5-1 in the prepared statement is incremented.
+**
+** See also: Prev
+*/
+/* Opcode: Prev P1 P2 * * P5
+**
+** Back up cursor P1 so that it points to the previous key/data pair in its
+** table or index. If there is no previous key/value pairs then fall through
+** to the following instruction. But if the cursor backup was successful,
+** jump immediately to P2.
+**
+** The P1 cursor must be for a real table, not a pseudo-table.
+**
+** P4 is always of type P4_ADVANCE. The function pointer points to
+** sqlite3BtreePrevious().
+**
+** If P5 is positive and the jump is taken, then event counter
+** number P5-1 in the prepared statement is incremented.
+*/
+case OP_SorterNext: /* jump */
+case OP_Prev: /* jump */
+case OP_Next: { /* jump */
+#if 0 /* local variables moved into u.br */
+ VdbeCursor *pC;
+ int res;
+#endif /* local variables moved into u.br */
+
+ CHECK_FOR_INTERRUPT;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p5<=ArraySize(p->aCounter) );
+ u.br.pC = p->apCsr[pOp->p1];
+ if( u.br.pC==0 ){
+ break; /* See ticket #2273 */
+ }
+ assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
+ if( isSorter(u.br.pC) ){
+ assert( pOp->opcode==OP_SorterNext );
+ rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
+ }else{
+ u.br.res = 1;
+ assert( u.br.pC->deferredMoveto==0 );
+ assert( u.br.pC->pCursor );
+ assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
+ assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
+ rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
+ }
+ u.br.pC->nullRow = (u8)u.br.res;
+ u.br.pC->cacheStatus = CACHE_STALE;
+ if( u.br.res==0 ){
+ pc = pOp->p2 - 1;
+ if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
+#ifdef SQLITE_TEST
+ sqlite3_search_count++;
+#endif
+ }
+ u.br.pC->rowidIsValid = 0;
+ break;
+}
+
+/* Opcode: IdxInsert P1 P2 P3 * P5
+**
+** Register P2 holds an SQL index key made using the
+** MakeRecord instructions. This opcode writes that key
+** into the index P1. Data for the entry is nil.
+**
+** P3 is a flag that provides a hint to the b-tree layer that this
+** insert is likely to be an append.
+**
+** This instruction only works for indices. The equivalent instruction
+** for tables is OP_Insert.
+*/
+case OP_SorterInsert: /* in2 */
+case OP_IdxInsert: { /* in2 */
+#if 0 /* local variables moved into u.bs */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int nKey;
+ const char *zKey;
+#endif /* local variables moved into u.bs */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bs.pC = p->apCsr[pOp->p1];
+ assert( u.bs.pC!=0 );
+ assert( u.bs.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
+ pIn2 = &aMem[pOp->p2];
+ assert( pIn2->flags & MEM_Blob );
+ u.bs.pCrsr = u.bs.pC->pCursor;
+ if( ALWAYS(u.bs.pCrsr!=0) ){
+ assert( u.bs.pC->isTable==0 );
+ rc = ExpandBlob(pIn2);
+ if( rc==SQLITE_OK ){
+ if( isSorter(u.bs.pC) ){
+ rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
+ }else{
+ u.bs.nKey = pIn2->n;
+ u.bs.zKey = pIn2->z;
+ rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
+ );
+ assert( u.bs.pC->deferredMoveto==0 );
+ u.bs.pC->cacheStatus = CACHE_STALE;
+ }
+ }
+ }
+ break;
+}
+
+/* Opcode: IdxDelete P1 P2 P3 * *
+**
+** The content of P3 registers starting at register P2 form
+** an unpacked index key. This opcode removes that entry from the
+** index opened by cursor P1.
+*/
+case OP_IdxDelete: {
+#if 0 /* local variables moved into u.bt */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ UnpackedRecord r;
+#endif /* local variables moved into u.bt */
+
+ assert( pOp->p3>0 );
+ assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bt.pC = p->apCsr[pOp->p1];
+ assert( u.bt.pC!=0 );
+ u.bt.pCrsr = u.bt.pC->pCursor;
+ if( ALWAYS(u.bt.pCrsr!=0) ){
+ u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
+ u.bt.r.nField = (u16)pOp->p3;
+ u.bt.r.flags = 0;
+ u.bt.r.aMem = &aMem[pOp->p2];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
+#endif
+ rc = sqlite3BtreeMovetoUnpacked(u.bt.pCrsr, &u.bt.r, 0, 0, &u.bt.res);
+ if( rc==SQLITE_OK && u.bt.res==0 ){
+ rc = sqlite3BtreeDelete(u.bt.pCrsr);
+ }
+ assert( u.bt.pC->deferredMoveto==0 );
+ u.bt.pC->cacheStatus = CACHE_STALE;
+ }
+ break;
+}
+
+/* Opcode: IdxRowid P1 P2 * * *
+**
+** Write into register P2 an integer which is the last entry in the record at
+** the end of the index key pointed to by cursor P1. This integer should be
+** the rowid of the table entry to which this index entry points.
+**
+** See also: Rowid, MakeRecord.
+*/
+case OP_IdxRowid: { /* out2-prerelease */
+#if 0 /* local variables moved into u.bu */
+ BtCursor *pCrsr;
+ VdbeCursor *pC;
+ i64 rowid;
+#endif /* local variables moved into u.bu */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bu.pC = p->apCsr[pOp->p1];
+ assert( u.bu.pC!=0 );
+ u.bu.pCrsr = u.bu.pC->pCursor;
+ pOut->flags = MEM_Null;
+ if( ALWAYS(u.bu.pCrsr!=0) ){
+ rc = sqlite3VdbeCursorMoveto(u.bu.pC);
+ if( NEVER(rc) ) goto abort_due_to_error;
+ assert( u.bu.pC->deferredMoveto==0 );
+ assert( u.bu.pC->isTable==0 );
+ if( !u.bu.pC->nullRow ){
+ rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ pOut->u.i = u.bu.rowid;
+ pOut->flags = MEM_Int;
+ }
+ }
+ break;
+}
+
+/* Opcode: IdxGE P1 P2 P3 P4 P5
+**
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
+** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+**
+** If the P1 index entry is greater than or equal to the key value
+** then jump to P2. Otherwise fall through to the next instruction.
+**
+** If P5 is non-zero then the key value is increased by an epsilon
+** prior to the comparison. This make the opcode work like IdxGT except
+** that if the key from register P3 is a prefix of the key in the cursor,
+** the result is false whereas it would be true with IdxGT.
+*/
+/* Opcode: IdxLT P1 P2 P3 P4 P5
+**
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
+** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+**
+** If the P1 index entry is less than the key value then jump to P2.
+** Otherwise fall through to the next instruction.
+**
+** If P5 is non-zero then the key value is increased by an epsilon prior
+** to the comparison. This makes the opcode work like IdxLE.
+*/
+case OP_IdxLT: /* jump */
+case OP_IdxGE: { /* jump */
+#if 0 /* local variables moved into u.bv */
+ VdbeCursor *pC;
+ int res;
+ UnpackedRecord r;
+#endif /* local variables moved into u.bv */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bv.pC = p->apCsr[pOp->p1];
+ assert( u.bv.pC!=0 );
+ assert( u.bv.pC->isOrdered );
+ if( ALWAYS(u.bv.pC->pCursor!=0) ){
+ assert( u.bv.pC->deferredMoveto==0 );
+ assert( pOp->p5==0 || pOp->p5==1 );
+ assert( pOp->p4type==P4_INT32 );
+ u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
+ u.bv.r.nField = (u16)pOp->p4.i;
+ if( pOp->p5 ){
+ u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
+ }else{
+ u.bv.r.flags = UNPACKED_PREFIX_MATCH;
+ }
+ u.bv.r.aMem = &aMem[pOp->p3];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<u.bv.r.nField; i++) assert( memIsValid(&u.bv.r.aMem[i]) ); }
+#endif
+ rc = sqlite3VdbeIdxKeyCompare(u.bv.pC, &u.bv.r, &u.bv.res);
+ if( pOp->opcode==OP_IdxLT ){
+ u.bv.res = -u.bv.res;
+ }else{
+ assert( pOp->opcode==OP_IdxGE );
+ u.bv.res++;
+ }
+ if( u.bv.res>0 ){
+ pc = pOp->p2 - 1 ;
+ }
+ }
+ break;
+}
+
+/* Opcode: Destroy P1 P2 P3 * *
+**
+** Delete an entire database table or index whose root page in the database
+** file is given by P1.
+**
+** The table being destroyed is in the main database file if P3==0. If
+** P3==1 then the table to be clear is in the auxiliary database file
+** that is used to store tables create using CREATE TEMPORARY TABLE.
+**
+** If AUTOVACUUM is enabled then it is possible that another root page
+** might be moved into the newly deleted root page in order to keep all
+** root pages contiguous at the beginning of the database. The former
+** value of the root page that moved - its value before the move occurred -
+** is stored in register P2. If no page
+** movement was required (because the table being dropped was already
+** the last one in the database) then a zero is stored in register P2.
+** If AUTOVACUUM is disabled then a zero is stored in register P2.
+**
+** See also: Clear
+*/
+case OP_Destroy: { /* out2-prerelease */
+#if 0 /* local variables moved into u.bw */
+ int iMoved;
+ int iCnt;
+ Vdbe *pVdbe;
+ int iDb;
+#endif /* local variables moved into u.bw */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ u.bw.iCnt = 0;
+ for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
+ if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){
+ u.bw.iCnt++;
+ }
+ }
+#else
+ u.bw.iCnt = db->activeVdbeCnt;
+#endif
+ pOut->flags = MEM_Null;
+ if( u.bw.iCnt>1 ){
+ rc = SQLITE_LOCKED;
+ p->errorAction = OE_Abort;
+ }else{
+ u.bw.iDb = pOp->p3;
+ assert( u.bw.iCnt==1 );
+ assert( (p->btreeMask & (((yDbMask)1)<<u.bw.iDb))!=0 );
+ rc = sqlite3BtreeDropTable(db->aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved);
+ pOut->flags = MEM_Int;
+ pOut->u.i = u.bw.iMoved;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( rc==SQLITE_OK && u.bw.iMoved!=0 ){
+ sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1);
+ /* All OP_Destroy operations occur on the same btree */
+ assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 );
+ resetSchemaOnFault = u.bw.iDb+1;
+ }
+#endif
+ }
+ break;
+}
+
+/* Opcode: Clear P1 P2 P3
+**
+** Delete all contents of the database table or index whose root page
+** in the database file is given by P1. But, unlike Destroy, do not
+** remove the table or index from the database file.
+**
+** The table being clear is in the main database file if P2==0. If
+** P2==1 then the table to be clear is in the auxiliary database file
+** that is used to store tables create using CREATE TEMPORARY TABLE.
+**
+** If the P3 value is non-zero, then the table referred to must be an
+** intkey table (an SQL table, not an index). In this case the row change
+** count is incremented by the number of rows in the table being cleared.
+** If P3 is greater than zero, then the value stored in register P3 is
+** also incremented by the number of rows in the table being cleared.
+**
+** See also: Destroy
+*/
+case OP_Clear: {
+#if 0 /* local variables moved into u.bx */
+ int nChange;
+#endif /* local variables moved into u.bx */
+
+ u.bx.nChange = 0;
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
+ rc = sqlite3BtreeClearTable(
+ db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
+ );
+ if( pOp->p3 ){
+ p->nChange += u.bx.nChange;
+ if( pOp->p3>0 ){
+ assert( memIsValid(&aMem[pOp->p3]) );
+ memAboutToChange(p, &aMem[pOp->p3]);
+ aMem[pOp->p3].u.i += u.bx.nChange;
+ }
+ }
+ break;
+}
+
+/* Opcode: CreateTable P1 P2 * * *
+**
+** Allocate a new table in the main database file if P1==0 or in the
+** auxiliary database file if P1==1 or in an attached database if
+** P1>1. Write the root page number of the new table into
+** register P2
+**
+** The difference between a table and an index is this: A table must
+** have a 4-byte integer key and can have arbitrary data. An index
+** has an arbitrary key but no data.
+**
+** See also: CreateIndex
+*/
+/* Opcode: CreateIndex P1 P2 * * *
+**
+** Allocate a new index in the main database file if P1==0 or in the
+** auxiliary database file if P1==1 or in an attached database if
+** P1>1. Write the root page number of the new table into
+** register P2.
+**
+** See documentation on OP_CreateTable for additional information.
+*/
+case OP_CreateIndex: /* out2-prerelease */
+case OP_CreateTable: { /* out2-prerelease */
+#if 0 /* local variables moved into u.by */
+ int pgno;
+ int flags;
+ Db *pDb;
+#endif /* local variables moved into u.by */
+
+ u.by.pgno = 0;
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ u.by.pDb = &db->aDb[pOp->p1];
+ assert( u.by.pDb->pBt!=0 );
+ if( pOp->opcode==OP_CreateTable ){
+ /* u.by.flags = BTREE_INTKEY; */
+ u.by.flags = BTREE_INTKEY;
+ }else{
+ u.by.flags = BTREE_BLOBKEY;
+ }
+ rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags);
+ pOut->u.i = u.by.pgno;
+ break;
+}
+
+/* Opcode: ParseSchema P1 * * P4 *
+**
+** Read and parse all entries from the SQLITE_MASTER table of database P1
+** that match the WHERE clause P4.
+**
+** This opcode invokes the parser to create a new virtual machine,
+** then runs the new virtual machine. It is thus a re-entrant opcode.
+*/
+case OP_ParseSchema: {
+#if 0 /* local variables moved into u.bz */
+ int iDb;
+ const char *zMaster;
+ char *zSql;
+ InitData initData;
+#endif /* local variables moved into u.bz */
+
+ /* Any prepared statement that invokes this opcode will hold mutexes
+ ** on every btree. This is a prerequisite for invoking
+ ** sqlite3InitCallback().
+ */
+#ifdef SQLITE_DEBUG
+ for(u.bz.iDb=0; u.bz.iDb<db->nDb; u.bz.iDb++){
+ assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) );
+ }
+#endif
+
+ u.bz.iDb = pOp->p1;
+ assert( u.bz.iDb>=0 && u.bz.iDb<db->nDb );
+ assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) );
+ /* Used to be a conditional */ {
+ u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb);
+ u.bz.initData.db = db;
+ u.bz.initData.iDb = pOp->p1;
+ u.bz.initData.pzErrMsg = &p->zErrMsg;
+ u.bz.zSql = sqlite3MPrintf(db,
+ "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
+ db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z);
+ if( u.bz.zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ assert( db->init.busy==0 );
+ db->init.busy = 1;
+ u.bz.initData.rc = SQLITE_OK;
+ assert( !db->mallocFailed );
+ rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0);
+ if( rc==SQLITE_OK ) rc = u.bz.initData.rc;
+ sqlite3DbFree(db, u.bz.zSql);
+ db->init.busy = 0;
+ }
+ }
+ if( rc ) sqlite3ResetAllSchemasOfConnection(db);
+ if( rc==SQLITE_NOMEM ){
+ goto no_mem;
+ }
+ break;
+}
+
+#if !defined(SQLITE_OMIT_ANALYZE)
+/* Opcode: LoadAnalysis P1 * * * *
+**
+** Read the sqlite_stat1 table for database P1 and load the content
+** of that table into the internal index hash table. This will cause
+** the analysis to be used when preparing all subsequent queries.
+*/
+case OP_LoadAnalysis: {
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ rc = sqlite3AnalysisLoad(db, pOp->p1);
+ break;
+}
+#endif /* !defined(SQLITE_OMIT_ANALYZE) */
+
+/* Opcode: DropTable P1 * * P4 *
+**
+** Remove the internal (in-memory) data structures that describe
+** the table named P4 in database P1. This is called after a table
+** is dropped in order to keep the internal representation of the
+** schema consistent with what is on disk.
+*/
+case OP_DropTable: {
+ sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
+ break;
+}
+
+/* Opcode: DropIndex P1 * * P4 *
+**
+** Remove the internal (in-memory) data structures that describe
+** the index named P4 in database P1. This is called after an index
+** is dropped in order to keep the internal representation of the
+** schema consistent with what is on disk.
+*/
+case OP_DropIndex: {
+ sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
+ break;
+}
+
+/* Opcode: DropTrigger P1 * * P4 *
+**
+** Remove the internal (in-memory) data structures that describe
+** the trigger named P4 in database P1. This is called after a trigger
+** is dropped in order to keep the internal representation of the
+** schema consistent with what is on disk.
+*/
+case OP_DropTrigger: {
+ sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
+ break;
+}
+
+
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
+/* Opcode: IntegrityCk P1 P2 P3 * P5
+**
+** Do an analysis of the currently open database. Store in
+** register P1 the text of an error message describing any problems.
+** If no problems are found, store a NULL in register P1.
+**
+** The register P3 contains the maximum number of allowed errors.
+** At most reg(P3) errors will be reported.
+** In other words, the analysis stops as soon as reg(P1) errors are
+** seen. Reg(P1) is updated with the number of errors remaining.
+**
+** The root page numbers of all tables in the database are integer
+** stored in reg(P1), reg(P1+1), reg(P1+2), .... There are P2 tables
+** total.
+**
+** If P5 is not zero, the check is done on the auxiliary database
+** file, not the main database file.
+**
+** This opcode is used to implement the integrity_check pragma.
+*/
+case OP_IntegrityCk: {
+#if 0 /* local variables moved into u.ca */
+ int nRoot; /* Number of tables to check. (Number of root pages.) */
+ int *aRoot; /* Array of rootpage numbers for tables to be checked */
+ int j; /* Loop counter */
+ int nErr; /* Number of errors reported */
+ char *z; /* Text of the error report */
+ Mem *pnErr; /* Register keeping track of errors remaining */
+#endif /* local variables moved into u.ca */
+
+ u.ca.nRoot = pOp->p2;
+ assert( u.ca.nRoot>0 );
+ u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
+ if( u.ca.aRoot==0 ) goto no_mem;
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ u.ca.pnErr = &aMem[pOp->p3];
+ assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
+ assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+ pIn1 = &aMem[pOp->p1];
+ for(u.ca.j=0; u.ca.j<u.ca.nRoot; u.ca.j++){
+ u.ca.aRoot[u.ca.j] = (int)sqlite3VdbeIntValue(&pIn1[u.ca.j]);
+ }
+ u.ca.aRoot[u.ca.j] = 0;
+ assert( pOp->p5<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
+ u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot,
+ (int)u.ca.pnErr->u.i, &u.ca.nErr);
+ sqlite3DbFree(db, u.ca.aRoot);
+ u.ca.pnErr->u.i -= u.ca.nErr;
+ sqlite3VdbeMemSetNull(pIn1);
+ if( u.ca.nErr==0 ){
+ assert( u.ca.z==0 );
+ }else if( u.ca.z==0 ){
+ goto no_mem;
+ }else{
+ sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free);
+ }
+ UPDATE_MAX_BLOBSIZE(pIn1);
+ sqlite3VdbeChangeEncoding(pIn1, encoding);
+ break;
+}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+/* Opcode: RowSetAdd P1 P2 * * *
+**
+** Insert the integer value held by register P2 into a boolean index
+** held in register P1.
+**
+** An assertion fails if P2 is not an integer.
+*/
+case OP_RowSetAdd: { /* in1, in2 */
+ pIn1 = &aMem[pOp->p1];
+ pIn2 = &aMem[pOp->p2];
+ assert( (pIn2->flags & MEM_Int)!=0 );
+ if( (pIn1->flags & MEM_RowSet)==0 ){
+ sqlite3VdbeMemSetRowSet(pIn1);
+ if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
+ }
+ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i);
+ break;
+}
+
+/* Opcode: RowSetRead P1 P2 P3 * *
+**
+** Extract the smallest value from boolean index P1 and put that value into
+** register P3. Or, if boolean index P1 is initially empty, leave P3
+** unchanged and jump to instruction P2.
+*/
+case OP_RowSetRead: { /* jump, in1, out3 */
+#if 0 /* local variables moved into u.cb */
+ i64 val;
+#endif /* local variables moved into u.cb */
+ CHECK_FOR_INTERRUPT;
+ pIn1 = &aMem[pOp->p1];
+ if( (pIn1->flags & MEM_RowSet)==0
+ || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
+ ){
+ /* The boolean index is empty */
+ sqlite3VdbeMemSetNull(pIn1);
+ pc = pOp->p2 - 1;
+ }else{
+ /* A value was pulled from the index */
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
+ }
+ break;
+}
+
+/* Opcode: RowSetTest P1 P2 P3 P4
+**
+** Register P3 is assumed to hold a 64-bit integer value. If register P1
+** contains a RowSet object and that RowSet object contains
+** the value held in P3, jump to register P2. Otherwise, insert the
+** integer in P3 into the RowSet and continue on to the
+** next opcode.
+**
+** The RowSet object is optimized for the case where successive sets
+** of integers, where each set contains no duplicates. Each set
+** of values is identified by a unique P4 value. The first set
+** must have P4==0, the final set P4=-1. P4 must be either -1 or
+** non-negative. For non-negative values of P4 only the lower 4
+** bits are significant.
+**
+** This allows optimizations: (a) when P4==0 there is no need to test
+** the rowset object for P3, as it is guaranteed not to contain it,
+** (b) when P4==-1 there is no need to insert the value, as it will
+** never be tested for, and (c) when a value that is part of set X is
+** inserted, there is no need to search to see if the same value was
+** previously inserted as part of set X (only if it was previously
+** inserted as part of some other set).
+*/
+case OP_RowSetTest: { /* jump, in1, in3 */
+#if 0 /* local variables moved into u.cc */
+ int iSet;
+ int exists;
+#endif /* local variables moved into u.cc */
+
+ pIn1 = &aMem[pOp->p1];
+ pIn3 = &aMem[pOp->p3];
+ u.cc.iSet = pOp->p4.i;
+ assert( pIn3->flags&MEM_Int );
+
+ /* If there is anything other than a rowset object in memory cell P1,
+ ** delete it now and initialize P1 with an empty rowset
+ */
+ if( (pIn1->flags & MEM_RowSet)==0 ){
+ sqlite3VdbeMemSetRowSet(pIn1);
+ if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
+ }
+
+ assert( pOp->p4type==P4_INT32 );
+ assert( u.cc.iSet==-1 || u.cc.iSet>=0 );
+ if( u.cc.iSet ){
+ u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+ (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff),
+ pIn3->u.i);
+ if( u.cc.exists ){
+ pc = pOp->p2 - 1;
+ break;
+ }
+ }
+ if( u.cc.iSet>=0 ){
+ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
+ }
+ break;
+}
+
+
+#ifndef SQLITE_OMIT_TRIGGER
+
+/* Opcode: Program P1 P2 P3 P4 *
+**
+** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
+**
+** P1 contains the address of the memory cell that contains the first memory
+** cell in an array of values used as arguments to the sub-program. P2
+** contains the address to jump to if the sub-program throws an IGNORE
+** exception using the RAISE() function. Register P3 contains the address
+** of a memory cell in this (the parent) VM that is used to allocate the
+** memory required by the sub-vdbe at runtime.
+**
+** P4 is a pointer to the VM containing the trigger program.
+*/
+case OP_Program: { /* jump */
+#if 0 /* local variables moved into u.cd */
+ int nMem; /* Number of memory registers for sub-program */
+ int nByte; /* Bytes of runtime space required for sub-program */
+ Mem *pRt; /* Register to allocate runtime space */
+ Mem *pMem; /* Used to iterate through memory cells */
+ Mem *pEnd; /* Last memory cell in new array */
+ VdbeFrame *pFrame; /* New vdbe frame to execute in */
+ SubProgram *pProgram; /* Sub-program to execute */
+ void *t; /* Token identifying trigger */
+#endif /* local variables moved into u.cd */
+
+ u.cd.pProgram = pOp->p4.pProgram;
+ u.cd.pRt = &aMem[pOp->p3];
+ assert( u.cd.pProgram->nOp>0 );
+
+ /* If the p5 flag is clear, then recursive invocation of triggers is
+ ** disabled for backwards compatibility (p5 is set if this sub-program
+ ** is really a trigger, not a foreign key action, and the flag set
+ ** and cleared by the "PRAGMA recursive_triggers" command is clear).
+ **
+ ** It is recursive invocation of triggers, at the SQL level, that is
+ ** disabled. In some cases a single trigger may generate more than one
+ ** SubProgram (if the trigger may be executed with more than one different
+ ** ON CONFLICT algorithm). SubProgram structures associated with a
+ ** single trigger all have the same value for the SubProgram.token
+ ** variable. */
+ if( pOp->p5 ){
+ u.cd.t = u.cd.pProgram->token;
+ for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent);
+ if( u.cd.pFrame ) break;
+ }
+
+ if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
+ rc = SQLITE_ERROR;
+ sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
+ break;
+ }
+
+ /* Register u.cd.pRt is used to store the memory required to save the state
+ ** of the current program, and the memory required at runtime to execute
+ ** the trigger program. If this trigger has been fired before, then u.cd.pRt
+ ** is already allocated. Otherwise, it must be initialized. */
+ if( (u.cd.pRt->flags&MEM_Frame)==0 ){
+ /* SubProgram.nMem is set to the number of memory cells used by the
+ ** program stored in SubProgram.aOp. As well as these, one memory
+ ** cell is required for each cursor used by the program. Set local
+ ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value.
+ */
+ u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr;
+ u.cd.nByte = ROUND8(sizeof(VdbeFrame))
+ + u.cd.nMem * sizeof(Mem)
+ + u.cd.pProgram->nCsr * sizeof(VdbeCursor *)
+ + u.cd.pProgram->nOnce * sizeof(u8);
+ u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte);
+ if( !u.cd.pFrame ){
+ goto no_mem;
+ }
+ sqlite3VdbeMemRelease(u.cd.pRt);
+ u.cd.pRt->flags = MEM_Frame;
+ u.cd.pRt->u.pFrame = u.cd.pFrame;
+
+ u.cd.pFrame->v = p;
+ u.cd.pFrame->nChildMem = u.cd.nMem;
+ u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr;
+ u.cd.pFrame->pc = pc;
+ u.cd.pFrame->aMem = p->aMem;
+ u.cd.pFrame->nMem = p->nMem;
+ u.cd.pFrame->apCsr = p->apCsr;
+ u.cd.pFrame->nCursor = p->nCursor;
+ u.cd.pFrame->aOp = p->aOp;
+ u.cd.pFrame->nOp = p->nOp;
+ u.cd.pFrame->token = u.cd.pProgram->token;
+ u.cd.pFrame->aOnceFlag = p->aOnceFlag;
+ u.cd.pFrame->nOnceFlag = p->nOnceFlag;
+
+ u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem];
+ for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){
+ u.cd.pMem->flags = MEM_Invalid;
+ u.cd.pMem->db = db;
+ }
+ }else{
+ u.cd.pFrame = u.cd.pRt->u.pFrame;
+ assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem );
+ assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr );
+ assert( pc==u.cd.pFrame->pc );
+ }
+
+ p->nFrame++;
+ u.cd.pFrame->pParent = p->pFrame;
+ u.cd.pFrame->lastRowid = lastRowid;
+ u.cd.pFrame->nChange = p->nChange;
+ p->nChange = 0;
+ p->pFrame = u.cd.pFrame;
+ p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1];
+ p->nMem = u.cd.pFrame->nChildMem;
+ p->nCursor = (u16)u.cd.pFrame->nChildCsr;
+ p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
+ p->aOp = aOp = u.cd.pProgram->aOp;
+ p->nOp = u.cd.pProgram->nOp;
+ p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
+ p->nOnceFlag = u.cd.pProgram->nOnce;
+ pc = -1;
+ memset(p->aOnceFlag, 0, p->nOnceFlag);
+
+ break;
+}
+
+/* Opcode: Param P1 P2 * * *
+**
+** This opcode is only ever present in sub-programs called via the
+** OP_Program instruction. Copy a value currently stored in a memory
+** cell of the calling (parent) frame to cell P2 in the current frames
+** address space. This is used by trigger programs to access the new.*
+** and old.* values.
+**
+** The address of the cell in the parent frame is determined by adding
+** the value of the P1 argument to the value of the P1 argument to the
+** calling OP_Program instruction.
+*/
+case OP_Param: { /* out2-prerelease */
+#if 0 /* local variables moved into u.ce */
+ VdbeFrame *pFrame;
+ Mem *pIn;
+#endif /* local variables moved into u.ce */
+ u.ce.pFrame = p->pFrame;
+ u.ce.pIn = &u.ce.pFrame->aMem[pOp->p1 + u.ce.pFrame->aOp[u.ce.pFrame->pc].p1];
+ sqlite3VdbeMemShallowCopy(pOut, u.ce.pIn, MEM_Ephem);
+ break;
+}
+
+#endif /* #ifndef SQLITE_OMIT_TRIGGER */
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+/* Opcode: FkCounter P1 P2 * * *
+**
+** Increment a "constraint counter" by P2 (P2 may be negative or positive).
+** If P1 is non-zero, the database constraint counter is incremented
+** (deferred foreign key constraints). Otherwise, if P1 is zero, the
+** statement counter is incremented (immediate foreign key constraints).
+*/
+case OP_FkCounter: {
+ if( pOp->p1 ){
+ db->nDeferredCons += pOp->p2;
+ }else{
+ p->nFkConstraint += pOp->p2;
+ }
+ break;
+}
+
+/* Opcode: FkIfZero P1 P2 * * *
+**
+** This opcode tests if a foreign key constraint-counter is currently zero.
+** If so, jump to instruction P2. Otherwise, fall through to the next
+** instruction.
+**
+** If P1 is non-zero, then the jump is taken if the database constraint-counter
+** is zero (the one that counts deferred constraint violations). If P1 is
+** zero, the jump is taken if the statement constraint-counter is zero
+** (immediate foreign key constraint violations).
+*/
+case OP_FkIfZero: { /* jump */
+ if( pOp->p1 ){
+ if( db->nDeferredCons==0 ) pc = pOp->p2-1;
+ }else{
+ if( p->nFkConstraint==0 ) pc = pOp->p2-1;
+ }
+ break;
+}
+#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+/* Opcode: MemMax P1 P2 * * *
+**
+** P1 is a register in the root frame of this VM (the root frame is
+** different from the current frame if this instruction is being executed
+** within a sub-program). Set the value of register P1 to the maximum of
+** its current value and the value in register P2.
+**
+** This instruction throws an error if the memory cell is not initially
+** an integer.
+*/
+case OP_MemMax: { /* in2 */
+#if 0 /* local variables moved into u.cf */
+ Mem *pIn1;
+ VdbeFrame *pFrame;
+#endif /* local variables moved into u.cf */
+ if( p->pFrame ){
+ for(u.cf.pFrame=p->pFrame; u.cf.pFrame->pParent; u.cf.pFrame=u.cf.pFrame->pParent);
+ u.cf.pIn1 = &u.cf.pFrame->aMem[pOp->p1];
+ }else{
+ u.cf.pIn1 = &aMem[pOp->p1];
+ }
+ assert( memIsValid(u.cf.pIn1) );
+ sqlite3VdbeMemIntegerify(u.cf.pIn1);
+ pIn2 = &aMem[pOp->p2];
+ sqlite3VdbeMemIntegerify(pIn2);
+ if( u.cf.pIn1->u.i<pIn2->u.i){
+ u.cf.pIn1->u.i = pIn2->u.i;
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
+
+/* Opcode: IfPos P1 P2 * * *
+**
+** If the value of register P1 is 1 or greater, jump to P2.
+**
+** It is illegal to use this instruction on a register that does
+** not contain an integer. An assertion fault will result if you try.
+*/
+case OP_IfPos: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags&MEM_Int );
+ if( pIn1->u.i>0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: IfNeg P1 P2 * * *
+**
+** If the value of register P1 is less than zero, jump to P2.
+**
+** It is illegal to use this instruction on a register that does
+** not contain an integer. An assertion fault will result if you try.
+*/
+case OP_IfNeg: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags&MEM_Int );
+ if( pIn1->u.i<0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: IfZero P1 P2 P3 * *
+**
+** The register P1 must contain an integer. Add literal P3 to the
+** value in register P1. If the result is exactly 0, jump to P2.
+**
+** It is illegal to use this instruction on a register that does
+** not contain an integer. An assertion fault will result if you try.
+*/
+case OP_IfZero: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags&MEM_Int );
+ pIn1->u.i += pOp->p3;
+ if( pIn1->u.i==0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: AggStep * P2 P3 P4 P5
+**
+** Execute the step function for an aggregate. The
+** function has P5 arguments. P4 is a pointer to the FuncDef
+** structure that specifies the function. Use register
+** P3 as the accumulator.
+**
+** The P5 arguments are taken from register P2 and its
+** successors.
+*/
+case OP_AggStep: {
+#if 0 /* local variables moved into u.cg */
+ int n;
+ int i;
+ Mem *pMem;
+ Mem *pRec;
+ sqlite3_context ctx;
+ sqlite3_value **apVal;
+#endif /* local variables moved into u.cg */
+
+ u.cg.n = pOp->p5;
+ assert( u.cg.n>=0 );
+ u.cg.pRec = &aMem[pOp->p2];
+ u.cg.apVal = p->apArg;
+ assert( u.cg.apVal || u.cg.n==0 );
+ for(u.cg.i=0; u.cg.i<u.cg.n; u.cg.i++, u.cg.pRec++){
+ assert( memIsValid(u.cg.pRec) );
+ u.cg.apVal[u.cg.i] = u.cg.pRec;
+ memAboutToChange(p, u.cg.pRec);
+ sqlite3VdbeMemStoreType(u.cg.pRec);
+ }
+ u.cg.ctx.pFunc = pOp->p4.pFunc;
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3];
+ u.cg.pMem->n++;
+ u.cg.ctx.s.flags = MEM_Null;
+ u.cg.ctx.s.z = 0;
+ u.cg.ctx.s.zMalloc = 0;
+ u.cg.ctx.s.xDel = 0;
+ u.cg.ctx.s.db = db;
+ u.cg.ctx.isError = 0;
+ u.cg.ctx.pColl = 0;
+ u.cg.ctx.skipFlag = 0;
+ if( u.cg.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ assert( pOp>p->aOp );
+ assert( pOp[-1].p4type==P4_COLLSEQ );
+ assert( pOp[-1].opcode==OP_CollSeq );
+ u.cg.ctx.pColl = pOp[-1].p4.pColl;
+ }
+ (u.cg.ctx.pFunc->xStep)(&u.cg.ctx, u.cg.n, u.cg.apVal); /* IMP: R-24505-23230 */
+ if( u.cg.ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cg.ctx.s));
+ rc = u.cg.ctx.isError;
+ }
+ if( u.cg.ctx.skipFlag ){
+ assert( pOp[-1].opcode==OP_CollSeq );
+ u.cg.i = pOp[-1].p1;
+ if( u.cg.i ) sqlite3VdbeMemSetInt64(&aMem[u.cg.i], 1);
+ }
+
+ sqlite3VdbeMemRelease(&u.cg.ctx.s);
+
+ break;
+}
+
+/* Opcode: AggFinal P1 P2 * P4 *
+**
+** Execute the finalizer function for an aggregate. P1 is
+** the memory location that is the accumulator for the aggregate.
+**
+** P2 is the number of arguments that the step function takes and
+** P4 is a pointer to the FuncDef for this function. The P2
+** argument is not used by this opcode. It is only there to disambiguate
+** functions that can take varying numbers of arguments. The
+** P4 argument is only needed for the degenerate case where
+** the step function was not previously called.
+*/
+case OP_AggFinal: {
+#if 0 /* local variables moved into u.ch */
+ Mem *pMem;
+#endif /* local variables moved into u.ch */
+ assert( pOp->p1>0 && pOp->p1<=p->nMem );
+ u.ch.pMem = &aMem[pOp->p1];
+ assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
+ rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc);
+ if( rc ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem));
+ }
+ sqlite3VdbeChangeEncoding(u.ch.pMem, encoding);
+ UPDATE_MAX_BLOBSIZE(u.ch.pMem);
+ if( sqlite3VdbeMemTooBig(u.ch.pMem) ){
+ goto too_big;
+ }
+ break;
+}
+
+#ifndef SQLITE_OMIT_WAL
+/* Opcode: Checkpoint P1 P2 P3 * *
+**
+** Checkpoint database P1. This is a no-op if P1 is not currently in
+** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL
+** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns
+** SQLITE_BUSY or not, respectively. Write the number of pages in the
+** WAL after the checkpoint into mem[P3+1] and the number of pages
+** in the WAL that have been checkpointed after the checkpoint
+** completes into mem[P3+2]. However on an error, mem[P3+1] and
+** mem[P3+2] are initialized to -1.
+*/
+case OP_Checkpoint: {
+#if 0 /* local variables moved into u.ci */
+ int i; /* Loop counter */
+ int aRes[3]; /* Results */
+ Mem *pMem; /* Write results here */
+#endif /* local variables moved into u.ci */
+
+ u.ci.aRes[0] = 0;
+ u.ci.aRes[1] = u.ci.aRes[2] = -1;
+ assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
+ || pOp->p2==SQLITE_CHECKPOINT_FULL
+ || pOp->p2==SQLITE_CHECKPOINT_RESTART
+ );
+ rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ci.aRes[1], &u.ci.aRes[2]);
+ if( rc==SQLITE_BUSY ){
+ rc = SQLITE_OK;
+ u.ci.aRes[0] = 1;
+ }
+ for(u.ci.i=0, u.ci.pMem = &aMem[pOp->p3]; u.ci.i<3; u.ci.i++, u.ci.pMem++){
+ sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]);
+ }
+ break;
+};
+#endif
+
+#ifndef SQLITE_OMIT_PRAGMA
+/* Opcode: JournalMode P1 P2 P3 * P5
+**
+** Change the journal mode of database P1 to P3. P3 must be one of the
+** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
+** modes (delete, truncate, persist, off and memory), this is a simple
+** operation. No IO is required.
+**
+** If changing into or out of WAL mode the procedure is more complicated.
+**
+** Write a string containing the final journal-mode to register P2.
+*/
+case OP_JournalMode: { /* out2-prerelease */
+#if 0 /* local variables moved into u.cj */
+ Btree *pBt; /* Btree to change journal mode of */
+ Pager *pPager; /* Pager associated with pBt */
+ int eNew; /* New journal mode */
+ int eOld; /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
+ const char *zFilename; /* Name of database file for pPager */
+#endif
+#endif /* local variables moved into u.cj */
+
+ u.cj.eNew = pOp->p3;
+ assert( u.cj.eNew==PAGER_JOURNALMODE_DELETE
+ || u.cj.eNew==PAGER_JOURNALMODE_TRUNCATE
+ || u.cj.eNew==PAGER_JOURNALMODE_PERSIST
+ || u.cj.eNew==PAGER_JOURNALMODE_OFF
+ || u.cj.eNew==PAGER_JOURNALMODE_MEMORY
+ || u.cj.eNew==PAGER_JOURNALMODE_WAL
+ || u.cj.eNew==PAGER_JOURNALMODE_QUERY
+ );
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+
+ u.cj.pBt = db->aDb[pOp->p1].pBt;
+ u.cj.pPager = sqlite3BtreePager(u.cj.pBt);
+ u.cj.eOld = sqlite3PagerGetJournalMode(u.cj.pPager);
+ if( u.cj.eNew==PAGER_JOURNALMODE_QUERY ) u.cj.eNew = u.cj.eOld;
+ if( !sqlite3PagerOkToChangeJournalMode(u.cj.pPager) ) u.cj.eNew = u.cj.eOld;
+
+#ifndef SQLITE_OMIT_WAL
+ u.cj.zFilename = sqlite3PagerFilename(u.cj.pPager, 1);
+
+ /* Do not allow a transition to journal_mode=WAL for a database
+ ** in temporary storage or if the VFS does not support shared memory
+ */
+ if( u.cj.eNew==PAGER_JOURNALMODE_WAL
+ && (sqlite3Strlen30(u.cj.zFilename)==0 /* Temp file */
+ || !sqlite3PagerWalSupported(u.cj.pPager)) /* No shared-memory support */
+ ){
+ u.cj.eNew = u.cj.eOld;
+ }
+
+ if( (u.cj.eNew!=u.cj.eOld)
+ && (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL)
+ ){
+ if( !db->autoCommit || db->activeVdbeCnt>1 ){
+ rc = SQLITE_ERROR;
+ sqlite3SetString(&p->zErrMsg, db,
+ "cannot change %s wal mode from within a transaction",
+ (u.cj.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+ );
+ break;
+ }else{
+
+ if( u.cj.eOld==PAGER_JOURNALMODE_WAL ){
+ /* If leaving WAL mode, close the log file. If successful, the call
+ ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
+ ** file. An EXCLUSIVE lock may still be held on the database file
+ ** after a successful return.
+ */
+ rc = sqlite3PagerCloseWal(u.cj.pPager);
+ if( rc==SQLITE_OK ){
+ sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
+ }
+ }else if( u.cj.eOld==PAGER_JOURNALMODE_MEMORY ){
+ /* Cannot transition directly from MEMORY to WAL. Use mode OFF
+ ** as an intermediate */
+ sqlite3PagerSetJournalMode(u.cj.pPager, PAGER_JOURNALMODE_OFF);
+ }
+
+ /* Open a transaction on the database file. Regardless of the journal
+ ** mode, this transaction always uses a rollback journal.
+ */
+ assert( sqlite3BtreeIsInTrans(u.cj.pBt)==0 );
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeSetVersion(u.cj.pBt, (u.cj.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+ }
+ }
+ }
+#endif /* ifndef SQLITE_OMIT_WAL */
+
+ if( rc ){
+ u.cj.eNew = u.cj.eOld;
+ }
+ u.cj.eNew = sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
+
+ pOut = &aMem[pOp->p2];
+ pOut->flags = MEM_Str|MEM_Static|MEM_Term;
+ pOut->z = (char *)sqlite3JournalModename(u.cj.eNew);
+ pOut->n = sqlite3Strlen30(pOut->z);
+ pOut->enc = SQLITE_UTF8;
+ sqlite3VdbeChangeEncoding(pOut, encoding);
+ break;
+};
+#endif /* SQLITE_OMIT_PRAGMA */
+
+#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
+/* Opcode: Vacuum * * * * *
+**
+** Vacuum the entire database. This opcode will cause other virtual
+** machines to be created and run. It may not be called from within
+** a transaction.
+*/
+case OP_Vacuum: {
+ rc = sqlite3RunVacuum(&p->zErrMsg, db);
+ break;
+}
+#endif
+
+#if !defined(SQLITE_OMIT_AUTOVACUUM)
+/* Opcode: IncrVacuum P1 P2 * * *
+**
+** Perform a single step of the incremental vacuum procedure on
+** the P1 database. If the vacuum has finished, jump to instruction
+** P2. Otherwise, fall through to the next instruction.
+*/
+case OP_IncrVacuum: { /* jump */
+#if 0 /* local variables moved into u.ck */
+ Btree *pBt;
+#endif /* local variables moved into u.ck */
+
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ u.ck.pBt = db->aDb[pOp->p1].pBt;
+ rc = sqlite3BtreeIncrVacuum(u.ck.pBt);
+ if( rc==SQLITE_DONE ){
+ pc = pOp->p2 - 1;
+ rc = SQLITE_OK;
+ }
+ break;
+}
+#endif
+
+/* Opcode: Expire P1 * * * *
+**
+** Cause precompiled statements to become expired. An expired statement
+** fails with an error code of SQLITE_SCHEMA if it is ever executed
+** (via sqlite3_step()).
+**
+** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
+** then only the currently executing statement is affected.
+*/
+case OP_Expire: {
+ if( !pOp->p1 ){
+ sqlite3ExpirePreparedStatements(db);
+ }else{
+ p->expired = 1;
+ }
+ break;
+}
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/* Opcode: TableLock P1 P2 P3 P4 *
+**
+** Obtain a lock on a particular table. This instruction is only used when
+** the shared-cache feature is enabled.
+**
+** P1 is the index of the database in sqlite3.aDb[] of the database
+** on which the lock is acquired. A readlock is obtained if P3==0 or
+** a write lock if P3==1.
+**
+** P2 contains the root-page of the table to lock.
+**
+** P4 contains a pointer to the name of the table being locked. This is only
+** used to generate an error message if the lock cannot be obtained.
+*/
+case OP_TableLock: {
+ u8 isWriteLock = (u8)pOp->p3;
+ if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
+ int p1 = pOp->p1;
+ assert( p1>=0 && p1<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<p1))!=0 );
+ assert( isWriteLock==0 || isWriteLock==1 );
+ rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
+ if( (rc&0xFF)==SQLITE_LOCKED ){
+ const char *z = pOp->p4.z;
+ sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
+ }
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_SHARED_CACHE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VBegin * * * P4 *
+**
+** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
+** xBegin method for that table.
+**
+** Also, whether or not P4 is set, check that this is not being called from
+** within a callback to a virtual table xSync() method. If it is, the error
+** code will be set to SQLITE_LOCKED.
+*/
+case OP_VBegin: {
+#if 0 /* local variables moved into u.cl */
+ VTable *pVTab;
+#endif /* local variables moved into u.cl */
+ u.cl.pVTab = pOp->p4.pVtab;
+ rc = sqlite3VtabBegin(db, u.cl.pVTab);
+ if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VCreate P1 * * P4 *
+**
+** P4 is the name of a virtual table in database P1. Call the xCreate method
+** for that table.
+*/
+case OP_VCreate: {
+ rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VDestroy P1 * * P4 *
+**
+** P4 is the name of a virtual table in database P1. Call the xDestroy method
+** of that table.
+*/
+case OP_VDestroy: {
+ p->inVtabMethod = 2;
+ rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
+ p->inVtabMethod = 0;
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VOpen P1 * * P4 *
+**
+** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
+** P1 is a cursor number. This opcode opens a cursor to the virtual
+** table and stores that cursor in P1.
+*/
+case OP_VOpen: {
+#if 0 /* local variables moved into u.cm */
+ VdbeCursor *pCur;
+ sqlite3_vtab_cursor *pVtabCursor;
+ sqlite3_vtab *pVtab;
+ sqlite3_module *pModule;
+#endif /* local variables moved into u.cm */
+
+ u.cm.pCur = 0;
+ u.cm.pVtabCursor = 0;
+ u.cm.pVtab = pOp->p4.pVtab->pVtab;
+ u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
+ assert(u.cm.pVtab && u.cm.pModule);
+ rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
+ importVtabErrMsg(p, u.cm.pVtab);
+ if( SQLITE_OK==rc ){
+ /* Initialize sqlite3_vtab_cursor base class */
+ u.cm.pVtabCursor->pVtab = u.cm.pVtab;
+
+ /* Initialize vdbe cursor object */
+ u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+ if( u.cm.pCur ){
+ u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
+ u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule;
+ }else{
+ db->mallocFailed = 1;
+ u.cm.pModule->xClose(u.cm.pVtabCursor);
+ }
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VFilter P1 P2 P3 P4 *
+**
+** P1 is a cursor opened using VOpen. P2 is an address to jump to if
+** the filtered result set is empty.
+**
+** P4 is either NULL or a string that was generated by the xBestIndex
+** method of the module. The interpretation of the P4 string is left
+** to the module implementation.
+**
+** This opcode invokes the xFilter method on the virtual table specified
+** by P1. The integer query plan parameter to xFilter is stored in register
+** P3. Register P3+1 stores the argc parameter to be passed to the
+** xFilter method. Registers P3+2..P3+1+argc are the argc
+** additional parameters which are passed to
+** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
+**
+** A jump is made to P2 if the result set after filtering would be empty.
+*/
+case OP_VFilter: { /* jump */
+#if 0 /* local variables moved into u.cn */
+ int nArg;
+ int iQuery;
+ const sqlite3_module *pModule;
+ Mem *pQuery;
+ Mem *pArgc;
+ sqlite3_vtab_cursor *pVtabCursor;
+ sqlite3_vtab *pVtab;
+ VdbeCursor *pCur;
+ int res;
+ int i;
+ Mem **apArg;
+#endif /* local variables moved into u.cn */
+
+ u.cn.pQuery = &aMem[pOp->p3];
+ u.cn.pArgc = &u.cn.pQuery[1];
+ u.cn.pCur = p->apCsr[pOp->p1];
+ assert( memIsValid(u.cn.pQuery) );
+ REGISTER_TRACE(pOp->p3, u.cn.pQuery);
+ assert( u.cn.pCur->pVtabCursor );
+ u.cn.pVtabCursor = u.cn.pCur->pVtabCursor;
+ u.cn.pVtab = u.cn.pVtabCursor->pVtab;
+ u.cn.pModule = u.cn.pVtab->pModule;
+
+ /* Grab the index number and argc parameters */
+ assert( (u.cn.pQuery->flags&MEM_Int)!=0 && u.cn.pArgc->flags==MEM_Int );
+ u.cn.nArg = (int)u.cn.pArgc->u.i;
+ u.cn.iQuery = (int)u.cn.pQuery->u.i;
+
+ /* Invoke the xFilter method */
+ {
+ u.cn.res = 0;
+ u.cn.apArg = p->apArg;
+ for(u.cn.i = 0; u.cn.i<u.cn.nArg; u.cn.i++){
+ u.cn.apArg[u.cn.i] = &u.cn.pArgc[u.cn.i+1];
+ sqlite3VdbeMemStoreType(u.cn.apArg[u.cn.i]);
+ }
+
+ p->inVtabMethod = 1;
+ rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
+ p->inVtabMethod = 0;
+ importVtabErrMsg(p, u.cn.pVtab);
+ if( rc==SQLITE_OK ){
+ u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
+ }
+
+ if( u.cn.res ){
+ pc = pOp->p2 - 1;
+ }
+ }
+ u.cn.pCur->nullRow = 0;
+
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VColumn P1 P2 P3 * *
+**
+** Store the value of the P2-th column of
+** the row of the virtual-table that the
+** P1 cursor is pointing to into register P3.
+*/
+case OP_VColumn: {
+#if 0 /* local variables moved into u.co */
+ sqlite3_vtab *pVtab;
+ const sqlite3_module *pModule;
+ Mem *pDest;
+ sqlite3_context sContext;
+#endif /* local variables moved into u.co */
+
+ VdbeCursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ u.co.pDest = &aMem[pOp->p3];
+ memAboutToChange(p, u.co.pDest);
+ if( pCur->nullRow ){
+ sqlite3VdbeMemSetNull(u.co.pDest);
+ break;
+ }
+ u.co.pVtab = pCur->pVtabCursor->pVtab;
+ u.co.pModule = u.co.pVtab->pModule;
+ assert( u.co.pModule->xColumn );
+ memset(&u.co.sContext, 0, sizeof(u.co.sContext));
+
+ /* The output cell may already have a buffer allocated. Move
+ ** the current contents to u.co.sContext.s so in case the user-function
+ ** can use the already allocated buffer instead of allocating a
+ ** new one.
+ */
+ sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest);
+ MemSetTypeFlag(&u.co.sContext.s, MEM_Null);
+
+ rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
+ importVtabErrMsg(p, u.co.pVtab);
+ if( u.co.sContext.isError ){
+ rc = u.co.sContext.isError;
+ }
+
+ /* Copy the result of the function to the P3 register. We
+ ** do this regardless of whether or not an error occurred to ensure any
+ ** dynamic allocation in u.co.sContext.s (a Mem struct) is released.
+ */
+ sqlite3VdbeChangeEncoding(&u.co.sContext.s, encoding);
+ sqlite3VdbeMemMove(u.co.pDest, &u.co.sContext.s);
+ REGISTER_TRACE(pOp->p3, u.co.pDest);
+ UPDATE_MAX_BLOBSIZE(u.co.pDest);
+
+ if( sqlite3VdbeMemTooBig(u.co.pDest) ){
+ goto too_big;
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VNext P1 P2 * * *
+**
+** Advance virtual table P1 to the next row in its result set and
+** jump to instruction P2. Or, if the virtual table has reached
+** the end of its result set, then fall through to the next instruction.
+*/
+case OP_VNext: { /* jump */
+#if 0 /* local variables moved into u.cp */
+ sqlite3_vtab *pVtab;
+ const sqlite3_module *pModule;
+ int res;
+ VdbeCursor *pCur;
+#endif /* local variables moved into u.cp */
+
+ u.cp.res = 0;
+ u.cp.pCur = p->apCsr[pOp->p1];
+ assert( u.cp.pCur->pVtabCursor );
+ if( u.cp.pCur->nullRow ){
+ break;
+ }
+ u.cp.pVtab = u.cp.pCur->pVtabCursor->pVtab;
+ u.cp.pModule = u.cp.pVtab->pModule;
+ assert( u.cp.pModule->xNext );
+
+ /* Invoke the xNext() method of the module. There is no way for the
+ ** underlying implementation to return an error if one occurs during
+ ** xNext(). Instead, if an error occurs, true is returned (indicating that
+ ** data is available) and the error code returned when xColumn or
+ ** some other method is next invoked on the save virtual table cursor.
+ */
+ p->inVtabMethod = 1;
+ rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
+ p->inVtabMethod = 0;
+ importVtabErrMsg(p, u.cp.pVtab);
+ if( rc==SQLITE_OK ){
+ u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
+ }
+
+ if( !u.cp.res ){
+ /* If there is data, jump to P2 */
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VRename P1 * * P4 *
+**
+** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
+** This opcode invokes the corresponding xRename method. The value
+** in register P1 is passed as the zName argument to the xRename method.
+*/
+case OP_VRename: {
+#if 0 /* local variables moved into u.cq */
+ sqlite3_vtab *pVtab;
+ Mem *pName;
+#endif /* local variables moved into u.cq */
+
+ u.cq.pVtab = pOp->p4.pVtab->pVtab;
+ u.cq.pName = &aMem[pOp->p1];
+ assert( u.cq.pVtab->pModule->xRename );
+ assert( memIsValid(u.cq.pName) );
+ REGISTER_TRACE(pOp->p1, u.cq.pName);
+ assert( u.cq.pName->flags & MEM_Str );
+ testcase( u.cq.pName->enc==SQLITE_UTF8 );
+ testcase( u.cq.pName->enc==SQLITE_UTF16BE );
+ testcase( u.cq.pName->enc==SQLITE_UTF16LE );
+ rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
+ if( rc==SQLITE_OK ){
+ rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
+ importVtabErrMsg(p, u.cq.pVtab);
+ p->expired = 0;
+ }
+ break;
+}
+#endif
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VUpdate P1 P2 P3 P4 *
+**
+** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
+** This opcode invokes the corresponding xUpdate method. P2 values
+** are contiguous memory cells starting at P3 to pass to the xUpdate
+** invocation. The value in register (P3+P2-1) corresponds to the
+** p2th element of the argv array passed to xUpdate.
+**
+** The xUpdate method will do a DELETE or an INSERT or both.
+** The argv[0] element (which corresponds to memory cell P3)
+** is the rowid of a row to delete. If argv[0] is NULL then no
+** deletion occurs. The argv[1] element is the rowid of the new
+** row. This can be NULL to have the virtual table select the new
+** rowid for itself. The subsequent elements in the array are
+** the values of columns in the new row.
+**
+** If P2==1 then no insert is performed. argv[0] is the rowid of
+** a row to delete.
+**
+** P1 is a boolean flag. If it is set to true and the xUpdate call
+** is successful, then the value returned by sqlite3_last_insert_rowid()
+** is set to the value of the rowid for the row just inserted.
+*/
+case OP_VUpdate: {
+#if 0 /* local variables moved into u.cr */
+ sqlite3_vtab *pVtab;
+ sqlite3_module *pModule;
+ int nArg;
+ int i;
+ sqlite_int64 rowid;
+ Mem **apArg;
+ Mem *pX;
+#endif /* local variables moved into u.cr */
+
+ assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
+ || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
+ );
+ u.cr.pVtab = pOp->p4.pVtab->pVtab;
+ u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule;
+ u.cr.nArg = pOp->p2;
+ assert( pOp->p4type==P4_VTAB );
+ if( ALWAYS(u.cr.pModule->xUpdate) ){
+ u8 vtabOnConflict = db->vtabOnConflict;
+ u.cr.apArg = p->apArg;
+ u.cr.pX = &aMem[pOp->p3];
+ for(u.cr.i=0; u.cr.i<u.cr.nArg; u.cr.i++){
+ assert( memIsValid(u.cr.pX) );
+ memAboutToChange(p, u.cr.pX);
+ sqlite3VdbeMemStoreType(u.cr.pX);
+ u.cr.apArg[u.cr.i] = u.cr.pX;
+ u.cr.pX++;
+ }
+ db->vtabOnConflict = pOp->p5;
+ rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
+ db->vtabOnConflict = vtabOnConflict;
+ importVtabErrMsg(p, u.cr.pVtab);
+ if( rc==SQLITE_OK && pOp->p1 ){
+ assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
+ db->lastRowid = lastRowid = u.cr.rowid;
+ }
+ if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
+ if( pOp->p5==OE_Ignore ){
+ rc = SQLITE_OK;
+ }else{
+ p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
+ }
+ }else{
+ p->nChange++;
+ }
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/* Opcode: Pagecount P1 P2 * * *
+**
+** Write the current number of pages in database P1 to memory cell P2.
+*/
+case OP_Pagecount: { /* out2-prerelease */
+ pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt);
+ break;
+}
+#endif
+
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/* Opcode: MaxPgcnt P1 P2 P3 * *
+**
+** Try to set the maximum page count for database P1 to the value in P3.
+** Do not let the maximum page count fall below the current page count and
+** do not change the maximum page count value if P3==0.
+**
+** Store the maximum page count after the change in register P2.
+*/
+case OP_MaxPgcnt: { /* out2-prerelease */
+ unsigned int newMax;
+ Btree *pBt;
+
+ pBt = db->aDb[pOp->p1].pBt;
+ newMax = 0;
+ if( pOp->p3 ){
+ newMax = sqlite3BtreeLastPage(pBt);
+ if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3;
+ }
+ pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax);
+ break;
+}
+#endif
+
+
+#ifndef SQLITE_OMIT_TRACE
+/* Opcode: Trace * * * P4 *
+**
+** If tracing is enabled (by the sqlite3_trace()) interface, then
+** the UTF-8 string contained in P4 is emitted on the trace callback.
+*/
+case OP_Trace: {
+#if 0 /* local variables moved into u.cs */
+ char *zTrace;
+ char *z;
+#endif /* local variables moved into u.cs */
+
+ if( db->xTrace
+ && !p->doingRerun
+ && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+ ){
+ u.cs.z = sqlite3VdbeExpandSql(p, u.cs.zTrace);
+ db->xTrace(db->pTraceArg, u.cs.z);
+ sqlite3DbFree(db, u.cs.z);
+ }
+#ifdef SQLITE_DEBUG
+ if( (db->flags & SQLITE_SqlTrace)!=0
+ && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+ ){
+ sqlite3DebugPrintf("SQL-trace: %s\n", u.cs.zTrace);
+ }
+#endif /* SQLITE_DEBUG */
+ break;
+}
+#endif
+
+
+/* Opcode: Noop * * * * *
+**
+** Do nothing. This instruction is often useful as a jump
+** destination.
+*/
+/*
+** The magic Explain opcode are only inserted when explain==2 (which
+** is to say when the EXPLAIN QUERY PLAN syntax is used.)
+** This opcode records information from the optimizer. It is the
+** the same as a no-op. This opcodesnever appears in a real VM program.
+*/
+default: { /* This is really OP_Noop and OP_Explain */
+ assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
+ break;
+}
+
+/*****************************************************************************
+** The cases of the switch statement above this line should all be indented
+** by 6 spaces. But the left-most 6 spaces have been removed to improve the
+** readability. From this point on down, the normal indentation rules are
+** restored.
+*****************************************************************************/
+ }
+
+#ifdef VDBE_PROFILE
+ {
+ u64 elapsed = sqlite3Hwtime() - start;
+ pOp->cycles += elapsed;
+ pOp->cnt++;
+#if 0
+ fprintf(stdout, "%10llu ", elapsed);
+ sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]);
+#endif
+ }
+#endif
+
+ /* The following code adds nothing to the actual functionality
+ ** of the program. It is only here for testing and debugging.
+ ** On the other hand, it does burn CPU cycles every time through
+ ** the evaluator loop. So we can leave it out when NDEBUG is defined.
+ */
+#ifndef NDEBUG
+ assert( pc>=-1 && pc<p->nOp );
+
+#ifdef SQLITE_DEBUG
+ if( p->trace ){
+ if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
+ if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
+ registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]);
+ }
+ if( pOp->opflags & OPFLG_OUT3 ){
+ registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]);
+ }
+ }
+#endif /* SQLITE_DEBUG */
+#endif /* NDEBUG */
+ } /* The end of the for(;;) loop the loops through opcodes */
+
+ /* If we reach this point, it means that execution is finished with
+ ** an error of some kind.
+ */
+vdbe_error_halt:
+ assert( rc );
+ p->rc = rc;
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(rc, "statement aborts at %d: [%s] %s",
+ pc, p->zSql, p->zErrMsg);
+ sqlite3VdbeHalt(p);
+ if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
+ rc = SQLITE_ERROR;
+ if( resetSchemaOnFault>0 ){
+ sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
+ }
+
+ /* This is the only way out of this procedure. We have to
+ ** release the mutexes on btrees that were acquired at the
+ ** top. */
+vdbe_return:
+ db->lastRowid = lastRowid;
+ sqlite3VdbeLeave(p);
+ return rc;
+
+ /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
+ ** is encountered.
+ */
+too_big:
+ sqlite3SetString(&p->zErrMsg, db, "string or blob too big");
+ rc = SQLITE_TOOBIG;
+ goto vdbe_error_halt;
+
+ /* Jump to here if a malloc() fails.
+ */
+no_mem:
+ db->mallocFailed = 1;
+ sqlite3SetString(&p->zErrMsg, db, "out of memory");
+ rc = SQLITE_NOMEM;
+ goto vdbe_error_halt;
+
+ /* Jump to here for any other kind of fatal error. The "rc" variable
+ ** should hold the error number.
+ */
+abort_due_to_error:
+ assert( p->zErrMsg==0 );
+ if( db->mallocFailed ) rc = SQLITE_NOMEM;
+ if( rc!=SQLITE_IOERR_NOMEM ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc));
+ }
+ goto vdbe_error_halt;
+
+ /* Jump to here if the sqlite3_interrupt() API sets the interrupt
+ ** flag.
+ */
+abort_due_to_interrupt:
+ assert( db->u1.isInterrupted );
+ rc = SQLITE_INTERRUPT;
+ p->rc = rc;
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc));
+ goto vdbe_error_halt;
+}
+
+/************** End of vdbe.c ************************************************/
+/************** Begin file vdbeblob.c ****************************************/
+/*
+** 2007 May 1
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code used to implement incremental BLOB I/O.
+*/
+
+
+#ifndef SQLITE_OMIT_INCRBLOB
+
+/*
+** Valid sqlite3_blob* handles point to Incrblob structures.
+*/
+typedef struct Incrblob Incrblob;
+struct Incrblob {
+ int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
+ int nByte; /* Size of open blob, in bytes */
+ int iOffset; /* Byte offset of blob in cursor data */
+ int iCol; /* Table column this handle is open on */
+ BtCursor *pCsr; /* Cursor pointing at blob row */
+ sqlite3_stmt *pStmt; /* Statement holding cursor open */
+ sqlite3 *db; /* The associated database */
+};
+
+
+/*
+** This function is used by both blob_open() and blob_reopen(). It seeks
+** the b-tree cursor associated with blob handle p to point to row iRow.
+** If successful, SQLITE_OK is returned and subsequent calls to
+** sqlite3_blob_read() or sqlite3_blob_write() access the specified row.
+**
+** If an error occurs, or if the specified row does not exist or does not
+** contain a value of type TEXT or BLOB in the column nominated when the
+** blob handle was opened, then an error code is returned and *pzErr may
+** be set to point to a buffer containing an error message. It is the
+** responsibility of the caller to free the error message buffer using
+** sqlite3DbFree().
+**
+** If an error does occur, then the b-tree cursor is closed. All subsequent
+** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
+** immediately return SQLITE_ABORT.
+*/
+static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
+ int rc; /* Error code */
+ char *zErr = 0; /* Error message */
+ Vdbe *v = (Vdbe *)p->pStmt;
+
+ /* Set the value of the SQL statements only variable to integer iRow.
+ ** This is done directly instead of using sqlite3_bind_int64() to avoid
+ ** triggering asserts related to mutexes.
+ */
+ assert( v->aVar[0].flags&MEM_Int );
+ v->aVar[0].u.i = iRow;
+
+ rc = sqlite3_step(p->pStmt);
+ if( rc==SQLITE_ROW ){
+ u32 type = v->apCsr[0]->aType[p->iCol];
+ if( type<12 ){
+ zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
+ type==0?"null": type==7?"real": "integer"
+ );
+ rc = SQLITE_ERROR;
+ sqlite3_finalize(p->pStmt);
+ p->pStmt = 0;
+ }else{
+ p->iOffset = v->apCsr[0]->aOffset[p->iCol];
+ p->nByte = sqlite3VdbeSerialTypeLen(type);
+ p->pCsr = v->apCsr[0]->pCursor;
+ sqlite3BtreeEnterCursor(p->pCsr);
+ sqlite3BtreeCacheOverflow(p->pCsr);
+ sqlite3BtreeLeaveCursor(p->pCsr);
+ }
+ }
+
+ if( rc==SQLITE_ROW ){
+ rc = SQLITE_OK;
+ }else if( p->pStmt ){
+ rc = sqlite3_finalize(p->pStmt);
+ p->pStmt = 0;
+ if( rc==SQLITE_OK ){
+ zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow);
+ rc = SQLITE_ERROR;
+ }else{
+ zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db));
+ }
+ }
+
+ assert( rc!=SQLITE_OK || zErr==0 );
+ assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE );
+
+ *pzErr = zErr;
+ return rc;
+}
+
+/*
+** Open a blob handle.
+*/
+SQLITE_API int sqlite3_blob_open(
+ sqlite3* db, /* The database connection */
+ const char *zDb, /* The attached database containing the blob */
+ const char *zTable, /* The table containing the blob */
+ const char *zColumn, /* The column containing the blob */
+ sqlite_int64 iRow, /* The row containing the glob */
+ int flags, /* True -> read/write access, false -> read-only */
+ sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
+){
+ int nAttempt = 0;
+ int iCol; /* Index of zColumn in row-record */
+
+ /* This VDBE program seeks a btree cursor to the identified
+ ** db/table/row entry. The reason for using a vdbe program instead
+ ** of writing code to use the b-tree layer directly is that the
+ ** vdbe program will take advantage of the various transaction,
+ ** locking and error handling infrastructure built into the vdbe.
+ **
+ ** After seeking the cursor, the vdbe executes an OP_ResultRow.
+ ** Code external to the Vdbe then "borrows" the b-tree cursor and
+ ** uses it to implement the blob_read(), blob_write() and
+ ** blob_bytes() functions.
+ **
+ ** The sqlite3_blob_close() function finalizes the vdbe program,
+ ** which closes the b-tree cursor and (possibly) commits the
+ ** transaction.
+ */
+ static const VdbeOpList openBlob[] = {
+ {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */
+ {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */
+ {OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */
+
+ /* One of the following two instructions is replaced by an OP_Noop. */
+ {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */
+ {OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */
+
+ {OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */
+ {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */
+ {OP_Column, 0, 0, 1}, /* 7 */
+ {OP_ResultRow, 1, 0, 0}, /* 8 */
+ {OP_Goto, 0, 5, 0}, /* 9 */
+ {OP_Close, 0, 0, 0}, /* 10 */
+ {OP_Halt, 0, 0, 0}, /* 11 */
+ };
+
+ int rc = SQLITE_OK;
+ char *zErr = 0;
+ Table *pTab;
+ Parse *pParse = 0;
+ Incrblob *pBlob = 0;
+
+ flags = !!flags; /* flags = (flags ? 1 : 0); */
+ *ppBlob = 0;
+
+ sqlite3_mutex_enter(db->mutex);
+
+ pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
+ if( !pBlob ) goto blob_open_out;
+ pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
+ if( !pParse ) goto blob_open_out;
+
+ do {
+ memset(pParse, 0, sizeof(Parse));
+ pParse->db = db;
+ sqlite3DbFree(db, zErr);
+ zErr = 0;
+
+ sqlite3BtreeEnterAll(db);
+ pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
+ if( pTab && IsVirtual(pTab) ){
+ pTab = 0;
+ sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
+ }
+#ifndef SQLITE_OMIT_VIEW
+ if( pTab && pTab->pSelect ){
+ pTab = 0;
+ sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable);
+ }
+#endif
+ if( !pTab ){
+ if( pParse->zErrMsg ){
+ sqlite3DbFree(db, zErr);
+ zErr = pParse->zErrMsg;
+ pParse->zErrMsg = 0;
+ }
+ rc = SQLITE_ERROR;
+ sqlite3BtreeLeaveAll(db);
+ goto blob_open_out;
+ }
+
+ /* Now search pTab for the exact column. */
+ for(iCol=0; iCol<pTab->nCol; iCol++) {
+ if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
+ break;
+ }
+ }
+ if( iCol==pTab->nCol ){
+ sqlite3DbFree(db, zErr);
+ zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
+ rc = SQLITE_ERROR;
+ sqlite3BtreeLeaveAll(db);
+ goto blob_open_out;
+ }
+
+ /* If the value is being opened for writing, check that the
+ ** column is not indexed, and that it is not part of a foreign key.
+ ** It is against the rules to open a column to which either of these
+ ** descriptions applies for writing. */
+ if( flags ){
+ const char *zFault = 0;
+ Index *pIdx;
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ if( db->flags&SQLITE_ForeignKeys ){
+ /* Check that the column is not part of an FK child key definition. It
+ ** is not necessary to check if it is part of a parent key, as parent
+ ** key columns must be indexed. The check below will pick up this
+ ** case. */
+ FKey *pFKey;
+ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ int j;
+ for(j=0; j<pFKey->nCol; j++){
+ if( pFKey->aCol[j].iFrom==iCol ){
+ zFault = "foreign key";
+ }
+ }
+ }
+ }
+#endif
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int j;
+ for(j=0; j<pIdx->nColumn; j++){
+ if( pIdx->aiColumn[j]==iCol ){
+ zFault = "indexed";
+ }
+ }
+ }
+ if( zFault ){
+ sqlite3DbFree(db, zErr);
+ zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
+ rc = SQLITE_ERROR;
+ sqlite3BtreeLeaveAll(db);
+ goto blob_open_out;
+ }
+ }
+
+ pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db);
+ assert( pBlob->pStmt || db->mallocFailed );
+ if( pBlob->pStmt ){
+ Vdbe *v = (Vdbe *)pBlob->pStmt;
+ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+
+ sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
+
+
+ /* Configure the OP_Transaction */
+ sqlite3VdbeChangeP1(v, 0, iDb);
+ sqlite3VdbeChangeP2(v, 0, flags);
+
+ /* Configure the OP_VerifyCookie */
+ sqlite3VdbeChangeP1(v, 1, iDb);
+ sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
+ sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);
+
+ /* Make sure a mutex is held on the table to be accessed */
+ sqlite3VdbeUsesBtree(v, iDb);
+
+ /* Configure the OP_TableLock instruction */
+#ifdef SQLITE_OMIT_SHARED_CACHE
+ sqlite3VdbeChangeToNoop(v, 2);
+#else
+ sqlite3VdbeChangeP1(v, 2, iDb);
+ sqlite3VdbeChangeP2(v, 2, pTab->tnum);
+ sqlite3VdbeChangeP3(v, 2, flags);
+ sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
+#endif
+
+ /* Remove either the OP_OpenWrite or OpenRead. Set the P2
+ ** parameter of the other to pTab->tnum. */
+ sqlite3VdbeChangeToNoop(v, 4 - flags);
+ sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
+ sqlite3VdbeChangeP3(v, 3 + flags, iDb);
+
+ /* Configure the number of columns. Configure the cursor to
+ ** think that the table has one more column than it really
+ ** does. An OP_Column to retrieve this imaginary column will
+ ** always return an SQL NULL. This is useful because it means
+ ** we can invoke OP_Column to fill in the vdbe cursors type
+ ** and offset cache without causing any IO.
+ */
+ sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
+ sqlite3VdbeChangeP2(v, 7, pTab->nCol);
+ if( !db->mallocFailed ){
+ pParse->nVar = 1;
+ pParse->nMem = 1;
+ pParse->nTab = 1;
+ sqlite3VdbeMakeReady(v, pParse);
+ }
+ }
+
+ pBlob->flags = flags;
+ pBlob->iCol = iCol;
+ pBlob->db = db;
+ sqlite3BtreeLeaveAll(db);
+ if( db->mallocFailed ){
+ goto blob_open_out;
+ }
+ sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
+ rc = blobSeekToRow(pBlob, iRow, &zErr);
+ } while( (++nAttempt)<5 && rc==SQLITE_SCHEMA );
+
+blob_open_out:
+ if( rc==SQLITE_OK && db->mallocFailed==0 ){
+ *ppBlob = (sqlite3_blob *)pBlob;
+ }else{
+ if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
+ sqlite3DbFree(db, pBlob);
+ }
+ sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
+ sqlite3DbFree(db, zErr);
+ sqlite3StackFree(db, pParse);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** Close a blob handle that was previously created using
+** sqlite3_blob_open().
+*/
+SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){
+ Incrblob *p = (Incrblob *)pBlob;
+ int rc;
+ sqlite3 *db;
+
+ if( p ){
+ db = p->db;
+ sqlite3_mutex_enter(db->mutex);
+ rc = sqlite3_finalize(p->pStmt);
+ sqlite3DbFree(db, p);
+ sqlite3_mutex_leave(db->mutex);
+ }else{
+ rc = SQLITE_OK;
+ }
+ return rc;
+}
+
+/*
+** Perform a read or write operation on a blob
+*/
+static int blobReadWrite(
+ sqlite3_blob *pBlob,
+ void *z,
+ int n,
+ int iOffset,
+ int (*xCall)(BtCursor*, u32, u32, void*)
+){
+ int rc;
+ Incrblob *p = (Incrblob *)pBlob;
+ Vdbe *v;
+ sqlite3 *db;
+
+ if( p==0 ) return SQLITE_MISUSE_BKPT;
+ db = p->db;
+ sqlite3_mutex_enter(db->mutex);
+ v = (Vdbe*)p->pStmt;
+
+ if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){
+ /* Request is out of range. Return a transient error. */
+ rc = SQLITE_ERROR;
+ sqlite3Error(db, SQLITE_ERROR, 0);
+ }else if( v==0 ){
+ /* If there is no statement handle, then the blob-handle has
+ ** already been invalidated. Return SQLITE_ABORT in this case.
+ */
+ rc = SQLITE_ABORT;
+ }else{
+ /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
+ ** returned, clean-up the statement handle.
+ */
+ assert( db == v->db );
+ sqlite3BtreeEnterCursor(p->pCsr);
+ rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
+ sqlite3BtreeLeaveCursor(p->pCsr);
+ if( rc==SQLITE_ABORT ){
+ sqlite3VdbeFinalize(v);
+ p->pStmt = 0;
+ }else{
+ db->errCode = rc;
+ v->rc = rc;
+ }
+ }
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** Read data from a blob handle.
+*/
+SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
+ return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
+}
+
+/*
+** Write data to a blob handle.
+*/
+SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
+ return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
+}
+
+/*
+** Query a blob handle for the size of the data.
+**
+** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
+** so no mutex is required for access.
+*/
+SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
+ Incrblob *p = (Incrblob *)pBlob;
+ return (p && p->pStmt) ? p->nByte : 0;
+}
+
+/*
+** Move an existing blob handle to point to a different row of the same
+** database table.
+**
+** If an error occurs, or if the specified row does not exist or does not
+** contain a blob or text value, then an error code is returned and the
+** database handle error code and message set. If this happens, then all
+** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
+** immediately return SQLITE_ABORT.
+*/
+SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
+ int rc;
+ Incrblob *p = (Incrblob *)pBlob;
+ sqlite3 *db;
+
+ if( p==0 ) return SQLITE_MISUSE_BKPT;
+ db = p->db;
+ sqlite3_mutex_enter(db->mutex);
+
+ if( p->pStmt==0 ){
+ /* If there is no statement handle, then the blob-handle has
+ ** already been invalidated. Return SQLITE_ABORT in this case.
+ */
+ rc = SQLITE_ABORT;
+ }else{
+ char *zErr;
+ rc = blobSeekToRow(p, iRow, &zErr);
+ if( rc!=SQLITE_OK ){
+ sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
+ sqlite3DbFree(db, zErr);
+ }
+ assert( rc!=SQLITE_SCHEMA );
+ }
+
+ rc = sqlite3ApiExit(db, rc);
+ assert( rc==SQLITE_OK || p->pStmt==0 );
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
+
+/************** End of vdbeblob.c ********************************************/
+/************** Begin file vdbesort.c ****************************************/
+/*
+** 2011 July 9
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code for the VdbeSorter object, used in concert with
+** a VdbeCursor to sort large numbers of keys (as may be required, for
+** example, by CREATE INDEX statements on tables too large to fit in main
+** memory).
+*/
+
+
+
+typedef struct VdbeSorterIter VdbeSorterIter;
+typedef struct SorterRecord SorterRecord;
+typedef struct FileWriter FileWriter;
+
+/*
+** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
+**
+** As keys are added to the sorter, they are written to disk in a series
+** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly
+** the same as the cache-size allowed for temporary databases. In order
+** to allow the caller to extract keys from the sorter in sorted order,
+** all PMAs currently stored on disk must be merged together. This comment
+** describes the data structure used to do so. The structure supports
+** merging any number of arrays in a single pass with no redundant comparison
+** operations.
+**
+** The aIter[] array contains an iterator for each of the PMAs being merged.
+** An aIter[] iterator either points to a valid key or else is at EOF. For
+** the purposes of the paragraphs below, we assume that the array is actually
+** N elements in size, where N is the smallest power of 2 greater to or equal
+** to the number of iterators being merged. The extra aIter[] elements are
+** treated as if they are empty (always at EOF).
+**
+** The aTree[] array is also N elements in size. The value of N is stored in
+** the VdbeSorter.nTree variable.
+**
+** The final (N/2) elements of aTree[] contain the results of comparing
+** pairs of iterator keys together. Element i contains the result of
+** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the
+** aTree element is set to the index of it.
+**
+** For the purposes of this comparison, EOF is considered greater than any
+** other key value. If the keys are equal (only possible with two EOF
+** values), it doesn't matter which index is stored.
+**
+** The (N/4) elements of aTree[] that preceed the final (N/2) described
+** above contains the index of the smallest of each block of 4 iterators.
+** And so on. So that aTree[1] contains the index of the iterator that
+** currently points to the smallest key value. aTree[0] is unused.
+**
+** Example:
+**
+** aIter[0] -> Banana
+** aIter[1] -> Feijoa
+** aIter[2] -> Elderberry
+** aIter[3] -> Currant
+** aIter[4] -> Grapefruit
+** aIter[5] -> Apple
+** aIter[6] -> Durian
+** aIter[7] -> EOF
+**
+** aTree[] = { X, 5 0, 5 0, 3, 5, 6 }
+**
+** The current element is "Apple" (the value of the key indicated by
+** iterator 5). When the Next() operation is invoked, iterator 5 will
+** be advanced to the next key in its segment. Say the next key is
+** "Eggplant":
+**
+** aIter[5] -> Eggplant
+**
+** The contents of aTree[] are updated first by comparing the new iterator
+** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator
+** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree.
+** The value of iterator 6 - "Durian" - is now smaller than that of iterator
+** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (Banana<Durian),
+** so the value written into element 1 of the array is 0. As follows:
+**
+** aTree[] = { X, 0 0, 6 0, 3, 5, 6 }
+**
+** In other words, each time we advance to the next sorter element, log2(N)
+** key comparison operations are required, where N is the number of segments
+** being merged (rounded up to the next power of 2).
+*/
+struct VdbeSorter {
+ i64 iWriteOff; /* Current write offset within file pTemp1 */
+ i64 iReadOff; /* Current read offset within file pTemp1 */
+ int nInMemory; /* Current size of pRecord list as PMA */
+ int nTree; /* Used size of aTree/aIter (power of 2) */
+ int nPMA; /* Number of PMAs stored in pTemp1 */
+ int mnPmaSize; /* Minimum PMA size, in bytes */
+ int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */
+ VdbeSorterIter *aIter; /* Array of iterators to merge */
+ int *aTree; /* Current state of incremental merge */
+ sqlite3_file *pTemp1; /* PMA file 1 */
+ SorterRecord *pRecord; /* Head of in-memory record list */
+ UnpackedRecord *pUnpacked; /* Used to unpack keys */
+};
+
+/*
+** The following type is an iterator for a PMA. It caches the current key in
+** variables nKey/aKey. If the iterator is at EOF, pFile==0.
+*/
+struct VdbeSorterIter {
+ i64 iReadOff; /* Current read offset */
+ i64 iEof; /* 1 byte past EOF for this iterator */
+ int nAlloc; /* Bytes of space at aAlloc */
+ int nKey; /* Number of bytes in key */
+ sqlite3_file *pFile; /* File iterator is reading from */
+ u8 *aAlloc; /* Allocated space */
+ u8 *aKey; /* Pointer to current key */
+ u8 *aBuffer; /* Current read buffer */
+ int nBuffer; /* Size of read buffer in bytes */
+};
+
+/*
+** An instance of this structure is used to organize the stream of records
+** being written to files by the merge-sort code into aligned, page-sized
+** blocks. Doing all I/O in aligned page-sized blocks helps I/O to go
+** faster on many operating systems.
+*/
+struct FileWriter {
+ int eFWErr; /* Non-zero if in an error state */
+ u8 *aBuffer; /* Pointer to write buffer */
+ int nBuffer; /* Size of write buffer in bytes */
+ int iBufStart; /* First byte of buffer to write */
+ int iBufEnd; /* Last byte of buffer to write */
+ i64 iWriteOff; /* Offset of start of buffer in file */
+ sqlite3_file *pFile; /* File to write to */
+};
+
+/*
+** A structure to store a single record. All in-memory records are connected
+** together into a linked list headed at VdbeSorter.pRecord using the
+** SorterRecord.pNext pointer.
+*/
+struct SorterRecord {
+ void *pVal;
+ int nVal;
+ SorterRecord *pNext;
+};
+
+/* Minimum allowable value for the VdbeSorter.nWorking variable */
+#define SORTER_MIN_WORKING 10
+
+/* Maximum number of segments to merge in a single pass. */
+#define SORTER_MAX_MERGE_COUNT 16
+
+/*
+** Free all memory belonging to the VdbeSorterIter object passed as the second
+** argument. All structure fields are set to zero before returning.
+*/
+static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
+ sqlite3DbFree(db, pIter->aAlloc);
+ sqlite3DbFree(db, pIter->aBuffer);
+ memset(pIter, 0, sizeof(VdbeSorterIter));
+}
+
+/*
+** Read nByte bytes of data from the stream of data iterated by object p.
+** If successful, set *ppOut to point to a buffer containing the data
+** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite
+** error code.
+**
+** The buffer indicated by *ppOut may only be considered valid until the
+** next call to this function.
+*/
+static int vdbeSorterIterRead(
+ sqlite3 *db, /* Database handle (for malloc) */
+ VdbeSorterIter *p, /* Iterator */
+ int nByte, /* Bytes of data to read */
+ u8 **ppOut /* OUT: Pointer to buffer containing data */
+){
+ int iBuf; /* Offset within buffer to read from */
+ int nAvail; /* Bytes of data available in buffer */
+ assert( p->aBuffer );
+
+ /* If there is no more data to be read from the buffer, read the next
+ ** p->nBuffer bytes of data from the file into it. Or, if there are less
+ ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */
+ iBuf = p->iReadOff % p->nBuffer;
+ if( iBuf==0 ){
+ int nRead; /* Bytes to read from disk */
+ int rc; /* sqlite3OsRead() return code */
+
+ /* Determine how many bytes of data to read. */
+ if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){
+ nRead = p->nBuffer;
+ }else{
+ nRead = (int)(p->iEof - p->iReadOff);
+ }
+ assert( nRead>0 );
+
+ /* Read data from the file. Return early if an error occurs. */
+ rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff);
+ assert( rc!=SQLITE_IOERR_SHORT_READ );
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ nAvail = p->nBuffer - iBuf;
+
+ if( nByte<=nAvail ){
+ /* The requested data is available in the in-memory buffer. In this
+ ** case there is no need to make a copy of the data, just return a
+ ** pointer into the buffer to the caller. */
+ *ppOut = &p->aBuffer[iBuf];
+ p->iReadOff += nByte;
+ }else{
+ /* The requested data is not all available in the in-memory buffer.
+ ** In this case, allocate space at p->aAlloc[] to copy the requested
+ ** range into. Then return a copy of pointer p->aAlloc to the caller. */
+ int nRem; /* Bytes remaining to copy */
+
+ /* Extend the p->aAlloc[] allocation if required. */
+ if( p->nAlloc<nByte ){
+ int nNew = p->nAlloc*2;
+ while( nByte>nNew ) nNew = nNew*2;
+ p->aAlloc = sqlite3DbReallocOrFree(db, p->aAlloc, nNew);
+ if( !p->aAlloc ) return SQLITE_NOMEM;
+ p->nAlloc = nNew;
+ }
+
+ /* Copy as much data as is available in the buffer into the start of
+ ** p->aAlloc[]. */
+ memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail);
+ p->iReadOff += nAvail;
+ nRem = nByte - nAvail;
+
+ /* The following loop copies up to p->nBuffer bytes per iteration into
+ ** the p->aAlloc[] buffer. */
+ while( nRem>0 ){
+ int rc; /* vdbeSorterIterRead() return code */
+ int nCopy; /* Number of bytes to copy */
+ u8 *aNext; /* Pointer to buffer to copy data from */
+
+ nCopy = nRem;
+ if( nRem>p->nBuffer ) nCopy = p->nBuffer;
+ rc = vdbeSorterIterRead(db, p, nCopy, &aNext);
+ if( rc!=SQLITE_OK ) return rc;
+ assert( aNext!=p->aAlloc );
+ memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
+ nRem -= nCopy;
+ }
+
+ *ppOut = p->aAlloc;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Read a varint from the stream of data accessed by p. Set *pnOut to
+** the value read.
+*/
+static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){
+ int iBuf;
+
+ iBuf = p->iReadOff % p->nBuffer;
+ if( iBuf && (p->nBuffer-iBuf)>=9 ){
+ p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
+ }else{
+ u8 aVarint[16], *a;
+ int i = 0, rc;
+ do{
+ rc = vdbeSorterIterRead(db, p, 1, &a);
+ if( rc ) return rc;
+ aVarint[(i++)&0xf] = a[0];
+ }while( (a[0]&0x80)!=0 );
+ sqlite3GetVarint(aVarint, pnOut);
+ }
+
+ return SQLITE_OK;
+}
+
+
+/*
+** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
+** no error occurs, or an SQLite error code if one does.
+*/
+static int vdbeSorterIterNext(
+ sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */
+ VdbeSorterIter *pIter /* Iterator to advance */
+){
+ int rc; /* Return Code */
+ u64 nRec = 0; /* Size of record in bytes */
+
+ if( pIter->iReadOff>=pIter->iEof ){
+ /* This is an EOF condition */
+ vdbeSorterIterZero(db, pIter);
+ return SQLITE_OK;
+ }
+
+ rc = vdbeSorterIterVarint(db, pIter, &nRec);
+ if( rc==SQLITE_OK ){
+ pIter->nKey = (int)nRec;
+ rc = vdbeSorterIterRead(db, pIter, (int)nRec, &pIter->aKey);
+ }
+
+ return rc;
+}
+
+/*
+** Initialize iterator pIter to scan through the PMA stored in file pFile
+** starting at offset iStart and ending at offset iEof-1. This function
+** leaves the iterator pointing to the first key in the PMA (or EOF if the
+** PMA is empty).
+*/
+static int vdbeSorterIterInit(
+ sqlite3 *db, /* Database handle */
+ const VdbeSorter *pSorter, /* Sorter object */
+ i64 iStart, /* Start offset in pFile */
+ VdbeSorterIter *pIter, /* Iterator to populate */
+ i64 *pnByte /* IN/OUT: Increment this value by PMA size */
+){
+ int rc = SQLITE_OK;
+ int nBuf;
+
+ nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+
+ assert( pSorter->iWriteOff>iStart );
+ assert( pIter->aAlloc==0 );
+ assert( pIter->aBuffer==0 );
+ pIter->pFile = pSorter->pTemp1;
+ pIter->iReadOff = iStart;
+ pIter->nAlloc = 128;
+ pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
+ pIter->nBuffer = nBuf;
+ pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
+
+ if( !pIter->aBuffer ){
+ rc = SQLITE_NOMEM;
+ }else{
+ int iBuf;
+
+ iBuf = iStart % nBuf;
+ if( iBuf ){
+ int nRead = nBuf - iBuf;
+ if( (iStart + nRead) > pSorter->iWriteOff ){
+ nRead = (int)(pSorter->iWriteOff - iStart);
+ }
+ rc = sqlite3OsRead(
+ pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
+ );
+ assert( rc!=SQLITE_IOERR_SHORT_READ );
+ }
+
+ if( rc==SQLITE_OK ){
+ u64 nByte; /* Size of PMA in bytes */
+ pIter->iEof = pSorter->iWriteOff;
+ rc = vdbeSorterIterVarint(db, pIter, &nByte);
+ pIter->iEof = pIter->iReadOff + nByte;
+ *pnByte += nByte;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = vdbeSorterIterNext(db, pIter);
+ }
+ return rc;
+}
+
+
+/*
+** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
+** size nKey2 bytes). Argument pKeyInfo supplies the collation functions
+** used by the comparison. If an error occurs, return an SQLite error code.
+** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive
+** value, depending on whether key1 is smaller, equal to or larger than key2.
+**
+** If the bOmitRowid argument is non-zero, assume both keys end in a rowid
+** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid
+** is true and key1 contains even a single NULL value, it is considered to
+** be less than key2. Even if key2 also contains NULL values.
+**
+** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
+** has been allocated and contains an unpacked record that is used as key2.
+*/
+static void vdbeSorterCompare(
+ const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
+ int bOmitRowid, /* Ignore rowid field at end of keys */
+ const void *pKey1, int nKey1, /* Left side of comparison */
+ const void *pKey2, int nKey2, /* Right side of comparison */
+ int *pRes /* OUT: Result of comparison */
+){
+ KeyInfo *pKeyInfo = pCsr->pKeyInfo;
+ VdbeSorter *pSorter = pCsr->pSorter;
+ UnpackedRecord *r2 = pSorter->pUnpacked;
+ int i;
+
+ if( pKey2 ){
+ sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
+ }
+
+ if( bOmitRowid ){
+ r2->nField = pKeyInfo->nField;
+ assert( r2->nField>0 );
+ for(i=0; i<r2->nField; i++){
+ if( r2->aMem[i].flags & MEM_Null ){
+ *pRes = -1;
+ return;
+ }
+ }
+ r2->flags |= UNPACKED_PREFIX_MATCH;
+ }
+
+ *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
+}
+
+/*
+** This function is called to compare two iterator keys when merging
+** multiple b-tree segments. Parameter iOut is the index of the aTree[]
+** value to recalculate.
+*/
+static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int i1;
+ int i2;
+ int iRes;
+ VdbeSorterIter *p1;
+ VdbeSorterIter *p2;
+
+ assert( iOut<pSorter->nTree && iOut>0 );
+
+ if( iOut>=(pSorter->nTree/2) ){
+ i1 = (iOut - pSorter->nTree/2) * 2;
+ i2 = i1 + 1;
+ }else{
+ i1 = pSorter->aTree[iOut*2];
+ i2 = pSorter->aTree[iOut*2+1];
+ }
+
+ p1 = &pSorter->aIter[i1];
+ p2 = &pSorter->aIter[i2];
+
+ if( p1->pFile==0 ){
+ iRes = i2;
+ }else if( p2->pFile==0 ){
+ iRes = i1;
+ }else{
+ int res;
+ assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */
+ vdbeSorterCompare(
+ pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
+ );
+ if( res<=0 ){
+ iRes = i1;
+ }else{
+ iRes = i2;
+ }
+ }
+
+ pSorter->aTree[iOut] = iRes;
+ return SQLITE_OK;
+}
+
+/*
+** Initialize the temporary index cursor just opened as a sorter cursor.
+*/
+SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
+ int pgsz; /* Page size of main database */
+ int mxCache; /* Cache size */
+ VdbeSorter *pSorter; /* The new sorter */
+ char *d; /* Dummy */
+
+ assert( pCsr->pKeyInfo && pCsr->pBt==0 );
+ pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
+ if( pSorter==0 ){
+ return SQLITE_NOMEM;
+ }
+
+ pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d);
+ if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM;
+ assert( pSorter->pUnpacked==(UnpackedRecord *)d );
+
+ if( !sqlite3TempInMemory(db) ){
+ pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+ pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
+ mxCache = db->aDb[0].pSchema->cache_size;
+ if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
+ pSorter->mxPmaSize = mxCache * pgsz;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Free the list of sorted records starting at pRecord.
+*/
+static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
+ SorterRecord *p;
+ SorterRecord *pNext;
+ for(p=pRecord; p; p=pNext){
+ pNext = p->pNext;
+ sqlite3DbFree(db, p);
+ }
+}
+
+/*
+** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ if( pSorter ){
+ if( pSorter->aIter ){
+ int i;
+ for(i=0; i<pSorter->nTree; i++){
+ vdbeSorterIterZero(db, &pSorter->aIter[i]);
+ }
+ sqlite3DbFree(db, pSorter->aIter);
+ }
+ if( pSorter->pTemp1 ){
+ sqlite3OsCloseFree(pSorter->pTemp1);
+ }
+ vdbeSorterRecordFree(db, pSorter->pRecord);
+ sqlite3DbFree(db, pSorter->pUnpacked);
+ sqlite3DbFree(db, pSorter);
+ pCsr->pSorter = 0;
+ }
+}
+
+/*
+** Allocate space for a file-handle and open a temporary file. If successful,
+** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK.
+** Otherwise, set *ppFile to 0 and return an SQLite error code.
+*/
+static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
+ int dummy;
+ return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
+ SQLITE_OPEN_TEMP_JOURNAL |
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+ SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy
+ );
+}
+
+/*
+** Merge the two sorted lists p1 and p2 into a single list.
+** Set *ppOut to the head of the new list.
+*/
+static void vdbeSorterMerge(
+ const VdbeCursor *pCsr, /* For pKeyInfo */
+ SorterRecord *p1, /* First list to merge */
+ SorterRecord *p2, /* Second list to merge */
+ SorterRecord **ppOut /* OUT: Head of merged list */
+){
+ SorterRecord *pFinal = 0;
+ SorterRecord **pp = &pFinal;
+ void *pVal2 = p2 ? p2->pVal : 0;
+
+ while( p1 && p2 ){
+ int res;
+ vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
+ if( res<=0 ){
+ *pp = p1;
+ pp = &p1->pNext;
+ p1 = p1->pNext;
+ pVal2 = 0;
+ }else{
+ *pp = p2;
+ pp = &p2->pNext;
+ p2 = p2->pNext;
+ if( p2==0 ) break;
+ pVal2 = p2->pVal;
+ }
+ }
+ *pp = p1 ? p1 : p2;
+ *ppOut = pFinal;
+}
+
+/*
+** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK
+** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
+** occurs.
+*/
+static int vdbeSorterSort(const VdbeCursor *pCsr){
+ int i;
+ SorterRecord **aSlot;
+ SorterRecord *p;
+ VdbeSorter *pSorter = pCsr->pSorter;
+
+ aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
+ if( !aSlot ){
+ return SQLITE_NOMEM;
+ }
+
+ p = pSorter->pRecord;
+ while( p ){
+ SorterRecord *pNext = p->pNext;
+ p->pNext = 0;
+ for(i=0; aSlot[i]; i++){
+ vdbeSorterMerge(pCsr, p, aSlot[i], &p);
+ aSlot[i] = 0;
+ }
+ aSlot[i] = p;
+ p = pNext;
+ }
+
+ p = 0;
+ for(i=0; i<64; i++){
+ vdbeSorterMerge(pCsr, p, aSlot[i], &p);
+ }
+ pSorter->pRecord = p;
+
+ sqlite3_free(aSlot);
+ return SQLITE_OK;
+}
+
+/*
+** Initialize a file-writer object.
+*/
+static void fileWriterInit(
+ sqlite3 *db, /* Database (for malloc) */
+ sqlite3_file *pFile, /* File to write to */
+ FileWriter *p, /* Object to populate */
+ i64 iStart /* Offset of pFile to begin writing at */
+){
+ int nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+
+ memset(p, 0, sizeof(FileWriter));
+ p->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
+ if( !p->aBuffer ){
+ p->eFWErr = SQLITE_NOMEM;
+ }else{
+ p->iBufEnd = p->iBufStart = (iStart % nBuf);
+ p->iWriteOff = iStart - p->iBufStart;
+ p->nBuffer = nBuf;
+ p->pFile = pFile;
+ }
+}
+
+/*
+** Write nData bytes of data to the file-write object. Return SQLITE_OK
+** if successful, or an SQLite error code if an error occurs.
+*/
+static void fileWriterWrite(FileWriter *p, u8 *pData, int nData){
+ int nRem = nData;
+ while( nRem>0 && p->eFWErr==0 ){
+ int nCopy = nRem;
+ if( nCopy>(p->nBuffer - p->iBufEnd) ){
+ nCopy = p->nBuffer - p->iBufEnd;
+ }
+
+ memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy);
+ p->iBufEnd += nCopy;
+ if( p->iBufEnd==p->nBuffer ){
+ p->eFWErr = sqlite3OsWrite(p->pFile,
+ &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
+ p->iWriteOff + p->iBufStart
+ );
+ p->iBufStart = p->iBufEnd = 0;
+ p->iWriteOff += p->nBuffer;
+ }
+ assert( p->iBufEnd<p->nBuffer );
+
+ nRem -= nCopy;
+ }
+}
+
+/*
+** Flush any buffered data to disk and clean up the file-writer object.
+** The results of using the file-writer after this call are undefined.
+** Return SQLITE_OK if flushing the buffered data succeeds or is not
+** required. Otherwise, return an SQLite error code.
+**
+** Before returning, set *piEof to the offset immediately following the
+** last byte written to the file.
+*/
+static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){
+ int rc;
+ if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){
+ p->eFWErr = sqlite3OsWrite(p->pFile,
+ &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
+ p->iWriteOff + p->iBufStart
+ );
+ }
+ *piEof = (p->iWriteOff + p->iBufEnd);
+ sqlite3DbFree(db, p->aBuffer);
+ rc = p->eFWErr;
+ memset(p, 0, sizeof(FileWriter));
+ return rc;
+}
+
+/*
+** Write value iVal encoded as a varint to the file-write object. Return
+** SQLITE_OK if successful, or an SQLite error code if an error occurs.
+*/
+static void fileWriterWriteVarint(FileWriter *p, u64 iVal){
+ int nByte;
+ u8 aByte[10];
+ nByte = sqlite3PutVarint(aByte, iVal);
+ fileWriterWrite(p, aByte, nByte);
+}
+
+/*
+** Write the current contents of the in-memory linked-list to a PMA. Return
+** SQLITE_OK if successful, or an SQLite error code otherwise.
+**
+** The format of a PMA is:
+**
+** * A varint. This varint contains the total number of bytes of content
+** in the PMA (not including the varint itself).
+**
+** * One or more records packed end-to-end in order of ascending keys.
+** Each record consists of a varint followed by a blob of data (the
+** key). The varint is the number of bytes in the blob of data.
+*/
+static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){
+ int rc = SQLITE_OK; /* Return code */
+ VdbeSorter *pSorter = pCsr->pSorter;
+ FileWriter writer;
+
+ memset(&writer, 0, sizeof(FileWriter));
+
+ if( pSorter->nInMemory==0 ){
+ assert( pSorter->pRecord==0 );
+ return rc;
+ }
+
+ rc = vdbeSorterSort(pCsr);
+
+ /* If the first temporary PMA file has not been opened, open it now. */
+ if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
+ rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
+ assert( rc!=SQLITE_OK || pSorter->pTemp1 );
+ assert( pSorter->iWriteOff==0 );
+ assert( pSorter->nPMA==0 );
+ }
+
+ if( rc==SQLITE_OK ){
+ SorterRecord *p;
+ SorterRecord *pNext = 0;
+
+ fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff);
+ pSorter->nPMA++;
+ fileWriterWriteVarint(&writer, pSorter->nInMemory);
+ for(p=pSorter->pRecord; p; p=pNext){
+ pNext = p->pNext;
+ fileWriterWriteVarint(&writer, p->nVal);
+ fileWriterWrite(&writer, p->pVal, p->nVal);
+ sqlite3DbFree(db, p);
+ }
+ pSorter->pRecord = p;
+ rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff);
+ }
+
+ return rc;
+}
+
+/*
+** Add a record to the sorter.
+*/
+SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
+ sqlite3 *db, /* Database handle */
+ const VdbeCursor *pCsr, /* Sorter cursor */
+ Mem *pVal /* Memory cell containing record */
+){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc = SQLITE_OK; /* Return Code */
+ SorterRecord *pNew; /* New list element */
+
+ assert( pSorter );
+ pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n;
+
+ pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord));
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pNew->pVal = (void *)&pNew[1];
+ memcpy(pNew->pVal, pVal->z, pVal->n);
+ pNew->nVal = pVal->n;
+ pNew->pNext = pSorter->pRecord;
+ pSorter->pRecord = pNew;
+ }
+
+ /* See if the contents of the sorter should now be written out. They
+ ** are written out when either of the following are true:
+ **
+ ** * The total memory allocated for the in-memory list is greater
+ ** than (page-size * cache-size), or
+ **
+ ** * The total memory allocated for the in-memory list is greater
+ ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
+ */
+ if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
+ (pSorter->nInMemory>pSorter->mxPmaSize)
+ || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
+ )){
+#ifdef SQLITE_DEBUG
+ i64 nExpect = pSorter->iWriteOff
+ + sqlite3VarintLen(pSorter->nInMemory)
+ + pSorter->nInMemory;
+#endif
+ rc = vdbeSorterListToPMA(db, pCsr);
+ pSorter->nInMemory = 0;
+ assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) );
+ }
+
+ return rc;
+}
+
+/*
+** Helper function for sqlite3VdbeSorterRewind().
+*/
+static int vdbeSorterInitMerge(
+ sqlite3 *db, /* Database handle */
+ const VdbeCursor *pCsr, /* Cursor handle for this sorter */
+ i64 *pnByte /* Sum of bytes in all opened PMAs */
+){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc = SQLITE_OK; /* Return code */
+ int i; /* Used to iterator through aIter[] */
+ i64 nByte = 0; /* Total bytes in all opened PMAs */
+
+ /* Initialize the iterators. */
+ for(i=0; i<SORTER_MAX_MERGE_COUNT; i++){
+ VdbeSorterIter *pIter = &pSorter->aIter[i];
+ rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte);
+ pSorter->iReadOff = pIter->iEof;
+ assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff );
+ if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break;
+ }
+
+ /* Initialize the aTree[] array. */
+ for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){
+ rc = vdbeSorterDoCompare(pCsr, i);
+ }
+
+ *pnByte = nByte;
+ return rc;
+}
+
+/*
+** Once the sorter has been populated, this function is called to prepare
+** for iterating through its contents in sorted order.
+*/
+SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc; /* Return code */
+ sqlite3_file *pTemp2 = 0; /* Second temp file to use */
+ i64 iWrite2 = 0; /* Write offset for pTemp2 */
+ int nIter; /* Number of iterators used */
+ int nByte; /* Bytes of space required for aIter/aTree */
+ int N = 2; /* Power of 2 >= nIter */
+
+ assert( pSorter );
+
+ /* If no data has been written to disk, then do not do so now. Instead,
+ ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly
+ ** from the in-memory list. */
+ if( pSorter->nPMA==0 ){
+ *pbEof = !pSorter->pRecord;
+ assert( pSorter->aTree==0 );
+ return vdbeSorterSort(pCsr);
+ }
+
+ /* Write the current in-memory list to a PMA. */
+ rc = vdbeSorterListToPMA(db, pCsr);
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* Allocate space for aIter[] and aTree[]. */
+ nIter = pSorter->nPMA;
+ if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT;
+ assert( nIter>0 );
+ while( N<nIter ) N += N;
+ nByte = N * (sizeof(int) + sizeof(VdbeSorterIter));
+ pSorter->aIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte);
+ if( !pSorter->aIter ) return SQLITE_NOMEM;
+ pSorter->aTree = (int *)&pSorter->aIter[N];
+ pSorter->nTree = N;
+
+ do {
+ int iNew; /* Index of new, merged, PMA */
+
+ for(iNew=0;
+ rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA;
+ iNew++
+ ){
+ int rc2; /* Return code from fileWriterFinish() */
+ FileWriter writer; /* Object used to write to disk */
+ i64 nWrite; /* Number of bytes in new PMA */
+
+ memset(&writer, 0, sizeof(FileWriter));
+
+ /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1,
+ ** initialize an iterator for each of them and break out of the loop.
+ ** These iterators will be incrementally merged as the VDBE layer calls
+ ** sqlite3VdbeSorterNext().
+ **
+ ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs,
+ ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs
+ ** are merged into a single PMA that is written to file pTemp2.
+ */
+ rc = vdbeSorterInitMerge(db, pCsr, &nWrite);
+ assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile );
+ if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
+ break;
+ }
+
+ /* Open the second temp file, if it is not already open. */
+ if( pTemp2==0 ){
+ assert( iWrite2==0 );
+ rc = vdbeSorterOpenTempFile(db, &pTemp2);
+ }
+
+ if( rc==SQLITE_OK ){
+ int bEof = 0;
+ fileWriterInit(db, pTemp2, &writer, iWrite2);
+ fileWriterWriteVarint(&writer, nWrite);
+ while( rc==SQLITE_OK && bEof==0 ){
+ VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ];
+ assert( pIter->pFile );
+
+ fileWriterWriteVarint(&writer, pIter->nKey);
+ fileWriterWrite(&writer, pIter->aKey, pIter->nKey);
+ rc = sqlite3VdbeSorterNext(db, pCsr, &bEof);
+ }
+ rc2 = fileWriterFinish(db, &writer, &iWrite2);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+ }
+
+ if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){
+ break;
+ }else{
+ sqlite3_file *pTmp = pSorter->pTemp1;
+ pSorter->nPMA = iNew;
+ pSorter->pTemp1 = pTemp2;
+ pTemp2 = pTmp;
+ pSorter->iWriteOff = iWrite2;
+ pSorter->iReadOff = 0;
+ iWrite2 = 0;
+ }
+ }while( rc==SQLITE_OK );
+
+ if( pTemp2 ){
+ sqlite3OsCloseFree(pTemp2);
+ }
+ *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+ return rc;
+}
+
+/*
+** Advance to the next element in the sorter.
+*/
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ int rc; /* Return code */
+
+ if( pSorter->aTree ){
+ int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
+ int i; /* Index of aTree[] to recalculate */
+
+ rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
+ for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
+ rc = vdbeSorterDoCompare(pCsr, i);
+ }
+
+ *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+ }else{
+ SorterRecord *pFree = pSorter->pRecord;
+ pSorter->pRecord = pFree->pNext;
+ pFree->pNext = 0;
+ vdbeSorterRecordFree(db, pFree);
+ *pbEof = !pSorter->pRecord;
+ rc = SQLITE_OK;
+ }
+ return rc;
+}
+
+/*
+** Return a pointer to a buffer owned by the sorter that contains the
+** current key.
+*/
+static void *vdbeSorterRowkey(
+ const VdbeSorter *pSorter, /* Sorter object */
+ int *pnKey /* OUT: Size of current key in bytes */
+){
+ void *pKey;
+ if( pSorter->aTree ){
+ VdbeSorterIter *pIter;
+ pIter = &pSorter->aIter[ pSorter->aTree[1] ];
+ *pnKey = pIter->nKey;
+ pKey = pIter->aKey;
+ }else{
+ *pnKey = pSorter->pRecord->nVal;
+ pKey = pSorter->pRecord->pVal;
+ }
+ return pKey;
+}
+
+/*
+** Copy the current sorter key into the memory cell pOut.
+*/
+SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ void *pKey; int nKey; /* Sorter key to copy into pOut */
+
+ pKey = vdbeSorterRowkey(pSorter, &nKey);
+ if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){
+ return SQLITE_NOMEM;
+ }
+ pOut->n = nKey;
+ MemSetTypeFlag(pOut, MEM_Blob);
+ memcpy(pOut->z, pKey, nKey);
+
+ return SQLITE_OK;
+}
+
+/*
+** Compare the key in memory cell pVal with the key that the sorter cursor
+** passed as the first argument currently points to. For the purposes of
+** the comparison, ignore the rowid field at the end of each record.
+**
+** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
+** Otherwise, set *pRes to a negative, zero or positive value if the
+** key in pVal is smaller than, equal to or larger than the current sorter
+** key.
+*/
+SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
+ const VdbeCursor *pCsr, /* Sorter cursor */
+ Mem *pVal, /* Value to compare to current sorter key */
+ int *pRes /* OUT: Result of comparison */
+){
+ VdbeSorter *pSorter = pCsr->pSorter;
+ void *pKey; int nKey; /* Sorter key to compare pVal with */
+
+ pKey = vdbeSorterRowkey(pSorter, &nKey);
+ vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
+ return SQLITE_OK;
+}
+
+/************** End of vdbesort.c ********************************************/
+/************** Begin file journal.c *****************************************/
+/*
+** 2007 August 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements a special kind of sqlite3_file object used
+** by SQLite to create journal files if the atomic-write optimization
+** is enabled.
+**
+** The distinctive characteristic of this sqlite3_file is that the
+** actual on disk file is created lazily. When the file is created,
+** the caller specifies a buffer size for an in-memory buffer to
+** be used to service read() and write() requests. The actual file
+** on disk is not created or populated until either:
+**
+** 1) The in-memory representation grows too large for the allocated
+** buffer, or
+** 2) The sqlite3JournalCreate() function is called.
+*/
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+
+
+/*
+** A JournalFile object is a subclass of sqlite3_file used by
+** as an open file handle for journal files.
+*/
+struct JournalFile {
+ sqlite3_io_methods *pMethod; /* I/O methods on journal files */
+ int nBuf; /* Size of zBuf[] in bytes */
+ char *zBuf; /* Space to buffer journal writes */
+ int iSize; /* Amount of zBuf[] currently used */
+ int flags; /* xOpen flags */
+ sqlite3_vfs *pVfs; /* The "real" underlying VFS */
+ sqlite3_file *pReal; /* The "real" underlying file descriptor */
+ const char *zJournal; /* Name of the journal file */
+};
+typedef struct JournalFile JournalFile;
+
+/*
+** If it does not already exists, create and populate the on-disk file
+** for JournalFile p.
+*/
+static int createFile(JournalFile *p){
+ int rc = SQLITE_OK;
+ if( !p->pReal ){
+ sqlite3_file *pReal = (sqlite3_file *)&p[1];
+ rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
+ if( rc==SQLITE_OK ){
+ p->pReal = pReal;
+ if( p->iSize>0 ){
+ assert(p->iSize<=p->nBuf);
+ rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
+ }
+ if( rc!=SQLITE_OK ){
+ /* If an error occurred while writing to the file, close it before
+ ** returning. This way, SQLite uses the in-memory journal data to
+ ** roll back changes made to the internal page-cache before this
+ ** function was called. */
+ sqlite3OsClose(pReal);
+ p->pReal = 0;
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Close the file.
+*/
+static int jrnlClose(sqlite3_file *pJfd){
+ JournalFile *p = (JournalFile *)pJfd;
+ if( p->pReal ){
+ sqlite3OsClose(p->pReal);
+ }
+ sqlite3_free(p->zBuf);
+ return SQLITE_OK;
+}
+
+/*
+** Read data from the file.
+*/
+static int jrnlRead(
+ sqlite3_file *pJfd, /* The journal file from which to read */
+ void *zBuf, /* Put the results here */
+ int iAmt, /* Number of bytes to read */
+ sqlite_int64 iOfst /* Begin reading at this offset */
+){
+ int rc = SQLITE_OK;
+ JournalFile *p = (JournalFile *)pJfd;
+ if( p->pReal ){
+ rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
+ }else if( (iAmt+iOfst)>p->iSize ){
+ rc = SQLITE_IOERR_SHORT_READ;
+ }else{
+ memcpy(zBuf, &p->zBuf[iOfst], iAmt);
+ }
+ return rc;
+}
+
+/*
+** Write data to the file.
+*/
+static int jrnlWrite(
+ sqlite3_file *pJfd, /* The journal file into which to write */
+ const void *zBuf, /* Take data to be written from here */
+ int iAmt, /* Number of bytes to write */
+ sqlite_int64 iOfst /* Begin writing at this offset into the file */
+){
+ int rc = SQLITE_OK;
+ JournalFile *p = (JournalFile *)pJfd;
+ if( !p->pReal && (iOfst+iAmt)>p->nBuf ){
+ rc = createFile(p);
+ }
+ if( rc==SQLITE_OK ){
+ if( p->pReal ){
+ rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
+ }else{
+ memcpy(&p->zBuf[iOfst], zBuf, iAmt);
+ if( p->iSize<(iOfst+iAmt) ){
+ p->iSize = (iOfst+iAmt);
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Truncate the file.
+*/
+static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
+ int rc = SQLITE_OK;
+ JournalFile *p = (JournalFile *)pJfd;
+ if( p->pReal ){
+ rc = sqlite3OsTruncate(p->pReal, size);
+ }else if( size<p->iSize ){
+ p->iSize = size;
+ }
+ return rc;
+}
+
+/*
+** Sync the file.
+*/
+static int jrnlSync(sqlite3_file *pJfd, int flags){
+ int rc;
+ JournalFile *p = (JournalFile *)pJfd;
+ if( p->pReal ){
+ rc = sqlite3OsSync(p->pReal, flags);
+ }else{
+ rc = SQLITE_OK;
+ }
+ return rc;
+}
+
+/*
+** Query the size of the file in bytes.
+*/
+static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
+ int rc = SQLITE_OK;
+ JournalFile *p = (JournalFile *)pJfd;
+ if( p->pReal ){
+ rc = sqlite3OsFileSize(p->pReal, pSize);
+ }else{
+ *pSize = (sqlite_int64) p->iSize;
+ }
+ return rc;
+}
+
+/*
+** Table of methods for JournalFile sqlite3_file object.
+*/
+static struct sqlite3_io_methods JournalFileMethods = {
+ 1, /* iVersion */
+ jrnlClose, /* xClose */
+ jrnlRead, /* xRead */
+ jrnlWrite, /* xWrite */
+ jrnlTruncate, /* xTruncate */
+ jrnlSync, /* xSync */
+ jrnlFileSize, /* xFileSize */
+ 0, /* xLock */
+ 0, /* xUnlock */
+ 0, /* xCheckReservedLock */
+ 0, /* xFileControl */
+ 0, /* xSectorSize */
+ 0, /* xDeviceCharacteristics */
+ 0, /* xShmMap */
+ 0, /* xShmLock */
+ 0, /* xShmBarrier */
+ 0 /* xShmUnmap */
+};
+
+/*
+** Open a journal file.
+*/
+SQLITE_PRIVATE int sqlite3JournalOpen(
+ sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */
+ const char *zName, /* Name of the journal file */
+ sqlite3_file *pJfd, /* Preallocated, blank file handle */
+ int flags, /* Opening flags */
+ int nBuf /* Bytes buffered before opening the file */
+){
+ JournalFile *p = (JournalFile *)pJfd;
+ memset(p, 0, sqlite3JournalSize(pVfs));
+ if( nBuf>0 ){
+ p->zBuf = sqlite3MallocZero(nBuf);
+ if( !p->zBuf ){
+ return SQLITE_NOMEM;
+ }
+ }else{
+ return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
+ }
+ p->pMethod = &JournalFileMethods;
+ p->nBuf = nBuf;
+ p->flags = flags;
+ p->zJournal = zName;
+ p->pVfs = pVfs;
+ return SQLITE_OK;
+}
+
+/*
+** If the argument p points to a JournalFile structure, and the underlying
+** file has not yet been created, create it now.
+*/
+SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
+ if( p->pMethods!=&JournalFileMethods ){
+ return SQLITE_OK;
+ }
+ return createFile((JournalFile *)p);
+}
+
+/*
+** The file-handle passed as the only argument is guaranteed to be an open
+** file. It may or may not be of class JournalFile. If the file is a
+** JournalFile, and the underlying file on disk has not yet been opened,
+** return 0. Otherwise, return 1.
+*/
+SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){
+ return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0);
+}
+
+/*
+** Return the number of bytes required to store a JournalFile that uses vfs
+** pVfs to create the underlying on-disk files.
+*/
+SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
+ return (pVfs->szOsFile+sizeof(JournalFile));
+}
+#endif
+
+/************** End of journal.c *********************************************/
+/************** Begin file memjournal.c **************************************/
+/*
+** 2008 October 7
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code use to implement an in-memory rollback journal.
+** The in-memory rollback journal is used to journal transactions for
+** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
+*/
+
+/* Forward references to internal structures */
+typedef struct MemJournal MemJournal;
+typedef struct FilePoint FilePoint;
+typedef struct FileChunk FileChunk;
+
+/* Space to hold the rollback journal is allocated in increments of
+** this many bytes.
+**
+** The size chosen is a little less than a power of two. That way,
+** the FileChunk object will have a size that almost exactly fills
+** a power-of-two allocation. This mimimizes wasted space in power-of-two
+** memory allocators.
+*/
+#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
+
+/* Macro to find the minimum of two numeric values.
+*/
+#ifndef MIN
+# define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+/*
+** The rollback journal is composed of a linked list of these structures.
+*/
+struct FileChunk {
+ FileChunk *pNext; /* Next chunk in the journal */
+ u8 zChunk[JOURNAL_CHUNKSIZE]; /* Content of this chunk */
+};
+
+/*
+** An instance of this object serves as a cursor into the rollback journal.
+** The cursor can be either for reading or writing.
+*/
+struct FilePoint {
+ sqlite3_int64 iOffset; /* Offset from the beginning of the file */
+ FileChunk *pChunk; /* Specific chunk into which cursor points */
+};
+
+/*
+** This subclass is a subclass of sqlite3_file. Each open memory-journal
+** is an instance of this class.
+*/
+struct MemJournal {
+ sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */
+ FileChunk *pFirst; /* Head of in-memory chunk-list */
+ FilePoint endpoint; /* Pointer to the end of the file */
+ FilePoint readpoint; /* Pointer to the end of the last xRead() */
+};
+
+/*
+** Read data from the in-memory journal file. This is the implementation
+** of the sqlite3_vfs.xRead method.
+*/
+static int memjrnlRead(
+ sqlite3_file *pJfd, /* The journal file from which to read */
+ void *zBuf, /* Put the results here */
+ int iAmt, /* Number of bytes to read */
+ sqlite_int64 iOfst /* Begin reading at this offset */
+){
+ MemJournal *p = (MemJournal *)pJfd;
+ u8 *zOut = zBuf;
+ int nRead = iAmt;
+ int iChunkOffset;
+ FileChunk *pChunk;
+
+ /* SQLite never tries to read past the end of a rollback journal file */
+ assert( iOfst+iAmt<=p->endpoint.iOffset );
+
+ if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
+ sqlite3_int64 iOff = 0;
+ for(pChunk=p->pFirst;
+ ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
+ pChunk=pChunk->pNext
+ ){
+ iOff += JOURNAL_CHUNKSIZE;
+ }
+ }else{
+ pChunk = p->readpoint.pChunk;
+ }
+
+ iChunkOffset = (int)(iOfst%JOURNAL_CHUNKSIZE);
+ do {
+ int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset;
+ int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset));
+ memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy);
+ zOut += nCopy;
+ nRead -= iSpace;
+ iChunkOffset = 0;
+ } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
+ p->readpoint.iOffset = iOfst+iAmt;
+ p->readpoint.pChunk = pChunk;
+
+ return SQLITE_OK;
+}
+
+/*
+** Write data to the file.
+*/
+static int memjrnlWrite(
+ sqlite3_file *pJfd, /* The journal file into which to write */
+ const void *zBuf, /* Take data to be written from here */
+ int iAmt, /* Number of bytes to write */
+ sqlite_int64 iOfst /* Begin writing at this offset into the file */
+){
+ MemJournal *p = (MemJournal *)pJfd;
+ int nWrite = iAmt;
+ u8 *zWrite = (u8 *)zBuf;
+
+ /* An in-memory journal file should only ever be appended to. Random
+ ** access writes are not required by sqlite.
+ */
+ assert( iOfst==p->endpoint.iOffset );
+ UNUSED_PARAMETER(iOfst);
+
+ while( nWrite>0 ){
+ FileChunk *pChunk = p->endpoint.pChunk;
+ int iChunkOffset = (int)(p->endpoint.iOffset%JOURNAL_CHUNKSIZE);
+ int iSpace = MIN(nWrite, JOURNAL_CHUNKSIZE - iChunkOffset);
+
+ if( iChunkOffset==0 ){
+ /* New chunk is required to extend the file. */
+ FileChunk *pNew = sqlite3_malloc(sizeof(FileChunk));
+ if( !pNew ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ pNew->pNext = 0;
+ if( pChunk ){
+ assert( p->pFirst );
+ pChunk->pNext = pNew;
+ }else{
+ assert( !p->pFirst );
+ p->pFirst = pNew;
+ }
+ p->endpoint.pChunk = pNew;
+ }
+
+ memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace);
+ zWrite += iSpace;
+ nWrite -= iSpace;
+ p->endpoint.iOffset += iSpace;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Truncate the file.
+*/
+static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
+ MemJournal *p = (MemJournal *)pJfd;
+ FileChunk *pChunk;
+ assert(size==0);
+ UNUSED_PARAMETER(size);
+ pChunk = p->pFirst;
+ while( pChunk ){
+ FileChunk *pTmp = pChunk;
+ pChunk = pChunk->pNext;
+ sqlite3_free(pTmp);
+ }
+ sqlite3MemJournalOpen(pJfd);
+ return SQLITE_OK;
+}
+
+/*
+** Close the file.
+*/
+static int memjrnlClose(sqlite3_file *pJfd){
+ memjrnlTruncate(pJfd, 0);
+ return SQLITE_OK;
+}
+
+
+/*
+** Sync the file.
+**
+** Syncing an in-memory journal is a no-op. And, in fact, this routine
+** is never called in a working implementation. This implementation
+** exists purely as a contingency, in case some malfunction in some other
+** part of SQLite causes Sync to be called by mistake.
+*/
+static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ return SQLITE_OK;
+}
+
+/*
+** Query the size of the file in bytes.
+*/
+static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
+ MemJournal *p = (MemJournal *)pJfd;
+ *pSize = (sqlite_int64) p->endpoint.iOffset;
+ return SQLITE_OK;
+}
+
+/*
+** Table of methods for MemJournal sqlite3_file object.
+*/
+static const struct sqlite3_io_methods MemJournalMethods = {
+ 1, /* iVersion */
+ memjrnlClose, /* xClose */
+ memjrnlRead, /* xRead */
+ memjrnlWrite, /* xWrite */
+ memjrnlTruncate, /* xTruncate */
+ memjrnlSync, /* xSync */
+ memjrnlFileSize, /* xFileSize */
+ 0, /* xLock */
+ 0, /* xUnlock */
+ 0, /* xCheckReservedLock */
+ 0, /* xFileControl */
+ 0, /* xSectorSize */
+ 0, /* xDeviceCharacteristics */
+ 0, /* xShmMap */
+ 0, /* xShmLock */
+ 0, /* xShmBarrier */
+ 0 /* xShmUnlock */
+};
+
+/*
+** Open a journal file.
+*/
+SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){
+ MemJournal *p = (MemJournal *)pJfd;
+ assert( EIGHT_BYTE_ALIGNMENT(p) );
+ memset(p, 0, sqlite3MemJournalSize());
+ p->pMethod = (sqlite3_io_methods*)&MemJournalMethods;
+}
+
+/*
+** Return true if the file-handle passed as an argument is
+** an in-memory journal
+*/
+SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){
+ return pJfd->pMethods==&MemJournalMethods;
+}
+
+/*
+** Return the number of bytes required to store a MemJournal file descriptor.
+*/
+SQLITE_PRIVATE int sqlite3MemJournalSize(void){
+ return sizeof(MemJournal);
+}
+
+/************** End of memjournal.c ******************************************/
+/************** Begin file walker.c ******************************************/
+/*
+** 2008 August 16
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains routines used for walking the parser tree for
+** an SQL statement.
+*/
+/* #include <stdlib.h> */
+/* #include <string.h> */
+
+
+/*
+** Walk an expression tree. Invoke the callback once for each node
+** of the expression, while decending. (In other words, the callback
+** is invoked before visiting children.)
+**
+** The return value from the callback should be one of the WRC_*
+** constants to specify how to proceed with the walk.
+**
+** WRC_Continue Continue descending down the tree.
+**
+** WRC_Prune Do not descend into child nodes. But allow
+** the walk to continue with sibling nodes.
+**
+** WRC_Abort Do no more callbacks. Unwind the stack and
+** return the top-level walk call.
+**
+** The return value from this routine is WRC_Abort to abandon the tree walk
+** and WRC_Continue to continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
+ int rc;
+ if( pExpr==0 ) return WRC_Continue;
+ testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
+ testcase( ExprHasProperty(pExpr, EP_Reduced) );
+ rc = pWalker->xExprCallback(pWalker, pExpr);
+ if( rc==WRC_Continue
+ && !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
+ if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
+ }else{
+ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ }
+ }
+ return rc & WRC_Abort;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in list p or until
+** an abort request is seen.
+*/
+SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
+ int i;
+ struct ExprList_item *pItem;
+ if( p ){
+ for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+ if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Walk all expressions associated with SELECT statement p. Do
+** not invoke the SELECT callback on p, but do (of course) invoke
+** any expr callbacks and SELECT callbacks that come from subqueries.
+** Return WRC_Abort or WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
+ if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
+ return WRC_Continue;
+}
+
+/*
+** Walk the parse trees associated with all subqueries in the
+** FROM clause of SELECT statement p. Do not invoke the select
+** callback on p, but do invoke it on each FROM clause subquery
+** and on any subqueries further down in the tree. Return
+** WRC_Abort or WRC_Continue;
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
+ SrcList *pSrc;
+ int i;
+ struct SrcList_item *pItem;
+
+ pSrc = p->pSrc;
+ if( ALWAYS(pSrc) ){
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+ if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in Select statement p.
+** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
+** on the compound select chain, p->pPrior.
+**
+** Return WRC_Continue under normal conditions. Return WRC_Abort if
+** there is an abort request.
+**
+** If the Walker does not have an xSelectCallback() then this routine
+** is a no-op returning WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
+ int rc;
+ if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
+ rc = WRC_Continue;
+ pWalker->walkerDepth++;
+ while( p ){
+ rc = pWalker->xSelectCallback(pWalker, p);
+ if( rc ) break;
+ if( sqlite3WalkSelectExpr(pWalker, p)
+ || sqlite3WalkSelectFrom(pWalker, p)
+ ){
+ pWalker->walkerDepth--;
+ return WRC_Abort;
+ }
+ p = p->pPrior;
+ }
+ pWalker->walkerDepth--;
+ return rc & WRC_Abort;
+}
+
+/************** End of walker.c **********************************************/
+/************** Begin file resolve.c *****************************************/
+/*
+** 2008 August 18
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains routines used for walking the parser tree and
+** resolve all identifiers by associating them with a particular
+** table and column.
+*/
+/* #include <stdlib.h> */
+/* #include <string.h> */
+
+/*
+** Walk the expression tree pExpr and increase the aggregate function
+** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
+** This needs to occur when copying a TK_AGG_FUNCTION node from an
+** outer query into an inner subquery.
+**
+** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
+** is a helper function - a callback for the tree walker.
+*/
+static int incrAggDepth(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i;
+ return WRC_Continue;
+}
+static void incrAggFunctionDepth(Expr *pExpr, int N){
+ if( N>0 ){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = incrAggDepth;
+ w.u.i = N;
+ sqlite3WalkExpr(&w, pExpr);
+ }
+}
+
+/*
+** Turn the pExpr expression into an alias for the iCol-th column of the
+** result set in pEList.
+**
+** If the result set column is a simple column reference, then this routine
+** makes an exact copy. But for any other kind of expression, this
+** routine make a copy of the result set column as the argument to the
+** TK_AS operator. The TK_AS operator causes the expression to be
+** evaluated just once and then reused for each alias.
+**
+** The reason for suppressing the TK_AS term when the expression is a simple
+** column reference is so that the column reference will be recognized as
+** usable by indices within the WHERE clause processing logic.
+**
+** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
+** that in a GROUP BY clause, the expression is evaluated twice. Hence:
+**
+** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
+**
+** Is equivalent to:
+**
+** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
+**
+** The result of random()%5 in the GROUP BY clause is probably different
+** from the result in the result-set. We might fix this someday. Or
+** then again, we might not...
+**
+** If the reference is followed by a COLLATE operator, then make sure
+** the COLLATE operator is preserved. For example:
+**
+** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
+**
+** Should be transformed into:
+**
+** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
+**
+** The nSubquery parameter specifies how many levels of subquery the
+** alias is removed from the original expression. The usually value is
+** zero but it might be more if the alias is contained within a subquery
+** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
+** structures must be increased by the nSubquery amount.
+*/
+static void resolveAlias(
+ Parse *pParse, /* Parsing context */
+ ExprList *pEList, /* A result set */
+ int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
+ Expr *pExpr, /* Transform this into an alias to the result set */
+ const char *zType, /* "GROUP" or "ORDER" or "" */
+ int nSubquery /* Number of subqueries that the label is moving */
+){
+ Expr *pOrig; /* The iCol-th column of the result set */
+ Expr *pDup; /* Copy of pOrig */
+ sqlite3 *db; /* The database connection */
+
+ assert( iCol>=0 && iCol<pEList->nExpr );
+ pOrig = pEList->a[iCol].pExpr;
+ assert( pOrig!=0 );
+ assert( pOrig->flags & EP_Resolved );
+ db = pParse->db;
+ pDup = sqlite3ExprDup(db, pOrig, 0);
+ if( pDup==0 ) return;
+ if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
+ incrAggFunctionDepth(pDup, nSubquery);
+ pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
+ if( pDup==0 ) return;
+ if( pEList->a[iCol].iAlias==0 ){
+ pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
+ }
+ pDup->iTable = pEList->a[iCol].iAlias;
+ }
+ if( pExpr->op==TK_COLLATE ){
+ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
+ }
+
+ /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
+ ** prevents ExprDelete() from deleting the Expr structure itself,
+ ** allowing it to be repopulated by the memcpy() on the following line.
+ ** The pExpr->u.zToken might point into memory that will be freed by the
+ ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
+ ** make a copy of the token before doing the sqlite3DbFree().
+ */
+ ExprSetProperty(pExpr, EP_Static);
+ sqlite3ExprDelete(db, pExpr);
+ memcpy(pExpr, pDup, sizeof(*pExpr));
+ if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
+ assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
+ pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
+ pExpr->flags2 |= EP2_MallocedToken;
+ }
+ sqlite3DbFree(db, pDup);
+}
+
+
+/*
+** Return TRUE if the name zCol occurs anywhere in the USING clause.
+**
+** Return FALSE if the USING clause is NULL or if it does not contain
+** zCol.
+*/
+static int nameInUsingClause(IdList *pUsing, const char *zCol){
+ if( pUsing ){
+ int k;
+ for(k=0; k<pUsing->nId; k++){
+ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+** Subqueries stores the original database, table and column names for their
+** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
+** Check to see if the zSpan given to this routine matches the zDb, zTab,
+** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
+** match anything.
+*/
+SQLITE_PRIVATE int sqlite3MatchSpanName(
+ const char *zSpan,
+ const char *zCol,
+ const char *zTab,
+ const char *zDb
+){
+ int n;
+ for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+ if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
+ return 0;
+ }
+ zSpan += n+1;
+ for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+ if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
+ return 0;
+ }
+ zSpan += n+1;
+ if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
+ return 0;
+ }
+ return 1;
+}
+
+/*
+** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
+** that name in the set of source tables in pSrcList and make the pExpr
+** expression node refer back to that source column. The following changes
+** are made to pExpr:
+**
+** pExpr->iDb Set the index in db->aDb[] of the database X
+** (even if X is implied).
+** pExpr->iTable Set to the cursor number for the table obtained
+** from pSrcList.
+** pExpr->pTab Points to the Table structure of X.Y (even if
+** X and/or Y are implied.)
+** pExpr->iColumn Set to the column number within the table.
+** pExpr->op Set to TK_COLUMN.
+** pExpr->pLeft Any expression this points to is deleted
+** pExpr->pRight Any expression this points to is deleted.
+**
+** The zDb variable is the name of the database (the "X"). This value may be
+** NULL meaning that name is of the form Y.Z or Z. Any available database
+** can be used. The zTable variable is the name of the table (the "Y"). This
+** value can be NULL if zDb is also NULL. If zTable is NULL it
+** means that the form of the name is Z and that columns from any table
+** can be used.
+**
+** If the name cannot be resolved unambiguously, leave an error message
+** in pParse and return WRC_Abort. Return WRC_Prune on success.
+*/
+static int lookupName(
+ Parse *pParse, /* The parsing context */
+ const char *zDb, /* Name of the database containing table, or NULL */
+ const char *zTab, /* Name of table containing column, or NULL */
+ const char *zCol, /* Name of the column. */
+ NameContext *pNC, /* The name context used to resolve the name */
+ Expr *pExpr /* Make this EXPR node point to the selected column */
+){
+ int i, j; /* Loop counters */
+ int cnt = 0; /* Number of matching column names */
+ int cntTab = 0; /* Number of matching table names */
+ int nSubquery = 0; /* How many levels of subquery */
+ sqlite3 *db = pParse->db; /* The database connection */
+ struct SrcList_item *pItem; /* Use for looping over pSrcList items */
+ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ NameContext *pTopNC = pNC; /* First namecontext in the list */
+ Schema *pSchema = 0; /* Schema of the expression */
+ int isTrigger = 0;
+
+ assert( pNC ); /* the name context cannot be NULL. */
+ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
+ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+
+ /* Initialize the node to no-match */
+ pExpr->iTable = -1;
+ pExpr->pTab = 0;
+ ExprSetIrreducible(pExpr);
+
+ /* Translate the schema name in zDb into a pointer to the corresponding
+ ** schema. If not found, pSchema will remain NULL and nothing will match
+ ** resulting in an appropriate error message toward the end of this routine
+ */
+ if( zDb ){
+ for(i=0; i<db->nDb; i++){
+ assert( db->aDb[i].zName );
+ if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
+ pSchema = db->aDb[i].pSchema;
+ break;
+ }
+ }
+ }
+
+ /* Start at the inner-most context and move outward until a match is found */
+ while( pNC && cnt==0 ){
+ ExprList *pEList;
+ SrcList *pSrcList = pNC->pSrcList;
+
+ if( pSrcList ){
+ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+ Table *pTab;
+ Column *pCol;
+
+ pTab = pItem->pTab;
+ assert( pTab!=0 && pTab->zName!=0 );
+ assert( pTab->nCol>0 );
+ if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
+ int hit = 0;
+ pEList = pItem->pSelect->pEList;
+ for(j=0; j<pEList->nExpr; j++){
+ if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
+ cnt++;
+ cntTab = 2;
+ pMatch = pItem;
+ pExpr->iColumn = j;
+ hit = 1;
+ }
+ }
+ if( hit || zTab==0 ) continue;
+ }
+ if( zDb && pTab->pSchema!=pSchema ){
+ continue;
+ }
+ if( zTab ){
+ const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
+ assert( zTabName!=0 );
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ){
+ continue;
+ }
+ }
+ if( 0==(cntTab++) ){
+ pMatch = pItem;
+ }
+ for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ /* If there has been exactly one prior match and this match
+ ** is for the right-hand table of a NATURAL JOIN or is in a
+ ** USING clause, then skip this match.
+ */
+ if( cnt==1 ){
+ if( pItem->jointype & JT_NATURAL ) continue;
+ if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
+ }
+ cnt++;
+ pMatch = pItem;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
+ break;
+ }
+ }
+ }
+ if( pMatch ){
+ pExpr->iTable = pMatch->iCursor;
+ pExpr->pTab = pMatch->pTab;
+ pSchema = pExpr->pTab->pSchema;
+ }
+ } /* if( pSrcList ) */
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If we have not already resolved the name, then maybe
+ ** it is a new.* or old.* trigger argument reference
+ */
+ if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
+ int op = pParse->eTriggerOp;
+ Table *pTab = 0;
+ assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
+ if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
+ pExpr->iTable = 1;
+ pTab = pParse->pTriggerTab;
+ }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
+ pExpr->iTable = 0;
+ pTab = pParse->pTriggerTab;
+ }
+
+ if( pTab ){
+ int iCol;
+ pSchema = pTab->pSchema;
+ cntTab++;
+ for(iCol=0; iCol<pTab->nCol; iCol++){
+ Column *pCol = &pTab->aCol[iCol];
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ if( iCol==pTab->iPKey ){
+ iCol = -1;
+ }
+ break;
+ }
+ }
+ if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) ){
+ iCol = -1; /* IMP: R-44911-55124 */
+ }
+ if( iCol<pTab->nCol ){
+ cnt++;
+ if( iCol<0 ){
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ }else if( pExpr->iTable==0 ){
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
+ }else{
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
+ }
+ pExpr->iColumn = (i16)iCol;
+ pExpr->pTab = pTab;
+ isTrigger = 1;
+ }
+ }
+ }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+
+ /*
+ ** Perhaps the name is a reference to the ROWID
+ */
+ if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+ cnt = 1;
+ pExpr->iColumn = -1; /* IMP: R-44911-55124 */
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ }
+
+ /*
+ ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+ ** might refer to an result-set alias. This happens, for example, when
+ ** we are resolving names in the WHERE clause of the following command:
+ **
+ ** SELECT a+b AS x FROM table WHERE x<10;
+ **
+ ** In cases like this, replace pExpr with a copy of the expression that
+ ** forms the result set entry ("a+b" in the example) and return immediately.
+ ** Note that the expression in the result set should have already been
+ ** resolved by the time the WHERE clause is resolved.
+ */
+ if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
+ for(j=0; j<pEList->nExpr; j++){
+ char *zAs = pEList->a[j].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ Expr *pOrig;
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ assert( pExpr->x.pList==0 );
+ assert( pExpr->x.pSelect==0 );
+ pOrig = pEList->a[j].pExpr;
+ if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
+ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
+ return WRC_Abort;
+ }
+ resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
+ cnt = 1;
+ pMatch = 0;
+ assert( zTab==0 && zDb==0 );
+ goto lookupname_end;
+ }
+ }
+ }
+
+ /* Advance to the next name context. The loop will exit when either
+ ** we have a match (cnt>0) or when we run out of name contexts.
+ */
+ if( cnt==0 ){
+ pNC = pNC->pNext;
+ nSubquery++;
+ }
+ }
+
+ /*
+ ** If X and Y are NULL (in other words if only the column name Z is
+ ** supplied) and the value of Z is enclosed in double-quotes, then
+ ** Z is a string literal if it doesn't match any column names. In that
+ ** case, we need to return right away and not make any changes to
+ ** pExpr.
+ **
+ ** Because no reference was made to outer contexts, the pNC->nRef
+ ** fields are not changed in any context.
+ */
+ if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
+ pExpr->op = TK_STRING;
+ pExpr->pTab = 0;
+ return WRC_Prune;
+ }
+
+ /*
+ ** cnt==0 means there was not match. cnt>1 means there were two or
+ ** more matches. Either way, we have an error.
+ */
+ if( cnt!=1 ){
+ const char *zErr;
+ zErr = cnt==0 ? "no such column" : "ambiguous column name";
+ if( zDb ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
+ }else if( zTab ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
+ }else{
+ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
+ }
+ pParse->checkSchema = 1;
+ pTopNC->nErr++;
+ }
+
+ /* If a column from a table in pSrcList is referenced, then record
+ ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
+ ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
+ ** column number is greater than the number of bits in the bitmask
+ ** then set the high-order bit of the bitmask.
+ */
+ if( pExpr->iColumn>=0 && pMatch!=0 ){
+ int n = pExpr->iColumn;
+ testcase( n==BMS-1 );
+ if( n>=BMS ){
+ n = BMS-1;
+ }
+ assert( pMatch->iCursor==pExpr->iTable );
+ pMatch->colUsed |= ((Bitmask)1)<<n;
+ }
+
+ /* Clean up and return
+ */
+ sqlite3ExprDelete(db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqlite3ExprDelete(db, pExpr->pRight);
+ pExpr->pRight = 0;
+ pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
+lookupname_end:
+ if( cnt==1 ){
+ assert( pNC!=0 );
+ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+ /* Increment the nRef value on all name contexts from TopNC up to
+ ** the point where the name matched. */
+ for(;;){
+ assert( pTopNC!=0 );
+ pTopNC->nRef++;
+ if( pTopNC==pNC ) break;
+ pTopNC = pTopNC->pNext;
+ }
+ return WRC_Prune;
+ } else {
+ return WRC_Abort;
+ }
+}
+
+/*
+** Allocate and return a pointer to an expression to load the column iCol
+** from datasource iSrc in SrcList pSrc.
+*/
+SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
+ Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
+ if( p ){
+ struct SrcList_item *pItem = &pSrc->a[iSrc];
+ p->pTab = pItem->pTab;
+ p->iTable = pItem->iCursor;
+ if( p->pTab->iPKey==iCol ){
+ p->iColumn = -1;
+ }else{
+ p->iColumn = (ynVar)iCol;
+ testcase( iCol==BMS );
+ testcase( iCol==BMS-1 );
+ pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
+ }
+ ExprSetProperty(p, EP_Resolved);
+ }
+ return p;
+}
+
+/*
+** This routine is callback for sqlite3WalkExpr().
+**
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree. Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
+**
+** This routine also does error checking and name resolution for
+** function names. The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
+*/
+static int resolveExprStep(Walker *pWalker, Expr *pExpr){
+ NameContext *pNC;
+ Parse *pParse;
+
+ pNC = pWalker->u.pNC;
+ assert( pNC!=0 );
+ pParse = pNC->pParse;
+ assert( pParse==pWalker->pParse );
+
+ if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
+ ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+ if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
+ SrcList *pSrcList = pNC->pSrcList;
+ int i;
+ for(i=0; i<pNC->pSrcList->nSrc; i++){
+ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+ }
+ }
+#endif
+ switch( pExpr->op ){
+
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
+ /* The special operator TK_ROW means use the rowid for the first
+ ** column in the FROM clause. This is used by the LIMIT and ORDER BY
+ ** clause processing on UPDATE and DELETE statements.
+ */
+ case TK_ROW: {
+ SrcList *pSrcList = pNC->pSrcList;
+ struct SrcList_item *pItem;
+ assert( pSrcList && pSrcList->nSrc==1 );
+ pItem = pSrcList->a;
+ pExpr->op = TK_COLUMN;
+ pExpr->pTab = pItem->pTab;
+ pExpr->iTable = pItem->iCursor;
+ pExpr->iColumn = -1;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ break;
+ }
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+
+ /* A lone identifier is the name of a column.
+ */
+ case TK_ID: {
+ return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
+ }
+
+ /* A table name and column name: ID.ID
+ ** Or a database, table and column: ID.ID.ID
+ */
+ case TK_DOT: {
+ const char *zColumn;
+ const char *zTable;
+ const char *zDb;
+ Expr *pRight;
+
+ /* if( pSrcList==0 ) break; */
+ pRight = pExpr->pRight;
+ if( pRight->op==TK_ID ){
+ zDb = 0;
+ zTable = pExpr->pLeft->u.zToken;
+ zColumn = pRight->u.zToken;
+ }else{
+ assert( pRight->op==TK_DOT );
+ zDb = pExpr->pLeft->u.zToken;
+ zTable = pRight->pLeft->u.zToken;
+ zColumn = pRight->pRight->u.zToken;
+ }
+ return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
+ }
+
+ /* Resolve function names
+ */
+ case TK_CONST_FUNC:
+ case TK_FUNCTION: {
+ ExprList *pList = pExpr->x.pList; /* The argument list */
+ int n = pList ? pList->nExpr : 0; /* Number of arguments */
+ int no_such_func = 0; /* True if no such function exists */
+ int wrong_num_args = 0; /* True if wrong number of arguments */
+ int is_agg = 0; /* True if is an aggregate function */
+ int auth; /* Authorization to use the function */
+ int nId; /* Number of characters in function name */
+ const char *zId; /* The function name. */
+ FuncDef *pDef; /* Information about the function */
+ u8 enc = ENC(pParse->db); /* The database encoding */
+
+ testcase( pExpr->op==TK_CONST_FUNC );
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ zId = pExpr->u.zToken;
+ nId = sqlite3Strlen30(zId);
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+ if( pDef==0 ){
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0);
+ if( pDef==0 ){
+ no_such_func = 1;
+ }else{
+ wrong_num_args = 1;
+ }
+ }else{
+ is_agg = pDef->xFunc==0;
+ }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pDef ){
+ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
+ if( auth!=SQLITE_OK ){
+ if( auth==SQLITE_DENY ){
+ sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
+ pDef->zName);
+ pNC->nErr++;
+ }
+ pExpr->op = TK_NULL;
+ return WRC_Prune;
+ }
+ }
+#endif
+ if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
+ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+ pNC->nErr++;
+ is_agg = 0;
+ }else if( no_such_func && pParse->db->init.busy==0 ){
+ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+ pNC->nErr++;
+ }else if( wrong_num_args ){
+ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+ nId, zId);
+ pNC->nErr++;
+ }
+ if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
+ sqlite3WalkExprList(pWalker, pList);
+ if( is_agg ){
+ NameContext *pNC2 = pNC;
+ pExpr->op = TK_AGG_FUNCTION;
+ pExpr->op2 = 0;
+ while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
+ pExpr->op2++;
+ pNC2 = pNC2->pNext;
+ }
+ if( pNC2 ) pNC2->ncFlags |= NC_HasAgg;
+ pNC->ncFlags |= NC_AllowAgg;
+ }
+ /* FIX ME: Compute pExpr->affinity based on the expected return
+ ** type of the function
+ */
+ return WRC_Prune;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT:
+ case TK_EXISTS: testcase( pExpr->op==TK_EXISTS );
+#endif
+ case TK_IN: {
+ testcase( pExpr->op==TK_IN );
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ int nRef = pNC->nRef;
+#ifndef SQLITE_OMIT_CHECK
+ if( (pNC->ncFlags & NC_IsCheck)!=0 ){
+ sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
+ }
+#endif
+ sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
+ assert( pNC->nRef>=nRef );
+ if( nRef!=pNC->nRef ){
+ ExprSetProperty(pExpr, EP_VarSelect);
+ }
+ }
+ break;
+ }
+#ifndef SQLITE_OMIT_CHECK
+ case TK_VARIABLE: {
+ if( (pNC->ncFlags & NC_IsCheck)!=0 ){
+ sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
+ }
+ break;
+ }
+#endif
+ }
+ return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
+}
+
+/*
+** pEList is a list of expressions which are really the result set of the
+** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause.
+** This routine checks to see if pE is a simple identifier which corresponds
+** to the AS-name of one of the terms of the expression list. If it is,
+** this routine return an integer between 1 and N where N is the number of
+** elements in pEList, corresponding to the matching entry. If there is
+** no match, or if pE is not a simple identifier, then this routine
+** return 0.
+**
+** pEList has been resolved. pE has not.
+*/
+static int resolveAsName(
+ Parse *pParse, /* Parsing context for error messages */
+ ExprList *pEList, /* List of expressions to scan */
+ Expr *pE /* Expression we are trying to match */
+){
+ int i; /* Loop counter */
+
+ UNUSED_PARAMETER(pParse);
+
+ if( pE->op==TK_ID ){
+ char *zCol = pE->u.zToken;
+ for(i=0; i<pEList->nExpr; i++){
+ char *zAs = pEList->a[i].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ return i+1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** pE is a pointer to an expression which is a single term in the
+** ORDER BY of a compound SELECT. The expression has not been
+** name resolved.
+**
+** At the point this routine is called, we already know that the
+** ORDER BY term is not an integer index into the result set. That
+** case is handled by the calling routine.
+**
+** Attempt to match pE against result set columns in the left-most
+** SELECT statement. Return the index i of the matching column,
+** as an indication to the caller that it should sort by the i-th column.
+** The left-most column is 1. In other words, the value returned is the
+** same integer value that would be used in the SQL statement to indicate
+** the column.
+**
+** If there is no match, return 0. Return -1 if an error occurs.
+*/
+static int resolveOrderByTermToExprList(
+ Parse *pParse, /* Parsing context for error messages */
+ Select *pSelect, /* The SELECT statement with the ORDER BY clause */
+ Expr *pE /* The specific ORDER BY term */
+){
+ int i; /* Loop counter */
+ ExprList *pEList; /* The columns of the result set */
+ NameContext nc; /* Name context for resolving pE */
+ sqlite3 *db; /* Database connection */
+ int rc; /* Return code from subprocedures */
+ u8 savedSuppErr; /* Saved value of db->suppressErr */
+
+ assert( sqlite3ExprIsInteger(pE, &i)==0 );
+ pEList = pSelect->pEList;
+
+ /* Resolve all names in the ORDER BY term expression
+ */
+ memset(&nc, 0, sizeof(nc));
+ nc.pParse = pParse;
+ nc.pSrcList = pSelect->pSrc;
+ nc.pEList = pEList;
+ nc.ncFlags = NC_AllowAgg;
+ nc.nErr = 0;
+ db = pParse->db;
+ savedSuppErr = db->suppressErr;
+ db->suppressErr = 1;
+ rc = sqlite3ResolveExprNames(&nc, pE);
+ db->suppressErr = savedSuppErr;
+ if( rc ) return 0;
+
+ /* Try to match the ORDER BY expression against an expression
+ ** in the result set. Return an 1-based index of the matching
+ ** result-set entry.
+ */
+ for(i=0; i<pEList->nExpr; i++){
+ if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
+ return i+1;
+ }
+ }
+
+ /* If no match, return 0. */
+ return 0;
+}
+
+/*
+** Generate an ORDER BY or GROUP BY term out-of-range error.
+*/
+static void resolveOutOfRangeError(
+ Parse *pParse, /* The error context into which to write the error */
+ const char *zType, /* "ORDER" or "GROUP" */
+ int i, /* The index (1-based) of the term out of range */
+ int mx /* Largest permissible value of i */
+){
+ sqlite3ErrorMsg(pParse,
+ "%r %s BY term out of range - should be "
+ "between 1 and %d", i, zType, mx);
+}
+
+/*
+** Analyze the ORDER BY clause in a compound SELECT statement. Modify
+** each term of the ORDER BY clause is a constant integer between 1
+** and N where N is the number of columns in the compound SELECT.
+**
+** ORDER BY terms that are already an integer between 1 and N are
+** unmodified. ORDER BY terms that are integers outside the range of
+** 1 through N generate an error. ORDER BY terms that are expressions
+** are matched against result set expressions of compound SELECT
+** beginning with the left-most SELECT and working toward the right.
+** At the first match, the ORDER BY expression is transformed into
+** the integer column number.
+**
+** Return the number of errors seen.
+*/
+static int resolveCompoundOrderBy(
+ Parse *pParse, /* Parsing context. Leave error messages here */
+ Select *pSelect /* The SELECT statement containing the ORDER BY */
+){
+ int i;
+ ExprList *pOrderBy;
+ ExprList *pEList;
+ sqlite3 *db;
+ int moreToDo = 1;
+
+ pOrderBy = pSelect->pOrderBy;
+ if( pOrderBy==0 ) return 0;
+ db = pParse->db;
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
+ return 1;
+ }
+#endif
+ for(i=0; i<pOrderBy->nExpr; i++){
+ pOrderBy->a[i].done = 0;
+ }
+ pSelect->pNext = 0;
+ while( pSelect->pPrior ){
+ pSelect->pPrior->pNext = pSelect;
+ pSelect = pSelect->pPrior;
+ }
+ while( pSelect && moreToDo ){
+ struct ExprList_item *pItem;
+ moreToDo = 0;
+ pEList = pSelect->pEList;
+ assert( pEList!=0 );
+ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+ int iCol = -1;
+ Expr *pE, *pDup;
+ if( pItem->done ) continue;
+ pE = sqlite3ExprSkipCollate(pItem->pExpr);
+ if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( iCol<=0 || iCol>pEList->nExpr ){
+ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
+ return 1;
+ }
+ }else{
+ iCol = resolveAsName(pParse, pEList, pE);
+ if( iCol==0 ){
+ pDup = sqlite3ExprDup(db, pE, 0);
+ if( !db->mallocFailed ){
+ assert(pDup);
+ iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
+ }
+ sqlite3ExprDelete(db, pDup);
+ }
+ }
+ if( iCol>0 ){
+ /* Convert the ORDER BY term into an integer column number iCol,
+ ** taking care to preserve the COLLATE clause if it exists */
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+ if( pNew==0 ) return 1;
+ pNew->flags |= EP_IntValue;
+ pNew->u.iValue = iCol;
+ if( pItem->pExpr==pE ){
+ pItem->pExpr = pNew;
+ }else{
+ assert( pItem->pExpr->op==TK_COLLATE );
+ assert( pItem->pExpr->pLeft==pE );
+ pItem->pExpr->pLeft = pNew;
+ }
+ sqlite3ExprDelete(db, pE);
+ pItem->iOrderByCol = (u16)iCol;
+ pItem->done = 1;
+ }else{
+ moreToDo = 1;
+ }
+ }
+ pSelect = pSelect->pNext;
+ }
+ for(i=0; i<pOrderBy->nExpr; i++){
+ if( pOrderBy->a[i].done==0 ){
+ sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
+ "column in the result set", i+1);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
+** the SELECT statement pSelect. If any term is reference to a
+** result set expression (as determined by the ExprList.a.iCol field)
+** then convert that term into a copy of the corresponding result set
+** column.
+**
+** If any errors are detected, add an error message to pParse and
+** return non-zero. Return zero if no errors are seen.
+*/
+SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
+ Parse *pParse, /* Parsing context. Leave error messages here */
+ Select *pSelect, /* The SELECT statement containing the clause */
+ ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
+ const char *zType /* "ORDER" or "GROUP" */
+){
+ int i;
+ sqlite3 *db = pParse->db;
+ ExprList *pEList;
+ struct ExprList_item *pItem;
+
+ if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
+ return 1;
+ }
+#endif
+ pEList = pSelect->pEList;
+ assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
+ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+ if( pItem->iOrderByCol ){
+ if( pItem->iOrderByCol>pEList->nExpr ){
+ resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
+ return 1;
+ }
+ resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
+ }
+ }
+ return 0;
+}
+
+/*
+** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
+** The Name context of the SELECT statement is pNC. zType is either
+** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
+**
+** This routine resolves each term of the clause into an expression.
+** If the order-by term is an integer I between 1 and N (where N is the
+** number of columns in the result set of the SELECT) then the expression
+** in the resolution is a copy of the I-th result-set expression. If
+** the order-by term is an identify that corresponds to the AS-name of
+** a result-set expression, then the term resolves to a copy of the
+** result-set expression. Otherwise, the expression is resolved in
+** the usual way - using sqlite3ResolveExprNames().
+**
+** This routine returns the number of errors. If errors occur, then
+** an appropriate error message might be left in pParse. (OOM errors
+** excepted.)
+*/
+static int resolveOrderGroupBy(
+ NameContext *pNC, /* The name context of the SELECT statement */
+ Select *pSelect, /* The SELECT statement holding pOrderBy */
+ ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */
+ const char *zType /* Either "ORDER" or "GROUP", as appropriate */
+){
+ int i, j; /* Loop counters */
+ int iCol; /* Column number */
+ struct ExprList_item *pItem; /* A term of the ORDER BY clause */
+ Parse *pParse; /* Parsing context */
+ int nResult; /* Number of terms in the result set */
+
+ if( pOrderBy==0 ) return 0;
+ nResult = pSelect->pEList->nExpr;
+ pParse = pNC->pParse;
+ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+ Expr *pE = pItem->pExpr;
+ iCol = resolveAsName(pParse, pSelect->pEList, pE);
+ if( iCol>0 ){
+ /* If an AS-name match is found, mark this ORDER BY column as being
+ ** a copy of the iCol-th result-set column. The subsequent call to
+ ** sqlite3ResolveOrderGroupBy() will convert the expression to a
+ ** copy of the iCol-th result-set expression. */
+ pItem->iOrderByCol = (u16)iCol;
+ continue;
+ }
+ if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
+ /* The ORDER BY term is an integer constant. Again, set the column
+ ** number so that sqlite3ResolveOrderGroupBy() will convert the
+ ** order-by term to a copy of the result-set expression */
+ if( iCol<1 || iCol>0xffff ){
+ resolveOutOfRangeError(pParse, zType, i+1, nResult);
+ return 1;
+ }
+ pItem->iOrderByCol = (u16)iCol;
+ continue;
+ }
+
+ /* Otherwise, treat the ORDER BY term as an ordinary expression */
+ pItem->iOrderByCol = 0;
+ if( sqlite3ResolveExprNames(pNC, pE) ){
+ return 1;
+ }
+ for(j=0; j<pSelect->pEList->nExpr; j++){
+ if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr)==0 ){
+ pItem->iOrderByCol = j+1;
+ }
+ }
+ }
+ return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
+}
+
+/*
+** Resolve names in the SELECT statement p and all of its descendents.
+*/
+static int resolveSelectStep(Walker *pWalker, Select *p){
+ NameContext *pOuterNC; /* Context that contains this SELECT */
+ NameContext sNC; /* Name context of this SELECT */
+ int isCompound; /* True if p is a compound select */
+ int nCompound; /* Number of compound terms processed so far */
+ Parse *pParse; /* Parsing context */
+ ExprList *pEList; /* Result set expression list */
+ int i; /* Loop counter */
+ ExprList *pGroupBy; /* The GROUP BY clause */
+ Select *pLeftmost; /* Left-most of SELECT of a compound */
+ sqlite3 *db; /* Database connection */
+
+
+ assert( p!=0 );
+ if( p->selFlags & SF_Resolved ){
+ return WRC_Prune;
+ }
+ pOuterNC = pWalker->u.pNC;
+ pParse = pWalker->pParse;
+ db = pParse->db;
+
+ /* Normally sqlite3SelectExpand() will be called first and will have
+ ** already expanded this SELECT. However, if this is a subquery within
+ ** an expression, sqlite3ResolveExprNames() will be called without a
+ ** prior call to sqlite3SelectExpand(). When that happens, let
+ ** sqlite3SelectPrep() do all of the processing for this SELECT.
+ ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
+ ** this routine in the correct order.
+ */
+ if( (p->selFlags & SF_Expanded)==0 ){
+ sqlite3SelectPrep(pParse, p, pOuterNC);
+ return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
+ }
+
+ isCompound = p->pPrior!=0;
+ nCompound = 0;
+ pLeftmost = p;
+ while( p ){
+ assert( (p->selFlags & SF_Expanded)!=0 );
+ assert( (p->selFlags & SF_Resolved)==0 );
+ p->selFlags |= SF_Resolved;
+
+ /* Resolve the expressions in the LIMIT and OFFSET clauses. These
+ ** are not allowed to refer to any names, so pass an empty NameContext.
+ */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
+ sqlite3ResolveExprNames(&sNC, p->pOffset) ){
+ return WRC_Abort;
+ }
+
+ /* Recursively resolve names in all subqueries
+ */
+ for(i=0; i<p->pSrc->nSrc; i++){
+ struct SrcList_item *pItem = &p->pSrc->a[i];
+ if( pItem->pSelect ){
+ NameContext *pNC; /* Used to iterate name contexts */
+ int nRef = 0; /* Refcount for pOuterNC and outer contexts */
+ const char *zSavedContext = pParse->zAuthContext;
+
+ /* Count the total number of references to pOuterNC and all of its
+ ** parent contexts. After resolving references to expressions in
+ ** pItem->pSelect, check if this value has changed. If so, then
+ ** SELECT statement pItem->pSelect must be correlated. Set the
+ ** pItem->isCorrelated flag if this is the case. */
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
+
+ if( pItem->zName ) pParse->zAuthContext = pItem->zName;
+ sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
+ pParse->zAuthContext = zSavedContext;
+ if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
+
+ for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
+ assert( pItem->isCorrelated==0 && nRef<=0 );
+ pItem->isCorrelated = (nRef!=0);
+ }
+ }
+
+ /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+ ** resolve the result-set expression list.
+ */
+ sNC.ncFlags = NC_AllowAgg;
+ sNC.pSrcList = p->pSrc;
+ sNC.pNext = pOuterNC;
+
+ /* Resolve names in the result set. */
+ pEList = p->pEList;
+ assert( pEList!=0 );
+ for(i=0; i<pEList->nExpr; i++){
+ Expr *pX = pEList->a[i].pExpr;
+ if( sqlite3ResolveExprNames(&sNC, pX) ){
+ return WRC_Abort;
+ }
+ }
+
+ /* If there are no aggregate functions in the result-set, and no GROUP BY
+ ** expression, do not allow aggregates in any of the other expressions.
+ */
+ assert( (p->selFlags & SF_Aggregate)==0 );
+ pGroupBy = p->pGroupBy;
+ if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
+ p->selFlags |= SF_Aggregate;
+ }else{
+ sNC.ncFlags &= ~NC_AllowAgg;
+ }
+
+ /* If a HAVING clause is present, then there must be a GROUP BY clause.
+ */
+ if( p->pHaving && !pGroupBy ){
+ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+ return WRC_Abort;
+ }
+
+ /* Add the expression list to the name-context before parsing the
+ ** other expressions in the SELECT statement. This is so that
+ ** expressions in the WHERE clause (etc.) can refer to expressions by
+ ** aliases in the result set.
+ **
+ ** Minor point: If this is the case, then the expression will be
+ ** re-evaluated for each reference to it.
+ */
+ sNC.pEList = p->pEList;
+ if( sqlite3ResolveExprNames(&sNC, p->pWhere) ||
+ sqlite3ResolveExprNames(&sNC, p->pHaving)
+ ){
+ return WRC_Abort;
+ }
+
+ /* The ORDER BY and GROUP BY clauses may not refer to terms in
+ ** outer queries
+ */
+ sNC.pNext = 0;
+ sNC.ncFlags |= NC_AllowAgg;
+
+ /* Process the ORDER BY clause for singleton SELECT statements.
+ ** The ORDER BY clause for compounds SELECT statements is handled
+ ** below, after all of the result-sets for all of the elements of
+ ** the compound have been resolved.
+ */
+ if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
+ return WRC_Abort;
+ }
+ if( db->mallocFailed ){
+ return WRC_Abort;
+ }
+
+ /* Resolve the GROUP BY clause. At the same time, make sure
+ ** the GROUP BY clause does not contain aggregate functions.
+ */
+ if( pGroupBy ){
+ struct ExprList_item *pItem;
+
+ if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
+ return WRC_Abort;
+ }
+ for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
+ if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
+ sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
+ "the GROUP BY clause");
+ return WRC_Abort;
+ }
+ }
+ }
+
+ /* Advance to the next term of the compound
+ */
+ p = p->pPrior;
+ nCompound++;
+ }
+
+ /* Resolve the ORDER BY on a compound SELECT after all terms of
+ ** the compound have been resolved.
+ */
+ if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
+ return WRC_Abort;
+ }
+
+ return WRC_Prune;
+}
+
+/*
+** This routine walks an expression tree and resolves references to
+** table columns and result-set columns. At the same time, do error
+** checking on function usage and set a flag if any aggregate functions
+** are seen.
+**
+** To resolve table columns references we look for nodes (or subtrees) of the
+** form X.Y.Z or Y.Z or just Z where
+**
+** X: The name of a database. Ex: "main" or "temp" or
+** the symbolic name assigned to an ATTACH-ed database.
+**
+** Y: The name of a table in a FROM clause. Or in a trigger
+** one of the special names "old" or "new".
+**
+** Z: The name of a column in table Y.
+**
+** The node at the root of the subtree is modified as follows:
+**
+** Expr.op Changed to TK_COLUMN
+** Expr.pTab Points to the Table object for X.Y
+** Expr.iColumn The column index in X.Y. -1 for the rowid.
+** Expr.iTable The VDBE cursor number for X.Y
+**
+**
+** To resolve result-set references, look for expression nodes of the
+** form Z (with no X and Y prefix) where the Z matches the right-hand
+** size of an AS clause in the result-set of a SELECT. The Z expression
+** is replaced by a copy of the left-hand side of the result-set expression.
+** Table-name and function resolution occurs on the substituted expression
+** tree. For example, in:
+**
+** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
+**
+** The "x" term of the order by is replaced by "a+b" to render:
+**
+** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
+**
+** Function calls are checked to make sure that the function is
+** defined and that the correct number of arguments are specified.
+** If the function is an aggregate function, then the NC_HasAgg flag is
+** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
+** If an expression contains aggregate functions then the EP_Agg
+** property on the expression is set.
+**
+** An error message is left in pParse if anything is amiss. The number
+** if errors is returned.
+*/
+SQLITE_PRIVATE int sqlite3ResolveExprNames(
+ NameContext *pNC, /* Namespace to resolve expressions in. */
+ Expr *pExpr /* The expression to be analyzed. */
+){
+ u8 savedHasAgg;
+ Walker w;
+
+ if( pExpr==0 ) return 0;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ {
+ Parse *pParse = pNC->pParse;
+ if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
+ return 1;
+ }
+ pParse->nHeight += pExpr->nHeight;
+ }
+#endif
+ savedHasAgg = pNC->ncFlags & NC_HasAgg;
+ pNC->ncFlags &= ~NC_HasAgg;
+ w.xExprCallback = resolveExprStep;
+ w.xSelectCallback = resolveSelectStep;
+ w.pParse = pNC->pParse;
+ w.u.pNC = pNC;
+ sqlite3WalkExpr(&w, pExpr);
+#if SQLITE_MAX_EXPR_DEPTH>0
+ pNC->pParse->nHeight -= pExpr->nHeight;
+#endif
+ if( pNC->nErr>0 || w.pParse->nErr>0 ){
+ ExprSetProperty(pExpr, EP_Error);
+ }
+ if( pNC->ncFlags & NC_HasAgg ){
+ ExprSetProperty(pExpr, EP_Agg);
+ }else if( savedHasAgg ){
+ pNC->ncFlags |= NC_HasAgg;
+ }
+ return ExprHasProperty(pExpr, EP_Error);
+}
+
+
+/*
+** Resolve all names in all expressions of a SELECT and in all
+** decendents of the SELECT, including compounds off of p->pPrior,
+** subqueries in expressions, and subqueries used as FROM clause
+** terms.
+**
+** See sqlite3ResolveExprNames() for a description of the kinds of
+** transformations that occur.
+**
+** All SELECT statements should have been expanded using
+** sqlite3SelectExpand() prior to invoking this routine.
+*/
+SQLITE_PRIVATE void sqlite3ResolveSelectNames(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The SELECT statement being coded. */
+ NameContext *pOuterNC /* Name context for parent SELECT statement */
+){
+ Walker w;
+
+ assert( p!=0 );
+ w.xExprCallback = resolveExprStep;
+ w.xSelectCallback = resolveSelectStep;
+ w.pParse = pParse;
+ w.u.pNC = pOuterNC;
+ sqlite3WalkSelect(&w, p);
+}
+
+/************** End of resolve.c *********************************************/
+/************** Begin file expr.c ********************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains routines used for analyzing expressions and
+** for generating VDBE code that evaluates expressions in SQLite.
+*/
+
+/*
+** Return the 'affinity' of the expression pExpr if any.
+**
+** If pExpr is a column, a reference to a column via an 'AS' alias,
+** or a sub-select with a column as the return value, then the
+** affinity of that column is returned. Otherwise, 0x00 is returned,
+** indicating no affinity for the expression.
+**
+** i.e. the WHERE clause expresssions in the following statements all
+** have an affinity:
+**
+** CREATE TABLE t1(a);
+** SELECT * FROM t1 WHERE a;
+** SELECT a AS b FROM t1 WHERE b;
+** SELECT * FROM t1 WHERE (select a from t1);
+*/
+SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
+ int op;
+ pExpr = sqlite3ExprSkipCollate(pExpr);
+ op = pExpr->op;
+ if( op==TK_SELECT ){
+ assert( pExpr->flags&EP_xIsSelect );
+ return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
+ }
+#ifndef SQLITE_OMIT_CAST
+ if( op==TK_CAST ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ return sqlite3AffinityType(pExpr->u.zToken);
+ }
+#endif
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
+ && pExpr->pTab!=0
+ ){
+ /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
+ int j = pExpr->iColumn;
+ if( j<0 ) return SQLITE_AFF_INTEGER;
+ assert( pExpr->pTab && j<pExpr->pTab->nCol );
+ return pExpr->pTab->aCol[j].affinity;
+ }
+ return pExpr->affinity;
+}
+
+/*
+** Set the collating sequence for expression pExpr to be the collating
+** sequence named by pToken. Return a pointer to a new Expr node that
+** implements the COLLATE operator.
+**
+** If a memory allocation error occurs, that fact is recorded in pParse->db
+** and the pExpr parameter is returned unchanged.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
+ if( pCollName->n>0 ){
+ Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
+ if( pNew ){
+ pNew->pLeft = pExpr;
+ pNew->flags |= EP_Collate;
+ pExpr = pNew;
+ }
+ }
+ return pExpr;
+}
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
+ Token s;
+ assert( zC!=0 );
+ s.z = zC;
+ s.n = sqlite3Strlen30(s.z);
+ return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
+}
+
+/*
+** Skip over any TK_COLLATE and/or TK_AS operators at the root of
+** an expression.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
+ while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
+ pExpr = pExpr->pLeft;
+ }
+ return pExpr;
+}
+
+/*
+** Return the collation sequence for the expression pExpr. If
+** there is no defined collating sequence, return NULL.
+**
+** The collating sequence might be determined by a COLLATE operator
+** or by the presence of a column with a defined collating sequence.
+** COLLATE operators take first precedence. Left operands take
+** precedence over right operands.
+*/
+SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
+ sqlite3 *db = pParse->db;
+ CollSeq *pColl = 0;
+ Expr *p = pExpr;
+ while( p ){
+ int op = p->op;
+ if( op==TK_CAST || op==TK_UPLUS ){
+ p = p->pLeft;
+ continue;
+ }
+ assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
+ if( op==TK_COLLATE ){
+ if( db->init.busy ){
+ /* Do not report errors when parsing while the schema */
+ pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
+ }else{
+ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
+ }
+ break;
+ }
+ if( p->pTab!=0
+ && (op==TK_AGG_COLUMN || op==TK_COLUMN
+ || op==TK_REGISTER || op==TK_TRIGGER)
+ ){
+ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
+ int j = p->iColumn;
+ if( j>=0 ){
+ const char *zColl = p->pTab->aCol[j].zColl;
+ pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
+ }
+ break;
+ }
+ if( p->flags & EP_Collate ){
+ if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
+ p = p->pLeft;
+ }else{
+ p = p->pRight;
+ }
+ }else{
+ break;
+ }
+ }
+ if( sqlite3CheckCollSeq(pParse, pColl) ){
+ pColl = 0;
+ }
+ return pColl;
+}
+
+/*
+** pExpr is an operand of a comparison operator. aff2 is the
+** type affinity of the other operand. This routine returns the
+** type affinity that should be used for the comparison operator.
+*/
+SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2){
+ char aff1 = sqlite3ExprAffinity(pExpr);
+ if( aff1 && aff2 ){
+ /* Both sides of the comparison are columns. If one has numeric
+ ** affinity, use that. Otherwise use no affinity.
+ */
+ if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
+ return SQLITE_AFF_NUMERIC;
+ }else{
+ return SQLITE_AFF_NONE;
+ }
+ }else if( !aff1 && !aff2 ){
+ /* Neither side of the comparison is a column. Compare the
+ ** results directly.
+ */
+ return SQLITE_AFF_NONE;
+ }else{
+ /* One side is a column, the other is not. Use the columns affinity. */
+ assert( aff1==0 || aff2==0 );
+ return (aff1 + aff2);
+ }
+}
+
+/*
+** pExpr is a comparison operator. Return the type affinity that should
+** be applied to both operands prior to doing the comparison.
+*/
+static char comparisonAffinity(Expr *pExpr){
+ char aff;
+ assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
+ pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
+ pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
+ assert( pExpr->pLeft );
+ aff = sqlite3ExprAffinity(pExpr->pLeft);
+ if( pExpr->pRight ){
+ aff = sqlite3CompareAffinity(pExpr->pRight, aff);
+ }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
+ }else if( !aff ){
+ aff = SQLITE_AFF_NONE;
+ }
+ return aff;
+}
+
+/*
+** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
+** idx_affinity is the affinity of an indexed column. Return true
+** if the index with affinity idx_affinity may be used to implement
+** the comparison in pExpr.
+*/
+SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
+ char aff = comparisonAffinity(pExpr);
+ switch( aff ){
+ case SQLITE_AFF_NONE:
+ return 1;
+ case SQLITE_AFF_TEXT:
+ return idx_affinity==SQLITE_AFF_TEXT;
+ default:
+ return sqlite3IsNumericAffinity(idx_affinity);
+ }
+}
+
+/*
+** Return the P5 value that should be used for a binary comparison
+** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
+*/
+static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
+ u8 aff = (char)sqlite3ExprAffinity(pExpr2);
+ aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
+ return aff;
+}
+
+/*
+** Return a pointer to the collation sequence that should be used by
+** a binary comparison operator comparing pLeft and pRight.
+**
+** If the left hand expression has a collating sequence type, then it is
+** used. Otherwise the collation sequence for the right hand expression
+** is used, or the default (BINARY) if neither expression has a collating
+** type.
+**
+** Argument pRight (but not pLeft) may be a null pointer. In this case,
+** it is not considered.
+*/
+SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
+ Parse *pParse,
+ Expr *pLeft,
+ Expr *pRight
+){
+ CollSeq *pColl;
+ assert( pLeft );
+ if( pLeft->flags & EP_Collate ){
+ pColl = sqlite3ExprCollSeq(pParse, pLeft);
+ }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
+ pColl = sqlite3ExprCollSeq(pParse, pRight);
+ }else{
+ pColl = sqlite3ExprCollSeq(pParse, pLeft);
+ if( !pColl ){
+ pColl = sqlite3ExprCollSeq(pParse, pRight);
+ }
+ }
+ return pColl;
+}
+
+/*
+** Generate code for a comparison operator.
+*/
+static int codeCompare(
+ Parse *pParse, /* The parsing (and code generating) context */
+ Expr *pLeft, /* The left operand */
+ Expr *pRight, /* The right operand */
+ int opcode, /* The comparison opcode */
+ int in1, int in2, /* Register holding operands */
+ int dest, /* Jump here if true. */
+ int jumpIfNull /* If true, jump if either operand is NULL */
+){
+ int p5;
+ int addr;
+ CollSeq *p4;
+
+ p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
+ p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
+ addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
+ (void*)p4, P4_COLLSEQ);
+ sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
+ return addr;
+}
+
+#if SQLITE_MAX_EXPR_DEPTH>0
+/*
+** Check that argument nHeight is less than or equal to the maximum
+** expression depth allowed. If it is not, leave an error message in
+** pParse.
+*/
+SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
+ int rc = SQLITE_OK;
+ int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
+ if( nHeight>mxHeight ){
+ sqlite3ErrorMsg(pParse,
+ "Expression tree is too large (maximum depth %d)", mxHeight
+ );
+ rc = SQLITE_ERROR;
+ }
+ return rc;
+}
+
+/* The following three functions, heightOfExpr(), heightOfExprList()
+** and heightOfSelect(), are used to determine the maximum height
+** of any expression tree referenced by the structure passed as the
+** first argument.
+**
+** If this maximum height is greater than the current value pointed
+** to by pnHeight, the second parameter, then set *pnHeight to that
+** value.
+*/
+static void heightOfExpr(Expr *p, int *pnHeight){
+ if( p ){
+ if( p->nHeight>*pnHeight ){
+ *pnHeight = p->nHeight;
+ }
+ }
+}
+static void heightOfExprList(ExprList *p, int *pnHeight){
+ if( p ){
+ int i;
+ for(i=0; i<p->nExpr; i++){
+ heightOfExpr(p->a[i].pExpr, pnHeight);
+ }
+ }
+}
+static void heightOfSelect(Select *p, int *pnHeight){
+ if( p ){
+ heightOfExpr(p->pWhere, pnHeight);
+ heightOfExpr(p->pHaving, pnHeight);
+ heightOfExpr(p->pLimit, pnHeight);
+ heightOfExpr(p->pOffset, pnHeight);
+ heightOfExprList(p->pEList, pnHeight);
+ heightOfExprList(p->pGroupBy, pnHeight);
+ heightOfExprList(p->pOrderBy, pnHeight);
+ heightOfSelect(p->pPrior, pnHeight);
+ }
+}
+
+/*
+** Set the Expr.nHeight variable in the structure passed as an
+** argument. An expression with no children, Expr.pList or
+** Expr.pSelect member has a height of 1. Any other expression
+** has a height equal to the maximum height of any other
+** referenced Expr plus one.
+*/
+static void exprSetHeight(Expr *p){
+ int nHeight = 0;
+ heightOfExpr(p->pLeft, &nHeight);
+ heightOfExpr(p->pRight, &nHeight);
+ if( ExprHasProperty(p, EP_xIsSelect) ){
+ heightOfSelect(p->x.pSelect, &nHeight);
+ }else{
+ heightOfExprList(p->x.pList, &nHeight);
+ }
+ p->nHeight = nHeight + 1;
+}
+
+/*
+** Set the Expr.nHeight variable using the exprSetHeight() function. If
+** the height is greater than the maximum allowed expression depth,
+** leave an error in pParse.
+*/
+SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
+ exprSetHeight(p);
+ sqlite3ExprCheckHeight(pParse, p->nHeight);
+}
+
+/*
+** Return the maximum height of any expression tree referenced
+** by the select statement passed as an argument.
+*/
+SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
+ int nHeight = 0;
+ heightOfSelect(p, &nHeight);
+ return nHeight;
+}
+#else
+ #define exprSetHeight(y)
+#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
+
+/*
+** This routine is the core allocator for Expr nodes.
+**
+** Construct a new expression node and return a pointer to it. Memory
+** for this node and for the pToken argument is a single allocation
+** obtained from sqlite3DbMalloc(). The calling function
+** is responsible for making sure the node eventually gets freed.
+**
+** If dequote is true, then the token (if it exists) is dequoted.
+** If dequote is false, no dequoting is performance. The deQuote
+** parameter is ignored if pToken is NULL or if the token does not
+** appear to be quoted. If the quotes were of the form "..." (double-quotes)
+** then the EP_DblQuoted flag is set on the expression node.
+**
+** Special case: If op==TK_INTEGER and pToken points to a string that
+** can be translated into a 32-bit integer, then the token is not
+** stored in u.zToken. Instead, the integer values is written
+** into u.iValue and the EP_IntValue flag is set. No extra storage
+** is allocated to hold the integer text and the dequote flag is ignored.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
+ sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
+ int op, /* Expression opcode */
+ const Token *pToken, /* Token argument. Might be NULL */
+ int dequote /* True to dequote */
+){
+ Expr *pNew;
+ int nExtra = 0;
+ int iValue = 0;
+
+ if( pToken ){
+ if( op!=TK_INTEGER || pToken->z==0
+ || sqlite3GetInt32(pToken->z, &iValue)==0 ){
+ nExtra = pToken->n+1;
+ assert( iValue>=0 );
+ }
+ }
+ pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
+ if( pNew ){
+ pNew->op = (u8)op;
+ pNew->iAgg = -1;
+ if( pToken ){
+ if( nExtra==0 ){
+ pNew->flags |= EP_IntValue;
+ pNew->u.iValue = iValue;
+ }else{
+ int c;
+ pNew->u.zToken = (char*)&pNew[1];
+ assert( pToken->z!=0 || pToken->n==0 );
+ if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
+ pNew->u.zToken[pToken->n] = 0;
+ if( dequote && nExtra>=3
+ && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
+ sqlite3Dequote(pNew->u.zToken);
+ if( c=='"' ) pNew->flags |= EP_DblQuoted;
+ }
+ }
+ }
+#if SQLITE_MAX_EXPR_DEPTH>0
+ pNew->nHeight = 1;
+#endif
+ }
+ return pNew;
+}
+
+/*
+** Allocate a new expression node from a zero-terminated token that has
+** already been dequoted.
+*/
+SQLITE_PRIVATE Expr *sqlite3Expr(
+ sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
+ int op, /* Expression opcode */
+ const char *zToken /* Token argument. Might be NULL */
+){
+ Token x;
+ x.z = zToken;
+ x.n = zToken ? sqlite3Strlen30(zToken) : 0;
+ return sqlite3ExprAlloc(db, op, &x, 0);
+}
+
+/*
+** Attach subtrees pLeft and pRight to the Expr node pRoot.
+**
+** If pRoot==NULL that means that a memory allocation error has occurred.
+** In that case, delete the subtrees pLeft and pRight.
+*/
+SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
+ sqlite3 *db,
+ Expr *pRoot,
+ Expr *pLeft,
+ Expr *pRight
+){
+ if( pRoot==0 ){
+ assert( db->mallocFailed );
+ sqlite3ExprDelete(db, pLeft);
+ sqlite3ExprDelete(db, pRight);
+ }else{
+ if( pRight ){
+ pRoot->pRight = pRight;
+ pRoot->flags |= EP_Collate & pRight->flags;
+ }
+ if( pLeft ){
+ pRoot->pLeft = pLeft;
+ pRoot->flags |= EP_Collate & pLeft->flags;
+ }
+ exprSetHeight(pRoot);
+ }
+}
+
+/*
+** Allocate a Expr node which joins as many as two subtrees.
+**
+** One or both of the subtrees can be NULL. Return a pointer to the new
+** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed,
+** free the subtrees and return NULL.
+*/
+SQLITE_PRIVATE Expr *sqlite3PExpr(
+ Parse *pParse, /* Parsing context */
+ int op, /* Expression opcode */
+ Expr *pLeft, /* Left operand */
+ Expr *pRight, /* Right operand */
+ const Token *pToken /* Argument token */
+){
+ Expr *p;
+ if( op==TK_AND && pLeft && pRight ){
+ /* Take advantage of short-circuit false optimization for AND */
+ p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
+ }else{
+ p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
+ }
+ if( p ) {
+ sqlite3ExprCheckHeight(pParse, p->nHeight);
+ }
+ return p;
+}
+
+/*
+** Return 1 if an expression must be FALSE in all cases and 0 if the
+** expression might be true. This is an optimization. If is OK to
+** return 0 here even if the expression really is always false (a
+** false negative). But it is a bug to return 1 if the expression
+** might be true in some rare circumstances (a false positive.)
+**
+** Note that if the expression is part of conditional for a
+** LEFT JOIN, then we cannot determine at compile-time whether or not
+** is it true or false, so always return 0.
+*/
+static int exprAlwaysFalse(Expr *p){
+ int v = 0;
+ if( ExprHasProperty(p, EP_FromJoin) ) return 0;
+ if( !sqlite3ExprIsInteger(p, &v) ) return 0;
+ return v==0;
+}
+
+/*
+** Join two expressions using an AND operator. If either expression is
+** NULL, then just return the other expression.
+**
+** If one side or the other of the AND is known to be false, then instead
+** of returning an AND expression, just return a constant expression with
+** a value of false.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
+ if( pLeft==0 ){
+ return pRight;
+ }else if( pRight==0 ){
+ return pLeft;
+ }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){
+ sqlite3ExprDelete(db, pLeft);
+ sqlite3ExprDelete(db, pRight);
+ return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
+ }else{
+ Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0);
+ sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
+ return pNew;
+ }
+}
+
+/*
+** Construct a new expression node for a function with multiple
+** arguments.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
+ Expr *pNew;
+ sqlite3 *db = pParse->db;
+ assert( pToken );
+ pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
+ if( pNew==0 ){
+ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
+ return 0;
+ }
+ pNew->x.pList = pList;
+ assert( !ExprHasProperty(pNew, EP_xIsSelect) );
+ sqlite3ExprSetHeight(pParse, pNew);
+ return pNew;
+}
+
+/*
+** Assign a variable number to an expression that encodes a wildcard
+** in the original SQL statement.
+**
+** Wildcards consisting of a single "?" are assigned the next sequential
+** variable number.
+**
+** Wildcards of the form "?nnn" are assigned the number "nnn". We make
+** sure "nnn" is not too be to avoid a denial of service attack when
+** the SQL statement comes from an external source.
+**
+** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
+** as the previous instance of the same wildcard. Or if this is the first
+** instance of the wildcard, the next sequenial variable number is
+** assigned.
+*/
+SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
+ sqlite3 *db = pParse->db;
+ const char *z;
+
+ if( pExpr==0 ) return;
+ assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
+ z = pExpr->u.zToken;
+ assert( z!=0 );
+ assert( z[0]!=0 );
+ if( z[1]==0 ){
+ /* Wildcard of the form "?". Assign the next variable number */
+ assert( z[0]=='?' );
+ pExpr->iColumn = (ynVar)(++pParse->nVar);
+ }else{
+ ynVar x = 0;
+ u32 n = sqlite3Strlen30(z);
+ if( z[0]=='?' ){
+ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
+ ** use it as the variable number */
+ i64 i;
+ int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
+ pExpr->iColumn = x = (ynVar)i;
+ testcase( i==0 );
+ testcase( i==1 );
+ testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
+ testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
+ if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
+ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
+ db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
+ x = 0;
+ }
+ if( i>pParse->nVar ){
+ pParse->nVar = (int)i;
+ }
+ }else{
+ /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
+ ** number as the prior appearance of the same name, or if the name
+ ** has never appeared before, reuse the same variable number
+ */
+ ynVar i;
+ for(i=0; i<pParse->nzVar; i++){
+ if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
+ pExpr->iColumn = x = (ynVar)i+1;
+ break;
+ }
+ }
+ if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
+ }
+ if( x>0 ){
+ if( x>pParse->nzVar ){
+ char **a;
+ a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
+ if( a==0 ) return; /* Error reported through db->mallocFailed */
+ pParse->azVar = a;
+ memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
+ pParse->nzVar = x;
+ }
+ if( z[0]!='?' || pParse->azVar[x-1]==0 ){
+ sqlite3DbFree(db, pParse->azVar[x-1]);
+ pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
+ }
+ }
+ }
+ if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
+ sqlite3ErrorMsg(pParse, "too many SQL variables");
+ }
+}
+
+/*
+** Recursively delete an expression tree.
+*/
+SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
+ if( p==0 ) return;
+ /* Sanity check: Assert that the IntValue is non-negative if it exists */
+ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
+ if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
+ sqlite3ExprDelete(db, p->pLeft);
+ sqlite3ExprDelete(db, p->pRight);
+ if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){
+ sqlite3DbFree(db, p->u.zToken);
+ }
+ if( ExprHasProperty(p, EP_xIsSelect) ){
+ sqlite3SelectDelete(db, p->x.pSelect);
+ }else{
+ sqlite3ExprListDelete(db, p->x.pList);
+ }
+ }
+ if( !ExprHasProperty(p, EP_Static) ){
+ sqlite3DbFree(db, p);
+ }
+}
+
+/*
+** Return the number of bytes allocated for the expression structure
+** passed as the first argument. This is always one of EXPR_FULLSIZE,
+** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
+*/
+static int exprStructSize(Expr *p){
+ if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
+ if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
+ return EXPR_FULLSIZE;
+}
+
+/*
+** The dupedExpr*Size() routines each return the number of bytes required
+** to store a copy of an expression or expression tree. They differ in
+** how much of the tree is measured.
+**
+** dupedExprStructSize() Size of only the Expr structure
+** dupedExprNodeSize() Size of Expr + space for token
+** dupedExprSize() Expr + token + subtree components
+**
+***************************************************************************
+**
+** The dupedExprStructSize() function returns two values OR-ed together:
+** (1) the space required for a copy of the Expr structure only and
+** (2) the EP_xxx flags that indicate what the structure size should be.
+** The return values is always one of:
+**
+** EXPR_FULLSIZE
+** EXPR_REDUCEDSIZE | EP_Reduced
+** EXPR_TOKENONLYSIZE | EP_TokenOnly
+**
+** The size of the structure can be found by masking the return value
+** of this routine with 0xfff. The flags can be found by masking the
+** return value with EP_Reduced|EP_TokenOnly.
+**
+** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
+** (unreduced) Expr objects as they or originally constructed by the parser.
+** During expression analysis, extra information is computed and moved into
+** later parts of teh Expr object and that extra information might get chopped
+** off if the expression is reduced. Note also that it does not work to
+** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal
+** to reduce a pristine expression tree from the parser. The implementation
+** of dupedExprStructSize() contain multiple assert() statements that attempt
+** to enforce this constraint.
+*/
+static int dupedExprStructSize(Expr *p, int flags){
+ int nSize;
+ assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
+ if( 0==(flags&EXPRDUP_REDUCE) ){
+ nSize = EXPR_FULLSIZE;
+ }else{
+ assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
+ assert( !ExprHasProperty(p, EP_FromJoin) );
+ assert( (p->flags2 & EP2_MallocedToken)==0 );
+ assert( (p->flags2 & EP2_Irreducible)==0 );
+ if( p->pLeft || p->pRight || p->x.pList ){
+ nSize = EXPR_REDUCEDSIZE | EP_Reduced;
+ }else{
+ nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
+ }
+ }
+ return nSize;
+}
+
+/*
+** This function returns the space in bytes required to store the copy
+** of the Expr structure and a copy of the Expr.u.zToken string (if that
+** string is defined.)
+*/
+static int dupedExprNodeSize(Expr *p, int flags){
+ int nByte = dupedExprStructSize(p, flags) & 0xfff;
+ if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
+ nByte += sqlite3Strlen30(p->u.zToken)+1;
+ }
+ return ROUND8(nByte);
+}
+
+/*
+** Return the number of bytes required to create a duplicate of the
+** expression passed as the first argument. The second argument is a
+** mask containing EXPRDUP_XXX flags.
+**
+** The value returned includes space to create a copy of the Expr struct
+** itself and the buffer referred to by Expr.u.zToken, if any.
+**
+** If the EXPRDUP_REDUCE flag is set, then the return value includes
+** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
+** and Expr.pRight variables (but not for any structures pointed to or
+** descended from the Expr.x.pList or Expr.x.pSelect variables).
+*/
+static int dupedExprSize(Expr *p, int flags){
+ int nByte = 0;
+ if( p ){
+ nByte = dupedExprNodeSize(p, flags);
+ if( flags&EXPRDUP_REDUCE ){
+ nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
+ }
+ }
+ return nByte;
+}
+
+/*
+** This function is similar to sqlite3ExprDup(), except that if pzBuffer
+** is not NULL then *pzBuffer is assumed to point to a buffer large enough
+** to store the copy of expression p, the copies of p->u.zToken
+** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
+** if any. Before returning, *pzBuffer is set to the first byte passed the
+** portion of the buffer copied into by this function.
+*/
+static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
+ Expr *pNew = 0; /* Value to return */
+ if( p ){
+ const int isReduced = (flags&EXPRDUP_REDUCE);
+ u8 *zAlloc;
+ u32 staticFlag = 0;
+
+ assert( pzBuffer==0 || isReduced );
+
+ /* Figure out where to write the new Expr structure. */
+ if( pzBuffer ){
+ zAlloc = *pzBuffer;
+ staticFlag = EP_Static;
+ }else{
+ zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags));
+ }
+ pNew = (Expr *)zAlloc;
+
+ if( pNew ){
+ /* Set nNewSize to the size allocated for the structure pointed to
+ ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
+ ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
+ ** by the copy of the p->u.zToken string (if any).
+ */
+ const unsigned nStructSize = dupedExprStructSize(p, flags);
+ const int nNewSize = nStructSize & 0xfff;
+ int nToken;
+ if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
+ nToken = sqlite3Strlen30(p->u.zToken) + 1;
+ }else{
+ nToken = 0;
+ }
+ if( isReduced ){
+ assert( ExprHasProperty(p, EP_Reduced)==0 );
+ memcpy(zAlloc, p, nNewSize);
+ }else{
+ int nSize = exprStructSize(p);
+ memcpy(zAlloc, p, nSize);
+ memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
+ }
+
+ /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
+ pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
+ pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
+ pNew->flags |= staticFlag;
+
+ /* Copy the p->u.zToken string, if any. */
+ if( nToken ){
+ char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
+ memcpy(zToken, p->u.zToken, nToken);
+ }
+
+ if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
+ /* Fill in the pNew->x.pSelect or pNew->x.pList member. */
+ if( ExprHasProperty(p, EP_xIsSelect) ){
+ pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
+ }else{
+ pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced);
+ }
+ }
+
+ /* Fill in pNew->pLeft and pNew->pRight. */
+ if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){
+ zAlloc += dupedExprNodeSize(p, flags);
+ if( ExprHasProperty(pNew, EP_Reduced) ){
+ pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
+ pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc);
+ }
+ if( pzBuffer ){
+ *pzBuffer = zAlloc;
+ }
+ }else{
+ pNew->flags2 = 0;
+ if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
+ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
+ pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
+ }
+ }
+
+ }
+ }
+ return pNew;
+}
+
+/*
+** The following group of routines make deep copies of expressions,
+** expression lists, ID lists, and select statements. The copies can
+** be deleted (by being passed to their respective ...Delete() routines)
+** without effecting the originals.
+**
+** The expression list, ID, and source lists return by sqlite3ExprListDup(),
+** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
+** by subsequent calls to sqlite*ListAppend() routines.
+**
+** Any tables that the SrcList might point to are not duplicated.
+**
+** The flags parameter contains a combination of the EXPRDUP_XXX flags.
+** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
+** truncated version of the usual Expr structure that will be stored as
+** part of the in-memory representation of the database schema.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
+ return exprDup(db, p, flags, 0);
+}
+SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
+ ExprList *pNew;
+ struct ExprList_item *pItem, *pOldItem;
+ int i;
+ if( p==0 ) return 0;
+ pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
+ if( pNew==0 ) return 0;
+ pNew->iECursor = 0;
+ pNew->nExpr = i = p->nExpr;
+ if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
+ pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) );
+ if( pItem==0 ){
+ sqlite3DbFree(db, pNew);
+ return 0;
+ }
+ pOldItem = p->a;
+ for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
+ Expr *pOldExpr = pOldItem->pExpr;
+ pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
+ pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
+ pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
+ pItem->sortOrder = pOldItem->sortOrder;
+ pItem->done = 0;
+ pItem->iOrderByCol = pOldItem->iOrderByCol;
+ pItem->iAlias = pOldItem->iAlias;
+ }
+ return pNew;
+}
+
+/*
+** If cursors, triggers, views and subqueries are all omitted from
+** the build, then none of the following routines, except for
+** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
+** called with a NULL argument.
+*/
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
+ || !defined(SQLITE_OMIT_SUBQUERY)
+SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
+ SrcList *pNew;
+ int i;
+ int nByte;
+ if( p==0 ) return 0;
+ nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
+ pNew = sqlite3DbMallocRaw(db, nByte );
+ if( pNew==0 ) return 0;
+ pNew->nSrc = pNew->nAlloc = p->nSrc;
+ for(i=0; i<p->nSrc; i++){
+ struct SrcList_item *pNewItem = &pNew->a[i];
+ struct SrcList_item *pOldItem = &p->a[i];
+ Table *pTab;
+ pNewItem->pSchema = pOldItem->pSchema;
+ pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
+ pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
+ pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
+ pNewItem->jointype = pOldItem->jointype;
+ pNewItem->iCursor = pOldItem->iCursor;
+ pNewItem->addrFillSub = pOldItem->addrFillSub;
+ pNewItem->regReturn = pOldItem->regReturn;
+ pNewItem->isCorrelated = pOldItem->isCorrelated;
+ pNewItem->viaCoroutine = pOldItem->viaCoroutine;
+ pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
+ pNewItem->notIndexed = pOldItem->notIndexed;
+ pNewItem->pIndex = pOldItem->pIndex;
+ pTab = pNewItem->pTab = pOldItem->pTab;
+ if( pTab ){
+ pTab->nRef++;
+ }
+ pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
+ pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
+ pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
+ pNewItem->colUsed = pOldItem->colUsed;
+ }
+ return pNew;
+}
+SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
+ IdList *pNew;
+ int i;
+ if( p==0 ) return 0;
+ pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
+ if( pNew==0 ) return 0;
+ pNew->nId = p->nId;
+ pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
+ if( pNew->a==0 ){
+ sqlite3DbFree(db, pNew);
+ return 0;
+ }
+ /* Note that because the size of the allocation for p->a[] is not
+ ** necessarily a power of two, sqlite3IdListAppend() may not be called
+ ** on the duplicate created by this function. */
+ for(i=0; i<p->nId; i++){
+ struct IdList_item *pNewItem = &pNew->a[i];
+ struct IdList_item *pOldItem = &p->a[i];
+ pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
+ pNewItem->idx = pOldItem->idx;
+ }
+ return pNew;
+}
+SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
+ Select *pNew, *pPrior;
+ if( p==0 ) return 0;
+ pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
+ if( pNew==0 ) return 0;
+ pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
+ pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
+ pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
+ pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
+ pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
+ pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
+ pNew->op = p->op;
+ pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags);
+ if( pPrior ) pPrior->pNext = pNew;
+ pNew->pNext = 0;
+ pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
+ pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
+ pNew->iLimit = 0;
+ pNew->iOffset = 0;
+ pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
+ pNew->pRightmost = 0;
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->addrOpenEphm[2] = -1;
+ return pNew;
+}
+#else
+SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
+ assert( p==0 );
+ return 0;
+}
+#endif
+
+
+/*
+** Add a new element to the end of an expression list. If pList is
+** initially NULL, then create a new expression list.
+**
+** If a memory allocation error occurs, the entire list is freed and
+** NULL is returned. If non-NULL is returned, then it is guaranteed
+** that the new entry was successfully appended.
+*/
+SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* List to which to append. Might be NULL */
+ Expr *pExpr /* Expression to be appended. Might be NULL */
+){
+ sqlite3 *db = pParse->db;
+ if( pList==0 ){
+ pList = sqlite3DbMallocZero(db, sizeof(ExprList) );
+ if( pList==0 ){
+ goto no_mem;
+ }
+ pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0]));
+ if( pList->a==0 ) goto no_mem;
+ }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
+ struct ExprList_item *a;
+ assert( pList->nExpr>0 );
+ a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0]));
+ if( a==0 ){
+ goto no_mem;
+ }
+ pList->a = a;
+ }
+ assert( pList->a!=0 );
+ if( 1 ){
+ struct ExprList_item *pItem = &pList->a[pList->nExpr++];
+ memset(pItem, 0, sizeof(*pItem));
+ pItem->pExpr = pExpr;
+ }
+ return pList;
+
+no_mem:
+ /* Avoid leaking memory if malloc has failed. */
+ sqlite3ExprDelete(db, pExpr);
+ sqlite3ExprListDelete(db, pList);
+ return 0;
+}
+
+/*
+** Set the ExprList.a[].zName element of the most recently added item
+** on the expression list.
+**
+** pList might be NULL following an OOM error. But pName should never be
+** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
+** is set.
+*/
+SQLITE_PRIVATE void sqlite3ExprListSetName(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* List to which to add the span. */
+ Token *pName, /* Name to be added */
+ int dequote /* True to cause the name to be dequoted */
+){
+ assert( pList!=0 || pParse->db->mallocFailed!=0 );
+ if( pList ){
+ struct ExprList_item *pItem;
+ assert( pList->nExpr>0 );
+ pItem = &pList->a[pList->nExpr-1];
+ assert( pItem->zName==0 );
+ pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
+ if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName);
+ }
+}
+
+/*
+** Set the ExprList.a[].zSpan element of the most recently added item
+** on the expression list.
+**
+** pList might be NULL following an OOM error. But pSpan should never be
+** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag
+** is set.
+*/
+SQLITE_PRIVATE void sqlite3ExprListSetSpan(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* List to which to add the span. */
+ ExprSpan *pSpan /* The span to be added */
+){
+ sqlite3 *db = pParse->db;
+ assert( pList!=0 || db->mallocFailed!=0 );
+ if( pList ){
+ struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
+ assert( pList->nExpr>0 );
+ assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr );
+ sqlite3DbFree(db, pItem->zSpan);
+ pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
+ (int)(pSpan->zEnd - pSpan->zStart));
+ }
+}
+
+/*
+** If the expression list pEList contains more than iLimit elements,
+** leave an error message in pParse.
+*/
+SQLITE_PRIVATE void sqlite3ExprListCheckLength(
+ Parse *pParse,
+ ExprList *pEList,
+ const char *zObject
+){
+ int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ testcase( pEList && pEList->nExpr==mx );
+ testcase( pEList && pEList->nExpr==mx+1 );
+ if( pEList && pEList->nExpr>mx ){
+ sqlite3ErrorMsg(pParse, "too many columns in %s", zObject);
+ }
+}
+
+/*
+** Delete an entire expression list.
+*/
+SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
+ int i;
+ struct ExprList_item *pItem;
+ if( pList==0 ) return;
+ assert( pList->a!=0 || pList->nExpr==0 );
+ for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
+ sqlite3ExprDelete(db, pItem->pExpr);
+ sqlite3DbFree(db, pItem->zName);
+ sqlite3DbFree(db, pItem->zSpan);
+ }
+ sqlite3DbFree(db, pList->a);
+ sqlite3DbFree(db, pList);
+}
+
+/*
+** These routines are Walker callbacks. Walker.u.pi is a pointer
+** to an integer. These routines are checking an expression to see
+** if it is a constant. Set *Walker.u.pi to 0 if the expression is
+** not constant.
+**
+** These callback routines are used to implement the following:
+**
+** sqlite3ExprIsConstant()
+** sqlite3ExprIsConstantNotJoin()
+** sqlite3ExprIsConstantOrFunction()
+**
+*/
+static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
+
+ /* If pWalker->u.i is 3 then any term of the expression that comes from
+ ** the ON or USING clauses of a join disqualifies the expression
+ ** from being considered constant. */
+ if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+ pWalker->u.i = 0;
+ return WRC_Abort;
+ }
+
+ switch( pExpr->op ){
+ /* Consider functions to be constant if all their arguments are constant
+ ** and pWalker->u.i==2 */
+ case TK_FUNCTION:
+ if( pWalker->u.i==2 ) return 0;
+ /* Fall through */
+ case TK_ID:
+ case TK_COLUMN:
+ case TK_AGG_FUNCTION:
+ case TK_AGG_COLUMN:
+ testcase( pExpr->op==TK_ID );
+ testcase( pExpr->op==TK_COLUMN );
+ testcase( pExpr->op==TK_AGG_FUNCTION );
+ testcase( pExpr->op==TK_AGG_COLUMN );
+ pWalker->u.i = 0;
+ return WRC_Abort;
+ default:
+ testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
+ testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
+ return WRC_Continue;
+ }
+}
+static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ pWalker->u.i = 0;
+ return WRC_Abort;
+}
+static int exprIsConst(Expr *p, int initFlag){
+ Walker w;
+ w.u.i = initFlag;
+ w.xExprCallback = exprNodeIsConstant;
+ w.xSelectCallback = selectNodeIsConstant;
+ sqlite3WalkExpr(&w, p);
+ return w.u.i;
+}
+
+/*
+** Walk an expression tree. Return 1 if the expression is constant
+** and 0 if it involves variables or function calls.
+**
+** For the purposes of this function, a double-quoted string (ex: "abc")
+** is considered a variable but a single-quoted string (ex: 'abc') is
+** a constant.
+*/
+SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
+ return exprIsConst(p, 1);
+}
+
+/*
+** Walk an expression tree. Return 1 if the expression is constant
+** that does no originate from the ON or USING clauses of a join.
+** Return 0 if it involves variables or function calls or terms from
+** an ON or USING clause.
+*/
+SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
+ return exprIsConst(p, 3);
+}
+
+/*
+** Walk an expression tree. Return 1 if the expression is constant
+** or a function call with constant arguments. Return and 0 if there
+** are any variables.
+**
+** For the purposes of this function, a double-quoted string (ex: "abc")
+** is considered a variable but a single-quoted string (ex: 'abc') is
+** a constant.
+*/
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p){
+ return exprIsConst(p, 2);
+}
+
+/*
+** If the expression p codes a constant integer that is small enough
+** to fit in a 32-bit integer, return 1 and put the value of the integer
+** in *pValue. If the expression is not an integer or if it is too big
+** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
+*/
+SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
+ int rc = 0;
+
+ /* If an expression is an integer literal that fits in a signed 32-bit
+ ** integer, then the EP_IntValue flag will have already been set */
+ assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0
+ || sqlite3GetInt32(p->u.zToken, &rc)==0 );
+
+ if( p->flags & EP_IntValue ){
+ *pValue = p->u.iValue;
+ return 1;
+ }
+ switch( p->op ){
+ case TK_UPLUS: {
+ rc = sqlite3ExprIsInteger(p->pLeft, pValue);
+ break;
+ }
+ case TK_UMINUS: {
+ int v;
+ if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+ *pValue = -v;
+ rc = 1;
+ }
+ break;
+ }
+ default: break;
+ }
+ return rc;
+}
+
+/*
+** Return FALSE if there is no chance that the expression can be NULL.
+**
+** If the expression might be NULL or if the expression is too complex
+** to tell return TRUE.
+**
+** This routine is used as an optimization, to skip OP_IsNull opcodes
+** when we know that a value cannot be NULL. Hence, a false positive
+** (returning TRUE when in fact the expression can never be NULL) might
+** be a small performance hit but is otherwise harmless. On the other
+** hand, a false negative (returning FALSE when the result could be NULL)
+** will likely result in an incorrect answer. So when in doubt, return
+** TRUE.
+*/
+SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
+ u8 op;
+ while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
+ op = p->op;
+ if( op==TK_REGISTER ) op = p->op2;
+ switch( op ){
+ case TK_INTEGER:
+ case TK_STRING:
+ case TK_FLOAT:
+ case TK_BLOB:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+/*
+** Generate an OP_IsNull instruction that tests register iReg and jumps
+** to location iDest if the value in iReg is NULL. The value in iReg
+** was computed by pExpr. If we can look at pExpr at compile-time and
+** determine that it can never generate a NULL, then the OP_IsNull operation
+** can be omitted.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(
+ Vdbe *v, /* The VDBE under construction */
+ const Expr *pExpr, /* Only generate OP_IsNull if this expr can be NULL */
+ int iReg, /* Test the value in this register for NULL */
+ int iDest /* Jump here if the value is null */
+){
+ if( sqlite3ExprCanBeNull(pExpr) ){
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest);
+ }
+}
+
+/*
+** Return TRUE if the given expression is a constant which would be
+** unchanged by OP_Affinity with the affinity given in the second
+** argument.
+**
+** This routine is used to determine if the OP_Affinity operation
+** can be omitted. When in doubt return FALSE. A false negative
+** is harmless. A false positive, however, can result in the wrong
+** answer.
+*/
+SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
+ u8 op;
+ if( aff==SQLITE_AFF_NONE ) return 1;
+ while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
+ op = p->op;
+ if( op==TK_REGISTER ) op = p->op2;
+ switch( op ){
+ case TK_INTEGER: {
+ return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
+ }
+ case TK_FLOAT: {
+ return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
+ }
+ case TK_STRING: {
+ return aff==SQLITE_AFF_TEXT;
+ }
+ case TK_BLOB: {
+ return 1;
+ }
+ case TK_COLUMN: {
+ assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */
+ return p->iColumn<0
+ && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
+ }
+ default: {
+ return 0;
+ }
+ }
+}
+
+/*
+** Return TRUE if the given string is a row-id column name.
+*/
+SQLITE_PRIVATE int sqlite3IsRowid(const char *z){
+ if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1;
+ if( sqlite3StrICmp(z, "ROWID")==0 ) return 1;
+ if( sqlite3StrICmp(z, "OID")==0 ) return 1;
+ return 0;
+}
+
+/*
+** Return true if we are able to the IN operator optimization on a
+** query of the form
+**
+** x IN (SELECT ...)
+**
+** Where the SELECT... clause is as specified by the parameter to this
+** routine.
+**
+** The Select object passed in has already been preprocessed and no
+** errors have been found.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+static int isCandidateForInOpt(Select *p){
+ SrcList *pSrc;
+ ExprList *pEList;
+ Table *pTab;
+ if( p==0 ) return 0; /* right-hand side of IN is SELECT */
+ if( p->pPrior ) return 0; /* Not a compound SELECT */
+ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
+ testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
+ testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
+ return 0; /* No DISTINCT keyword and no aggregate functions */
+ }
+ assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
+ if( p->pLimit ) return 0; /* Has no LIMIT clause */
+ assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */
+ if( p->pWhere ) return 0; /* Has no WHERE clause */
+ pSrc = p->pSrc;
+ assert( pSrc!=0 );
+ if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
+ if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
+ pTab = pSrc->a[0].pTab;
+ if( NEVER(pTab==0) ) return 0;
+ assert( pTab->pSelect==0 ); /* FROM clause is not a view */
+ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
+ pEList = p->pEList;
+ if( pEList->nExpr!=1 ) return 0; /* One column in the result set */
+ if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */
+ return 1;
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+/*
+** Code an OP_Once instruction and allocate space for its flag. Return the
+** address of the new instruction.
+*/
+SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
+ return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
+}
+
+/*
+** This function is used by the implementation of the IN (...) operator.
+** The pX parameter is the expression on the RHS of the IN operator, which
+** might be either a list of expressions or a subquery.
+**
+** The job of this routine is to find or create a b-tree object that can
+** be used either to test for membership in the RHS set or to iterate through
+** all members of the RHS set, skipping duplicates.
+**
+** A cursor is opened on the b-tree object that the RHS of the IN operator
+** and pX->iTable is set to the index of that cursor.
+**
+** The returned value of this function indicates the b-tree type, as follows:
+**
+** IN_INDEX_ROWID - The cursor was opened on a database table.
+** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
+** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
+** IN_INDEX_EPH - The cursor was opened on a specially created and
+** populated epheremal table.
+**
+** An existing b-tree might be used if the RHS expression pX is a simple
+** subquery such as:
+**
+** SELECT <column> FROM <table>
+**
+** If the RHS of the IN operator is a list or a more complex subquery, then
+** an ephemeral table might need to be generated from the RHS and then
+** pX->iTable made to point to the ephermeral table instead of an
+** existing table.
+**
+** If the prNotFound parameter is 0, then the b-tree will be used to iterate
+** through the set members, skipping any duplicates. In this case an
+** epheremal table must be used unless the selected <column> is guaranteed
+** to be unique - either because it is an INTEGER PRIMARY KEY or it
+** has a UNIQUE constraint or UNIQUE index.
+**
+** If the prNotFound parameter is not 0, then the b-tree will be used
+** for fast set membership tests. In this case an epheremal table must
+** be used unless <column> is an INTEGER PRIMARY KEY or an index can
+** be found with <column> as its left-most column.
+**
+** When the b-tree is being used for membership tests, the calling function
+** needs to know whether or not the structure contains an SQL NULL
+** value in order to correctly evaluate expressions like "X IN (Y, Z)".
+** If there is any chance that the (...) might contain a NULL value at
+** runtime, then a register is allocated and the register number written
+** to *prNotFound. If there is no chance that the (...) contains a
+** NULL value, then *prNotFound is left unchanged.
+**
+** If a register is allocated and its location stored in *prNotFound, then
+** its initial value is NULL. If the (...) does not remain constant
+** for the duration of the query (i.e. the SELECT within the (...)
+** is a correlated subquery) then the value of the allocated register is
+** reset to NULL each time the subquery is rerun. This allows the
+** caller to use vdbe code equivalent to the following:
+**
+** if( register==NULL ){
+** has_null = <test if data structure contains null>
+** register = 1
+** }
+**
+** in order to avoid running the <test if data structure contains null>
+** test more often than is necessary.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
+ Select *p; /* SELECT to the right of IN operator */
+ int eType = 0; /* Type of RHS table. IN_INDEX_* */
+ int iTab = pParse->nTab++; /* Cursor of the RHS table */
+ int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
+
+ assert( pX->op==TK_IN );
+
+ /* Check to see if an existing table or index can be used to
+ ** satisfy the query. This is preferable to generating a new
+ ** ephemeral table.
+ */
+ p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
+ if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
+ sqlite3 *db = pParse->db; /* Database connection */
+ Table *pTab; /* Table <table>. */
+ Expr *pExpr; /* Expression <column> */
+ int iCol; /* Index of column <column> */
+ int iDb; /* Database idx for pTab */
+
+ assert( p ); /* Because of isCandidateForInOpt(p) */
+ assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
+ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
+ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
+ pTab = p->pSrc->a[0].pTab;
+ pExpr = p->pEList->a[0].pExpr;
+ iCol = pExpr->iColumn;
+
+ /* Code an OP_VerifyCookie and OP_TableLock for <table>. */
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+
+ /* This function is only called from two places. In both cases the vdbe
+ ** has already been allocated. So assume sqlite3GetVdbe() is always
+ ** successful here.
+ */
+ assert(v);
+ if( iCol<0 ){
+ int iAddr;
+
+ iAddr = sqlite3CodeOnce(pParse);
+
+ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
+ eType = IN_INDEX_ROWID;
+
+ sqlite3VdbeJumpHere(v, iAddr);
+ }else{
+ Index *pIdx; /* Iterator variable */
+
+ /* The collation sequence used by the comparison. If an index is to
+ ** be used in place of a temp-table, it must be ordered according
+ ** to this collation sequence. */
+ CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr);
+
+ /* Check that the affinity that will be used to perform the
+ ** comparison is the same as the affinity of the column. If
+ ** it is not, it is not possible to use any index.
+ */
+ int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
+
+ for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
+ if( (pIdx->aiColumn[0]==iCol)
+ && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
+ && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
+ ){
+ int iAddr;
+ char *pKey;
+
+ pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
+ iAddr = sqlite3CodeOnce(pParse);
+
+ sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
+ pKey,P4_KEYINFO_HANDOFF);
+ VdbeComment((v, "%s", pIdx->zName));
+ assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
+ eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
+
+ sqlite3VdbeJumpHere(v, iAddr);
+ if( prNotFound && !pTab->aCol[iCol].notNull ){
+ *prNotFound = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
+ }
+ }
+ }
+ }
+ }
+
+ if( eType==0 ){
+ /* Could not found an existing table or index to use as the RHS b-tree.
+ ** We will have to generate an ephemeral table to do the job.
+ */
+ double savedNQueryLoop = pParse->nQueryLoop;
+ int rMayHaveNull = 0;
+ eType = IN_INDEX_EPH;
+ if( prNotFound ){
+ *prNotFound = rMayHaveNull = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
+ }else{
+ testcase( pParse->nQueryLoop>(double)1 );
+ pParse->nQueryLoop = (double)1;
+ if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
+ eType = IN_INDEX_ROWID;
+ }
+ }
+ sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
+ pParse->nQueryLoop = savedNQueryLoop;
+ }else{
+ pX->iTable = iTab;
+ }
+ return eType;
+}
+#endif
+
+/*
+** Generate code for scalar subqueries used as a subquery expression, EXISTS,
+** or IN operators. Examples:
+**
+** (SELECT a FROM b) -- subquery
+** EXISTS (SELECT a FROM b) -- EXISTS subquery
+** x IN (4,5,11) -- IN operator with list on right-hand side
+** x IN (SELECT a FROM b) -- IN operator with subquery on the right
+**
+** The pExpr parameter describes the expression that contains the IN
+** operator or subquery.
+**
+** If parameter isRowid is non-zero, then expression pExpr is guaranteed
+** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
+** to some integer key column of a table B-Tree. In this case, use an
+** intkey B-Tree to store the set of IN(...) values instead of the usual
+** (slower) variable length keys B-Tree.
+**
+** If rMayHaveNull is non-zero, that means that the operation is an IN
+** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
+** Furthermore, the IN is in a WHERE clause and that we really want
+** to iterate over the RHS of the IN operator in order to quickly locate
+** all corresponding LHS elements. All this routine does is initialize
+** the register given by rMayHaveNull to NULL. Calling routines will take
+** care of changing this register value to non-NULL if the RHS is NULL-free.
+**
+** If rMayHaveNull is zero, that means that the subquery is being used
+** for membership testing only. There is no need to initialize any
+** registers to indicate the presense or absence of NULLs on the RHS.
+**
+** For a SELECT or EXISTS operator, return the register that holds the
+** result. For IN operators or if an error occurs, the return value is 0.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+SQLITE_PRIVATE int sqlite3CodeSubselect(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
+ int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
+ int isRowid /* If true, LHS of IN operator is a rowid */
+){
+ int testAddr = -1; /* One-time test address */
+ int rReg = 0; /* Register storing resulting */
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( NEVER(v==0) ) return 0;
+ sqlite3ExprCachePush(pParse);
+
+ /* This code must be run in its entirety every time it is encountered
+ ** if any of the following is true:
+ **
+ ** * The right-hand side is a correlated subquery
+ ** * The right-hand side is an expression list containing variables
+ ** * We are inside a trigger
+ **
+ ** If all of the above are false, then we can run this code just once
+ ** save the results, and reuse the same result on subsequent invocations.
+ */
+ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){
+ testAddr = sqlite3CodeOnce(pParse);
+ }
+
+#ifndef SQLITE_OMIT_EXPLAIN
+ if( pParse->explain==2 ){
+ char *zMsg = sqlite3MPrintf(
+ pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
+ pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
+ );
+ sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
+ }
+#endif
+
+ switch( pExpr->op ){
+ case TK_IN: {
+ char affinity; /* Affinity of the LHS of the IN */
+ KeyInfo keyInfo; /* Keyinfo for the generated table */
+ static u8 sortOrder = 0; /* Fake aSortOrder for keyInfo */
+ int addr; /* Address of OP_OpenEphemeral instruction */
+ Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
+
+ if( rMayHaveNull ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
+ }
+
+ affinity = sqlite3ExprAffinity(pLeft);
+
+ /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
+ ** expression it is handled the same way. An ephemeral table is
+ ** filled with single-field index keys representing the results
+ ** from the SELECT or the <exprlist>.
+ **
+ ** If the 'x' expression is a column value, or the SELECT...
+ ** statement returns a column value, then the affinity of that
+ ** column is used to build the index keys. If both 'x' and the
+ ** SELECT... statement are columns, then numeric affinity is used
+ ** if either column has NUMERIC or INTEGER affinity. If neither
+ ** 'x' nor the SELECT... statement are columns, then numeric affinity
+ ** is used.
+ */
+ pExpr->iTable = pParse->nTab++;
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
+ if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
+ memset(&keyInfo, 0, sizeof(keyInfo));
+ keyInfo.nField = 1;
+ keyInfo.aSortOrder = &sortOrder;
+
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ /* Case 1: expr IN (SELECT ...)
+ **
+ ** Generate code to write the results of the select into the temporary
+ ** table allocated and opened above.
+ */
+ SelectDest dest;
+ ExprList *pEList;
+
+ assert( !isRowid );
+ sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
+ dest.affSdst = (u8)affinity;
+ assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
+ pExpr->x.pSelect->iLimit = 0;
+ if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
+ return 0;
+ }
+ pEList = pExpr->x.pSelect->pEList;
+ if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
+ keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
+ pEList->a[0].pExpr);
+ }
+ }else if( ALWAYS(pExpr->x.pList!=0) ){
+ /* Case 2: expr IN (exprlist)
+ **
+ ** For each expression, build an index key from the evaluation and
+ ** store it in the temporary table. If <expr> is a column, then use
+ ** that columns affinity when building index keys. If <expr> is not
+ ** a column, use numeric affinity.
+ */
+ int i;
+ ExprList *pList = pExpr->x.pList;
+ struct ExprList_item *pItem;
+ int r1, r2, r3;
+
+ if( !affinity ){
+ affinity = SQLITE_AFF_NONE;
+ }
+ keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+ keyInfo.aSortOrder = &sortOrder;
+
+ /* Loop through each expression in <exprlist>. */
+ r1 = sqlite3GetTempReg(pParse);
+ r2 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
+ for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+ Expr *pE2 = pItem->pExpr;
+ int iValToIns;
+
+ /* If the expression is not constant then we will need to
+ ** disable the test that was generated above that makes sure
+ ** this code only executes once. Because for a non-constant
+ ** expression we need to rerun this code each time.
+ */
+ if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
+ sqlite3VdbeChangeToNoop(v, testAddr);
+ testAddr = -1;
+ }
+
+ /* Evaluate the expression and insert it into the temp table */
+ if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
+ sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
+ }else{
+ r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
+ if( isRowid ){
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
+ sqlite3VdbeCurrentAddr(v)+2);
+ sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
+ }else{
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
+ sqlite3ExprCacheAffinityChange(pParse, r3, 1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
+ }
+ }
+ }
+ sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ReleaseTempReg(pParse, r2);
+ }
+ if( !isRowid ){
+ sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
+ }
+ break;
+ }
+
+ case TK_EXISTS:
+ case TK_SELECT:
+ default: {
+ /* If this has to be a scalar SELECT. Generate code to put the
+ ** value of this select in a memory cell and record the number
+ ** of the memory cell in iColumn. If this is an EXISTS, write
+ ** an integer 0 (not exists) or 1 (exists) into a memory cell
+ ** and record that memory cell in iColumn.
+ */
+ Select *pSel; /* SELECT statement to encode */
+ SelectDest dest; /* How to deal with SELECt result */
+
+ testcase( pExpr->op==TK_EXISTS );
+ testcase( pExpr->op==TK_SELECT );
+ assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
+
+ assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+ pSel = pExpr->x.pSelect;
+ sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
+ if( pExpr->op==TK_SELECT ){
+ dest.eDest = SRT_Mem;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm);
+ VdbeComment((v, "Init subquery result"));
+ }else{
+ dest.eDest = SRT_Exists;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
+ VdbeComment((v, "Init EXISTS result"));
+ }
+ sqlite3ExprDelete(pParse->db, pSel->pLimit);
+ pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
+ &sqlite3IntTokens[1]);
+ pSel->iLimit = 0;
+ if( sqlite3Select(pParse, pSel, &dest) ){
+ return 0;
+ }
+ rReg = dest.iSDParm;
+ ExprSetIrreducible(pExpr);
+ break;
+ }
+ }
+
+ if( testAddr>=0 ){
+ sqlite3VdbeJumpHere(v, testAddr);
+ }
+ sqlite3ExprCachePop(pParse, 1);
+
+ return rReg;
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** Generate code for an IN expression.
+**
+** x IN (SELECT ...)
+** x IN (value, value, ...)
+**
+** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS)
+** is an array of zero or more values. The expression is true if the LHS is
+** contained within the RHS. The value of the expression is unknown (NULL)
+** if the LHS is NULL or if the LHS is not contained within the RHS and the
+** RHS contains one or more NULL values.
+**
+** This routine generates code will jump to destIfFalse if the LHS is not
+** contained within the RHS. If due to NULLs we cannot determine if the LHS
+** is contained in the RHS then jump to destIfNull. If the LHS is contained
+** within the RHS then fall through.
+*/
+static void sqlite3ExprCodeIN(
+ Parse *pParse, /* Parsing and code generating context */
+ Expr *pExpr, /* The IN expression */
+ int destIfFalse, /* Jump here if LHS is not contained in the RHS */
+ int destIfNull /* Jump here if the results are unknown due to NULLs */
+){
+ int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
+ char affinity; /* Comparison affinity to use */
+ int eType; /* Type of the RHS */
+ int r1; /* Temporary use register */
+ Vdbe *v; /* Statement under construction */
+
+ /* Compute the RHS. After this step, the table with cursor
+ ** pExpr->iTable will contains the values that make up the RHS.
+ */
+ v = pParse->pVdbe;
+ assert( v!=0 ); /* OOM detected prior to this routine */
+ VdbeNoopComment((v, "begin IN expr"));
+ eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull);
+
+ /* Figure out the affinity to use to create a key from the results
+ ** of the expression. affinityStr stores a static string suitable for
+ ** P4 of OP_MakeRecord.
+ */
+ affinity = comparisonAffinity(pExpr);
+
+ /* Code the LHS, the <expr> from "<expr> IN (...)".
+ */
+ sqlite3ExprCachePush(pParse);
+ r1 = sqlite3GetTempReg(pParse);
+ sqlite3ExprCode(pParse, pExpr->pLeft, r1);
+
+ /* If the LHS is NULL, then the result is either false or NULL depending
+ ** on whether the RHS is empty or not, respectively.
+ */
+ if( destIfNull==destIfFalse ){
+ /* Shortcut for the common case where the false and NULL outcomes are
+ ** the same. */
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull);
+ }else{
+ int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1);
+ sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
+ sqlite3VdbeJumpHere(v, addr1);
+ }
+
+ if( eType==IN_INDEX_ROWID ){
+ /* In this case, the RHS is the ROWID of table b-tree
+ */
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse);
+ sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
+ }else{
+ /* In this case, the RHS is an index b-tree.
+ */
+ sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
+
+ /* If the set membership test fails, then the result of the
+ ** "x IN (...)" expression must be either 0 or NULL. If the set
+ ** contains no NULL values, then the result is 0. If the set
+ ** contains one or more NULL values, then the result of the
+ ** expression is also NULL.
+ */
+ if( rRhsHasNull==0 || destIfFalse==destIfNull ){
+ /* This branch runs if it is known at compile time that the RHS
+ ** cannot contain NULL values. This happens as the result
+ ** of a "NOT NULL" constraint in the database schema.
+ **
+ ** Also run this branch if NULL is equivalent to FALSE
+ ** for this particular IN operator.
+ */
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
+
+ }else{
+ /* In this branch, the RHS of the IN might contain a NULL and
+ ** the presence of a NULL on the RHS makes a difference in the
+ ** outcome.
+ */
+ int j1, j2, j3;
+
+ /* First check to see if the LHS is contained in the RHS. If so,
+ ** then the presence of NULLs in the RHS does not matter, so jump
+ ** over all of the code that follows.
+ */
+ j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
+
+ /* Here we begin generating code that runs if the LHS is not
+ ** contained within the RHS. Generate additional code that
+ ** tests the RHS for NULLs. If the RHS contains a NULL then
+ ** jump to destIfNull. If there are no NULLs in the RHS then
+ ** jump to destIfFalse.
+ */
+ j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull);
+ j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull);
+ sqlite3VdbeJumpHere(v, j3);
+ sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1);
+ sqlite3VdbeJumpHere(v, j2);
+
+ /* Jump to the appropriate target depending on whether or not
+ ** the RHS contains a NULL
+ */
+ sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
+
+ /* The OP_Found at the top of this branch jumps here when true,
+ ** causing the overall IN expression evaluation to fall through.
+ */
+ sqlite3VdbeJumpHere(v, j1);
+ }
+ }
+ sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ExprCachePop(pParse, 1);
+ VdbeComment((v, "end IN expr"));
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+/*
+** Duplicate an 8-byte value
+*/
+static char *dup8bytes(Vdbe *v, const char *in){
+ char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8);
+ if( out ){
+ memcpy(out, in, 8);
+ }
+ return out;
+}
+
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/*
+** Generate an instruction that will put the floating point
+** value described by z[0..n-1] into register iMem.
+**
+** The z[] string will probably not be zero-terminated. But the
+** z[n] character is guaranteed to be something that does not look
+** like the continuation of the number.
+*/
+static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
+ if( ALWAYS(z!=0) ){
+ double value;
+ char *zV;
+ sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
+ assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
+ if( negateFlag ) value = -value;
+ zV = dup8bytes(v, (char*)&value);
+ sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
+ }
+}
+#endif
+
+
+/*
+** Generate an instruction that will put the integer describe by
+** text z[0..n-1] into register iMem.
+**
+** Expr.u.zToken is always UTF8 and zero-terminated.
+*/
+static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
+ Vdbe *v = pParse->pVdbe;
+ if( pExpr->flags & EP_IntValue ){
+ int i = pExpr->u.iValue;
+ assert( i>=0 );
+ if( negFlag ) i = -i;
+ sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
+ }else{
+ int c;
+ i64 value;
+ const char *z = pExpr->u.zToken;
+ assert( z!=0 );
+ c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
+ if( c==0 || (c==2 && negFlag) ){
+ char *zV;
+ if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
+ zV = dup8bytes(v, (char*)&value);
+ sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
+ }else{
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
+#else
+ codeReal(v, z, negFlag, iMem);
+#endif
+ }
+ }
+}
+
+/*
+** Clear a cache entry.
+*/
+static void cacheEntryClear(Parse *pParse, struct yColCache *p){
+ if( p->tempReg ){
+ if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
+ pParse->aTempReg[pParse->nTempReg++] = p->iReg;
+ }
+ p->tempReg = 0;
+ }
+}
+
+
+/*
+** Record in the column cache that a particular column from a
+** particular table is stored in a particular register.
+*/
+SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
+ int i;
+ int minLru;
+ int idxLru;
+ struct yColCache *p;
+
+ assert( iReg>0 ); /* Register numbers are always positive */
+ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
+
+ /* The SQLITE_ColumnCache flag disables the column cache. This is used
+ ** for testing only - to verify that SQLite always gets the same answer
+ ** with and without the column cache.
+ */
+ if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
+
+ /* First replace any existing entry.
+ **
+ ** Actually, the way the column cache is currently used, we are guaranteed
+ ** that the object will never already be in cache. Verify this guarantee.
+ */
+#ifndef NDEBUG
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
+ }
+#endif
+
+ /* Find an empty slot and replace it */
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg==0 ){
+ p->iLevel = pParse->iCacheLevel;
+ p->iTable = iTab;
+ p->iColumn = iCol;
+ p->iReg = iReg;
+ p->tempReg = 0;
+ p->lru = pParse->iCacheCnt++;
+ return;
+ }
+ }
+
+ /* Replace the last recently used */
+ minLru = 0x7fffffff;
+ idxLru = -1;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->lru<minLru ){
+ idxLru = i;
+ minLru = p->lru;
+ }
+ }
+ if( ALWAYS(idxLru>=0) ){
+ p = &pParse->aColCache[idxLru];
+ p->iLevel = pParse->iCacheLevel;
+ p->iTable = iTab;
+ p->iColumn = iCol;
+ p->iReg = iReg;
+ p->tempReg = 0;
+ p->lru = pParse->iCacheCnt++;
+ return;
+ }
+}
+
+/*
+** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
+** Purge the range of registers from the column cache.
+*/
+SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
+ int i;
+ int iLast = iReg + nReg - 1;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ int r = p->iReg;
+ if( r>=iReg && r<=iLast ){
+ cacheEntryClear(pParse, p);
+ p->iReg = 0;
+ }
+ }
+}
+
+/*
+** Remember the current column cache context. Any new entries added
+** added to the column cache after this call are removed when the
+** corresponding pop occurs.
+*/
+SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){
+ pParse->iCacheLevel++;
+}
+
+/*
+** Remove from the column cache any entries that were added since the
+** the previous N Push operations. In other words, restore the cache
+** to the state it was in N Pushes ago.
+*/
+SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse, int N){
+ int i;
+ struct yColCache *p;
+ assert( N>0 );
+ assert( pParse->iCacheLevel>=N );
+ pParse->iCacheLevel -= N;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg && p->iLevel>pParse->iCacheLevel ){
+ cacheEntryClear(pParse, p);
+ p->iReg = 0;
+ }
+ }
+}
+
+/*
+** When a cached column is reused, make sure that its register is
+** no longer available as a temp register. ticket #3879: that same
+** register might be in the cache in multiple places, so be sure to
+** get them all.
+*/
+static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
+ int i;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg==iReg ){
+ p->tempReg = 0;
+ }
+ }
+}
+
+/*
+** Generate code to extract the value of the iCol-th column of a table.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
+ Vdbe *v, /* The VDBE under construction */
+ Table *pTab, /* The table containing the value */
+ int iTabCur, /* The cursor for this table */
+ int iCol, /* Index of the column to extract */
+ int regOut /* Extract the valud into this register */
+){
+ if( iCol<0 || iCol==pTab->iPKey ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
+ }else{
+ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
+ sqlite3VdbeAddOp3(v, op, iTabCur, iCol, regOut);
+ }
+ if( iCol>=0 ){
+ sqlite3ColumnDefault(v, pTab, iCol, regOut);
+ }
+}
+
+/*
+** Generate code that will extract the iColumn-th column from
+** table pTab and store the column value in a register. An effort
+** is made to store the column value in register iReg, but this is
+** not guaranteed. The location of the column value is returned.
+**
+** There must be an open cursor to pTab in iTable when this routine
+** is called. If iColumn<0 then code is generated that extracts the rowid.
+*/
+SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
+ Parse *pParse, /* Parsing and code generating context */
+ Table *pTab, /* Description of the table we are reading from */
+ int iColumn, /* Index of the table column */
+ int iTable, /* The cursor pointing to the table */
+ int iReg, /* Store results here */
+ u8 p5 /* P5 value for OP_Column */
+){
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ struct yColCache *p;
+
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
+ p->lru = pParse->iCacheCnt++;
+ sqlite3ExprCachePinRegister(pParse, p->iReg);
+ return p->iReg;
+ }
+ }
+ assert( v!=0 );
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
+ if( p5 ){
+ sqlite3VdbeChangeP5(v, p5);
+ }else{
+ sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
+ }
+ return iReg;
+}
+
+/*
+** Clear all column cache entries.
+*/
+SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
+ int i;
+ struct yColCache *p;
+
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg ){
+ cacheEntryClear(pParse, p);
+ p->iReg = 0;
+ }
+ }
+}
+
+/*
+** Record the fact that an affinity change has occurred on iCount
+** registers starting with iStart.
+*/
+SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
+ sqlite3ExprCacheRemove(pParse, iStart, iCount);
+}
+
+/*
+** Generate code to move content from registers iFrom...iFrom+nReg-1
+** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
+ int i;
+ struct yColCache *p;
+ assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1);
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ int x = p->iReg;
+ if( x>=iFrom && x<iFrom+nReg ){
+ p->iReg += iTo-iFrom;
+ }
+ }
+}
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+/*
+** Return true if any register in the range iFrom..iTo (inclusive)
+** is used as part of the column cache.
+**
+** This routine is used within assert() and testcase() macros only
+** and does not appear in a normal build.
+*/
+static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
+ int i;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ int r = p->iReg;
+ if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
+ }
+ return 0;
+}
+#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
+
+/*
+** Generate code into the current Vdbe to evaluate the given
+** expression. Attempt to store the results in register "target".
+** Return the register where results are stored.
+**
+** With this routine, there is no guarantee that results will
+** be stored in target. The result might be stored in some other
+** register if it is convenient to do so. The calling function
+** must check the return code and move the results to the desired
+** register.
+*/
+SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
+ Vdbe *v = pParse->pVdbe; /* The VM under construction */
+ int op; /* The opcode being coded */
+ int inReg = target; /* Results stored in register inReg */
+ int regFree1 = 0; /* If non-zero free this temporary register */
+ int regFree2 = 0; /* If non-zero free this temporary register */
+ int r1, r2, r3, r4; /* Various register numbers */
+ sqlite3 *db = pParse->db; /* The database connection */
+
+ assert( target>0 && target<=pParse->nMem );
+ if( v==0 ){
+ assert( pParse->db->mallocFailed );
+ return 0;
+ }
+
+ if( pExpr==0 ){
+ op = TK_NULL;
+ }else{
+ op = pExpr->op;
+ }
+ switch( op ){
+ case TK_AGG_COLUMN: {
+ AggInfo *pAggInfo = pExpr->pAggInfo;
+ struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
+ if( !pAggInfo->directMode ){
+ assert( pCol->iMem>0 );
+ inReg = pCol->iMem;
+ break;
+ }else if( pAggInfo->useSortingIdx ){
+ sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
+ pCol->iSorterColumn, target);
+ break;
+ }
+ /* Otherwise, fall thru into the TK_COLUMN case */
+ }
+ case TK_COLUMN: {
+ if( pExpr->iTable<0 ){
+ /* This only happens when coding check constraints */
+ assert( pParse->ckBase>0 );
+ inReg = pExpr->iColumn + pParse->ckBase;
+ }else{
+ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ pExpr->iColumn, pExpr->iTable, target,
+ pExpr->op2);
+ }
+ break;
+ }
+ case TK_INTEGER: {
+ codeInteger(pParse, pExpr, 0, target);
+ break;
+ }
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ case TK_FLOAT: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ codeReal(v, pExpr->u.zToken, 0, target);
+ break;
+ }
+#endif
+ case TK_STRING: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0);
+ break;
+ }
+ case TK_NULL: {
+ sqlite3VdbeAddOp2(v, OP_Null, 0, target);
+ break;
+ }
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+ case TK_BLOB: {
+ int n;
+ const char *z;
+ char *zBlob;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
+ assert( pExpr->u.zToken[1]=='\'' );
+ z = &pExpr->u.zToken[2];
+ n = sqlite3Strlen30(z) - 1;
+ assert( z[n]=='\'' );
+ zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
+ sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
+ break;
+ }
+#endif
+ case TK_VARIABLE: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ assert( pExpr->u.zToken!=0 );
+ assert( pExpr->u.zToken[0]!=0 );
+ sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
+ if( pExpr->u.zToken[1]!=0 ){
+ assert( pExpr->u.zToken[0]=='?'
+ || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
+ sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
+ }
+ break;
+ }
+ case TK_REGISTER: {
+ inReg = pExpr->iTable;
+ break;
+ }
+ case TK_AS: {
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ break;
+ }
+#ifndef SQLITE_OMIT_CAST
+ case TK_CAST: {
+ /* Expressions of the form: CAST(pLeft AS token) */
+ int aff, to_op;
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ aff = sqlite3AffinityType(pExpr->u.zToken);
+ to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
+ assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
+ assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
+ assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
+ assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
+ assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL );
+ testcase( to_op==OP_ToText );
+ testcase( to_op==OP_ToBlob );
+ testcase( to_op==OP_ToNumeric );
+ testcase( to_op==OP_ToInt );
+ testcase( to_op==OP_ToReal );
+ if( inReg!=target ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
+ inReg = target;
+ }
+ sqlite3VdbeAddOp1(v, to_op, inReg);
+ testcase( usedAsColumnCache(pParse, inReg, inReg) );
+ sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
+ break;
+ }
+#endif /* SQLITE_OMIT_CAST */
+ case TK_LT:
+ case TK_LE:
+ case TK_GT:
+ case TK_GE:
+ case TK_NE:
+ case TK_EQ: {
+ assert( TK_LT==OP_Lt );
+ assert( TK_LE==OP_Le );
+ assert( TK_GT==OP_Gt );
+ assert( TK_GE==OP_Ge );
+ assert( TK_EQ==OP_Eq );
+ assert( TK_NE==OP_Ne );
+ testcase( op==TK_LT );
+ testcase( op==TK_LE );
+ testcase( op==TK_GT );
+ testcase( op==TK_GE );
+ testcase( op==TK_EQ );
+ testcase( op==TK_NE );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, inReg, SQLITE_STOREP2);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
+ case TK_IS:
+ case TK_ISNOT: {
+ testcase( op==TK_IS );
+ testcase( op==TK_ISNOT );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ op = (op==TK_IS) ? TK_EQ : TK_NE;
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
+ case TK_AND:
+ case TK_OR:
+ case TK_PLUS:
+ case TK_STAR:
+ case TK_MINUS:
+ case TK_REM:
+ case TK_BITAND:
+ case TK_BITOR:
+ case TK_SLASH:
+ case TK_LSHIFT:
+ case TK_RSHIFT:
+ case TK_CONCAT: {
+ assert( TK_AND==OP_And );
+ assert( TK_OR==OP_Or );
+ assert( TK_PLUS==OP_Add );
+ assert( TK_MINUS==OP_Subtract );
+ assert( TK_REM==OP_Remainder );
+ assert( TK_BITAND==OP_BitAnd );
+ assert( TK_BITOR==OP_BitOr );
+ assert( TK_SLASH==OP_Divide );
+ assert( TK_LSHIFT==OP_ShiftLeft );
+ assert( TK_RSHIFT==OP_ShiftRight );
+ assert( TK_CONCAT==OP_Concat );
+ testcase( op==TK_AND );
+ testcase( op==TK_OR );
+ testcase( op==TK_PLUS );
+ testcase( op==TK_MINUS );
+ testcase( op==TK_REM );
+ testcase( op==TK_BITAND );
+ testcase( op==TK_BITOR );
+ testcase( op==TK_SLASH );
+ testcase( op==TK_LSHIFT );
+ testcase( op==TK_RSHIFT );
+ testcase( op==TK_CONCAT );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ sqlite3VdbeAddOp3(v, op, r2, r1, target);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
+ case TK_UMINUS: {
+ Expr *pLeft = pExpr->pLeft;
+ assert( pLeft );
+ if( pLeft->op==TK_INTEGER ){
+ codeInteger(pParse, pLeft, 1, target);
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ }else if( pLeft->op==TK_FLOAT ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ codeReal(v, pLeft->u.zToken, 1, target);
+#endif
+ }else{
+ regFree1 = r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
+ sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
+ testcase( regFree2==0 );
+ }
+ inReg = target;
+ break;
+ }
+ case TK_BITNOT:
+ case TK_NOT: {
+ assert( TK_BITNOT==OP_BitNot );
+ assert( TK_NOT==OP_Not );
+ testcase( op==TK_BITNOT );
+ testcase( op==TK_NOT );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ testcase( regFree1==0 );
+ inReg = target;
+ sqlite3VdbeAddOp2(v, op, r1, inReg);
+ break;
+ }
+ case TK_ISNULL:
+ case TK_NOTNULL: {
+ int addr;
+ assert( TK_ISNULL==OP_IsNull );
+ assert( TK_NOTNULL==OP_NotNull );
+ testcase( op==TK_ISNULL );
+ testcase( op==TK_NOTNULL );
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ testcase( regFree1==0 );
+ addr = sqlite3VdbeAddOp1(v, op, r1);
+ sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
+ sqlite3VdbeJumpHere(v, addr);
+ break;
+ }
+ case TK_AGG_FUNCTION: {
+ AggInfo *pInfo = pExpr->pAggInfo;
+ if( pInfo==0 ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
+ }else{
+ inReg = pInfo->aFunc[pExpr->iAgg].iMem;
+ }
+ break;
+ }
+ case TK_CONST_FUNC:
+ case TK_FUNCTION: {
+ ExprList *pFarg; /* List of function arguments */
+ int nFarg; /* Number of function arguments */
+ FuncDef *pDef; /* The function definition object */
+ int nId; /* Length of the function name in bytes */
+ const char *zId; /* The function name */
+ int constMask = 0; /* Mask of function arguments that are constant */
+ int i; /* Loop counter */
+ u8 enc = ENC(db); /* The text encoding used by this database */
+ CollSeq *pColl = 0; /* A collating sequence */
+
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ testcase( op==TK_CONST_FUNC );
+ testcase( op==TK_FUNCTION );
+ if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
+ pFarg = 0;
+ }else{
+ pFarg = pExpr->x.pList;
+ }
+ nFarg = pFarg ? pFarg->nExpr : 0;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ zId = pExpr->u.zToken;
+ nId = sqlite3Strlen30(zId);
+ pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
+ if( pDef==0 ){
+ sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
+ break;
+ }
+
+ /* Attempt a direct implementation of the built-in COALESCE() and
+ ** IFNULL() functions. This avoids unnecessary evalation of
+ ** arguments past the first non-NULL argument.
+ */
+ if( pDef->flags & SQLITE_FUNC_COALESCE ){
+ int endCoalesce = sqlite3VdbeMakeLabel(v);
+ assert( nFarg>=2 );
+ sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
+ for(i=1; i<nFarg; i++){
+ sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
+ sqlite3ExprCacheRemove(pParse, target, 1);
+ sqlite3ExprCachePush(pParse);
+ sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
+ sqlite3ExprCachePop(pParse, 1);
+ }
+ sqlite3VdbeResolveLabel(v, endCoalesce);
+ break;
+ }
+
+
+ if( pFarg ){
+ r1 = sqlite3GetTempRange(pParse, nFarg);
+
+ /* For length() and typeof() functions with a column argument,
+ ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
+ ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
+ ** loading.
+ */
+ if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
+ u8 exprOp;
+ assert( nFarg==1 );
+ assert( pFarg->a[0].pExpr!=0 );
+ exprOp = pFarg->a[0].pExpr->op;
+ if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
+ assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
+ assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
+ testcase( pDef->flags==SQLITE_FUNC_LENGTH );
+ pFarg->a[0].pExpr->op2 = pDef->flags;
+ }
+ }
+
+ sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
+ sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
+ sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
+ }else{
+ r1 = 0;
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Possibly overload the function if the first argument is
+ ** a virtual table column.
+ **
+ ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the
+ ** second argument, not the first, as the argument to test to
+ ** see if it is a column in a virtual table. This is done because
+ ** the left operand of infix functions (the operand we want to
+ ** control overloading) ends up as the second argument to the
+ ** function. The expression "A glob B" is equivalent to
+ ** "glob(B,A). We want to use the A in "A glob B" to test
+ ** for function overloading. But we use the B term in "glob(B,A)".
+ */
+ if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){
+ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr);
+ }else if( nFarg>0 ){
+ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
+ }
+#endif
+ for(i=0; i<nFarg; i++){
+ if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
+ constMask |= (1<<i);
+ }
+ if( (pDef->flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
+ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
+ }
+ }
+ if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( !pColl ) pColl = db->pDfltColl;
+ sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
+ }
+ sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
+ (char*)pDef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, (u8)nFarg);
+ if( nFarg ){
+ sqlite3ReleaseTempRange(pParse, r1, nFarg);
+ }
+ break;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_EXISTS:
+ case TK_SELECT: {
+ testcase( op==TK_EXISTS );
+ testcase( op==TK_SELECT );
+ inReg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
+ break;
+ }
+ case TK_IN: {
+ int destIfFalse = sqlite3VdbeMakeLabel(v);
+ int destIfNull = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, target);
+ sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
+ sqlite3VdbeResolveLabel(v, destIfFalse);
+ sqlite3VdbeAddOp2(v, OP_AddImm, target, 0);
+ sqlite3VdbeResolveLabel(v, destIfNull);
+ break;
+ }
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+
+ /*
+ ** x BETWEEN y AND z
+ **
+ ** This is equivalent to
+ **
+ ** x>=y AND x<=z
+ **
+ ** X is stored in pExpr->pLeft.
+ ** Y is stored in pExpr->pList->a[0].pExpr.
+ ** Z is stored in pExpr->pList->a[1].pExpr.
+ */
+ case TK_BETWEEN: {
+ Expr *pLeft = pExpr->pLeft;
+ struct ExprList_item *pLItem = pExpr->x.pList->a;
+ Expr *pRight = pLItem->pExpr;
+
+ r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ r3 = sqlite3GetTempReg(pParse);
+ r4 = sqlite3GetTempReg(pParse);
+ codeCompare(pParse, pLeft, pRight, OP_Ge,
+ r1, r2, r3, SQLITE_STOREP2);
+ pLItem++;
+ pRight = pLItem->pExpr;
+ sqlite3ReleaseTempReg(pParse, regFree2);
+ r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
+ testcase( regFree2==0 );
+ codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
+ sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
+ sqlite3ReleaseTempReg(pParse, r3);
+ sqlite3ReleaseTempReg(pParse, r4);
+ break;
+ }
+ case TK_COLLATE:
+ case TK_UPLUS: {
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ break;
+ }
+
+ case TK_TRIGGER: {
+ /* If the opcode is TK_TRIGGER, then the expression is a reference
+ ** to a column in the new.* or old.* pseudo-tables available to
+ ** trigger programs. In this case Expr.iTable is set to 1 for the
+ ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
+ ** is set to the column of the pseudo-table to read, or to -1 to
+ ** read the rowid field.
+ **
+ ** The expression is implemented using an OP_Param opcode. The p1
+ ** parameter is set to 0 for an old.rowid reference, or to (i+1)
+ ** to reference another column of the old.* pseudo-table, where
+ ** i is the index of the column. For a new.rowid reference, p1 is
+ ** set to (n+1), where n is the number of columns in each pseudo-table.
+ ** For a reference to any other column in the new.* pseudo-table, p1
+ ** is set to (n+2+i), where n and i are as defined previously. For
+ ** example, if the table on which triggers are being fired is
+ ** declared as:
+ **
+ ** CREATE TABLE t1(a, b);
+ **
+ ** Then p1 is interpreted as follows:
+ **
+ ** p1==0 -> old.rowid p1==3 -> new.rowid
+ ** p1==1 -> old.a p1==4 -> new.a
+ ** p1==2 -> old.b p1==5 -> new.b
+ */
+ Table *pTab = pExpr->pTab;
+ int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
+
+ assert( pExpr->iTable==0 || pExpr->iTable==1 );
+ assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
+ assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
+ assert( p1>=0 && p1<(pTab->nCol*2+2) );
+
+ sqlite3VdbeAddOp2(v, OP_Param, p1, target);
+ VdbeComment((v, "%s.%s -> $%d",
+ (pExpr->iTable ? "new" : "old"),
+ (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
+ target
+ ));
+
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ /* If the column has REAL affinity, it may currently be stored as an
+ ** integer. Use OP_RealAffinity to make sure it is really real. */
+ if( pExpr->iColumn>=0
+ && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
+ ){
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
+ }
+#endif
+ break;
+ }
+
+
+ /*
+ ** Form A:
+ ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
+ **
+ ** Form B:
+ ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
+ **
+ ** Form A is can be transformed into the equivalent form B as follows:
+ ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ...
+ ** WHEN x=eN THEN rN ELSE y END
+ **
+ ** X (if it exists) is in pExpr->pLeft.
+ ** Y is in pExpr->pRight. The Y is also optional. If there is no
+ ** ELSE clause and no other term matches, then the result of the
+ ** exprssion is NULL.
+ ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
+ **
+ ** The result of the expression is the Ri for the first matching Ei,
+ ** or if there is no matching Ei, the ELSE term Y, or if there is
+ ** no ELSE term, NULL.
+ */
+ default: assert( op==TK_CASE ); {
+ int endLabel; /* GOTO label for end of CASE stmt */
+ int nextCase; /* GOTO label for next WHEN clause */
+ int nExpr; /* 2x number of WHEN terms */
+ int i; /* Loop counter */
+ ExprList *pEList; /* List of WHEN terms */
+ struct ExprList_item *aListelem; /* Array of WHEN terms */
+ Expr opCompare; /* The X==Ei expression */
+ Expr cacheX; /* Cached expression X */
+ Expr *pX; /* The X expression */
+ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
+ VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
+
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
+ assert((pExpr->x.pList->nExpr % 2) == 0);
+ assert(pExpr->x.pList->nExpr > 0);
+ pEList = pExpr->x.pList;
+ aListelem = pEList->a;
+ nExpr = pEList->nExpr;
+ endLabel = sqlite3VdbeMakeLabel(v);
+ if( (pX = pExpr->pLeft)!=0 ){
+ cacheX = *pX;
+ testcase( pX->op==TK_COLUMN );
+ testcase( pX->op==TK_REGISTER );
+ cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
+ testcase( regFree1==0 );
+ cacheX.op = TK_REGISTER;
+ opCompare.op = TK_EQ;
+ opCompare.pLeft = &cacheX;
+ pTest = &opCompare;
+ /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
+ ** The value in regFree1 might get SCopy-ed into the file result.
+ ** So make sure that the regFree1 register is not reused for other
+ ** purposes and possibly overwritten. */
+ regFree1 = 0;
+ }
+ for(i=0; i<nExpr; i=i+2){
+ sqlite3ExprCachePush(pParse);
+ if( pX ){
+ assert( pTest!=0 );
+ opCompare.pRight = aListelem[i].pExpr;
+ }else{
+ pTest = aListelem[i].pExpr;
+ }
+ nextCase = sqlite3VdbeMakeLabel(v);
+ testcase( pTest->op==TK_COLUMN );
+ sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
+ testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
+ testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
+ sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
+ sqlite3ExprCachePop(pParse, 1);
+ sqlite3VdbeResolveLabel(v, nextCase);
+ }
+ if( pExpr->pRight ){
+ sqlite3ExprCachePush(pParse);
+ sqlite3ExprCode(pParse, pExpr->pRight, target);
+ sqlite3ExprCachePop(pParse, 1);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, target);
+ }
+ assert( db->mallocFailed || pParse->nErr>0
+ || pParse->iCacheLevel==iCacheLevel );
+ sqlite3VdbeResolveLabel(v, endLabel);
+ break;
+ }
+#ifndef SQLITE_OMIT_TRIGGER
+ case TK_RAISE: {
+ assert( pExpr->affinity==OE_Rollback
+ || pExpr->affinity==OE_Abort
+ || pExpr->affinity==OE_Fail
+ || pExpr->affinity==OE_Ignore
+ );
+ if( !pParse->pTriggerTab ){
+ sqlite3ErrorMsg(pParse,
+ "RAISE() may only be used within a trigger-program");
+ return 0;
+ }
+ if( pExpr->affinity==OE_Abort ){
+ sqlite3MayAbort(pParse);
+ }
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ if( pExpr->affinity==OE_Ignore ){
+ sqlite3VdbeAddOp4(
+ v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
+ }else{
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
+ pExpr->affinity, pExpr->u.zToken, 0);
+ }
+
+ break;
+ }
+#endif
+ }
+ sqlite3ReleaseTempReg(pParse, regFree1);
+ sqlite3ReleaseTempReg(pParse, regFree2);
+ return inReg;
+}
+
+/*
+** Generate code to evaluate an expression and store the results
+** into a register. Return the register number where the results
+** are stored.
+**
+** If the register is a temporary register that can be deallocated,
+** then write its number into *pReg. If the result register is not
+** a temporary, then set *pReg to zero.
+*/
+SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
+ int r1 = sqlite3GetTempReg(pParse);
+ int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+ if( r2==r1 ){
+ *pReg = r1;
+ }else{
+ sqlite3ReleaseTempReg(pParse, r1);
+ *pReg = 0;
+ }
+ return r2;
+}
+
+/*
+** Generate code that will evaluate expression pExpr and store the
+** results in register target. The results are guaranteed to appear
+** in register target.
+*/
+SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
+ int inReg;
+
+ assert( target>0 && target<=pParse->nMem );
+ if( pExpr && pExpr->op==TK_REGISTER ){
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
+ }else{
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
+ assert( pParse->pVdbe || pParse->db->mallocFailed );
+ if( inReg!=target && pParse->pVdbe ){
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
+ }
+ }
+ return target;
+}
+
+/*
+** Generate code that evalutes the given expression and puts the result
+** in register target.
+**
+** Also make a copy of the expression results into another "cache" register
+** and modify the expression so that the next time it is evaluated,
+** the result is a copy of the cache register.
+**
+** This routine is used for expressions that are used multiple
+** times. They are evaluated once and the results of the expression
+** are reused.
+*/
+SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
+ Vdbe *v = pParse->pVdbe;
+ int inReg;
+ inReg = sqlite3ExprCode(pParse, pExpr, target);
+ assert( target>0 );
+ /* This routine is called for terms to INSERT or UPDATE. And the only
+ ** other place where expressions can be converted into TK_REGISTER is
+ ** in WHERE clause processing. So as currently implemented, there is
+ ** no way for a TK_REGISTER to exist here. But it seems prudent to
+ ** keep the ALWAYS() in case the conditions above change with future
+ ** modifications or enhancements. */
+ if( ALWAYS(pExpr->op!=TK_REGISTER) ){
+ int iMem;
+ iMem = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
+ pExpr->iTable = iMem;
+ pExpr->op2 = pExpr->op;
+ pExpr->op = TK_REGISTER;
+ }
+ return inReg;
+}
+
+#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
+/*
+** Generate a human-readable explanation of an expression tree.
+*/
+SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
+ int op; /* The opcode being coded */
+ const char *zBinOp = 0; /* Binary operator */
+ const char *zUniOp = 0; /* Unary operator */
+ if( pExpr==0 ){
+ op = TK_NULL;
+ }else{
+ op = pExpr->op;
+ }
+ switch( op ){
+ case TK_AGG_COLUMN: {
+ sqlite3ExplainPrintf(pOut, "AGG{%d:%d}",
+ pExpr->iTable, pExpr->iColumn);
+ break;
+ }
+ case TK_COLUMN: {
+ if( pExpr->iTable<0 ){
+ /* This only happens when coding check constraints */
+ sqlite3ExplainPrintf(pOut, "COLUMN(%d)", pExpr->iColumn);
+ }else{
+ sqlite3ExplainPrintf(pOut, "{%d:%d}",
+ pExpr->iTable, pExpr->iColumn);
+ }
+ break;
+ }
+ case TK_INTEGER: {
+ if( pExpr->flags & EP_IntValue ){
+ sqlite3ExplainPrintf(pOut, "%d", pExpr->u.iValue);
+ }else{
+ sqlite3ExplainPrintf(pOut, "%s", pExpr->u.zToken);
+ }
+ break;
+ }
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ case TK_FLOAT: {
+ sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken);
+ break;
+ }
+#endif
+ case TK_STRING: {
+ sqlite3ExplainPrintf(pOut,"%Q", pExpr->u.zToken);
+ break;
+ }
+ case TK_NULL: {
+ sqlite3ExplainPrintf(pOut,"NULL");
+ break;
+ }
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+ case TK_BLOB: {
+ sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken);
+ break;
+ }
+#endif
+ case TK_VARIABLE: {
+ sqlite3ExplainPrintf(pOut,"VARIABLE(%s,%d)",
+ pExpr->u.zToken, pExpr->iColumn);
+ break;
+ }
+ case TK_REGISTER: {
+ sqlite3ExplainPrintf(pOut,"REGISTER(%d)", pExpr->iTable);
+ break;
+ }
+ case TK_AS: {
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ break;
+ }
+#ifndef SQLITE_OMIT_CAST
+ case TK_CAST: {
+ /* Expressions of the form: CAST(pLeft AS token) */
+ const char *zAff = "unk";
+ switch( sqlite3AffinityType(pExpr->u.zToken) ){
+ case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
+ case SQLITE_AFF_NONE: zAff = "NONE"; break;
+ case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
+ case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
+ case SQLITE_AFF_REAL: zAff = "REAL"; break;
+ }
+ sqlite3ExplainPrintf(pOut, "CAST-%s(", zAff);
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ sqlite3ExplainPrintf(pOut, ")");
+ break;
+ }
+#endif /* SQLITE_OMIT_CAST */
+ case TK_LT: zBinOp = "LT"; break;
+ case TK_LE: zBinOp = "LE"; break;
+ case TK_GT: zBinOp = "GT"; break;
+ case TK_GE: zBinOp = "GE"; break;
+ case TK_NE: zBinOp = "NE"; break;
+ case TK_EQ: zBinOp = "EQ"; break;
+ case TK_IS: zBinOp = "IS"; break;
+ case TK_ISNOT: zBinOp = "ISNOT"; break;
+ case TK_AND: zBinOp = "AND"; break;
+ case TK_OR: zBinOp = "OR"; break;
+ case TK_PLUS: zBinOp = "ADD"; break;
+ case TK_STAR: zBinOp = "MUL"; break;
+ case TK_MINUS: zBinOp = "SUB"; break;
+ case TK_REM: zBinOp = "REM"; break;
+ case TK_BITAND: zBinOp = "BITAND"; break;
+ case TK_BITOR: zBinOp = "BITOR"; break;
+ case TK_SLASH: zBinOp = "DIV"; break;
+ case TK_LSHIFT: zBinOp = "LSHIFT"; break;
+ case TK_RSHIFT: zBinOp = "RSHIFT"; break;
+ case TK_CONCAT: zBinOp = "CONCAT"; break;
+
+ case TK_UMINUS: zUniOp = "UMINUS"; break;
+ case TK_UPLUS: zUniOp = "UPLUS"; break;
+ case TK_BITNOT: zUniOp = "BITNOT"; break;
+ case TK_NOT: zUniOp = "NOT"; break;
+ case TK_ISNULL: zUniOp = "ISNULL"; break;
+ case TK_NOTNULL: zUniOp = "NOTNULL"; break;
+
+ case TK_COLLATE: {
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
+ break;
+ }
+
+ case TK_AGG_FUNCTION:
+ case TK_CONST_FUNC:
+ case TK_FUNCTION: {
+ ExprList *pFarg; /* List of function arguments */
+ if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
+ pFarg = 0;
+ }else{
+ pFarg = pExpr->x.pList;
+ }
+ if( op==TK_AGG_FUNCTION ){
+ sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(",
+ pExpr->op2, pExpr->u.zToken);
+ }else{
+ sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken);
+ }
+ if( pFarg ){
+ sqlite3ExplainExprList(pOut, pFarg);
+ }
+ sqlite3ExplainPrintf(pOut, ")");
+ break;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_EXISTS: {
+ sqlite3ExplainPrintf(pOut, "EXISTS(");
+ sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
+ sqlite3ExplainPrintf(pOut,")");
+ break;
+ }
+ case TK_SELECT: {
+ sqlite3ExplainPrintf(pOut, "(");
+ sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
+ sqlite3ExplainPrintf(pOut, ")");
+ break;
+ }
+ case TK_IN: {
+ sqlite3ExplainPrintf(pOut, "IN(");
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ sqlite3ExplainPrintf(pOut, ",");
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
+ }else{
+ sqlite3ExplainExprList(pOut, pExpr->x.pList);
+ }
+ sqlite3ExplainPrintf(pOut, ")");
+ break;
+ }
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+ /*
+ ** x BETWEEN y AND z
+ **
+ ** This is equivalent to
+ **
+ ** x>=y AND x<=z
+ **
+ ** X is stored in pExpr->pLeft.
+ ** Y is stored in pExpr->pList->a[0].pExpr.
+ ** Z is stored in pExpr->pList->a[1].pExpr.
+ */
+ case TK_BETWEEN: {
+ Expr *pX = pExpr->pLeft;
+ Expr *pY = pExpr->x.pList->a[0].pExpr;
+ Expr *pZ = pExpr->x.pList->a[1].pExpr;
+ sqlite3ExplainPrintf(pOut, "BETWEEN(");
+ sqlite3ExplainExpr(pOut, pX);
+ sqlite3ExplainPrintf(pOut, ",");
+ sqlite3ExplainExpr(pOut, pY);
+ sqlite3ExplainPrintf(pOut, ",");
+ sqlite3ExplainExpr(pOut, pZ);
+ sqlite3ExplainPrintf(pOut, ")");
+ break;
+ }
+ case TK_TRIGGER: {
+ /* If the opcode is TK_TRIGGER, then the expression is a reference
+ ** to a column in the new.* or old.* pseudo-tables available to
+ ** trigger programs. In this case Expr.iTable is set to 1 for the
+ ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
+ ** is set to the column of the pseudo-table to read, or to -1 to
+ ** read the rowid field.
+ */
+ sqlite3ExplainPrintf(pOut, "%s(%d)",
+ pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
+ break;
+ }
+ case TK_CASE: {
+ sqlite3ExplainPrintf(pOut, "CASE(");
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ sqlite3ExplainPrintf(pOut, ",");
+ sqlite3ExplainExprList(pOut, pExpr->x.pList);
+ break;
+ }
+#ifndef SQLITE_OMIT_TRIGGER
+ case TK_RAISE: {
+ const char *zType = "unk";
+ switch( pExpr->affinity ){
+ case OE_Rollback: zType = "rollback"; break;
+ case OE_Abort: zType = "abort"; break;
+ case OE_Fail: zType = "fail"; break;
+ case OE_Ignore: zType = "ignore"; break;
+ }
+ sqlite3ExplainPrintf(pOut, "RAISE-%s(%s)", zType, pExpr->u.zToken);
+ break;
+ }
+#endif
+ }
+ if( zBinOp ){
+ sqlite3ExplainPrintf(pOut,"%s(", zBinOp);
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ sqlite3ExplainPrintf(pOut,",");
+ sqlite3ExplainExpr(pOut, pExpr->pRight);
+ sqlite3ExplainPrintf(pOut,")");
+ }else if( zUniOp ){
+ sqlite3ExplainPrintf(pOut,"%s(", zUniOp);
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ sqlite3ExplainPrintf(pOut,")");
+ }
+}
+#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */
+
+#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
+/*
+** Generate a human-readable explanation of an expression list.
+*/
+SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
+ int i;
+ if( pList==0 || pList->nExpr==0 ){
+ sqlite3ExplainPrintf(pOut, "(empty-list)");
+ return;
+ }else if( pList->nExpr==1 ){
+ sqlite3ExplainExpr(pOut, pList->a[0].pExpr);
+ }else{
+ sqlite3ExplainPush(pOut);
+ for(i=0; i<pList->nExpr; i++){
+ sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
+ sqlite3ExplainPush(pOut);
+ sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
+ sqlite3ExplainPop(pOut);
+ if( pList->a[i].zName ){
+ sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
+ }
+ if( pList->a[i].bSpanIsTab ){
+ sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
+ }
+ if( i<pList->nExpr-1 ){
+ sqlite3ExplainNL(pOut);
+ }
+ }
+ sqlite3ExplainPop(pOut);
+ }
+}
+#endif /* SQLITE_DEBUG */
+
+/*
+** Return TRUE if pExpr is an constant expression that is appropriate
+** for factoring out of a loop. Appropriate expressions are:
+**
+** * Any expression that evaluates to two or more opcodes.
+**
+** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
+** or OP_Variable that does not need to be placed in a
+** specific register.
+**
+** There is no point in factoring out single-instruction constant
+** expressions that need to be placed in a particular register.
+** We could factor them out, but then we would end up adding an
+** OP_SCopy instruction to move the value into the correct register
+** later. We might as well just use the original instruction and
+** avoid the OP_SCopy.
+*/
+static int isAppropriateForFactoring(Expr *p){
+ if( !sqlite3ExprIsConstantNotJoin(p) ){
+ return 0; /* Only constant expressions are appropriate for factoring */
+ }
+ if( (p->flags & EP_FixedDest)==0 ){
+ return 1; /* Any constant without a fixed destination is appropriate */
+ }
+ while( p->op==TK_UPLUS ) p = p->pLeft;
+ switch( p->op ){
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+ case TK_BLOB:
+#endif
+ case TK_VARIABLE:
+ case TK_INTEGER:
+ case TK_FLOAT:
+ case TK_NULL:
+ case TK_STRING: {
+ testcase( p->op==TK_BLOB );
+ testcase( p->op==TK_VARIABLE );
+ testcase( p->op==TK_INTEGER );
+ testcase( p->op==TK_FLOAT );
+ testcase( p->op==TK_NULL );
+ testcase( p->op==TK_STRING );
+ /* Single-instruction constants with a fixed destination are
+ ** better done in-line. If we factor them, they will just end
+ ** up generating an OP_SCopy to move the value to the destination
+ ** register. */
+ return 0;
+ }
+ case TK_UMINUS: {
+ if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){
+ return 0;
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return 1;
+}
+
+/*
+** If pExpr is a constant expression that is appropriate for
+** factoring out of a loop, then evaluate the expression
+** into a register and convert the expression into a TK_REGISTER
+** expression.
+*/
+static int evalConstExpr(Walker *pWalker, Expr *pExpr){
+ Parse *pParse = pWalker->pParse;
+ switch( pExpr->op ){
+ case TK_IN:
+ case TK_REGISTER: {
+ return WRC_Prune;
+ }
+ case TK_COLLATE: {
+ return WRC_Continue;
+ }
+ case TK_FUNCTION:
+ case TK_AGG_FUNCTION:
+ case TK_CONST_FUNC: {
+ /* The arguments to a function have a fixed destination.
+ ** Mark them this way to avoid generated unneeded OP_SCopy
+ ** instructions.
+ */
+ ExprList *pList = pExpr->x.pList;
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ if( pList ){
+ int i = pList->nExpr;
+ struct ExprList_item *pItem = pList->a;
+ for(; i>0; i--, pItem++){
+ if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest;
+ }
+ }
+ break;
+ }
+ }
+ if( isAppropriateForFactoring(pExpr) ){
+ int r1 = ++pParse->nMem;
+ int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+ /* If r2!=r1, it means that register r1 is never used. That is harmless
+ ** but suboptimal, so we want to know about the situation to fix it.
+ ** Hence the following assert: */
+ assert( r2==r1 );
+ pExpr->op2 = pExpr->op;
+ pExpr->op = TK_REGISTER;
+ pExpr->iTable = r2;
+ return WRC_Prune;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Preevaluate constant subexpressions within pExpr and store the
+** results in registers. Modify pExpr so that the constant subexpresions
+** are TK_REGISTER opcodes that refer to the precomputed values.
+**
+** This routine is a no-op if the jump to the cookie-check code has
+** already occur. Since the cookie-check jump is generated prior to
+** any other serious processing, this check ensures that there is no
+** way to accidently bypass the constant initializations.
+**
+** This routine is also a no-op if the SQLITE_FactorOutConst optimization
+** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS)
+** interface. This allows test logic to verify that the same answer is
+** obtained for queries regardless of whether or not constants are
+** precomputed into registers or if they are inserted in-line.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
+ Walker w;
+ if( pParse->cookieGoto ) return;
+ if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
+ w.xExprCallback = evalConstExpr;
+ w.xSelectCallback = 0;
+ w.pParse = pParse;
+ sqlite3WalkExpr(&w, pExpr);
+}
+
+
+/*
+** Generate code that pushes the value of every element of the given
+** expression list into a sequence of registers beginning at target.
+**
+** Return the number of elements evaluated.
+*/
+SQLITE_PRIVATE int sqlite3ExprCodeExprList(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* The expression list to be coded */
+ int target, /* Where to write results */
+ int doHardCopy /* Make a hard copy of every element */
+){
+ struct ExprList_item *pItem;
+ int i, n;
+ assert( pList!=0 );
+ assert( target>0 );
+ assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
+ n = pList->nExpr;
+ for(pItem=pList->a, i=0; i<n; i++, pItem++){
+ Expr *pExpr = pItem->pExpr;
+ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
+ if( inReg!=target+i ){
+ sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy,
+ inReg, target+i);
+ }
+ }
+ return n;
+}
+
+/*
+** Generate code for a BETWEEN operator.
+**
+** x BETWEEN y AND z
+**
+** The above is equivalent to
+**
+** x>=y AND x<=z
+**
+** Code it as such, taking care to do the common subexpression
+** elementation of x.
+*/
+static void exprCodeBetween(
+ Parse *pParse, /* Parsing and code generating context */
+ Expr *pExpr, /* The BETWEEN expression */
+ int dest, /* Jump here if the jump is taken */
+ int jumpIfTrue, /* Take the jump if the BETWEEN is true */
+ int jumpIfNull /* Take the jump if the BETWEEN is NULL */
+){
+ Expr exprAnd; /* The AND operator in x>=y AND x<=z */
+ Expr compLeft; /* The x>=y term */
+ Expr compRight; /* The x<=z term */
+ Expr exprX; /* The x subexpression */
+ int regFree1 = 0; /* Temporary use register */
+
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ exprX = *pExpr->pLeft;
+ exprAnd.op = TK_AND;
+ exprAnd.pLeft = &compLeft;
+ exprAnd.pRight = &compRight;
+ compLeft.op = TK_GE;
+ compLeft.pLeft = &exprX;
+ compLeft.pRight = pExpr->x.pList->a[0].pExpr;
+ compRight.op = TK_LE;
+ compRight.pLeft = &exprX;
+ compRight.pRight = pExpr->x.pList->a[1].pExpr;
+ exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
+ exprX.op = TK_REGISTER;
+ if( jumpIfTrue ){
+ sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
+ }else{
+ sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
+ }
+ sqlite3ReleaseTempReg(pParse, regFree1);
+
+ /* Ensure adequate test coverage */
+ testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 );
+ testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 );
+ testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 );
+ testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 );
+ testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 );
+ testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 );
+ testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 );
+ testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 );
+}
+
+/*
+** Generate code for a boolean expression such that a jump is made
+** to the label "dest" if the expression is true but execution
+** continues straight thru if the expression is false.
+**
+** If the expression evaluates to NULL (neither true nor false), then
+** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL.
+**
+** This code depends on the fact that certain token values (ex: TK_EQ)
+** are the same as opcode values (ex: OP_Eq) that implement the corresponding
+** operation. Special comments in vdbe.c and the mkopcodeh.awk script in
+** the make process cause these values to align. Assert()s in the code
+** below verify that the numbers are aligned correctly.
+*/
+SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
+ Vdbe *v = pParse->pVdbe;
+ int op = 0;
+ int regFree1 = 0;
+ int regFree2 = 0;
+ int r1, r2;
+
+ assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
+ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
+ if( NEVER(pExpr==0) ) return; /* No way this can happen */
+ op = pExpr->op;
+ switch( op ){
+ case TK_AND: {
+ int d2 = sqlite3VdbeMakeLabel(v);
+ testcase( jumpIfNull==0 );
+ sqlite3ExprCachePush(pParse);
+ sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
+ sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+ sqlite3VdbeResolveLabel(v, d2);
+ sqlite3ExprCachePop(pParse, 1);
+ break;
+ }
+ case TK_OR: {
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
+ sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+ break;
+ }
+ case TK_NOT: {
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
+ break;
+ }
+ case TK_LT:
+ case TK_LE:
+ case TK_GT:
+ case TK_GE:
+ case TK_NE:
+ case TK_EQ: {
+ assert( TK_LT==OP_Lt );
+ assert( TK_LE==OP_Le );
+ assert( TK_GT==OP_Gt );
+ assert( TK_GE==OP_Ge );
+ assert( TK_EQ==OP_Eq );
+ assert( TK_NE==OP_Ne );
+ testcase( op==TK_LT );
+ testcase( op==TK_LE );
+ testcase( op==TK_GT );
+ testcase( op==TK_GE );
+ testcase( op==TK_EQ );
+ testcase( op==TK_NE );
+ testcase( jumpIfNull==0 );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, dest, jumpIfNull);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
+ case TK_IS:
+ case TK_ISNOT: {
+ testcase( op==TK_IS );
+ testcase( op==TK_ISNOT );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ op = (op==TK_IS) ? TK_EQ : TK_NE;
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, dest, SQLITE_NULLEQ);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
+ case TK_ISNULL:
+ case TK_NOTNULL: {
+ assert( TK_ISNULL==OP_IsNull );
+ assert( TK_NOTNULL==OP_NotNull );
+ testcase( op==TK_ISNULL );
+ testcase( op==TK_NOTNULL );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ sqlite3VdbeAddOp2(v, op, r1, dest);
+ testcase( regFree1==0 );
+ break;
+ }
+ case TK_BETWEEN: {
+ testcase( jumpIfNull==0 );
+ exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull);
+ break;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_IN: {
+ int destIfFalse = sqlite3VdbeMakeLabel(v);
+ int destIfNull = jumpIfNull ? dest : destIfFalse;
+ sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
+ sqlite3VdbeResolveLabel(v, destIfFalse);
+ break;
+ }
+#endif
+ default: {
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
+ sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
+ testcase( regFree1==0 );
+ testcase( jumpIfNull==0 );
+ break;
+ }
+ }
+ sqlite3ReleaseTempReg(pParse, regFree1);
+ sqlite3ReleaseTempReg(pParse, regFree2);
+}
+
+/*
+** Generate code for a boolean expression such that a jump is made
+** to the label "dest" if the expression is false but execution
+** continues straight thru if the expression is true.
+**
+** If the expression evaluates to NULL (neither true nor false) then
+** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull
+** is 0.
+*/
+SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
+ Vdbe *v = pParse->pVdbe;
+ int op = 0;
+ int regFree1 = 0;
+ int regFree2 = 0;
+ int r1, r2;
+
+ assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
+ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
+ if( pExpr==0 ) return;
+
+ /* The value of pExpr->op and op are related as follows:
+ **
+ ** pExpr->op op
+ ** --------- ----------
+ ** TK_ISNULL OP_NotNull
+ ** TK_NOTNULL OP_IsNull
+ ** TK_NE OP_Eq
+ ** TK_EQ OP_Ne
+ ** TK_GT OP_Le
+ ** TK_LE OP_Gt
+ ** TK_GE OP_Lt
+ ** TK_LT OP_Ge
+ **
+ ** For other values of pExpr->op, op is undefined and unused.
+ ** The value of TK_ and OP_ constants are arranged such that we
+ ** can compute the mapping above using the following expression.
+ ** Assert()s verify that the computation is correct.
+ */
+ op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1);
+
+ /* Verify correct alignment of TK_ and OP_ constants
+ */
+ assert( pExpr->op!=TK_ISNULL || op==OP_NotNull );
+ assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull );
+ assert( pExpr->op!=TK_NE || op==OP_Eq );
+ assert( pExpr->op!=TK_EQ || op==OP_Ne );
+ assert( pExpr->op!=TK_LT || op==OP_Ge );
+ assert( pExpr->op!=TK_LE || op==OP_Gt );
+ assert( pExpr->op!=TK_GT || op==OP_Le );
+ assert( pExpr->op!=TK_GE || op==OP_Lt );
+
+ switch( pExpr->op ){
+ case TK_AND: {
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
+ sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+ break;
+ }
+ case TK_OR: {
+ int d2 = sqlite3VdbeMakeLabel(v);
+ testcase( jumpIfNull==0 );
+ sqlite3ExprCachePush(pParse);
+ sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
+ sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+ sqlite3VdbeResolveLabel(v, d2);
+ sqlite3ExprCachePop(pParse, 1);
+ break;
+ }
+ case TK_NOT: {
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
+ break;
+ }
+ case TK_LT:
+ case TK_LE:
+ case TK_GT:
+ case TK_GE:
+ case TK_NE:
+ case TK_EQ: {
+ testcase( op==TK_LT );
+ testcase( op==TK_LE );
+ testcase( op==TK_GT );
+ testcase( op==TK_GE );
+ testcase( op==TK_EQ );
+ testcase( op==TK_NE );
+ testcase( jumpIfNull==0 );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, dest, jumpIfNull);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
+ case TK_IS:
+ case TK_ISNOT: {
+ testcase( pExpr->op==TK_IS );
+ testcase( pExpr->op==TK_ISNOT );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, dest, SQLITE_NULLEQ);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
+ case TK_ISNULL:
+ case TK_NOTNULL: {
+ testcase( op==TK_ISNULL );
+ testcase( op==TK_NOTNULL );
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ sqlite3VdbeAddOp2(v, op, r1, dest);
+ testcase( regFree1==0 );
+ break;
+ }
+ case TK_BETWEEN: {
+ testcase( jumpIfNull==0 );
+ exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull);
+ break;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_IN: {
+ if( jumpIfNull ){
+ sqlite3ExprCodeIN(pParse, pExpr, dest, dest);
+ }else{
+ int destIfNull = sqlite3VdbeMakeLabel(v);
+ sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull);
+ sqlite3VdbeResolveLabel(v, destIfNull);
+ }
+ break;
+ }
+#endif
+ default: {
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
+ sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
+ testcase( regFree1==0 );
+ testcase( jumpIfNull==0 );
+ break;
+ }
+ }
+ sqlite3ReleaseTempReg(pParse, regFree1);
+ sqlite3ReleaseTempReg(pParse, regFree2);
+}
+
+/*
+** Do a deep comparison of two expression trees. Return 0 if the two
+** expressions are completely identical. Return 1 if they differ only
+** by a COLLATE operator at the top level. Return 2 if there are differences
+** other than the top-level COLLATE operator.
+**
+** Sometimes this routine will return 2 even if the two expressions
+** really are equivalent. If we cannot prove that the expressions are
+** identical, we return 2 just to be safe. So if this routine
+** returns 2, then you do not really know for certain if the two
+** expressions are the same. But if you get a 0 or 1 return, then you
+** can be sure the expressions are the same. In the places where
+** this routine is used, it does not hurt to get an extra 2 - that
+** just might result in some slightly slower code. But returning
+** an incorrect 0 or 1 could lead to a malfunction.
+*/
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
+ if( pA==0||pB==0 ){
+ return pB==pA ? 0 : 2;
+ }
+ assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
+ assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
+ if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
+ return 2;
+ }
+ if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
+ if( pA->op!=pB->op ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+ return 1;
+ }
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+ return 1;
+ }
+ return 2;
+ }
+ if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
+ if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
+ if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
+ if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
+ if( ExprHasProperty(pA, EP_IntValue) ){
+ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
+ return 2;
+ }
+ }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
+ if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
+ if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
+ return pA->op==TK_COLLATE ? 1 : 2;
+ }
+ }
+ return 0;
+}
+
+/*
+** Compare two ExprList objects. Return 0 if they are identical and
+** non-zero if they differ in any way.
+**
+** This routine might return non-zero for equivalent ExprLists. The
+** only consequence will be disabled optimizations. But this routine
+** must never return 0 if the two ExprList objects are different, or
+** a malfunction will result.
+**
+** Two NULL pointers are considered to be the same. But a NULL pointer
+** always differs from a non-NULL pointer.
+*/
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
+ int i;
+ if( pA==0 && pB==0 ) return 0;
+ if( pA==0 || pB==0 ) return 1;
+ if( pA->nExpr!=pB->nExpr ) return 1;
+ for(i=0; i<pA->nExpr; i++){
+ Expr *pExprA = pA->a[i].pExpr;
+ Expr *pExprB = pB->a[i].pExpr;
+ if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
+ if( sqlite3ExprCompare(pExprA, pExprB) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** An instance of the following structure is used by the tree walker
+** to count references to table columns in the arguments of an
+** aggregate function, in order to implement the
+** sqlite3FunctionThisSrc() routine.
+*/
+struct SrcCount {
+ SrcList *pSrc; /* One particular FROM clause in a nested query */
+ int nThis; /* Number of references to columns in pSrcList */
+ int nOther; /* Number of references to columns in other FROM clauses */
+};
+
+/*
+** Count the number of references to columns.
+*/
+static int exprSrcCount(Walker *pWalker, Expr *pExpr){
+ /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
+ ** is always called before sqlite3ExprAnalyzeAggregates() and so the
+ ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
+ ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
+ ** NEVER() will need to be removed. */
+ if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
+ int i;
+ struct SrcCount *p = pWalker->u.pSrcCount;
+ SrcList *pSrc = p->pSrc;
+ for(i=0; i<pSrc->nSrc; i++){
+ if( pExpr->iTable==pSrc->a[i].iCursor ) break;
+ }
+ if( i<pSrc->nSrc ){
+ p->nThis++;
+ }else{
+ p->nOther++;
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Determine if any of the arguments to the pExpr Function reference
+** pSrcList. Return true if they do. Also return true if the function
+** has no arguments or has only constant arguments. Return false if pExpr
+** references columns but not columns of tables found in pSrcList.
+*/
+SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
+ Walker w;
+ struct SrcCount cnt;
+ assert( pExpr->op==TK_AGG_FUNCTION );
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = exprSrcCount;
+ w.u.pSrcCount = &cnt;
+ cnt.pSrc = pSrcList;
+ cnt.nThis = 0;
+ cnt.nOther = 0;
+ sqlite3WalkExprList(&w, pExpr->x.pList);
+ return cnt.nThis>0 || cnt.nOther==0;
+}
+
+/*
+** Add a new element to the pAggInfo->aCol[] array. Return the index of
+** the new element. Return a negative number if malloc fails.
+*/
+static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
+ int i;
+ pInfo->aCol = sqlite3ArrayAllocate(
+ db,
+ pInfo->aCol,
+ sizeof(pInfo->aCol[0]),
+ &pInfo->nColumn,
+ &i
+ );
+ return i;
+}
+
+/*
+** Add a new element to the pAggInfo->aFunc[] array. Return the index of
+** the new element. Return a negative number if malloc fails.
+*/
+static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
+ int i;
+ pInfo->aFunc = sqlite3ArrayAllocate(
+ db,
+ pInfo->aFunc,
+ sizeof(pInfo->aFunc[0]),
+ &pInfo->nFunc,
+ &i
+ );
+ return i;
+}
+
+/*
+** This is the xExprCallback for a tree walker. It is used to
+** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
+** for additional information.
+*/
+static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
+ int i;
+ NameContext *pNC = pWalker->u.pNC;
+ Parse *pParse = pNC->pParse;
+ SrcList *pSrcList = pNC->pSrcList;
+ AggInfo *pAggInfo = pNC->pAggInfo;
+
+ switch( pExpr->op ){
+ case TK_AGG_COLUMN:
+ case TK_COLUMN: {
+ testcase( pExpr->op==TK_AGG_COLUMN );
+ testcase( pExpr->op==TK_COLUMN );
+ /* Check to see if the column is in one of the tables in the FROM
+ ** clause of the aggregate query */
+ if( ALWAYS(pSrcList!=0) ){
+ struct SrcList_item *pItem = pSrcList->a;
+ for(i=0; i<pSrcList->nSrc; i++, pItem++){
+ struct AggInfo_col *pCol;
+ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+ if( pExpr->iTable==pItem->iCursor ){
+ /* If we reach this point, it means that pExpr refers to a table
+ ** that is in the FROM clause of the aggregate query.
+ **
+ ** Make an entry for the column in pAggInfo->aCol[] if there
+ ** is not an entry there already.
+ */
+ int k;
+ pCol = pAggInfo->aCol;
+ for(k=0; k<pAggInfo->nColumn; k++, pCol++){
+ if( pCol->iTable==pExpr->iTable &&
+ pCol->iColumn==pExpr->iColumn ){
+ break;
+ }
+ }
+ if( (k>=pAggInfo->nColumn)
+ && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
+ ){
+ pCol = &pAggInfo->aCol[k];
+ pCol->pTab = pExpr->pTab;
+ pCol->iTable = pExpr->iTable;
+ pCol->iColumn = pExpr->iColumn;
+ pCol->iMem = ++pParse->nMem;
+ pCol->iSorterColumn = -1;
+ pCol->pExpr = pExpr;
+ if( pAggInfo->pGroupBy ){
+ int j, n;
+ ExprList *pGB = pAggInfo->pGroupBy;
+ struct ExprList_item *pTerm = pGB->a;
+ n = pGB->nExpr;
+ for(j=0; j<n; j++, pTerm++){
+ Expr *pE = pTerm->pExpr;
+ if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
+ pE->iColumn==pExpr->iColumn ){
+ pCol->iSorterColumn = j;
+ break;
+ }
+ }
+ }
+ if( pCol->iSorterColumn<0 ){
+ pCol->iSorterColumn = pAggInfo->nSortingColumn++;
+ }
+ }
+ /* There is now an entry for pExpr in pAggInfo->aCol[] (either
+ ** because it was there before or because we just created it).
+ ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
+ ** pAggInfo->aCol[] entry.
+ */
+ ExprSetIrreducible(pExpr);
+ pExpr->pAggInfo = pAggInfo;
+ pExpr->op = TK_AGG_COLUMN;
+ pExpr->iAgg = (i16)k;
+ break;
+ } /* endif pExpr->iTable==pItem->iCursor */
+ } /* end loop over pSrcList */
+ }
+ return WRC_Prune;
+ }
+ case TK_AGG_FUNCTION: {
+ if( (pNC->ncFlags & NC_InAggFunc)==0
+ && pWalker->walkerDepth==pExpr->op2
+ ){
+ /* Check to see if pExpr is a duplicate of another aggregate
+ ** function that is already in the pAggInfo structure
+ */
+ struct AggInfo_func *pItem = pAggInfo->aFunc;
+ for(i=0; i<pAggInfo->nFunc; i++, pItem++){
+ if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
+ break;
+ }
+ }
+ if( i>=pAggInfo->nFunc ){
+ /* pExpr is original. Make a new entry in pAggInfo->aFunc[]
+ */
+ u8 enc = ENC(pParse->db);
+ i = addAggInfoFunc(pParse->db, pAggInfo);
+ if( i>=0 ){
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ pItem = &pAggInfo->aFunc[i];
+ pItem->pExpr = pExpr;
+ pItem->iMem = ++pParse->nMem;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ pItem->pFunc = sqlite3FindFunction(pParse->db,
+ pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken),
+ pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
+ if( pExpr->flags & EP_Distinct ){
+ pItem->iDistinct = pParse->nTab++;
+ }else{
+ pItem->iDistinct = -1;
+ }
+ }
+ }
+ /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
+ */
+ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+ ExprSetIrreducible(pExpr);
+ pExpr->iAgg = (i16)i;
+ pExpr->pAggInfo = pAggInfo;
+ return WRC_Prune;
+ }else{
+ return WRC_Continue;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
+ UNUSED_PARAMETER(pWalker);
+ UNUSED_PARAMETER(pSelect);
+ return WRC_Continue;
+}
+
+/*
+** Analyze the pExpr expression looking for aggregate functions and
+** for variables that need to be added to AggInfo object that pNC->pAggInfo
+** points to. Additional entries are made on the AggInfo object as
+** necessary.
+**
+** This routine should only be called after the expression has been
+** analyzed by sqlite3ResolveExprNames().
+*/
+SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.xExprCallback = analyzeAggregate;
+ w.xSelectCallback = analyzeAggregatesInSelect;
+ w.u.pNC = pNC;
+ assert( pNC->pSrcList!=0 );
+ sqlite3WalkExpr(&w, pExpr);
+}
+
+/*
+** Call sqlite3ExprAnalyzeAggregates() for every expression in an
+** expression list. Return the number of errors.
+**
+** If an error is found, the analysis is cut short.
+*/
+SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
+ struct ExprList_item *pItem;
+ int i;
+ if( pList ){
+ for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
+ sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr);
+ }
+ }
+}
+
+/*
+** Allocate a single new register for use to hold some intermediate result.
+*/
+SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
+ if( pParse->nTempReg==0 ){
+ return ++pParse->nMem;
+ }
+ return pParse->aTempReg[--pParse->nTempReg];
+}
+
+/*
+** Deallocate a register, making available for reuse for some other
+** purpose.
+**
+** If a register is currently being used by the column cache, then
+** the dallocation is deferred until the column cache line that uses
+** the register becomes stale.
+*/
+SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
+ if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
+ int i;
+ struct yColCache *p;
+ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
+ if( p->iReg==iReg ){
+ p->tempReg = 1;
+ return;
+ }
+ }
+ pParse->aTempReg[pParse->nTempReg++] = iReg;
+ }
+}
+
+/*
+** Allocate or deallocate a block of nReg consecutive registers
+*/
+SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){
+ int i, n;
+ i = pParse->iRangeReg;
+ n = pParse->nRangeReg;
+ if( nReg<=n ){
+ assert( !usedAsColumnCache(pParse, i, i+n-1) );
+ pParse->iRangeReg += nReg;
+ pParse->nRangeReg -= nReg;
+ }else{
+ i = pParse->nMem+1;
+ pParse->nMem += nReg;
+ }
+ return i;
+}
+SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
+ sqlite3ExprCacheRemove(pParse, iReg, nReg);
+ if( nReg>pParse->nRangeReg ){
+ pParse->nRangeReg = nReg;
+ pParse->iRangeReg = iReg;
+ }
+}
+
+/*
+** Mark all temporary registers as being unavailable for reuse.
+*/
+SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){
+ pParse->nTempReg = 0;
+ pParse->nRangeReg = 0;
+}
+
+/************** End of expr.c ************************************************/
+/************** Begin file alter.c *******************************************/
+/*
+** 2005 February 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that used to generate VDBE code
+** that implements the ALTER TABLE command.
+*/
+
+/*
+** The code in this file only exists if we are not omitting the
+** ALTER TABLE logic from the build.
+*/
+#ifndef SQLITE_OMIT_ALTERTABLE
+
+
+/*
+** This function is used by SQL generated to implement the
+** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
+** CREATE INDEX command. The second is a table name. The table name in
+** the CREATE TABLE or CREATE INDEX statement is replaced with the third
+** argument and the result returned. Examples:
+**
+** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
+** -> 'CREATE TABLE def(a, b, c)'
+**
+** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
+** -> 'CREATE INDEX i ON def(a, b, c)'
+*/
+static void renameTableFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ unsigned char const *zSql = sqlite3_value_text(argv[0]);
+ unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+ int token;
+ Token tname;
+ unsigned char const *zCsr = zSql;
+ int len = 0;
+ char *zRet;
+
+ sqlite3 *db = sqlite3_context_db_handle(context);
+
+ UNUSED_PARAMETER(NotUsed);
+
+ /* The principle used to locate the table name in the CREATE TABLE
+ ** statement is that the table name is the first non-space token that
+ ** is immediately followed by a TK_LP or TK_USING token.
+ */
+ if( zSql ){
+ do {
+ if( !*zCsr ){
+ /* Ran out of input before finding an opening bracket. Return NULL. */
+ return;
+ }
+
+ /* Store the token that zCsr points to in tname. */
+ tname.z = (char*)zCsr;
+ tname.n = len;
+
+ /* Advance zCsr to the next token. Store that token type in 'token',
+ ** and its length in 'len' (to be used next iteration of this loop).
+ */
+ do {
+ zCsr += len;
+ len = sqlite3GetToken(zCsr, &token);
+ } while( token==TK_SPACE );
+ assert( len>0 );
+ } while( token!=TK_LP && token!=TK_USING );
+
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
+ zTableName, tname.z+tname.n);
+ sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
+ }
+}
+
+/*
+** This C function implements an SQL user function that is used by SQL code
+** generated by the ALTER TABLE ... RENAME command to modify the definition
+** of any foreign key constraints that use the table being renamed as the
+** parent table. It is passed three arguments:
+**
+** 1) The complete text of the CREATE TABLE statement being modified,
+** 2) The old name of the table being renamed, and
+** 3) The new name of the table being renamed.
+**
+** It returns the new CREATE TABLE statement. For example:
+**
+** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3')
+** -> 'CREATE TABLE t1(a REFERENCES t3)'
+*/
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+static void renameParentFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ char *zOutput = 0;
+ char *zResult;
+ unsigned char const *zInput = sqlite3_value_text(argv[0]);
+ unsigned char const *zOld = sqlite3_value_text(argv[1]);
+ unsigned char const *zNew = sqlite3_value_text(argv[2]);
+
+ unsigned const char *z; /* Pointer to token */
+ int n; /* Length of token z */
+ int token; /* Type of token */
+
+ UNUSED_PARAMETER(NotUsed);
+ for(z=zInput; *z; z=z+n){
+ n = sqlite3GetToken(z, &token);
+ if( token==TK_REFERENCES ){
+ char *zParent;
+ do {
+ z += n;
+ n = sqlite3GetToken(z, &token);
+ }while( token==TK_SPACE );
+
+ zParent = sqlite3DbStrNDup(db, (const char *)z, n);
+ if( zParent==0 ) break;
+ sqlite3Dequote(zParent);
+ if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
+ char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
+ (zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew
+ );
+ sqlite3DbFree(db, zOutput);
+ zOutput = zOut;
+ zInput = &z[n];
+ }
+ sqlite3DbFree(db, zParent);
+ }
+ }
+
+ zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
+ sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
+ sqlite3DbFree(db, zOutput);
+}
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
+/* This function is used by SQL generated to implement the
+** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
+** statement. The second is a table name. The table name in the CREATE
+** TRIGGER statement is replaced with the third argument and the result
+** returned. This is analagous to renameTableFunc() above, except for CREATE
+** TRIGGER, not CREATE INDEX and CREATE TABLE.
+*/
+static void renameTriggerFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ unsigned char const *zSql = sqlite3_value_text(argv[0]);
+ unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+ int token;
+ Token tname;
+ int dist = 3;
+ unsigned char const *zCsr = zSql;
+ int len = 0;
+ char *zRet;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+
+ UNUSED_PARAMETER(NotUsed);
+
+ /* The principle used to locate the table name in the CREATE TRIGGER
+ ** statement is that the table name is the first token that is immediatedly
+ ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
+ ** of TK_WHEN, TK_BEGIN or TK_FOR.
+ */
+ if( zSql ){
+ do {
+
+ if( !*zCsr ){
+ /* Ran out of input before finding the table name. Return NULL. */
+ return;
+ }
+
+ /* Store the token that zCsr points to in tname. */
+ tname.z = (char*)zCsr;
+ tname.n = len;
+
+ /* Advance zCsr to the next token. Store that token type in 'token',
+ ** and its length in 'len' (to be used next iteration of this loop).
+ */
+ do {
+ zCsr += len;
+ len = sqlite3GetToken(zCsr, &token);
+ }while( token==TK_SPACE );
+ assert( len>0 );
+
+ /* Variable 'dist' stores the number of tokens read since the most
+ ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
+ ** token is read and 'dist' equals 2, the condition stated above
+ ** to be met.
+ **
+ ** Note that ON cannot be a database, table or column name, so
+ ** there is no need to worry about syntax like
+ ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
+ */
+ dist++;
+ if( token==TK_DOT || token==TK_ON ){
+ dist = 0;
+ }
+ } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
+
+ /* Variable tname now contains the token that is the old table-name
+ ** in the CREATE TRIGGER statement.
+ */
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
+ zTableName, tname.z+tname.n);
+ sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
+ }
+}
+#endif /* !SQLITE_OMIT_TRIGGER */
+
+/*
+** Register built-in functions used to help implement ALTER TABLE
+*/
+SQLITE_PRIVATE void sqlite3AlterFunctions(void){
+ static SQLITE_WSD FuncDef aAlterTableFuncs[] = {
+ FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc),
+#ifndef SQLITE_OMIT_TRIGGER
+ FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
+#endif
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc),
+#endif
+ };
+ int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs);
+
+ for(i=0; i<ArraySize(aAlterTableFuncs); i++){
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
+ }
+}
+
+/*
+** This function is used to create the text of expressions of the form:
+**
+** name=<constant1> OR name=<constant2> OR ...
+**
+** If argument zWhere is NULL, then a pointer string containing the text
+** "name=<constant>" is returned, where <constant> is the quoted version
+** of the string passed as argument zConstant. The returned buffer is
+** allocated using sqlite3DbMalloc(). It is the responsibility of the
+** caller to ensure that it is eventually freed.
+**
+** If argument zWhere is not NULL, then the string returned is
+** "<where> OR name=<constant>", where <where> is the contents of zWhere.
+** In this case zWhere is passed to sqlite3DbFree() before returning.
+**
+*/
+static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){
+ char *zNew;
+ if( !zWhere ){
+ zNew = sqlite3MPrintf(db, "name=%Q", zConstant);
+ }else{
+ zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant);
+ sqlite3DbFree(db, zWhere);
+ }
+ return zNew;
+}
+
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+/*
+** Generate the text of a WHERE expression which can be used to select all
+** tables that have foreign key constraints that refer to table pTab (i.e.
+** constraints for which pTab is the parent table) from the sqlite_master
+** table.
+*/
+static char *whereForeignKeys(Parse *pParse, Table *pTab){
+ FKey *p;
+ char *zWhere = 0;
+ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
+ zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName);
+ }
+ return zWhere;
+}
+#endif
+
+/*
+** Generate the text of a WHERE expression which can be used to select all
+** temporary triggers on table pTab from the sqlite_temp_master table. If
+** table pTab has no temporary triggers, or is itself stored in the
+** temporary database, NULL is returned.
+*/
+static char *whereTempTriggers(Parse *pParse, Table *pTab){
+ Trigger *pTrig;
+ char *zWhere = 0;
+ const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
+
+ /* If the table is not located in the temp-db (in which case NULL is
+ ** returned, loop through the tables list of triggers. For each trigger
+ ** that is not part of the temp-db schema, add a clause to the WHERE
+ ** expression being built up in zWhere.
+ */
+ if( pTab->pSchema!=pTempSchema ){
+ sqlite3 *db = pParse->db;
+ for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
+ if( pTrig->pSchema==pTempSchema ){
+ zWhere = whereOrName(db, zWhere, pTrig->zName);
+ }
+ }
+ }
+ if( zWhere ){
+ char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere);
+ sqlite3DbFree(pParse->db, zWhere);
+ zWhere = zNew;
+ }
+ return zWhere;
+}
+
+/*
+** Generate code to drop and reload the internal representation of table
+** pTab from the database, including triggers and temporary triggers.
+** Argument zName is the name of the table in the database schema at
+** the time the generated code is executed. This can be different from
+** pTab->zName if this function is being called to code part of an
+** "ALTER TABLE RENAME TO" statement.
+*/
+static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
+ Vdbe *v;
+ char *zWhere;
+ int iDb; /* Index of database containing pTab */
+#ifndef SQLITE_OMIT_TRIGGER
+ Trigger *pTrig;
+#endif
+
+ v = sqlite3GetVdbe(pParse);
+ if( NEVER(v==0) ) return;
+ assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ assert( iDb>=0 );
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* Drop any table triggers from the internal schema. */
+ for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
+ int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
+ assert( iTrigDb==iDb || iTrigDb==1 );
+ sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0);
+ }
+#endif
+
+ /* Drop the table and index from the internal schema. */
+ sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
+
+ /* Reload the table, index and permanent trigger schemas. */
+ zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
+ if( !zWhere ) return;
+ sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* Now, if the table is not stored in the temp database, reload any temp
+ ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
+ */
+ if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
+ sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
+ }
+#endif
+}
+
+/*
+** Parameter zName is the name of a table that is about to be altered
+** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
+** If the table is a system table, this function leaves an error message
+** in pParse->zErr (system tables may not be altered) and returns non-zero.
+**
+** Or, if zName is not a system table, zero is returned.
+*/
+static int isSystemTable(Parse *pParse, const char *zName){
+ if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
+ sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
+** command.
+*/
+SQLITE_PRIVATE void sqlite3AlterRenameTable(
+ Parse *pParse, /* Parser context. */
+ SrcList *pSrc, /* The table to rename. */
+ Token *pName /* The new table name. */
+){
+ int iDb; /* Database that contains the table */
+ char *zDb; /* Name of database iDb */
+ Table *pTab; /* Table being renamed */
+ char *zName = 0; /* NULL-terminated version of pName */
+ sqlite3 *db = pParse->db; /* Database connection */
+ int nTabName; /* Number of UTF-8 characters in zTabName */
+ const char *zTabName; /* Original name of the table */
+ Vdbe *v;
+#ifndef SQLITE_OMIT_TRIGGER
+ char *zWhere = 0; /* Where clause to locate temp triggers */
+#endif
+ VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
+ int savedDbFlags; /* Saved value of db->flags */
+
+ savedDbFlags = db->flags;
+ if( NEVER(db->mallocFailed) ) goto exit_rename_table;
+ assert( pSrc->nSrc==1 );
+ assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
+
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
+ if( !pTab ) goto exit_rename_table;
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ zDb = db->aDb[iDb].zName;
+ db->flags |= SQLITE_PreferBuiltin;
+
+ /* Get a NULL terminated version of the new table name. */
+ zName = sqlite3NameFromToken(db, pName);
+ if( !zName ) goto exit_rename_table;
+
+ /* Check that a table or index named 'zName' does not already exist
+ ** in database iDb. If so, this is an error.
+ */
+ if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
+ sqlite3ErrorMsg(pParse,
+ "there is already another table or index with this name: %s", zName);
+ goto exit_rename_table;
+ }
+
+ /* Make sure it is not a system table being altered, or a reserved name
+ ** that the table is being renamed to.
+ */
+ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
+ goto exit_rename_table;
+ }
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
+ exit_rename_table;
+ }
+
+#ifndef SQLITE_OMIT_VIEW
+ if( pTab->pSelect ){
+ sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
+ goto exit_rename_table;
+ }
+#endif
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+ goto exit_rename_table;
+ }
+#endif
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+ goto exit_rename_table;
+ }
+ if( IsVirtual(pTab) ){
+ pVTab = sqlite3GetVTable(db, pTab);
+ if( pVTab->pVtab->pModule->xRename==0 ){
+ pVTab = 0;
+ }
+ }
+#endif
+
+ /* Begin a transaction and code the VerifyCookie for database iDb.
+ ** Then modify the schema cookie (since the ALTER TABLE modifies the
+ ** schema). Open a statement transaction if the table is a virtual
+ ** table.
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ){
+ goto exit_rename_table;
+ }
+ sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb);
+ sqlite3ChangeCookie(pParse, iDb);
+
+ /* If this is a virtual table, invoke the xRename() function if
+ ** one is defined. The xRename() callback will modify the names
+ ** of any resources used by the v-table implementation (including other
+ ** SQLite tables) that are identified by the name of the virtual table.
+ */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pVTab ){
+ int i = ++pParse->nMem;
+ sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0);
+ sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
+ sqlite3MayAbort(pParse);
+ }
+#endif
+
+ /* figure out how many UTF-8 characters are in zName */
+ zTabName = pTab->zName;
+ nTabName = sqlite3Utf8CharLen(zTabName, -1);
+
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+ if( db->flags&SQLITE_ForeignKeys ){
+ /* If foreign-key support is enabled, rewrite the CREATE TABLE
+ ** statements corresponding to all child tables of foreign key constraints
+ ** for which the renamed table is the parent table. */
+ if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\".%s SET "
+ "sql = sqlite_rename_parent(sql, %Q, %Q) "
+ "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
+ sqlite3DbFree(db, zWhere);
+ }
+ }
+#endif
+
+ /* Modify the sqlite_master table to use the new table name. */
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s SET "
+#ifdef SQLITE_OMIT_TRIGGER
+ "sql = sqlite_rename_table(sql, %Q), "
+#else
+ "sql = CASE "
+ "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
+ "ELSE sqlite_rename_table(sql, %Q) END, "
+#endif
+ "tbl_name = %Q, "
+ "name = CASE "
+ "WHEN type='table' THEN %Q "
+ "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
+ "'sqlite_autoindex_' || %Q || substr(name,%d+18) "
+ "ELSE name END "
+ "WHERE tbl_name=%Q COLLATE nocase AND "
+ "(type='table' OR type='index' OR type='trigger');",
+ zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
+#ifndef SQLITE_OMIT_TRIGGER
+ zName,
+#endif
+ zName, nTabName, zTabName
+ );
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* If the sqlite_sequence table exists in this database, then update
+ ** it with the new table name.
+ */
+ if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q",
+ zDb, zName, pTab->zName);
+ }
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If there are TEMP triggers on this table, modify the sqlite_temp_master
+ ** table. Don't do this if the table being ALTERed is itself located in
+ ** the temp database.
+ */
+ if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
+ sqlite3NestedParse(pParse,
+ "UPDATE sqlite_temp_master SET "
+ "sql = sqlite_rename_trigger(sql, %Q), "
+ "tbl_name = %Q "
+ "WHERE %s;", zName, zName, zWhere);
+ sqlite3DbFree(db, zWhere);
+ }
+#endif
+
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+ if( db->flags&SQLITE_ForeignKeys ){
+ FKey *p;
+ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
+ Table *pFrom = p->pFrom;
+ if( pFrom!=pTab ){
+ reloadTableSchema(pParse, p->pFrom, pFrom->zName);
+ }
+ }
+ }
+#endif
+
+ /* Drop and reload the internal table schema. */
+ reloadTableSchema(pParse, pTab, zName);
+
+exit_rename_table:
+ sqlite3SrcListDelete(db, pSrc);
+ sqlite3DbFree(db, zName);
+ db->flags = savedDbFlags;
+}
+
+
+/*
+** Generate code to make sure the file format number is at least minFormat.
+** The generated code will increase the file format number if necessary.
+*/
+SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
+ Vdbe *v;
+ v = sqlite3GetVdbe(pParse);
+ /* The VDBE should have been allocated before this routine is called.
+ ** If that allocation failed, we would have quit before reaching this
+ ** point */
+ if( ALWAYS(v) ){
+ int r1 = sqlite3GetTempReg(pParse);
+ int r2 = sqlite3GetTempReg(pParse);
+ int j1;
+ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
+ sqlite3VdbeUsesBtree(v, iDb);
+ sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
+ j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2);
+ sqlite3VdbeJumpHere(v, j1);
+ sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ReleaseTempReg(pParse, r2);
+ }
+}
+
+/*
+** This function is called after an "ALTER TABLE ... ADD" statement
+** has been parsed. Argument pColDef contains the text of the new
+** column definition.
+**
+** The Table structure pParse->pNewTable was extended to include
+** the new column during parsing.
+*/
+SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
+ Table *pNew; /* Copy of pParse->pNewTable */
+ Table *pTab; /* Table being altered */
+ int iDb; /* Database number */
+ const char *zDb; /* Database name */
+ const char *zTab; /* Table name */
+ char *zCol; /* Null-terminated column definition */
+ Column *pCol; /* The new column */
+ Expr *pDflt; /* Default value for the new column */
+ sqlite3 *db; /* The database connection; */
+
+ db = pParse->db;
+ if( pParse->nErr || db->mallocFailed ) return;
+ pNew = pParse->pNewTable;
+ assert( pNew );
+
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
+ zDb = db->aDb[iDb].zName;
+ zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
+ pCol = &pNew->aCol[pNew->nCol-1];
+ pDflt = pCol->pDflt;
+ pTab = sqlite3FindTable(db, zTab, zDb);
+ assert( pTab );
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+ return;
+ }
+#endif
+
+ /* If the default value for the new column was specified with a
+ ** literal NULL, then set pDflt to 0. This simplifies checking
+ ** for an SQL NULL default below.
+ */
+ if( pDflt && pDflt->op==TK_NULL ){
+ pDflt = 0;
+ }
+
+ /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
+ ** If there is a NOT NULL constraint, then the default value for the
+ ** column must not be NULL.
+ */
+ if( pCol->colFlags & COLFLAG_PRIMKEY ){
+ sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
+ return;
+ }
+ if( pNew->pIndex ){
+ sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
+ return;
+ }
+ if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
+ sqlite3ErrorMsg(pParse,
+ "Cannot add a REFERENCES column with non-NULL default value");
+ return;
+ }
+ if( pCol->notNull && !pDflt ){
+ sqlite3ErrorMsg(pParse,
+ "Cannot add a NOT NULL column with default value NULL");
+ return;
+ }
+
+ /* Ensure the default expression is something that sqlite3ValueFromExpr()
+ ** can handle (i.e. not CURRENT_TIME etc.)
+ */
+ if( pDflt ){
+ sqlite3_value *pVal;
+ if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
+ db->mallocFailed = 1;
+ return;
+ }
+ if( !pVal ){
+ sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
+ return;
+ }
+ sqlite3ValueFree(pVal);
+ }
+
+ /* Modify the CREATE TABLE statement. */
+ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
+ if( zCol ){
+ char *zEnd = &zCol[pColDef->n-1];
+ int savedDbFlags = db->flags;
+ while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
+ *zEnd-- = '\0';
+ }
+ db->flags |= SQLITE_PreferBuiltin;
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\".%s SET "
+ "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
+ "WHERE type = 'table' AND name = %Q",
+ zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
+ zTab
+ );
+ sqlite3DbFree(db, zCol);
+ db->flags = savedDbFlags;
+ }
+
+ /* If the default value of the new column is NULL, then set the file
+ ** format to 2. If the default value of the new column is not NULL,
+ ** the file format becomes 3.
+ */
+ sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2);
+
+ /* Reload the schema of the modified table. */
+ reloadTableSchema(pParse, pTab, pTab->zName);
+}
+
+/*
+** This function is called by the parser after the table-name in
+** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
+** pSrc is the full-name of the table being altered.
+**
+** This routine makes a (partial) copy of the Table structure
+** for the table being altered and sets Parse.pNewTable to point
+** to it. Routines called by the parser as the column definition
+** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
+** the copy. The copy of the Table structure is deleted by tokenize.c
+** after parsing is finished.
+**
+** Routine sqlite3AlterFinishAddColumn() will be called to complete
+** coding the "ALTER TABLE ... ADD" statement.
+*/
+SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
+ Table *pNew;
+ Table *pTab;
+ Vdbe *v;
+ int iDb;
+ int i;
+ int nAlloc;
+ sqlite3 *db = pParse->db;
+
+ /* Look up the table being altered. */
+ assert( pParse->pNewTable==0 );
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ if( db->mallocFailed ) goto exit_begin_add_column;
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
+ if( !pTab ) goto exit_begin_add_column;
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
+ goto exit_begin_add_column;
+ }
+#endif
+
+ /* Make sure this is not an attempt to ALTER a view. */
+ if( pTab->pSelect ){
+ sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
+ goto exit_begin_add_column;
+ }
+ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
+ goto exit_begin_add_column;
+ }
+
+ assert( pTab->addColOffset>0 );
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+
+ /* Put a copy of the Table struct in Parse.pNewTable for the
+ ** sqlite3AddColumn() function and friends to modify. But modify
+ ** the name by adding an "sqlite_altertab_" prefix. By adding this
+ ** prefix, we insure that the name will not collide with an existing
+ ** table because user table are not allowed to have the "sqlite_"
+ ** prefix on their name.
+ */
+ pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
+ if( !pNew ) goto exit_begin_add_column;
+ pParse->pNewTable = pNew;
+ pNew->nRef = 1;
+ pNew->nCol = pTab->nCol;
+ assert( pNew->nCol>0 );
+ nAlloc = (((pNew->nCol-1)/8)*8)+8;
+ assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
+ pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
+ pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
+ if( !pNew->aCol || !pNew->zName ){
+ db->mallocFailed = 1;
+ goto exit_begin_add_column;
+ }
+ memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
+ for(i=0; i<pNew->nCol; i++){
+ Column *pCol = &pNew->aCol[i];
+ pCol->zName = sqlite3DbStrDup(db, pCol->zName);
+ pCol->zColl = 0;
+ pCol->zType = 0;
+ pCol->pDflt = 0;
+ pCol->zDflt = 0;
+ }
+ pNew->pSchema = db->aDb[iDb].pSchema;
+ pNew->addColOffset = pTab->addColOffset;
+ pNew->nRef = 1;
+
+ /* Begin a transaction and increment the schema cookie. */
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ v = sqlite3GetVdbe(pParse);
+ if( !v ) goto exit_begin_add_column;
+ sqlite3ChangeCookie(pParse, iDb);
+
+exit_begin_add_column:
+ sqlite3SrcListDelete(db, pSrc);
+ return;
+}
+#endif /* SQLITE_ALTER_TABLE */
+
+/************** End of alter.c ***********************************************/
+/************** Begin file analyze.c *****************************************/
+/*
+** 2005 July 8
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code associated with the ANALYZE command.
+**
+** The ANALYZE command gather statistics about the content of tables
+** and indices. These statistics are made available to the query planner
+** to help it make better decisions about how to perform queries.
+**
+** The following system tables are or have been supported:
+**
+** CREATE TABLE sqlite_stat1(tbl, idx, stat);
+** CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample);
+** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
+**
+** Additional tables might be added in future releases of SQLite.
+** The sqlite_stat2 table is not created or used unless the SQLite version
+** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
+** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated.
+** The sqlite_stat2 table is superceded by sqlite_stat3, which is only
+** created and used by SQLite versions 3.7.9 and later and with
+** SQLITE_ENABLE_STAT3 defined. The fucntionality of sqlite_stat3
+** is a superset of sqlite_stat2.
+**
+** Format of sqlite_stat1:
+**
+** There is normally one row per index, with the index identified by the
+** name in the idx column. The tbl column is the name of the table to
+** which the index belongs. In each such row, the stat column will be
+** a string consisting of a list of integers. The first integer in this
+** list is the number of rows in the index and in the table. The second
+** integer is the average number of rows in the index that have the same
+** value in the first column of the index. The third integer is the average
+** number of rows in the index that have the same value for the first two
+** columns. The N-th integer (for N>1) is the average number of rows in
+** the index which have the same value for the first N-1 columns. For
+** a K-column index, there will be K+1 integers in the stat column. If
+** the index is unique, then the last integer will be 1.
+**
+** The list of integers in the stat column can optionally be followed
+** by the keyword "unordered". The "unordered" keyword, if it is present,
+** must be separated from the last integer by a single space. If the
+** "unordered" keyword is present, then the query planner assumes that
+** the index is unordered and will not use the index for a range query.
+**
+** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
+** column contains a single integer which is the (estimated) number of
+** rows in the table identified by sqlite_stat1.tbl.
+**
+** Format of sqlite_stat2:
+**
+** The sqlite_stat2 is only created and is only used if SQLite is compiled
+** with SQLITE_ENABLE_STAT2 and if the SQLite version number is between
+** 3.6.18 and 3.7.8. The "stat2" table contains additional information
+** about the distribution of keys within an index. The index is identified by
+** the "idx" column and the "tbl" column is the name of the table to which
+** the index belongs. There are usually 10 rows in the sqlite_stat2
+** table for each index.
+**
+** The sqlite_stat2 entries for an index that have sampleno between 0 and 9
+** inclusive are samples of the left-most key value in the index taken at
+** evenly spaced points along the index. Let the number of samples be S
+** (10 in the standard build) and let C be the number of rows in the index.
+** Then the sampled rows are given by:
+**
+** rownumber = (i*C*2 + C)/(S*2)
+**
+** For i between 0 and S-1. Conceptually, the index space is divided into
+** S uniform buckets and the samples are the middle row from each bucket.
+**
+** The format for sqlite_stat2 is recorded here for legacy reference. This
+** version of SQLite does not support sqlite_stat2. It neither reads nor
+** writes the sqlite_stat2 table. This version of SQLite only supports
+** sqlite_stat3.
+**
+** Format for sqlite_stat3:
+**
+** The sqlite_stat3 is an enhancement to sqlite_stat2. A new name is
+** used to avoid compatibility problems.
+**
+** The format of the sqlite_stat3 table is similar to the format of
+** the sqlite_stat2 table. There are multiple entries for each index.
+** The idx column names the index and the tbl column is the table of the
+** index. If the idx and tbl columns are the same, then the sample is
+** of the INTEGER PRIMARY KEY. The sample column is a value taken from
+** the left-most column of the index. The nEq column is the approximate
+** number of entires in the index whose left-most column exactly matches
+** the sample. nLt is the approximate number of entires whose left-most
+** column is less than the sample. The nDLt column is the approximate
+** number of distinct left-most entries in the index that are less than
+** the sample.
+**
+** Future versions of SQLite might change to store a string containing
+** multiple integers values in the nDLt column of sqlite_stat3. The first
+** integer will be the number of prior index entires that are distinct in
+** the left-most column. The second integer will be the number of prior index
+** entries that are distinct in the first two columns. The third integer
+** will be the number of prior index entries that are distinct in the first
+** three columns. And so forth. With that extension, the nDLt field is
+** similar in function to the sqlite_stat1.stat field.
+**
+** There can be an arbitrary number of sqlite_stat3 entries per index.
+** The ANALYZE command will typically generate sqlite_stat3 tables
+** that contain between 10 and 40 samples which are distributed across
+** the key space, though not uniformly, and which include samples with
+** largest possible nEq values.
+*/
+#ifndef SQLITE_OMIT_ANALYZE
+
+/*
+** This routine generates code that opens the sqlite_stat1 table for
+** writing with cursor iStatCur. If the library was built with the
+** SQLITE_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is
+** opened for writing using cursor (iStatCur+1)
+**
+** If the sqlite_stat1 tables does not previously exist, it is created.
+** Similarly, if the sqlite_stat3 table does not exist and the library
+** is compiled with SQLITE_ENABLE_STAT3 defined, it is created.
+**
+** Argument zWhere may be a pointer to a buffer containing a table name,
+** or it may be a NULL pointer. If it is not NULL, then all entries in
+** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated
+** with the named table are deleted. If zWhere==0, then code is generated
+** to delete all stat table entries.
+*/
+static void openStatTable(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* The database we are looking in */
+ int iStatCur, /* Open the sqlite_stat1 table on this cursor */
+ const char *zWhere, /* Delete entries for this table or index */
+ const char *zWhereType /* Either "tbl" or "idx" */
+){
+ static const struct {
+ const char *zName;
+ const char *zCols;
+ } aTable[] = {
+ { "sqlite_stat1", "tbl,idx,stat" },
+#ifdef SQLITE_ENABLE_STAT3
+ { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
+#endif
+ };
+
+ int aRoot[] = {0, 0};
+ u8 aCreateTbl[] = {0, 0};
+
+ int i;
+ sqlite3 *db = pParse->db;
+ Db *pDb;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v==0 ) return;
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ assert( sqlite3VdbeDb(v)==db );
+ pDb = &db->aDb[iDb];
+
+ /* Create new statistic tables if they do not exist, or clear them
+ ** if they do already exist.
+ */
+ for(i=0; i<ArraySize(aTable); i++){
+ const char *zTab = aTable[i].zName;
+ Table *pStat;
+ if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
+ /* The sqlite_stat[12] table does not exist. Create it. Note that a
+ ** side-effect of the CREATE TABLE statement is to leave the rootpage
+ ** of the new table in register pParse->regRoot. This is important
+ ** because the OpenWrite opcode below will be needing it. */
+ sqlite3NestedParse(pParse,
+ "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
+ );
+ aRoot[i] = pParse->regRoot;
+ aCreateTbl[i] = OPFLAG_P2ISREG;
+ }else{
+ /* The table already exists. If zWhere is not NULL, delete all entries
+ ** associated with the table zWhere. If zWhere is NULL, delete the
+ ** entire contents of the table. */
+ aRoot[i] = pStat->tnum;
+ sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
+ if( zWhere ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
+ );
+ }else{
+ /* The sqlite_stat[12] table already exists. Delete all rows. */
+ sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
+ }
+ }
+ }
+
+ /* Open the sqlite_stat[13] tables for writing. */
+ for(i=0; i<ArraySize(aTable); i++){
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
+ sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
+ sqlite3VdbeChangeP5(v, aCreateTbl[i]);
+ }
+}
+
+/*
+** Recommended number of samples for sqlite_stat3
+*/
+#ifndef SQLITE_STAT3_SAMPLES
+# define SQLITE_STAT3_SAMPLES 24
+#endif
+
+/*
+** Three SQL functions - stat3_init(), stat3_push(), and stat3_pop() -
+** share an instance of the following structure to hold their state
+** information.
+*/
+typedef struct Stat3Accum Stat3Accum;
+struct Stat3Accum {
+ tRowcnt nRow; /* Number of rows in the entire table */
+ tRowcnt nPSample; /* How often to do a periodic sample */
+ int iMin; /* Index of entry with minimum nEq and hash */
+ int mxSample; /* Maximum number of samples to accumulate */
+ int nSample; /* Current number of samples */
+ u32 iPrn; /* Pseudo-random number used for sampling */
+ struct Stat3Sample {
+ i64 iRowid; /* Rowid in main table of the key */
+ tRowcnt nEq; /* sqlite_stat3.nEq */
+ tRowcnt nLt; /* sqlite_stat3.nLt */
+ tRowcnt nDLt; /* sqlite_stat3.nDLt */
+ u8 isPSample; /* True if a periodic sample */
+ u32 iHash; /* Tiebreaker hash */
+ } *a; /* An array of samples */
+};
+
+#ifdef SQLITE_ENABLE_STAT3
+/*
+** Implementation of the stat3_init(C,S) SQL function. The two parameters
+** are the number of rows in the table or index (C) and the number of samples
+** to accumulate (S).
+**
+** This routine allocates the Stat3Accum object.
+**
+** The return value is the Stat3Accum object (P).
+*/
+static void stat3Init(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ Stat3Accum *p;
+ tRowcnt nRow;
+ int mxSample;
+ int n;
+
+ UNUSED_PARAMETER(argc);
+ nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
+ mxSample = sqlite3_value_int(argv[1]);
+ n = sizeof(*p) + sizeof(p->a[0])*mxSample;
+ p = sqlite3MallocZero( n );
+ if( p==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ p->a = (struct Stat3Sample*)&p[1];
+ p->nRow = nRow;
+ p->mxSample = mxSample;
+ p->nPSample = p->nRow/(mxSample/3+1) + 1;
+ sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
+ sqlite3_result_blob(context, p, sizeof(p), sqlite3_free);
+}
+static const FuncDef stat3InitFuncdef = {
+ 2, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ stat3Init, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat3_init", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+};
+
+
+/*
+** Implementation of the stat3_push(nEq,nLt,nDLt,rowid,P) SQL function. The
+** arguments describe a single key instance. This routine makes the
+** decision about whether or not to retain this key for the sqlite_stat3
+** table.
+**
+** The return value is NULL.
+*/
+static void stat3Push(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[4]);
+ tRowcnt nEq = sqlite3_value_int64(argv[0]);
+ tRowcnt nLt = sqlite3_value_int64(argv[1]);
+ tRowcnt nDLt = sqlite3_value_int64(argv[2]);
+ i64 rowid = sqlite3_value_int64(argv[3]);
+ u8 isPSample = 0;
+ u8 doInsert = 0;
+ int iMin = p->iMin;
+ struct Stat3Sample *pSample;
+ int i;
+ u32 h;
+
+ UNUSED_PARAMETER(context);
+ UNUSED_PARAMETER(argc);
+ if( nEq==0 ) return;
+ h = p->iPrn = p->iPrn*1103515245 + 12345;
+ if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){
+ doInsert = isPSample = 1;
+ }else if( p->nSample<p->mxSample ){
+ doInsert = 1;
+ }else{
+ if( nEq>p->a[iMin].nEq || (nEq==p->a[iMin].nEq && h>p->a[iMin].iHash) ){
+ doInsert = 1;
+ }
+ }
+ if( !doInsert ) return;
+ if( p->nSample==p->mxSample ){
+ assert( p->nSample - iMin - 1 >= 0 );
+ memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1));
+ pSample = &p->a[p->nSample-1];
+ }else{
+ pSample = &p->a[p->nSample++];
+ }
+ pSample->iRowid = rowid;
+ pSample->nEq = nEq;
+ pSample->nLt = nLt;
+ pSample->nDLt = nDLt;
+ pSample->iHash = h;
+ pSample->isPSample = isPSample;
+
+ /* Find the new minimum */
+ if( p->nSample==p->mxSample ){
+ pSample = p->a;
+ i = 0;
+ while( pSample->isPSample ){
+ i++;
+ pSample++;
+ assert( i<p->nSample );
+ }
+ nEq = pSample->nEq;
+ h = pSample->iHash;
+ iMin = i;
+ for(i++, pSample++; i<p->nSample; i++, pSample++){
+ if( pSample->isPSample ) continue;
+ if( pSample->nEq<nEq
+ || (pSample->nEq==nEq && pSample->iHash<h)
+ ){
+ iMin = i;
+ nEq = pSample->nEq;
+ h = pSample->iHash;
+ }
+ }
+ p->iMin = iMin;
+ }
+}
+static const FuncDef stat3PushFuncdef = {
+ 5, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ stat3Push, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat3_push", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+};
+
+/*
+** Implementation of the stat3_get(P,N,...) SQL function. This routine is
+** used to query the results. Content is returned for the Nth sqlite_stat3
+** row where N is between 0 and S-1 and S is the number of samples. The
+** value returned depends on the number of arguments.
+**
+** argc==2 result: rowid
+** argc==3 result: nEq
+** argc==4 result: nLt
+** argc==5 result: nDLt
+*/
+static void stat3Get(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int n = sqlite3_value_int(argv[1]);
+ Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[0]);
+
+ assert( p!=0 );
+ if( p->nSample<=n ) return;
+ switch( argc ){
+ case 2: sqlite3_result_int64(context, p->a[n].iRowid); break;
+ case 3: sqlite3_result_int64(context, p->a[n].nEq); break;
+ case 4: sqlite3_result_int64(context, p->a[n].nLt); break;
+ default: sqlite3_result_int64(context, p->a[n].nDLt); break;
+ }
+}
+static const FuncDef stat3GetFuncdef = {
+ -1, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ stat3Get, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat3_get", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+};
+#endif /* SQLITE_ENABLE_STAT3 */
+
+
+
+
+/*
+** Generate code to do an analysis of all indices associated with
+** a single table.
+*/
+static void analyzeOneTable(
+ Parse *pParse, /* Parser context */
+ Table *pTab, /* Table whose indices are to be analyzed */
+ Index *pOnlyIdx, /* If not NULL, only analyze this one index */
+ int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
+ int iMem /* Available memory locations begin here */
+){
+ sqlite3 *db = pParse->db; /* Database handle */
+ Index *pIdx; /* An index to being analyzed */
+ int iIdxCur; /* Cursor open on index being analyzed */
+ Vdbe *v; /* The virtual machine being built up */
+ int i; /* Loop counter */
+ int topOfLoop; /* The top of the loop */
+ int endOfLoop; /* The end of the loop */
+ int jZeroRows = -1; /* Jump from here if number of rows is zero */
+ int iDb; /* Index of database containing pTab */
+ int regTabname = iMem++; /* Register containing table name */
+ int regIdxname = iMem++; /* Register containing index name */
+ int regStat1 = iMem++; /* The stat column of sqlite_stat1 */
+#ifdef SQLITE_ENABLE_STAT3
+ int regNumEq = regStat1; /* Number of instances. Same as regStat1 */
+ int regNumLt = iMem++; /* Number of keys less than regSample */
+ int regNumDLt = iMem++; /* Number of distinct keys less than regSample */
+ int regSample = iMem++; /* The next sample value */
+ int regRowid = regSample; /* Rowid of a sample */
+ int regAccum = iMem++; /* Register to hold Stat3Accum object */
+ int regLoop = iMem++; /* Loop counter */
+ int regCount = iMem++; /* Number of rows in the table or index */
+ int regTemp1 = iMem++; /* Intermediate register */
+ int regTemp2 = iMem++; /* Intermediate register */
+ int once = 1; /* One-time initialization */
+ int shortJump = 0; /* Instruction address */
+ int iTabCur = pParse->nTab++; /* Table cursor */
+#endif
+ int regCol = iMem++; /* Content of a column in analyzed table */
+ int regRec = iMem++; /* Register holding completed record */
+ int regTemp = iMem++; /* Temporary use register */
+ int regNewRowid = iMem++; /* Rowid for the inserted record */
+
+
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 || NEVER(pTab==0) ){
+ return;
+ }
+ if( pTab->tnum==0 ){
+ /* Do not gather statistics on views or virtual tables */
+ return;
+ }
+ if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
+ /* Do not gather statistics on system tables */
+ return;
+ }
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb>=0 );
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
+ db->aDb[iDb].zName ) ){
+ return;
+ }
+#endif
+
+ /* Establish a read-lock on the table at the shared-cache level. */
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+
+ iIdxCur = pParse->nTab++;
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int nCol;
+ KeyInfo *pKey;
+ int addrIfNot = 0; /* address of OP_IfNot */
+ int *aChngAddr; /* Array of jump instruction addresses */
+
+ if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
+ VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
+ nCol = pIdx->nColumn;
+ aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*nCol);
+ if( aChngAddr==0 ) continue;
+ pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+ if( iMem+1+(nCol*2)>pParse->nMem ){
+ pParse->nMem = iMem+1+(nCol*2);
+ }
+
+ /* Open a cursor to the index to be analyzed. */
+ assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
+ sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb,
+ (char *)pKey, P4_KEYINFO_HANDOFF);
+ VdbeComment((v, "%s", pIdx->zName));
+
+ /* Populate the register containing the index name. */
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0);
+
+#ifdef SQLITE_ENABLE_STAT3
+ if( once ){
+ once = 0;
+ sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
+ }
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount);
+ sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_STAT3_SAMPLES, regTemp1);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumEq);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumLt);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regNumDLt);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, regSample, regAccum);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regCount, regAccum,
+ (char*)&stat3InitFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 2);
+#endif /* SQLITE_ENABLE_STAT3 */
+
+ /* The block of memory cells initialized here is used as follows.
+ **
+ ** iMem:
+ ** The total number of rows in the table.
+ **
+ ** iMem+1 .. iMem+nCol:
+ ** Number of distinct entries in index considering the
+ ** left-most N columns only, where N is between 1 and nCol,
+ ** inclusive.
+ **
+ ** iMem+nCol+1 .. Mem+2*nCol:
+ ** Previous value of indexed columns, from left to right.
+ **
+ ** Cells iMem through iMem+nCol are initialized to 0. The others are
+ ** initialized to contain an SQL NULL.
+ */
+ for(i=0; i<=nCol; i++){
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i);
+ }
+ for(i=0; i<nCol; i++){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1);
+ }
+
+ /* Start the analysis loop. This loop runs through all the entries in
+ ** the index b-tree. */
+ endOfLoop = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
+ topOfLoop = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); /* Increment row counter */
+
+ for(i=0; i<nCol; i++){
+ CollSeq *pColl;
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
+ if( i==0 ){
+ /* Always record the very first row */
+ addrIfNot = sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
+ }
+ assert( pIdx->azColl!=0 );
+ assert( pIdx->azColl[i]!=0 );
+ pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
+ aChngAddr[i] = sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1,
+ (char*)pColl, P4_COLLSEQ);
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ VdbeComment((v, "jump if column %d changed", i));
+#ifdef SQLITE_ENABLE_STAT3
+ if( i==0 ){
+ sqlite3VdbeAddOp2(v, OP_AddImm, regNumEq, 1);
+ VdbeComment((v, "incr repeat count"));
+ }
+#endif
+ }
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
+ for(i=0; i<nCol; i++){
+ sqlite3VdbeJumpHere(v, aChngAddr[i]); /* Set jump dest for the OP_Ne */
+ if( i==0 ){
+ sqlite3VdbeJumpHere(v, addrIfNot); /* Jump dest for OP_IfNot */
+#ifdef SQLITE_ENABLE_STAT3
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
+ (char*)&stat3PushFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 5);
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, pIdx->nColumn, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt);
+ sqlite3VdbeAddOp2(v, OP_AddImm, regNumDLt, 1);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regNumEq);
+#endif
+ }
+ sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
+ }
+ sqlite3DbFree(db, aChngAddr);
+
+ /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
+ sqlite3VdbeResolveLabel(v, endOfLoop);
+
+ sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
+ sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
+#ifdef SQLITE_ENABLE_STAT3
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
+ (char*)&stat3PushFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 5);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop);
+ shortJump =
+ sqlite3VdbeAddOp2(v, OP_AddImm, regLoop, 1);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regTemp1,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 2);
+ sqlite3VdbeAddOp1(v, OP_IsNull, regTemp1);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, shortJump, regTemp1);
+ sqlite3VdbeAddOp3(v, OP_Column, iTabCur, pIdx->aiColumn[0], regSample);
+ sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[0], regSample);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumEq,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 3);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumLt,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 4);
+ sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumDLt,
+ (char*)&stat3GetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 5);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, shortJump);
+ sqlite3VdbeJumpHere(v, shortJump+2);
+#endif
+
+ /* Store the results in sqlite_stat1.
+ **
+ ** The result is a single row of the sqlite_stat1 table. The first
+ ** two columns are the names of the table and index. The third column
+ ** is a string composed of a list of integer statistics about the
+ ** index. The first integer in the list is the total number of entries
+ ** in the index. There is one additional integer in the list for each
+ ** column of the table. This additional integer is a guess of how many
+ ** rows of the table the index will select. If D is the count of distinct
+ ** values and K is the total number of rows, then the integer is computed
+ ** as:
+ **
+ ** I = (K+D-1)/D
+ **
+ ** If K==0 then no entry is made into the sqlite_stat1 table.
+ ** If K>0 then it is always the case the D>0 so division by zero
+ ** is never possible.
+ */
+ sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
+ if( jZeroRows<0 ){
+ jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
+ }
+ for(i=0; i<nCol; i++){
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
+ sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
+ sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp);
+ sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1);
+ sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp);
+ sqlite3VdbeAddOp1(v, OP_ToInt, regTemp);
+ sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
+ }
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ }
+
+ /* If the table has no indices, create a single sqlite_stat1 entry
+ ** containing NULL as the index name and the row count as the content.
+ */
+ if( pTab->pIndex==0 ){
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb);
+ VdbeComment((v, "%s", pTab->zName));
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat1);
+ sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
+ jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
+ }else{
+ sqlite3VdbeJumpHere(v, jZeroRows);
+ jZeroRows = sqlite3VdbeAddOp0(v, OP_Goto);
+ }
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ if( pParse->nMem<regRec ) pParse->nMem = regRec;
+ sqlite3VdbeJumpHere(v, jZeroRows);
+}
+
+
+/*
+** Generate code that will cause the most recent index analysis to
+** be loaded into internal hash tables where is can be used.
+*/
+static void loadAnalysis(Parse *pParse, int iDb){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb);
+ }
+}
+
+/*
+** Generate code that will do an analysis of an entire database
+*/
+static void analyzeDatabase(Parse *pParse, int iDb){
+ sqlite3 *db = pParse->db;
+ Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */
+ HashElem *k;
+ int iStatCur;
+ int iMem;
+
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ iStatCur = pParse->nTab;
+ pParse->nTab += 3;
+ openStatTable(pParse, iDb, iStatCur, 0, 0);
+ iMem = pParse->nMem+1;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
+ Table *pTab = (Table*)sqliteHashData(k);
+ analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
+ }
+ loadAnalysis(pParse, iDb);
+}
+
+/*
+** Generate code that will do an analysis of a single table in
+** a database. If pOnlyIdx is not NULL then it is a single index
+** in pTab that should be analyzed.
+*/
+static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
+ int iDb;
+ int iStatCur;
+
+ assert( pTab!=0 );
+ assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ iStatCur = pParse->nTab;
+ pParse->nTab += 3;
+ if( pOnlyIdx ){
+ openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx");
+ }else{
+ openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
+ }
+ analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1);
+ loadAnalysis(pParse, iDb);
+}
+
+/*
+** Generate code for the ANALYZE command. The parser calls this routine
+** when it recognizes an ANALYZE command.
+**
+** ANALYZE -- 1
+** ANALYZE <database> -- 2
+** ANALYZE ?<database>.?<tablename> -- 3
+**
+** Form 1 causes all indices in all attached databases to be analyzed.
+** Form 2 analyzes all indices the single database named.
+** Form 3 analyzes all indices associated with the named table.
+*/
+SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
+ sqlite3 *db = pParse->db;
+ int iDb;
+ int i;
+ char *z, *zDb;
+ Table *pTab;
+ Index *pIdx;
+ Token *pTableName;
+
+ /* Read the database schema. If an error occurs, leave an error message
+ ** and code in pParse and return NULL. */
+ assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ return;
+ }
+
+ assert( pName2!=0 || pName1==0 );
+ if( pName1==0 ){
+ /* Form 1: Analyze everything */
+ for(i=0; i<db->nDb; i++){
+ if( i==1 ) continue; /* Do not analyze the TEMP database */
+ analyzeDatabase(pParse, i);
+ }
+ }else if( pName2->n==0 ){
+ /* Form 2: Analyze the database or table named */
+ iDb = sqlite3FindDb(db, pName1);
+ if( iDb>=0 ){
+ analyzeDatabase(pParse, iDb);
+ }else{
+ z = sqlite3NameFromToken(db, pName1);
+ if( z ){
+ if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){
+ analyzeTable(pParse, pIdx->pTable, pIdx);
+ }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){
+ analyzeTable(pParse, pTab, 0);
+ }
+ sqlite3DbFree(db, z);
+ }
+ }
+ }else{
+ /* Form 3: Analyze the fully qualified table name */
+ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
+ if( iDb>=0 ){
+ zDb = db->aDb[iDb].zName;
+ z = sqlite3NameFromToken(db, pTableName);
+ if( z ){
+ if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
+ analyzeTable(pParse, pIdx->pTable, pIdx);
+ }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){
+ analyzeTable(pParse, pTab, 0);
+ }
+ sqlite3DbFree(db, z);
+ }
+ }
+ }
+}
+
+/*
+** Used to pass information from the analyzer reader through to the
+** callback routine.
+*/
+typedef struct analysisInfo analysisInfo;
+struct analysisInfo {
+ sqlite3 *db;
+ const char *zDatabase;
+};
+
+/*
+** This callback is invoked once for each index when reading the
+** sqlite_stat1 table.
+**
+** argv[0] = name of the table
+** argv[1] = name of the index (might be NULL)
+** argv[2] = results of analysis - on integer for each column
+**
+** Entries for which argv[1]==NULL simply record the number of rows in
+** the table.
+*/
+static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
+ analysisInfo *pInfo = (analysisInfo*)pData;
+ Index *pIndex;
+ Table *pTable;
+ int i, c, n;
+ tRowcnt v;
+ const char *z;
+
+ assert( argc==3 );
+ UNUSED_PARAMETER2(NotUsed, argc);
+
+ if( argv==0 || argv[0]==0 || argv[2]==0 ){
+ return 0;
+ }
+ pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase);
+ if( pTable==0 ){
+ return 0;
+ }
+ if( argv[1] ){
+ pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
+ }else{
+ pIndex = 0;
+ }
+ n = pIndex ? pIndex->nColumn : 0;
+ z = argv[2];
+ for(i=0; *z && i<=n; i++){
+ v = 0;
+ while( (c=z[0])>='0' && c<='9' ){
+ v = v*10 + c - '0';
+ z++;
+ }
+ if( i==0 ) pTable->nRowEst = v;
+ if( pIndex==0 ) break;
+ pIndex->aiRowEst[i] = v;
+ if( *z==' ' ) z++;
+ if( strcmp(z, "unordered")==0 ){
+ pIndex->bUnordered = 1;
+ break;
+ }
+ }
+ return 0;
+}
+
+/*
+** If the Index.aSample variable is not NULL, delete the aSample[] array
+** and its contents.
+*/
+SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
+#ifdef SQLITE_ENABLE_STAT3
+ if( pIdx->aSample ){
+ int j;
+ for(j=0; j<pIdx->nSample; j++){
+ IndexSample *p = &pIdx->aSample[j];
+ if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
+ sqlite3DbFree(db, p->u.z);
+ }
+ }
+ sqlite3DbFree(db, pIdx->aSample);
+ }
+ if( db && db->pnBytesFreed==0 ){
+ pIdx->nSample = 0;
+ pIdx->aSample = 0;
+ }
+#else
+ UNUSED_PARAMETER(db);
+ UNUSED_PARAMETER(pIdx);
+#endif
+}
+
+#ifdef SQLITE_ENABLE_STAT3
+/*
+** Load content from the sqlite_stat3 table into the Index.aSample[]
+** arrays of all indices.
+*/
+static int loadStat3(sqlite3 *db, const char *zDb){
+ int rc; /* Result codes from subroutines */
+ sqlite3_stmt *pStmt = 0; /* An SQL statement being run */
+ char *zSql; /* Text of the SQL statement */
+ Index *pPrevIdx = 0; /* Previous index in the loop */
+ int idx = 0; /* slot in pIdx->aSample[] for next sample */
+ int eType; /* Datatype of a sample */
+ IndexSample *pSample; /* A slot in pIdx->aSample[] */
+
+ assert( db->lookaside.bEnabled==0 );
+ if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
+ return SQLITE_OK;
+ }
+
+ zSql = sqlite3MPrintf(db,
+ "SELECT idx,count(*) FROM %Q.sqlite_stat3"
+ " GROUP BY idx", zDb);
+ if( !zSql ){
+ return SQLITE_NOMEM;
+ }
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ sqlite3DbFree(db, zSql);
+ if( rc ) return rc;
+
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int nSample; /* Number of samples */
+
+ zIndex = (char *)sqlite3_column_text(pStmt, 0);
+ if( zIndex==0 ) continue;
+ nSample = sqlite3_column_int(pStmt, 1);
+ pIdx = sqlite3FindIndex(db, zIndex, zDb);
+ if( pIdx==0 ) continue;
+ assert( pIdx->nSample==0 );
+ pIdx->nSample = nSample;
+ pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample));
+ pIdx->avgEq = pIdx->aiRowEst[1];
+ if( pIdx->aSample==0 ){
+ db->mallocFailed = 1;
+ sqlite3_finalize(pStmt);
+ return SQLITE_NOMEM;
+ }
+ }
+ rc = sqlite3_finalize(pStmt);
+ if( rc ) return rc;
+
+ zSql = sqlite3MPrintf(db,
+ "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
+ if( !zSql ){
+ return SQLITE_NOMEM;
+ }
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ sqlite3DbFree(db, zSql);
+ if( rc ) return rc;
+
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int i; /* Loop counter */
+ tRowcnt sumEq; /* Sum of the nEq values */
+
+ zIndex = (char *)sqlite3_column_text(pStmt, 0);
+ if( zIndex==0 ) continue;
+ pIdx = sqlite3FindIndex(db, zIndex, zDb);
+ if( pIdx==0 ) continue;
+ if( pIdx==pPrevIdx ){
+ idx++;
+ }else{
+ pPrevIdx = pIdx;
+ idx = 0;
+ }
+ assert( idx<pIdx->nSample );
+ pSample = &pIdx->aSample[idx];
+ pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1);
+ pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2);
+ pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3);
+ if( idx==pIdx->nSample-1 ){
+ if( pSample->nDLt>0 ){
+ for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
+ pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
+ }
+ if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
+ }
+ eType = sqlite3_column_type(pStmt, 4);
+ pSample->eType = (u8)eType;
+ switch( eType ){
+ case SQLITE_INTEGER: {
+ pSample->u.i = sqlite3_column_int64(pStmt, 4);
+ break;
+ }
+ case SQLITE_FLOAT: {
+ pSample->u.r = sqlite3_column_double(pStmt, 4);
+ break;
+ }
+ case SQLITE_NULL: {
+ break;
+ }
+ default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); {
+ const char *z = (const char *)(
+ (eType==SQLITE_BLOB) ?
+ sqlite3_column_blob(pStmt, 4):
+ sqlite3_column_text(pStmt, 4)
+ );
+ int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
+ pSample->nByte = n;
+ if( n < 1){
+ pSample->u.z = 0;
+ }else{
+ pSample->u.z = sqlite3DbMallocRaw(db, n);
+ if( pSample->u.z==0 ){
+ db->mallocFailed = 1;
+ sqlite3_finalize(pStmt);
+ return SQLITE_NOMEM;
+ }
+ memcpy(pSample->u.z, z, n);
+ }
+ }
+ }
+ }
+ return sqlite3_finalize(pStmt);
+}
+#endif /* SQLITE_ENABLE_STAT3 */
+
+/*
+** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The
+** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
+** arrays. The contents of sqlite_stat3 are used to populate the
+** Index.aSample[] arrays.
+**
+** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
+** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined
+** during compilation and the sqlite_stat3 table is present, no data is
+** read from it.
+**
+** If SQLITE_ENABLE_STAT3 was defined during compilation and the
+** sqlite_stat3 table is not present in the database, SQLITE_ERROR is
+** returned. However, in this case, data is read from the sqlite_stat1
+** table (if it is present) before returning.
+**
+** If an OOM error occurs, this function always sets db->mallocFailed.
+** This means if the caller does not care about other errors, the return
+** code may be ignored.
+*/
+SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
+ analysisInfo sInfo;
+ HashElem *i;
+ char *zSql;
+ int rc;
+
+ assert( iDb>=0 && iDb<db->nDb );
+ assert( db->aDb[iDb].pBt!=0 );
+
+ /* Clear any prior statistics */
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
+ Index *pIdx = sqliteHashData(i);
+ sqlite3DefaultRowEst(pIdx);
+#ifdef SQLITE_ENABLE_STAT3
+ sqlite3DeleteIndexSamples(db, pIdx);
+ pIdx->aSample = 0;
+#endif
+ }
+
+ /* Check to make sure the sqlite_stat1 table exists */
+ sInfo.db = db;
+ sInfo.zDatabase = db->aDb[iDb].zName;
+ if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
+ return SQLITE_ERROR;
+ }
+
+ /* Load new statistics out of the sqlite_stat1 table */
+ zSql = sqlite3MPrintf(db,
+ "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
+ sqlite3DbFree(db, zSql);
+ }
+
+
+ /* Load the statistics from the sqlite_stat3 table. */
+#ifdef SQLITE_ENABLE_STAT3
+ if( rc==SQLITE_OK ){
+ int lookasideEnabled = db->lookaside.bEnabled;
+ db->lookaside.bEnabled = 0;
+ rc = loadStat3(db, sInfo.zDatabase);
+ db->lookaside.bEnabled = lookasideEnabled;
+ }
+#endif
+
+ if( rc==SQLITE_NOMEM ){
+ db->mallocFailed = 1;
+ }
+ return rc;
+}
+
+
+#endif /* SQLITE_OMIT_ANALYZE */
+
+/************** End of analyze.c *********************************************/
+/************** Begin file attach.c ******************************************/
+/*
+** 2003 April 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used to implement the ATTACH and DETACH commands.
+*/
+
+#ifndef SQLITE_OMIT_ATTACH
+/*
+** Resolve an expression that was part of an ATTACH or DETACH statement. This
+** is slightly different from resolving a normal SQL expression, because simple
+** identifiers are treated as strings, not possible column names or aliases.
+**
+** i.e. if the parser sees:
+**
+** ATTACH DATABASE abc AS def
+**
+** it treats the two expressions as literal strings 'abc' and 'def' instead of
+** looking for columns of the same name.
+**
+** This only applies to the root node of pExpr, so the statement:
+**
+** ATTACH DATABASE abc||def AS 'db2'
+**
+** will fail because neither abc or def can be resolved.
+*/
+static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
+{
+ int rc = SQLITE_OK;
+ if( pExpr ){
+ if( pExpr->op!=TK_ID ){
+ rc = sqlite3ResolveExprNames(pName, pExpr);
+ if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
+ sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken);
+ return SQLITE_ERROR;
+ }
+ }else{
+ pExpr->op = TK_STRING;
+ }
+ }
+ return rc;
+}
+
+/*
+** An SQL user-function registered to do the work of an ATTACH statement. The
+** three arguments to the function come directly from an attach statement:
+**
+** ATTACH DATABASE x AS y KEY z
+**
+** SELECT sqlite_attach(x, y, z)
+**
+** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
+** third argument.
+*/
+static void attachFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ int i;
+ int rc = 0;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ const char *zName;
+ const char *zFile;
+ char *zPath = 0;
+ char *zErr = 0;
+ unsigned int flags;
+ Db *aNew;
+ char *zErrDyn = 0;
+ sqlite3_vfs *pVfs;
+
+ UNUSED_PARAMETER(NotUsed);
+
+ zFile = (const char *)sqlite3_value_text(argv[0]);
+ zName = (const char *)sqlite3_value_text(argv[1]);
+ if( zFile==0 ) zFile = "";
+ if( zName==0 ) zName = "";
+
+ /* Check for the following errors:
+ **
+ ** * Too many attached databases,
+ ** * Transaction currently open
+ ** * Specified database name already being used.
+ */
+ if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
+ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
+ db->aLimit[SQLITE_LIMIT_ATTACHED]
+ );
+ goto attach_error;
+ }
+ if( !db->autoCommit ){
+ zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
+ goto attach_error;
+ }
+ for(i=0; i<db->nDb; i++){
+ char *z = db->aDb[i].zName;
+ assert( z && zName );
+ if( sqlite3StrICmp(z, zName)==0 ){
+ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
+ goto attach_error;
+ }
+ }
+
+ /* Allocate the new entry in the db->aDb[] array and initialize the schema
+ ** hash tables.
+ */
+ if( db->aDb==db->aDbStatic ){
+ aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 );
+ if( aNew==0 ) return;
+ memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
+ }else{
+ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
+ if( aNew==0 ) return;
+ }
+ db->aDb = aNew;
+ aNew = &db->aDb[db->nDb];
+ memset(aNew, 0, sizeof(*aNew));
+
+ /* Open the database file. If the btree is successfully opened, use
+ ** it to obtain the database schema. At this point the schema may
+ ** or may not be initialized.
+ */
+ flags = db->openFlags;
+ rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+ sqlite3_result_error(context, zErr, -1);
+ sqlite3_free(zErr);
+ return;
+ }
+ assert( pVfs );
+ flags |= SQLITE_OPEN_MAIN_DB;
+ rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
+ sqlite3_free( zPath );
+ db->nDb++;
+ if( rc==SQLITE_CONSTRAINT ){
+ rc = SQLITE_ERROR;
+ zErrDyn = sqlite3MPrintf(db, "database is already attached");
+ }else if( rc==SQLITE_OK ){
+ Pager *pPager;
+ aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
+ if( !aNew->pSchema ){
+ rc = SQLITE_NOMEM;
+ }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
+ zErrDyn = sqlite3MPrintf(db,
+ "attached databases must use the same text encoding as main database");
+ rc = SQLITE_ERROR;
+ }
+ pPager = sqlite3BtreePager(aNew->pBt);
+ sqlite3PagerLockingMode(pPager, db->dfltLockMode);
+ sqlite3BtreeSecureDelete(aNew->pBt,
+ sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
+ }
+ aNew->safety_level = 3;
+ aNew->zName = sqlite3DbStrDup(db, zName);
+ if( rc==SQLITE_OK && aNew->zName==0 ){
+ rc = SQLITE_NOMEM;
+ }
+
+
+#ifdef SQLITE_HAS_CODEC
+ if( rc==SQLITE_OK ){
+ extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
+ extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
+ int nKey;
+ char *zKey;
+ int t = sqlite3_value_type(argv[2]);
+ switch( t ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
+ rc = SQLITE_ERROR;
+ break;
+
+ case SQLITE_TEXT:
+ case SQLITE_BLOB:
+ nKey = sqlite3_value_bytes(argv[2]);
+ zKey = (char *)sqlite3_value_blob(argv[2]);
+ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ break;
+
+ case SQLITE_NULL:
+ /* No key specified. Use the key from the main database */
+ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
+ if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){
+ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ }
+ break;
+ }
+ }
+#endif
+
+ /* If the file was opened successfully, read the schema for the new database.
+ ** If this fails, or if opening the file failed, then close the file and
+ ** remove the entry from the db->aDb[] array. i.e. put everything back the way
+ ** we found it.
+ */
+ if( rc==SQLITE_OK ){
+ sqlite3BtreeEnterAll(db);
+ rc = sqlite3Init(db, &zErrDyn);
+ sqlite3BtreeLeaveAll(db);
+ }
+ if( rc ){
+ int iDb = db->nDb - 1;
+ assert( iDb>=2 );
+ if( db->aDb[iDb].pBt ){
+ sqlite3BtreeClose(db->aDb[iDb].pBt);
+ db->aDb[iDb].pBt = 0;
+ db->aDb[iDb].pSchema = 0;
+ }
+ sqlite3ResetAllSchemasOfConnection(db);
+ db->nDb = iDb;
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ db->mallocFailed = 1;
+ sqlite3DbFree(db, zErrDyn);
+ zErrDyn = sqlite3MPrintf(db, "out of memory");
+ }else if( zErrDyn==0 ){
+ zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
+ }
+ goto attach_error;
+ }
+
+ return;
+
+attach_error:
+ /* Return an error if we get here */
+ if( zErrDyn ){
+ sqlite3_result_error(context, zErrDyn, -1);
+ sqlite3DbFree(db, zErrDyn);
+ }
+ if( rc ) sqlite3_result_error_code(context, rc);
+}
+
+/*
+** An SQL user-function registered to do the work of an DETACH statement. The
+** three arguments to the function come directly from a detach statement:
+**
+** DETACH DATABASE x
+**
+** SELECT sqlite_detach(x)
+*/
+static void detachFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ const char *zName = (const char *)sqlite3_value_text(argv[0]);
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ int i;
+ Db *pDb = 0;
+ char zErr[128];
+
+ UNUSED_PARAMETER(NotUsed);
+
+ if( zName==0 ) zName = "";
+ for(i=0; i<db->nDb; i++){
+ pDb = &db->aDb[i];
+ if( pDb->pBt==0 ) continue;
+ if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
+ }
+
+ if( i>=db->nDb ){
+ sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
+ goto detach_error;
+ }
+ if( i<2 ){
+ sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
+ goto detach_error;
+ }
+ if( !db->autoCommit ){
+ sqlite3_snprintf(sizeof(zErr), zErr,
+ "cannot DETACH database within transaction");
+ goto detach_error;
+ }
+ if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
+ sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
+ goto detach_error;
+ }
+
+ sqlite3BtreeClose(pDb->pBt);
+ pDb->pBt = 0;
+ pDb->pSchema = 0;
+ sqlite3ResetAllSchemasOfConnection(db);
+ return;
+
+detach_error:
+ sqlite3_result_error(context, zErr, -1);
+}
+
+/*
+** This procedure generates VDBE code for a single invocation of either the
+** sqlite_detach() or sqlite_attach() SQL user functions.
+*/
+static void codeAttach(
+ Parse *pParse, /* The parser context */
+ int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */
+ FuncDef const *pFunc,/* FuncDef wrapper for detachFunc() or attachFunc() */
+ Expr *pAuthArg, /* Expression to pass to authorization callback */
+ Expr *pFilename, /* Name of database file */
+ Expr *pDbname, /* Name of the database to use internally */
+ Expr *pKey /* Database key for encryption extension */
+){
+ int rc;
+ NameContext sName;
+ Vdbe *v;
+ sqlite3* db = pParse->db;
+ int regArgs;
+
+ memset(&sName, 0, sizeof(NameContext));
+ sName.pParse = pParse;
+
+ if(
+ SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
+ SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
+ SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
+ ){
+ pParse->nErr++;
+ goto attach_end;
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pAuthArg ){
+ char *zAuthArg;
+ if( pAuthArg->op==TK_STRING ){
+ zAuthArg = pAuthArg->u.zToken;
+ }else{
+ zAuthArg = 0;
+ }
+ rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
+ if(rc!=SQLITE_OK ){
+ goto attach_end;
+ }
+ }
+#endif /* SQLITE_OMIT_AUTHORIZATION */
+
+
+ v = sqlite3GetVdbe(pParse);
+ regArgs = sqlite3GetTempRange(pParse, 4);
+ sqlite3ExprCode(pParse, pFilename, regArgs);
+ sqlite3ExprCode(pParse, pDbname, regArgs+1);
+ sqlite3ExprCode(pParse, pKey, regArgs+2);
+
+ assert( v || db->mallocFailed );
+ if( v ){
+ sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3);
+ assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
+ sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
+ sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
+
+ /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
+ ** statement only). For DETACH, set it to false (expire all existing
+ ** statements).
+ */
+ sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH));
+ }
+
+attach_end:
+ sqlite3ExprDelete(db, pFilename);
+ sqlite3ExprDelete(db, pDbname);
+ sqlite3ExprDelete(db, pKey);
+}
+
+/*
+** Called by the parser to compile a DETACH statement.
+**
+** DETACH pDbname
+*/
+SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
+ static const FuncDef detach_func = {
+ 1, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ detachFunc, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "sqlite_detach", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+ };
+ codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname);
+}
+
+/*
+** Called by the parser to compile an ATTACH statement.
+**
+** ATTACH p AS pDbname KEY pKey
+*/
+SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
+ static const FuncDef attach_func = {
+ 3, /* nArg */
+ SQLITE_UTF8, /* iPrefEnc */
+ 0, /* flags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ attachFunc, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "sqlite_attach", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+ };
+ codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey);
+}
+#endif /* SQLITE_OMIT_ATTACH */
+
+/*
+** Initialize a DbFixer structure. This routine must be called prior
+** to passing the structure to one of the sqliteFixAAAA() routines below.
+**
+** The return value indicates whether or not fixation is required. TRUE
+** means we do need to fix the database references, FALSE means we do not.
+*/
+SQLITE_PRIVATE int sqlite3FixInit(
+ DbFixer *pFix, /* The fixer to be initialized */
+ Parse *pParse, /* Error messages will be written here */
+ int iDb, /* This is the database that must be used */
+ const char *zType, /* "view", "trigger", or "index" */
+ const Token *pName /* Name of the view, trigger, or index */
+){
+ sqlite3 *db;
+
+ if( NEVER(iDb<0) || iDb==1 ) return 0;
+ db = pParse->db;
+ assert( db->nDb>iDb );
+ pFix->pParse = pParse;
+ pFix->zDb = db->aDb[iDb].zName;
+ pFix->pSchema = db->aDb[iDb].pSchema;
+ pFix->zType = zType;
+ pFix->pName = pName;
+ return 1;
+}
+
+/*
+** The following set of routines walk through the parse tree and assign
+** a specific database to all table references where the database name
+** was left unspecified in the original SQL statement. The pFix structure
+** must have been initialized by a prior call to sqlite3FixInit().
+**
+** These routines are used to make sure that an index, trigger, or
+** view in one database does not refer to objects in a different database.
+** (Exception: indices, triggers, and views in the TEMP database are
+** allowed to refer to anything.) If a reference is explicitly made
+** to an object in a different database, an error message is added to
+** pParse->zErrMsg and these routines return non-zero. If everything
+** checks out, these routines return 0.
+*/
+SQLITE_PRIVATE int sqlite3FixSrcList(
+ DbFixer *pFix, /* Context of the fixation */
+ SrcList *pList /* The Source list to check and modify */
+){
+ int i;
+ const char *zDb;
+ struct SrcList_item *pItem;
+
+ if( NEVER(pList==0) ) return 0;
+ zDb = pFix->zDb;
+ for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
+ sqlite3ErrorMsg(pFix->pParse,
+ "%s %T cannot reference objects in database %s",
+ pFix->zType, pFix->pName, pItem->zDatabase);
+ return 1;
+ }
+ sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
+ pItem->zDatabase = 0;
+ pItem->pSchema = pFix->pSchema;
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
+ if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
+ if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
+#endif
+ }
+ return 0;
+}
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
+SQLITE_PRIVATE int sqlite3FixSelect(
+ DbFixer *pFix, /* Context of the fixation */
+ Select *pSelect /* The SELECT statement to be fixed to one database */
+){
+ while( pSelect ){
+ if( sqlite3FixExprList(pFix, pSelect->pEList) ){
+ return 1;
+ }
+ if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
+ return 1;
+ }
+ if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
+ return 1;
+ }
+ if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
+ return 1;
+ }
+ pSelect = pSelect->pPrior;
+ }
+ return 0;
+}
+SQLITE_PRIVATE int sqlite3FixExpr(
+ DbFixer *pFix, /* Context of the fixation */
+ Expr *pExpr /* The expression to be fixed to one database */
+){
+ while( pExpr ){
+ if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
+ }else{
+ if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
+ }
+ if( sqlite3FixExpr(pFix, pExpr->pRight) ){
+ return 1;
+ }
+ pExpr = pExpr->pLeft;
+ }
+ return 0;
+}
+SQLITE_PRIVATE int sqlite3FixExprList(
+ DbFixer *pFix, /* Context of the fixation */
+ ExprList *pList /* The expression to be fixed to one database */
+){
+ int i;
+ struct ExprList_item *pItem;
+ if( pList==0 ) return 0;
+ for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
+ if( sqlite3FixExpr(pFix, pItem->pExpr) ){
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE int sqlite3FixTriggerStep(
+ DbFixer *pFix, /* Context of the fixation */
+ TriggerStep *pStep /* The trigger step be fixed to one database */
+){
+ while( pStep ){
+ if( sqlite3FixSelect(pFix, pStep->pSelect) ){
+ return 1;
+ }
+ if( sqlite3FixExpr(pFix, pStep->pWhere) ){
+ return 1;
+ }
+ if( sqlite3FixExprList(pFix, pStep->pExprList) ){
+ return 1;
+ }
+ pStep = pStep->pNext;
+ }
+ return 0;
+}
+#endif
+
+/************** End of attach.c **********************************************/
+/************** Begin file auth.c ********************************************/
+/*
+** 2003 January 11
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used to implement the sqlite3_set_authorizer()
+** API. This facility is an optional feature of the library. Embedded
+** systems that do not need this facility may omit it by recompiling
+** the library with -DSQLITE_OMIT_AUTHORIZATION=1
+*/
+
+/*
+** All of the code in this file may be omitted by defining a single
+** macro.
+*/
+#ifndef SQLITE_OMIT_AUTHORIZATION
+
+/*
+** Set or clear the access authorization function.
+**
+** The access authorization function is be called during the compilation
+** phase to verify that the user has read and/or write access permission on
+** various fields of the database. The first argument to the auth function
+** is a copy of the 3rd argument to this routine. The second argument
+** to the auth function is one of these constants:
+**
+** SQLITE_CREATE_INDEX
+** SQLITE_CREATE_TABLE
+** SQLITE_CREATE_TEMP_INDEX
+** SQLITE_CREATE_TEMP_TABLE
+** SQLITE_CREATE_TEMP_TRIGGER
+** SQLITE_CREATE_TEMP_VIEW
+** SQLITE_CREATE_TRIGGER
+** SQLITE_CREATE_VIEW
+** SQLITE_DELETE
+** SQLITE_DROP_INDEX
+** SQLITE_DROP_TABLE
+** SQLITE_DROP_TEMP_INDEX
+** SQLITE_DROP_TEMP_TABLE
+** SQLITE_DROP_TEMP_TRIGGER
+** SQLITE_DROP_TEMP_VIEW
+** SQLITE_DROP_TRIGGER
+** SQLITE_DROP_VIEW
+** SQLITE_INSERT
+** SQLITE_PRAGMA
+** SQLITE_READ
+** SQLITE_SELECT
+** SQLITE_TRANSACTION
+** SQLITE_UPDATE
+**
+** The third and fourth arguments to the auth function are the name of
+** the table and the column that are being accessed. The auth function
+** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If
+** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY
+** means that the SQL statement will never-run - the sqlite3_exec() call
+** will return with an error. SQLITE_IGNORE means that the SQL statement
+** should run but attempts to read the specified column will return NULL
+** and attempts to write the column will be ignored.
+**
+** Setting the auth function to NULL disables this hook. The default
+** setting of the auth function is NULL.
+*/
+SQLITE_API int sqlite3_set_authorizer(
+ sqlite3 *db,
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
+ void *pArg
+){
+ sqlite3_mutex_enter(db->mutex);
+ db->xAuth = xAuth;
+ db->pAuthArg = pArg;
+ sqlite3ExpirePreparedStatements(db);
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+
+/*
+** Write an error message into pParse->zErrMsg that explains that the
+** user-supplied authorization function returned an illegal value.
+*/
+static void sqliteAuthBadReturnCode(Parse *pParse){
+ sqlite3ErrorMsg(pParse, "authorizer malfunction");
+ pParse->rc = SQLITE_ERROR;
+}
+
+/*
+** Invoke the authorization callback for permission to read column zCol from
+** table zTab in database zDb. This function assumes that an authorization
+** callback has been registered (i.e. that sqlite3.xAuth is not NULL).
+**
+** If SQLITE_IGNORE is returned and pExpr is not NULL, then pExpr is changed
+** to an SQL NULL expression. Otherwise, if pExpr is NULL, then SQLITE_IGNORE
+** is treated as SQLITE_DENY. In this case an error is left in pParse.
+*/
+SQLITE_PRIVATE int sqlite3AuthReadCol(
+ Parse *pParse, /* The parser context */
+ const char *zTab, /* Table name */
+ const char *zCol, /* Column name */
+ int iDb /* Index of containing database. */
+){
+ sqlite3 *db = pParse->db; /* Database handle */
+ char *zDb = db->aDb[iDb].zName; /* Name of attached database */
+ int rc; /* Auth callback return code */
+
+ rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
+ if( rc==SQLITE_DENY ){
+ if( db->nDb>2 || iDb!=0 ){
+ sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
+ }else{
+ sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
+ }
+ pParse->rc = SQLITE_AUTH;
+ }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){
+ sqliteAuthBadReturnCode(pParse);
+ }
+ return rc;
+}
+
+/*
+** The pExpr should be a TK_COLUMN expression. The table referred to
+** is in pTabList or else it is the NEW or OLD table of a trigger.
+** Check to see if it is OK to read this particular column.
+**
+** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
+** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
+** then generate an error.
+*/
+SQLITE_PRIVATE void sqlite3AuthRead(
+ Parse *pParse, /* The parser context */
+ Expr *pExpr, /* The expression to check authorization on */
+ Schema *pSchema, /* The schema of the expression */
+ SrcList *pTabList /* All table that pExpr might refer to */
+){
+ sqlite3 *db = pParse->db;
+ Table *pTab = 0; /* The table being read */
+ const char *zCol; /* Name of the column of the table */
+ int iSrc; /* Index in pTabList->a[] of table being read */
+ int iDb; /* The index of the database the expression refers to */
+ int iCol; /* Index of column in table */
+
+ if( db->xAuth==0 ) return;
+ iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
+ if( iDb<0 ){
+ /* An attempt to read a column out of a subquery or other
+ ** temporary table. */
+ return;
+ }
+
+ assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
+ if( pExpr->op==TK_TRIGGER ){
+ pTab = pParse->pTriggerTab;
+ }else{
+ assert( pTabList );
+ for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
+ if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
+ pTab = pTabList->a[iSrc].pTab;
+ break;
+ }
+ }
+ }
+ iCol = pExpr->iColumn;
+ if( NEVER(pTab==0) ) return;
+
+ if( iCol>=0 ){
+ assert( iCol<pTab->nCol );
+ zCol = pTab->aCol[iCol].zName;
+ }else if( pTab->iPKey>=0 ){
+ assert( pTab->iPKey<pTab->nCol );
+ zCol = pTab->aCol[pTab->iPKey].zName;
+ }else{
+ zCol = "ROWID";
+ }
+ assert( iDb>=0 && iDb<db->nDb );
+ if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
+ pExpr->op = TK_NULL;
+ }
+}
+
+/*
+** Do an authorization check using the code and arguments given. Return
+** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
+** is returned, then the error count and error message in pParse are
+** modified appropriately.
+*/
+SQLITE_PRIVATE int sqlite3AuthCheck(
+ Parse *pParse,
+ int code,
+ const char *zArg1,
+ const char *zArg2,
+ const char *zArg3
+){
+ sqlite3 *db = pParse->db;
+ int rc;
+
+ /* Don't do any authorization checks if the database is initialising
+ ** or if the parser is being invoked from within sqlite3_declare_vtab.
+ */
+ if( db->init.busy || IN_DECLARE_VTAB ){
+ return SQLITE_OK;
+ }
+
+ if( db->xAuth==0 ){
+ return SQLITE_OK;
+ }
+ rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
+ if( rc==SQLITE_DENY ){
+ sqlite3ErrorMsg(pParse, "not authorized");
+ pParse->rc = SQLITE_AUTH;
+ }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
+ rc = SQLITE_DENY;
+ sqliteAuthBadReturnCode(pParse);
+ }
+ return rc;
+}
+
+/*
+** Push an authorization context. After this routine is called, the
+** zArg3 argument to authorization callbacks will be zContext until
+** popped. Or if pParse==0, this routine is a no-op.
+*/
+SQLITE_PRIVATE void sqlite3AuthContextPush(
+ Parse *pParse,
+ AuthContext *pContext,
+ const char *zContext
+){
+ assert( pParse );
+ pContext->pParse = pParse;
+ pContext->zAuthContext = pParse->zAuthContext;
+ pParse->zAuthContext = zContext;
+}
+
+/*
+** Pop an authorization context that was previously pushed
+** by sqlite3AuthContextPush
+*/
+SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){
+ if( pContext->pParse ){
+ pContext->pParse->zAuthContext = pContext->zAuthContext;
+ pContext->pParse = 0;
+ }
+}
+
+#endif /* SQLITE_OMIT_AUTHORIZATION */
+
+/************** End of auth.c ************************************************/
+/************** Begin file build.c *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that are called by the SQLite parser
+** when syntax rules are reduced. The routines in this file handle the
+** following kinds of SQL syntax:
+**
+** CREATE TABLE
+** DROP TABLE
+** CREATE INDEX
+** DROP INDEX
+** creating ID lists
+** BEGIN TRANSACTION
+** COMMIT
+** ROLLBACK
+*/
+
+/*
+** This routine is called when a new SQL statement is beginning to
+** be parsed. Initialize the pParse structure as needed.
+*/
+SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){
+ pParse->explain = (u8)explainFlag;
+ pParse->nVar = 0;
+}
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/*
+** The TableLock structure is only used by the sqlite3TableLock() and
+** codeTableLocks() functions.
+*/
+struct TableLock {
+ int iDb; /* The database containing the table to be locked */
+ int iTab; /* The root page of the table to be locked */
+ u8 isWriteLock; /* True for write lock. False for a read lock */
+ const char *zName; /* Name of the table */
+};
+
+/*
+** Record the fact that we want to lock a table at run-time.
+**
+** The table to be locked has root page iTab and is found in database iDb.
+** A read or a write lock can be taken depending on isWritelock.
+**
+** This routine just records the fact that the lock is desired. The
+** code to make the lock occur is generated by a later call to
+** codeTableLocks() which occurs during sqlite3FinishCoding().
+*/
+SQLITE_PRIVATE void sqlite3TableLock(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* Index of the database containing the table to lock */
+ int iTab, /* Root page number of the table to be locked */
+ u8 isWriteLock, /* True for a write lock */
+ const char *zName /* Name of the table to be locked */
+){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ int i;
+ int nBytes;
+ TableLock *p;
+ assert( iDb>=0 );
+
+ for(i=0; i<pToplevel->nTableLock; i++){
+ p = &pToplevel->aTableLock[i];
+ if( p->iDb==iDb && p->iTab==iTab ){
+ p->isWriteLock = (p->isWriteLock || isWriteLock);
+ return;
+ }
+ }
+
+ nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
+ pToplevel->aTableLock =
+ sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
+ if( pToplevel->aTableLock ){
+ p = &pToplevel->aTableLock[pToplevel->nTableLock++];
+ p->iDb = iDb;
+ p->iTab = iTab;
+ p->isWriteLock = isWriteLock;
+ p->zName = zName;
+ }else{
+ pToplevel->nTableLock = 0;
+ pToplevel->db->mallocFailed = 1;
+ }
+}
+
+/*
+** Code an OP_TableLock instruction for each table locked by the
+** statement (configured by calls to sqlite3TableLock()).
+*/
+static void codeTableLocks(Parse *pParse){
+ int i;
+ Vdbe *pVdbe;
+
+ pVdbe = sqlite3GetVdbe(pParse);
+ assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
+
+ for(i=0; i<pParse->nTableLock; i++){
+ TableLock *p = &pParse->aTableLock[i];
+ int p1 = p->iDb;
+ sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
+ p->zName, P4_STATIC);
+ }
+}
+#else
+ #define codeTableLocks(x)
+#endif
+
+/*
+** This routine is called after a single SQL statement has been
+** parsed and a VDBE program to execute that statement has been
+** prepared. This routine puts the finishing touches on the
+** VDBE program and resets the pParse structure for the next
+** parse.
+**
+** Note that if an error occurred, it might be the case that
+** no VDBE code was generated.
+*/
+SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
+ sqlite3 *db;
+ Vdbe *v;
+
+ assert( pParse->pToplevel==0 );
+ db = pParse->db;
+ if( db->mallocFailed ) return;
+ if( pParse->nested ) return;
+ if( pParse->nErr ) return;
+
+ /* Begin by generating some termination code at the end of the
+ ** vdbe program
+ */
+ v = sqlite3GetVdbe(pParse);
+ assert( !pParse->isMultiWrite
+ || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
+ if( v ){
+ sqlite3VdbeAddOp0(v, OP_Halt);
+
+ /* The cookie mask contains one bit for each database file open.
+ ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
+ ** set for each database that is used. Generate code to start a
+ ** transaction on each used database and to verify the schema cookie
+ ** on each used database.
+ */
+ if( pParse->cookieGoto>0 ){
+ yDbMask mask;
+ int iDb;
+ sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
+ for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
+ if( (mask & pParse->cookieMask)==0 ) continue;
+ sqlite3VdbeUsesBtree(v, iDb);
+ sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
+ if( db->init.busy==0 ){
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ sqlite3VdbeAddOp3(v, OP_VerifyCookie,
+ iDb, pParse->cookieValue[iDb],
+ db->aDb[iDb].pSchema->iGeneration);
+ }
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ {
+ int i;
+ for(i=0; i<pParse->nVtabLock; i++){
+ char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
+ sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
+ }
+ pParse->nVtabLock = 0;
+ }
+#endif
+
+ /* Once all the cookies have been verified and transactions opened,
+ ** obtain the required table-locks. This is a no-op unless the
+ ** shared-cache feature is enabled.
+ */
+ codeTableLocks(pParse);
+
+ /* Initialize any AUTOINCREMENT data structures required.
+ */
+ sqlite3AutoincrementBegin(pParse);
+
+ /* Finally, jump back to the beginning of the executable code. */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
+ }
+ }
+
+
+ /* Get the VDBE program ready for execution
+ */
+ if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
+#ifdef SQLITE_DEBUG
+ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
+ sqlite3VdbeTrace(v, trace);
+#endif
+ assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
+ /* A minimum of one cursor is required if autoincrement is used
+ * See ticket [a696379c1f08866] */
+ if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
+ sqlite3VdbeMakeReady(v, pParse);
+ pParse->rc = SQLITE_DONE;
+ pParse->colNamesSet = 0;
+ }else{
+ pParse->rc = SQLITE_ERROR;
+ }
+ pParse->nTab = 0;
+ pParse->nMem = 0;
+ pParse->nSet = 0;
+ pParse->nVar = 0;
+ pParse->cookieMask = 0;
+ pParse->cookieGoto = 0;
+}
+
+/*
+** Run the parser and code generator recursively in order to generate
+** code for the SQL statement given onto the end of the pParse context
+** currently under construction. When the parser is run recursively
+** this way, the final OP_Halt is not appended and other initialization
+** and finalization steps are omitted because those are handling by the
+** outermost parser.
+**
+** Not everything is nestable. This facility is designed to permit
+** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
+** care if you decide to try to use this routine for some other purposes.
+*/
+SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
+ va_list ap;
+ char *zSql;
+ char *zErrMsg = 0;
+ sqlite3 *db = pParse->db;
+# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
+ char saveBuf[SAVE_SZ];
+
+ if( pParse->nErr ) return;
+ assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
+ va_start(ap, zFormat);
+ zSql = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ if( zSql==0 ){
+ return; /* A malloc must have failed */
+ }
+ pParse->nested++;
+ memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
+ memset(&pParse->nVar, 0, SAVE_SZ);
+ sqlite3RunParser(pParse, zSql, &zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
+ sqlite3DbFree(db, zSql);
+ memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
+ pParse->nested--;
+}
+
+/*
+** Locate the in-memory structure that describes a particular database
+** table given the name of that table and (optionally) the name of the
+** database containing the table. Return NULL if not found.
+**
+** If zDatabase is 0, all databases are searched for the table and the
+** first matching table is returned. (No checking for duplicate table
+** names is done.) The search order is TEMP first, then MAIN, then any
+** auxiliary databases added using the ATTACH command.
+**
+** See also sqlite3LocateTable().
+*/
+SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
+ Table *p = 0;
+ int i;
+ int nName;
+ assert( zName!=0 );
+ nName = sqlite3Strlen30(zName);
+ /* All mutexes are required for schema access. Make sure we hold them. */
+ assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
+ for(i=OMIT_TEMPDB; i<db->nDb; i++){
+ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
+ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
+ assert( sqlite3SchemaMutexHeld(db, j, 0) );
+ p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName);
+ if( p ) break;
+ }
+ return p;
+}
+
+/*
+** Locate the in-memory structure that describes a particular database
+** table given the name of that table and (optionally) the name of the
+** database containing the table. Return NULL if not found. Also leave an
+** error message in pParse->zErrMsg.
+**
+** The difference between this routine and sqlite3FindTable() is that this
+** routine leaves an error message in pParse->zErrMsg where
+** sqlite3FindTable() does not.
+*/
+SQLITE_PRIVATE Table *sqlite3LocateTable(
+ Parse *pParse, /* context in which to report errors */
+ int isView, /* True if looking for a VIEW rather than a TABLE */
+ const char *zName, /* Name of the table we are looking for */
+ const char *zDbase /* Name of the database. Might be NULL */
+){
+ Table *p;
+
+ /* Read the database schema. If an error occurs, leave an error message
+ ** and code in pParse and return NULL. */
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ return 0;
+ }
+
+ p = sqlite3FindTable(pParse->db, zName, zDbase);
+ if( p==0 ){
+ const char *zMsg = isView ? "no such view" : "no such table";
+ if( zDbase ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
+ }else{
+ sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
+ }
+ pParse->checkSchema = 1;
+ }
+ return p;
+}
+
+/*
+** Locate the table identified by *p.
+**
+** This is a wrapper around sqlite3LocateTable(). The difference between
+** sqlite3LocateTable() and this function is that this function restricts
+** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
+** non-NULL if it is part of a view or trigger program definition. See
+** sqlite3FixSrcList() for details.
+*/
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(
+ Parse *pParse,
+ int isView,
+ struct SrcList_item *p
+){
+ const char *zDb;
+ assert( p->pSchema==0 || p->zDatabase==0 );
+ if( p->pSchema ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+ zDb = pParse->db->aDb[iDb].zName;
+ }else{
+ zDb = p->zDatabase;
+ }
+ return sqlite3LocateTable(pParse, isView, p->zName, zDb);
+}
+
+/*
+** Locate the in-memory structure that describes
+** a particular index given the name of that index
+** and the name of the database that contains the index.
+** Return NULL if not found.
+**
+** If zDatabase is 0, all databases are searched for the
+** table and the first matching index is returned. (No checking
+** for duplicate index names is done.) The search order is
+** TEMP first, then MAIN, then any auxiliary databases added
+** using the ATTACH command.
+*/
+SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
+ Index *p = 0;
+ int i;
+ int nName = sqlite3Strlen30(zName);
+ /* All mutexes are required for schema access. Make sure we hold them. */
+ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
+ for(i=OMIT_TEMPDB; i<db->nDb; i++){
+ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
+ Schema *pSchema = db->aDb[j].pSchema;
+ assert( pSchema );
+ if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
+ assert( sqlite3SchemaMutexHeld(db, j, 0) );
+ p = sqlite3HashFind(&pSchema->idxHash, zName, nName);
+ if( p ) break;
+ }
+ return p;
+}
+
+/*
+** Reclaim the memory used by an index
+*/
+static void freeIndex(sqlite3 *db, Index *p){
+#ifndef SQLITE_OMIT_ANALYZE
+ sqlite3DeleteIndexSamples(db, p);
+#endif
+ sqlite3DbFree(db, p->zColAff);
+ sqlite3DbFree(db, p);
+}
+
+/*
+** For the index called zIdxName which is found in the database iDb,
+** unlike that index from its Table then remove the index from
+** the index hash table and free all memory structures associated
+** with the index.
+*/
+SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
+ Index *pIndex;
+ int len;
+ Hash *pHash;
+
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ pHash = &db->aDb[iDb].pSchema->idxHash;
+ len = sqlite3Strlen30(zIdxName);
+ pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0);
+ if( ALWAYS(pIndex) ){
+ if( pIndex->pTable->pIndex==pIndex ){
+ pIndex->pTable->pIndex = pIndex->pNext;
+ }else{
+ Index *p;
+ /* Justification of ALWAYS(); The index must be on the list of
+ ** indices. */
+ p = pIndex->pTable->pIndex;
+ while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; }
+ if( ALWAYS(p && p->pNext==pIndex) ){
+ p->pNext = pIndex->pNext;
+ }
+ }
+ freeIndex(db, pIndex);
+ }
+ db->flags |= SQLITE_InternChanges;
+}
+
+/*
+** Look through the list of open database files in db->aDb[] and if
+** any have been closed, remove them from the list. Reallocate the
+** db->aDb[] structure to a smaller size, if possible.
+**
+** Entry 0 (the "main" database) and entry 1 (the "temp" database)
+** are never candidates for being collapsed.
+*/
+SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){
+ int i, j;
+ for(i=j=2; i<db->nDb; i++){
+ struct Db *pDb = &db->aDb[i];
+ if( pDb->pBt==0 ){
+ sqlite3DbFree(db, pDb->zName);
+ pDb->zName = 0;
+ continue;
+ }
+ if( j<i ){
+ db->aDb[j] = db->aDb[i];
+ }
+ j++;
+ }
+ memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
+ db->nDb = j;
+ if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
+ memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
+ sqlite3DbFree(db, db->aDb);
+ db->aDb = db->aDbStatic;
+ }
+}
+
+/*
+** Reset the schema for the database at index iDb. Also reset the
+** TEMP schema.
+*/
+SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
+ Db *pDb;
+ assert( iDb<db->nDb );
+
+ /* Case 1: Reset the single schema identified by iDb */
+ pDb = &db->aDb[iDb];
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ assert( pDb->pSchema!=0 );
+ sqlite3SchemaClear(pDb->pSchema);
+
+ /* If any database other than TEMP is reset, then also reset TEMP
+ ** since TEMP might be holding triggers that reference tables in the
+ ** other database.
+ */
+ if( iDb!=1 ){
+ pDb = &db->aDb[1];
+ assert( pDb->pSchema!=0 );
+ sqlite3SchemaClear(pDb->pSchema);
+ }
+ return;
+}
+
+/*
+** Erase all schema information from all attached databases (including
+** "main" and "temp") for a single database connection.
+*/
+SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
+ int i;
+ sqlite3BtreeEnterAll(db);
+ for(i=0; i<db->nDb; i++){
+ Db *pDb = &db->aDb[i];
+ if( pDb->pSchema ){
+ sqlite3SchemaClear(pDb->pSchema);
+ }
+ }
+ db->flags &= ~SQLITE_InternChanges;
+ sqlite3VtabUnlockList(db);
+ sqlite3BtreeLeaveAll(db);
+ sqlite3CollapseDatabaseArray(db);
+}
+
+/*
+** This routine is called when a commit occurs.
+*/
+SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){
+ db->flags &= ~SQLITE_InternChanges;
+}
+
+/*
+** Delete memory allocated for the column names of a table or view (the
+** Table.aCol[] array).
+*/
+static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){
+ int i;
+ Column *pCol;
+ assert( pTable!=0 );
+ if( (pCol = pTable->aCol)!=0 ){
+ for(i=0; i<pTable->nCol; i++, pCol++){
+ sqlite3DbFree(db, pCol->zName);
+ sqlite3ExprDelete(db, pCol->pDflt);
+ sqlite3DbFree(db, pCol->zDflt);
+ sqlite3DbFree(db, pCol->zType);
+ sqlite3DbFree(db, pCol->zColl);
+ }
+ sqlite3DbFree(db, pTable->aCol);
+ }
+}
+
+/*
+** Remove the memory data structures associated with the given
+** Table. No changes are made to disk by this routine.
+**
+** This routine just deletes the data structure. It does not unlink
+** the table data structure from the hash table. But it does destroy
+** memory structures of the indices and foreign keys associated with
+** the table.
+**
+** The db parameter is optional. It is needed if the Table object
+** contains lookaside memory. (Table objects in the schema do not use
+** lookaside memory, but some ephemeral Table objects do.) Or the
+** db parameter can be used with db->pnBytesFreed to measure the memory
+** used by the Table object.
+*/
+SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
+ Index *pIndex, *pNext;
+ TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */
+
+ assert( !pTable || pTable->nRef>0 );
+
+ /* Do not delete the table until the reference count reaches zero. */
+ if( !pTable ) return;
+ if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
+
+ /* Record the number of outstanding lookaside allocations in schema Tables
+ ** prior to doing any free() operations. Since schema Tables do not use
+ ** lookaside, this number should not change. */
+ TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ?
+ db->lookaside.nOut : 0 );
+
+ /* Delete all indices associated with this table. */
+ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
+ pNext = pIndex->pNext;
+ assert( pIndex->pSchema==pTable->pSchema );
+ if( !db || db->pnBytesFreed==0 ){
+ char *zName = pIndex->zName;
+ TESTONLY ( Index *pOld = ) sqlite3HashInsert(
+ &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
+ );
+ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
+ assert( pOld==pIndex || pOld==0 );
+ }
+ freeIndex(db, pIndex);
+ }
+
+ /* Delete any foreign keys attached to this table. */
+ sqlite3FkDelete(db, pTable);
+
+ /* Delete the Table structure itself.
+ */
+ sqliteDeleteColumnNames(db, pTable);
+ sqlite3DbFree(db, pTable->zName);
+ sqlite3DbFree(db, pTable->zColAff);
+ sqlite3SelectDelete(db, pTable->pSelect);
+#ifndef SQLITE_OMIT_CHECK
+ sqlite3ExprListDelete(db, pTable->pCheck);
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3VtabClear(db, pTable);
+#endif
+ sqlite3DbFree(db, pTable);
+
+ /* Verify that no lookaside memory was used by schema tables */
+ assert( nLookaside==0 || nLookaside==db->lookaside.nOut );
+}
+
+/*
+** Unlink the given table from the hash tables and the delete the
+** table structure with all its indices and foreign keys.
+*/
+SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
+ Table *p;
+ Db *pDb;
+
+ assert( db!=0 );
+ assert( iDb>=0 && iDb<db->nDb );
+ assert( zTabName );
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
+ pDb = &db->aDb[iDb];
+ p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
+ sqlite3Strlen30(zTabName),0);
+ sqlite3DeleteTable(db, p);
+ db->flags |= SQLITE_InternChanges;
+}
+
+/*
+** Given a token, return a string that consists of the text of that
+** token. Space to hold the returned string
+** is obtained from sqliteMalloc() and must be freed by the calling
+** function.
+**
+** Any quotation marks (ex: "name", 'name', [name], or `name`) that
+** surround the body of the token are removed.
+**
+** Tokens are often just pointers into the original SQL text and so
+** are not \000 terminated and are not persistent. The returned string
+** is \000 terminated and is persistent.
+*/
+SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
+ char *zName;
+ if( pName ){
+ zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
+ sqlite3Dequote(zName);
+ }else{
+ zName = 0;
+ }
+ return zName;
+}
+
+/*
+** Open the sqlite_master table stored in database number iDb for
+** writing. The table is opened using cursor 0.
+*/
+SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){
+ Vdbe *v = sqlite3GetVdbe(p);
+ sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
+ sqlite3VdbeChangeP4(v, -1, (char *)5, P4_INT32); /* 5 column table */
+ if( p->nTab==0 ){
+ p->nTab = 1;
+ }
+}
+
+/*
+** Parameter zName points to a nul-terminated buffer containing the name
+** of a database ("main", "temp" or the name of an attached db). This
+** function returns the index of the named database in db->aDb[], or
+** -1 if the named db cannot be found.
+*/
+SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){
+ int i = -1; /* Database number */
+ if( zName ){
+ Db *pDb;
+ int n = sqlite3Strlen30(zName);
+ for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
+ if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) &&
+ 0==sqlite3StrICmp(pDb->zName, zName) ){
+ break;
+ }
+ }
+ }
+ return i;
+}
+
+/*
+** The token *pName contains the name of a database (either "main" or
+** "temp" or the name of an attached db). This routine returns the
+** index of the named database in db->aDb[], or -1 if the named db
+** does not exist.
+*/
+SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){
+ int i; /* Database number */
+ char *zName; /* Name we are searching for */
+ zName = sqlite3NameFromToken(db, pName);
+ i = sqlite3FindDbName(db, zName);
+ sqlite3DbFree(db, zName);
+ return i;
+}
+
+/* The table or view or trigger name is passed to this routine via tokens
+** pName1 and pName2. If the table name was fully qualified, for example:
+**
+** CREATE TABLE xxx.yyy (...);
+**
+** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
+** the table name is not fully qualified, i.e.:
+**
+** CREATE TABLE yyy(...);
+**
+** Then pName1 is set to "yyy" and pName2 is "".
+**
+** This routine sets the *ppUnqual pointer to point at the token (pName1 or
+** pName2) that stores the unqualified table name. The index of the
+** database "xxx" is returned.
+*/
+SQLITE_PRIVATE int sqlite3TwoPartName(
+ Parse *pParse, /* Parsing and code generating context */
+ Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */
+ Token *pName2, /* The "yyy" in the name "xxx.yyy" */
+ Token **pUnqual /* Write the unqualified object name here */
+){
+ int iDb; /* Database holding the object */
+ sqlite3 *db = pParse->db;
+
+ if( ALWAYS(pName2!=0) && pName2->n>0 ){
+ if( db->init.busy ) {
+ sqlite3ErrorMsg(pParse, "corrupt database");
+ pParse->nErr++;
+ return -1;
+ }
+ *pUnqual = pName2;
+ iDb = sqlite3FindDb(db, pName1);
+ if( iDb<0 ){
+ sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
+ pParse->nErr++;
+ return -1;
+ }
+ }else{
+ assert( db->init.iDb==0 || db->init.busy );
+ iDb = db->init.iDb;
+ *pUnqual = pName1;
+ }
+ return iDb;
+}
+
+/*
+** This routine is used to check if the UTF-8 string zName is a legal
+** unqualified name for a new schema object (table, index, view or
+** trigger). All names are legal except those that begin with the string
+** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
+** is reserved for internal use.
+*/
+SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){
+ if( !pParse->db->init.busy && pParse->nested==0
+ && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
+ sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Begin constructing a new table representation in memory. This is
+** the first of several action routines that get called in response
+** to a CREATE TABLE statement. In particular, this routine is called
+** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
+** flag is true if the table should be stored in the auxiliary database
+** file instead of in the main database file. This is normally the case
+** when the "TEMP" or "TEMPORARY" keyword occurs in between
+** CREATE and TABLE.
+**
+** The new table record is initialized and put in pParse->pNewTable.
+** As more of the CREATE TABLE statement is parsed, additional action
+** routines will be called to add more information to this record.
+** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine
+** is called to complete the construction of the new table record.
+*/
+SQLITE_PRIVATE void sqlite3StartTable(
+ Parse *pParse, /* Parser context */
+ Token *pName1, /* First part of the name of the table or view */
+ Token *pName2, /* Second part of the name of the table or view */
+ int isTemp, /* True if this is a TEMP table */
+ int isView, /* True if this is a VIEW */
+ int isVirtual, /* True if this is a VIRTUAL table */
+ int noErr /* Do nothing if table already exists */
+){
+ Table *pTable;
+ char *zName = 0; /* The name of the new table */
+ sqlite3 *db = pParse->db;
+ Vdbe *v;
+ int iDb; /* Database number to create the table in */
+ Token *pName; /* Unqualified name of the table to create */
+
+ /* The table or view name to create is passed to this routine via tokens
+ ** pName1 and pName2. If the table name was fully qualified, for example:
+ **
+ ** CREATE TABLE xxx.yyy (...);
+ **
+ ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
+ ** the table name is not fully qualified, i.e.:
+ **
+ ** CREATE TABLE yyy(...);
+ **
+ ** Then pName1 is set to "yyy" and pName2 is "".
+ **
+ ** The call below sets the pName pointer to point at the token (pName1 or
+ ** pName2) that stores the unqualified table name. The variable iDb is
+ ** set to the index of the database that the table or view is to be
+ ** created in.
+ */
+ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
+ if( iDb<0 ) return;
+ if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){
+ /* If creating a temp table, the name may not be qualified. Unless
+ ** the database name is "temp" anyway. */
+ sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
+ return;
+ }
+ if( !OMIT_TEMPDB && isTemp ) iDb = 1;
+
+ pParse->sNameToken = *pName;
+ zName = sqlite3NameFromToken(db, pName);
+ if( zName==0 ) return;
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+ goto begin_table_error;
+ }
+ if( db->init.iDb==1 ) isTemp = 1;
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ assert( (isTemp & 1)==isTemp );
+ {
+ int code;
+ char *zDb = db->aDb[iDb].zName;
+ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
+ goto begin_table_error;
+ }
+ if( isView ){
+ if( !OMIT_TEMPDB && isTemp ){
+ code = SQLITE_CREATE_TEMP_VIEW;
+ }else{
+ code = SQLITE_CREATE_VIEW;
+ }
+ }else{
+ if( !OMIT_TEMPDB && isTemp ){
+ code = SQLITE_CREATE_TEMP_TABLE;
+ }else{
+ code = SQLITE_CREATE_TABLE;
+ }
+ }
+ if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){
+ goto begin_table_error;
+ }
+ }
+#endif
+
+ /* Make sure the new table name does not collide with an existing
+ ** index or table name in the same database. Issue an error message if
+ ** it does. The exception is if the statement being parsed was passed
+ ** to an sqlite3_declare_vtab() call. In that case only the column names
+ ** and types will be used, so there is no need to test for namespace
+ ** collisions.
+ */
+ if( !IN_DECLARE_VTAB ){
+ char *zDb = db->aDb[iDb].zName;
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ goto begin_table_error;
+ }
+ pTable = sqlite3FindTable(db, zName, zDb);
+ if( pTable ){
+ if( !noErr ){
+ sqlite3ErrorMsg(pParse, "table %T already exists", pName);
+ }else{
+ assert( !db->init.busy );
+ sqlite3CodeVerifySchema(pParse, iDb);
+ }
+ goto begin_table_error;
+ }
+ if( sqlite3FindIndex(db, zName, zDb)!=0 ){
+ sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
+ goto begin_table_error;
+ }
+ }
+
+ pTable = sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTable==0 ){
+ db->mallocFailed = 1;
+ pParse->rc = SQLITE_NOMEM;
+ pParse->nErr++;
+ goto begin_table_error;
+ }
+ pTable->zName = zName;
+ pTable->iPKey = -1;
+ pTable->pSchema = db->aDb[iDb].pSchema;
+ pTable->nRef = 1;
+ pTable->nRowEst = 1000000;
+ assert( pParse->pNewTable==0 );
+ pParse->pNewTable = pTable;
+
+ /* If this is the magic sqlite_sequence table used by autoincrement,
+ ** then record a pointer to this table in the main database structure
+ ** so that INSERT can find the table easily.
+ */
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ pTable->pSchema->pSeqTab = pTable;
+ }
+#endif
+
+ /* Begin generating the code that will insert the table record into
+ ** the SQLITE_MASTER table. Note in particular that we must go ahead
+ ** and allocate the record number for the table entry now. Before any
+ ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
+ ** indices to be created and the table record must come before the
+ ** indices. Hence, the record number for the table must be allocated
+ ** now.
+ */
+ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
+ int j1;
+ int fileFormat;
+ int reg1, reg2, reg3;
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( isVirtual ){
+ sqlite3VdbeAddOp0(v, OP_VBegin);
+ }
+#endif
+
+ /* If the file format and encoding in the database have not been set,
+ ** set them now.
+ */
+ reg1 = pParse->regRowid = ++pParse->nMem;
+ reg2 = pParse->regRoot = ++pParse->nMem;
+ reg3 = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
+ sqlite3VdbeUsesBtree(v, iDb);
+ j1 = sqlite3VdbeAddOp1(v, OP_If, reg3);
+ fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
+ 1 : SQLITE_MAX_FILE_FORMAT;
+ sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3);
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3);
+ sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3);
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3);
+ sqlite3VdbeJumpHere(v, j1);
+
+ /* This just creates a place-holder record in the sqlite_master table.
+ ** The record created does not contain anything yet. It will be replaced
+ ** by the real entry in code generated at sqlite3EndTable().
+ **
+ ** The rowid for the new entry is left in register pParse->regRowid.
+ ** The root page number of the new table is left in reg pParse->regRoot.
+ ** The rowid and root page number values are needed by the code that
+ ** sqlite3EndTable will generate.
+ */
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
+ if( isView || isVirtual ){
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2);
+ }else
+#endif
+ {
+ sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
+ }
+ sqlite3OpenMasterTable(pParse, iDb);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, reg3);
+ sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ sqlite3VdbeAddOp0(v, OP_Close);
+ }
+
+ /* Normal (non-error) return. */
+ return;
+
+ /* If an error occurs, we jump here */
+begin_table_error:
+ sqlite3DbFree(db, zName);
+ return;
+}
+
+/*
+** This macro is used to compare two strings in a case-insensitive manner.
+** It is slightly faster than calling sqlite3StrICmp() directly, but
+** produces larger code.
+**
+** WARNING: This macro is not compatible with the strcmp() family. It
+** returns true if the two strings are equal, otherwise false.
+*/
+#define STRICMP(x, y) (\
+sqlite3UpperToLower[*(unsigned char *)(x)]== \
+sqlite3UpperToLower[*(unsigned char *)(y)] \
+&& sqlite3StrICmp((x)+1,(y)+1)==0 )
+
+/*
+** Add a new column to the table currently being constructed.
+**
+** The parser calls this routine once for each column declaration
+** in a CREATE TABLE statement. sqlite3StartTable() gets called
+** first to get things going. Then this routine is called for each
+** column.
+*/
+SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){
+ Table *p;
+ int i;
+ char *z;
+ Column *pCol;
+ sqlite3 *db = pParse->db;
+ if( (p = pParse->pNewTable)==0 ) return;
+#if SQLITE_MAX_COLUMN
+ if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
+ return;
+ }
+#endif
+ z = sqlite3NameFromToken(db, pName);
+ if( z==0 ) return;
+ for(i=0; i<p->nCol; i++){
+ if( STRICMP(z, p->aCol[i].zName) ){
+ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
+ sqlite3DbFree(db, z);
+ return;
+ }
+ }
+ if( (p->nCol & 0x7)==0 ){
+ Column *aNew;
+ aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
+ if( aNew==0 ){
+ sqlite3DbFree(db, z);
+ return;
+ }
+ p->aCol = aNew;
+ }
+ pCol = &p->aCol[p->nCol];
+ memset(pCol, 0, sizeof(p->aCol[0]));
+ pCol->zName = z;
+
+ /* If there is no type specified, columns have the default affinity
+ ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
+ ** be called next to set pCol->affinity correctly.
+ */
+ pCol->affinity = SQLITE_AFF_NONE;
+ p->nCol++;
+}
+
+/*
+** This routine is called by the parser while in the middle of
+** parsing a CREATE TABLE statement. A "NOT NULL" constraint has
+** been seen on a column. This routine sets the notNull flag on
+** the column currently under construction.
+*/
+SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){
+ Table *p;
+ p = pParse->pNewTable;
+ if( p==0 || NEVER(p->nCol<1) ) return;
+ p->aCol[p->nCol-1].notNull = (u8)onError;
+}
+
+/*
+** Scan the column type name zType (length nType) and return the
+** associated affinity type.
+**
+** This routine does a case-independent search of zType for the
+** substrings in the following table. If one of the substrings is
+** found, the corresponding affinity is returned. If zType contains
+** more than one of the substrings, entries toward the top of
+** the table take priority. For example, if zType is 'BLOBINT',
+** SQLITE_AFF_INTEGER is returned.
+**
+** Substring | Affinity
+** --------------------------------
+** 'INT' | SQLITE_AFF_INTEGER
+** 'CHAR' | SQLITE_AFF_TEXT
+** 'CLOB' | SQLITE_AFF_TEXT
+** 'TEXT' | SQLITE_AFF_TEXT
+** 'BLOB' | SQLITE_AFF_NONE
+** 'REAL' | SQLITE_AFF_REAL
+** 'FLOA' | SQLITE_AFF_REAL
+** 'DOUB' | SQLITE_AFF_REAL
+**
+** If none of the substrings in the above table are found,
+** SQLITE_AFF_NUMERIC is returned.
+*/
+SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
+ u32 h = 0;
+ char aff = SQLITE_AFF_NUMERIC;
+
+ if( zIn ) while( zIn[0] ){
+ h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
+ zIn++;
+ if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
+ aff = SQLITE_AFF_TEXT;
+ }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
+ aff = SQLITE_AFF_TEXT;
+ }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
+ aff = SQLITE_AFF_TEXT;
+ }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
+ && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
+ aff = SQLITE_AFF_NONE;
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
+ && aff==SQLITE_AFF_NUMERIC ){
+ aff = SQLITE_AFF_REAL;
+ }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
+ && aff==SQLITE_AFF_NUMERIC ){
+ aff = SQLITE_AFF_REAL;
+ }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */
+ && aff==SQLITE_AFF_NUMERIC ){
+ aff = SQLITE_AFF_REAL;
+#endif
+ }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */
+ aff = SQLITE_AFF_INTEGER;
+ break;
+ }
+ }
+
+ return aff;
+}
+
+/*
+** This routine is called by the parser while in the middle of
+** parsing a CREATE TABLE statement. The pFirst token is the first
+** token in the sequence of tokens that describe the type of the
+** column currently under construction. pLast is the last token
+** in the sequence. Use this information to construct a string
+** that contains the typename of the column and store that string
+** in zType.
+*/
+SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){
+ Table *p;
+ Column *pCol;
+
+ p = pParse->pNewTable;
+ if( p==0 || NEVER(p->nCol<1) ) return;
+ pCol = &p->aCol[p->nCol-1];
+ assert( pCol->zType==0 );
+ pCol->zType = sqlite3NameFromToken(pParse->db, pType);
+ pCol->affinity = sqlite3AffinityType(pCol->zType);
+}
+
+/*
+** The expression is the default value for the most recently added column
+** of the table currently under construction.
+**
+** Default value expressions must be constant. Raise an exception if this
+** is not the case.
+**
+** This routine is called by the parser while in the middle of
+** parsing a CREATE TABLE statement.
+*/
+SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
+ Table *p;
+ Column *pCol;
+ sqlite3 *db = pParse->db;
+ p = pParse->pNewTable;
+ if( p!=0 ){
+ pCol = &(p->aCol[p->nCol-1]);
+ if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){
+ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
+ pCol->zName);
+ }else{
+ /* A copy of pExpr is used instead of the original, as pExpr contains
+ ** tokens that point to volatile memory. The 'span' of the expression
+ ** is required by pragma table_info.
+ */
+ sqlite3ExprDelete(db, pCol->pDflt);
+ pCol->pDflt = sqlite3ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE);
+ sqlite3DbFree(db, pCol->zDflt);
+ pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
+ (int)(pSpan->zEnd - pSpan->zStart));
+ }
+ }
+ sqlite3ExprDelete(db, pSpan->pExpr);
+}
+
+/*
+** Designate the PRIMARY KEY for the table. pList is a list of names
+** of columns that form the primary key. If pList is NULL, then the
+** most recently added column of the table is the primary key.
+**
+** A table can have at most one primary key. If the table already has
+** a primary key (and this is the second primary key) then create an
+** error.
+**
+** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
+** then we will try to use that column as the rowid. Set the Table.iPKey
+** field of the table under construction to be the index of the
+** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is
+** no INTEGER PRIMARY KEY.
+**
+** If the key is not an INTEGER PRIMARY KEY, then create a unique
+** index for the key. No index is created for INTEGER PRIMARY KEYs.
+*/
+SQLITE_PRIVATE void sqlite3AddPrimaryKey(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* List of field names to be indexed */
+ int onError, /* What to do with a uniqueness conflict */
+ int autoInc, /* True if the AUTOINCREMENT keyword is present */
+ int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */
+){
+ Table *pTab = pParse->pNewTable;
+ char *zType = 0;
+ int iCol = -1, i;
+ if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
+ if( pTab->tabFlags & TF_HasPrimaryKey ){
+ sqlite3ErrorMsg(pParse,
+ "table \"%s\" has more than one primary key", pTab->zName);
+ goto primary_key_exit;
+ }
+ pTab->tabFlags |= TF_HasPrimaryKey;
+ if( pList==0 ){
+ iCol = pTab->nCol - 1;
+ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
+ }else{
+ for(i=0; i<pList->nExpr; i++){
+ for(iCol=0; iCol<pTab->nCol; iCol++){
+ if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){
+ break;
+ }
+ }
+ if( iCol<pTab->nCol ){
+ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
+ }
+ }
+ if( pList->nExpr>1 ) iCol = -1;
+ }
+ if( iCol>=0 && iCol<pTab->nCol ){
+ zType = pTab->aCol[iCol].zType;
+ }
+ if( zType && sqlite3StrICmp(zType, "INTEGER")==0
+ && sortOrder==SQLITE_SO_ASC ){
+ pTab->iPKey = iCol;
+ pTab->keyConf = (u8)onError;
+ assert( autoInc==0 || autoInc==1 );
+ pTab->tabFlags |= autoInc*TF_Autoincrement;
+ }else if( autoInc ){
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
+ "INTEGER PRIMARY KEY");
+#endif
+ }else{
+ Index *p;
+ p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0);
+ if( p ){
+ p->autoIndex = 2;
+ }
+ pList = 0;
+ }
+
+primary_key_exit:
+ sqlite3ExprListDelete(pParse->db, pList);
+ return;
+}
+
+/*
+** Add a new CHECK constraint to the table currently under construction.
+*/
+SQLITE_PRIVATE void sqlite3AddCheckConstraint(
+ Parse *pParse, /* Parsing context */
+ Expr *pCheckExpr /* The check expression */
+){
+#ifndef SQLITE_OMIT_CHECK
+ Table *pTab = pParse->pNewTable;
+ if( pTab && !IN_DECLARE_VTAB ){
+ pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
+ if( pParse->constraintName.n ){
+ sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+ }
+ }else
+#endif
+ {
+ sqlite3ExprDelete(pParse->db, pCheckExpr);
+ }
+}
+
+/*
+** Set the collation function of the most recently parsed table column
+** to the CollSeq given.
+*/
+SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
+ Table *p;
+ int i;
+ char *zColl; /* Dequoted name of collation sequence */
+ sqlite3 *db;
+
+ if( (p = pParse->pNewTable)==0 ) return;
+ i = p->nCol-1;
+ db = pParse->db;
+ zColl = sqlite3NameFromToken(db, pToken);
+ if( !zColl ) return;
+
+ if( sqlite3LocateCollSeq(pParse, zColl) ){
+ Index *pIdx;
+ p->aCol[i].zColl = zColl;
+
+ /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
+ ** then an index may have been created on this column before the
+ ** collation type was added. Correct this if it is the case.
+ */
+ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
+ assert( pIdx->nColumn==1 );
+ if( pIdx->aiColumn[0]==i ){
+ pIdx->azColl[0] = p->aCol[i].zColl;
+ }
+ }
+ }else{
+ sqlite3DbFree(db, zColl);
+ }
+}
+
+/*
+** This function returns the collation sequence for database native text
+** encoding identified by the string zName, length nName.
+**
+** If the requested collation sequence is not available, or not available
+** in the database native encoding, the collation factory is invoked to
+** request it. If the collation factory does not supply such a sequence,
+** and the sequence is available in another text encoding, then that is
+** returned instead.
+**
+** If no versions of the requested collations sequence are available, or
+** another error occurs, NULL is returned and an error message written into
+** pParse.
+**
+** This routine is a wrapper around sqlite3FindCollSeq(). This routine
+** invokes the collation factory if the named collation cannot be found
+** and generates an error message.
+**
+** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
+*/
+SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
+ sqlite3 *db = pParse->db;
+ u8 enc = ENC(db);
+ u8 initbusy = db->init.busy;
+ CollSeq *pColl;
+
+ pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
+ if( !initbusy && (!pColl || !pColl->xCmp) ){
+ pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
+ }
+
+ return pColl;
+}
+
+
+/*
+** Generate code that will increment the schema cookie.
+**
+** The schema cookie is used to determine when the schema for the
+** database changes. After each schema change, the cookie value
+** changes. When a process first reads the schema it records the
+** cookie. Thereafter, whenever it goes to access the database,
+** it checks the cookie to make sure the schema has not changed
+** since it was last read.
+**
+** This plan is not completely bullet-proof. It is possible for
+** the schema to change multiple times and for the cookie to be
+** set back to prior value. But schema changes are infrequent
+** and the probability of hitting the same cookie value is only
+** 1 chance in 2^32. So we're safe enough.
+*/
+SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3 *db = pParse->db;
+ Vdbe *v = pParse->pVdbe;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1);
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1);
+ sqlite3ReleaseTempReg(pParse, r1);
+}
+
+/*
+** Measure the number of characters needed to output the given
+** identifier. The number returned includes any quotes used
+** but does not include the null terminator.
+**
+** The estimate is conservative. It might be larger that what is
+** really needed.
+*/
+static int identLength(const char *z){
+ int n;
+ for(n=0; *z; n++, z++){
+ if( *z=='"' ){ n++; }
+ }
+ return n + 2;
+}
+
+/*
+** The first parameter is a pointer to an output buffer. The second
+** parameter is a pointer to an integer that contains the offset at
+** which to write into the output buffer. This function copies the
+** nul-terminated string pointed to by the third parameter, zSignedIdent,
+** to the specified offset in the buffer and updates *pIdx to refer
+** to the first byte after the last byte written before returning.
+**
+** If the string zSignedIdent consists entirely of alpha-numeric
+** characters, does not begin with a digit and is not an SQL keyword,
+** then it is copied to the output buffer exactly as it is. Otherwise,
+** it is quoted using double-quotes.
+*/
+static void identPut(char *z, int *pIdx, char *zSignedIdent){
+ unsigned char *zIdent = (unsigned char*)zSignedIdent;
+ int i, j, needQuote;
+ i = *pIdx;
+
+ for(j=0; zIdent[j]; j++){
+ if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
+ }
+ needQuote = sqlite3Isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID;
+ if( !needQuote ){
+ needQuote = zIdent[j];
+ }
+
+ if( needQuote ) z[i++] = '"';
+ for(j=0; zIdent[j]; j++){
+ z[i++] = zIdent[j];
+ if( zIdent[j]=='"' ) z[i++] = '"';
+ }
+ if( needQuote ) z[i++] = '"';
+ z[i] = 0;
+ *pIdx = i;
+}
+
+/*
+** Generate a CREATE TABLE statement appropriate for the given
+** table. Memory to hold the text of the statement is obtained
+** from sqliteMalloc() and must be freed by the calling function.
+*/
+static char *createTableStmt(sqlite3 *db, Table *p){
+ int i, k, n;
+ char *zStmt;
+ char *zSep, *zSep2, *zEnd;
+ Column *pCol;
+ n = 0;
+ for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
+ n += identLength(pCol->zName) + 5;
+ }
+ n += identLength(p->zName);
+ if( n<50 ){
+ zSep = "";
+ zSep2 = ",";
+ zEnd = ")";
+ }else{
+ zSep = "\n ";
+ zSep2 = ",\n ";
+ zEnd = "\n)";
+ }
+ n += 35 + 6*p->nCol;
+ zStmt = sqlite3DbMallocRaw(0, n);
+ if( zStmt==0 ){
+ db->mallocFailed = 1;
+ return 0;
+ }
+ sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
+ k = sqlite3Strlen30(zStmt);
+ identPut(zStmt, &k, p->zName);
+ zStmt[k++] = '(';
+ for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
+ static const char * const azType[] = {
+ /* SQLITE_AFF_TEXT */ " TEXT",
+ /* SQLITE_AFF_NONE */ "",
+ /* SQLITE_AFF_NUMERIC */ " NUM",
+ /* SQLITE_AFF_INTEGER */ " INT",
+ /* SQLITE_AFF_REAL */ " REAL"
+ };
+ int len;
+ const char *zType;
+
+ sqlite3_snprintf(n-k, &zStmt[k], zSep);
+ k += sqlite3Strlen30(&zStmt[k]);
+ zSep = zSep2;
+ identPut(zStmt, &k, pCol->zName);
+ assert( pCol->affinity-SQLITE_AFF_TEXT >= 0 );
+ assert( pCol->affinity-SQLITE_AFF_TEXT < ArraySize(azType) );
+ testcase( pCol->affinity==SQLITE_AFF_TEXT );
+ testcase( pCol->affinity==SQLITE_AFF_NONE );
+ testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
+ testcase( pCol->affinity==SQLITE_AFF_INTEGER );
+ testcase( pCol->affinity==SQLITE_AFF_REAL );
+
+ zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
+ len = sqlite3Strlen30(zType);
+ assert( pCol->affinity==SQLITE_AFF_NONE
+ || pCol->affinity==sqlite3AffinityType(zType) );
+ memcpy(&zStmt[k], zType, len);
+ k += len;
+ assert( k<=n );
+ }
+ sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
+ return zStmt;
+}
+
+/*
+** This routine is called to report the final ")" that terminates
+** a CREATE TABLE statement.
+**
+** The table structure that other action routines have been building
+** is added to the internal hash tables, assuming no errors have
+** occurred.
+**
+** An entry for the table is made in the master table on disk, unless
+** this is a temporary table or db->init.busy==1. When db->init.busy==1
+** it means we are reading the sqlite_master table because we just
+** connected to the database or because the sqlite_master table has
+** recently changed, so the entry for this table already exists in
+** the sqlite_master table. We do not want to create it again.
+**
+** If the pSelect argument is not NULL, it means that this routine
+** was called to create a table generated from a
+** "CREATE TABLE ... AS SELECT ..." statement. The column names of
+** the new table will match the result set of the SELECT.
+*/
+SQLITE_PRIVATE void sqlite3EndTable(
+ Parse *pParse, /* Parse context */
+ Token *pCons, /* The ',' token after the last column defn. */
+ Token *pEnd, /* The final ')' token in the CREATE TABLE */
+ Select *pSelect /* Select from a "CREATE ... AS SELECT" */
+){
+ Table *p;
+ sqlite3 *db = pParse->db;
+ int iDb;
+
+ if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
+ return;
+ }
+ p = pParse->pNewTable;
+ if( p==0 ) return;
+
+ assert( !db->init.busy || !pSelect );
+
+ iDb = sqlite3SchemaToIndex(db, p->pSchema);
+
+#ifndef SQLITE_OMIT_CHECK
+ /* Resolve names in all CHECK constraint expressions.
+ */
+ if( p->pCheck ){
+ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
+ NameContext sNC; /* Name context for pParse->pNewTable */
+ ExprList *pList; /* List of all CHECK constraints */
+ int i; /* Loop counter */
+
+ memset(&sNC, 0, sizeof(sNC));
+ memset(&sSrc, 0, sizeof(sSrc));
+ sSrc.nSrc = 1;
+ sSrc.a[0].zName = p->zName;
+ sSrc.a[0].pTab = p;
+ sSrc.a[0].iCursor = -1;
+ sNC.pParse = pParse;
+ sNC.pSrcList = &sSrc;
+ sNC.ncFlags = NC_IsCheck;
+ pList = p->pCheck;
+ for(i=0; i<pList->nExpr; i++){
+ if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+ return;
+ }
+ }
+ }
+#endif /* !defined(SQLITE_OMIT_CHECK) */
+
+ /* If the db->init.busy is 1 it means we are reading the SQL off the
+ ** "sqlite_master" or "sqlite_temp_master" table on the disk.
+ ** So do not write to the disk again. Extract the root page number
+ ** for the table from the db->init.newTnum field. (The page number
+ ** should have been put there by the sqliteOpenCb routine.)
+ */
+ if( db->init.busy ){
+ p->tnum = db->init.newTnum;
+ }
+
+ /* If not initializing, then create a record for the new table
+ ** in the SQLITE_MASTER table of the database.
+ **
+ ** If this is a TEMPORARY table, write the entry into the auxiliary
+ ** file instead of into the main database file.
+ */
+ if( !db->init.busy ){
+ int n;
+ Vdbe *v;
+ char *zType; /* "view" or "table" */
+ char *zType2; /* "VIEW" or "TABLE" */
+ char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */
+
+ v = sqlite3GetVdbe(pParse);
+ if( NEVER(v==0) ) return;
+
+ sqlite3VdbeAddOp1(v, OP_Close, 0);
+
+ /*
+ ** Initialize zType for the new view or table.
+ */
+ if( p->pSelect==0 ){
+ /* A regular table */
+ zType = "table";
+ zType2 = "TABLE";
+#ifndef SQLITE_OMIT_VIEW
+ }else{
+ /* A view */
+ zType = "view";
+ zType2 = "VIEW";
+#endif
+ }
+
+ /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
+ ** statement to populate the new table. The root-page number for the
+ ** new table is in register pParse->regRoot.
+ **
+ ** Once the SELECT has been coded by sqlite3Select(), it is in a
+ ** suitable state to query for the column names and types to be used
+ ** by the new table.
+ **
+ ** A shared-cache write-lock is not required to write to the new table,
+ ** as a schema-lock must have already been obtained to create it. Since
+ ** a schema-lock excludes all other database users, the write-lock would
+ ** be redundant.
+ */
+ if( pSelect ){
+ SelectDest dest;
+ Table *pSelTab;
+
+ assert(pParse->nTab==1);
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
+ sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
+ pParse->nTab = 2;
+ sqlite3SelectDestInit(&dest, SRT_Table, 1);
+ sqlite3Select(pParse, pSelect, &dest);
+ sqlite3VdbeAddOp1(v, OP_Close, 1);
+ if( pParse->nErr==0 ){
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
+ if( pSelTab==0 ) return;
+ assert( p->aCol==0 );
+ p->nCol = pSelTab->nCol;
+ p->aCol = pSelTab->aCol;
+ pSelTab->nCol = 0;
+ pSelTab->aCol = 0;
+ sqlite3DeleteTable(db, pSelTab);
+ }
+ }
+
+ /* Compute the complete text of the CREATE statement */
+ if( pSelect ){
+ zStmt = createTableStmt(db, p);
+ }else{
+ n = (int)(pEnd->z - pParse->sNameToken.z) + 1;
+ zStmt = sqlite3MPrintf(db,
+ "CREATE %s %.*s", zType2, n, pParse->sNameToken.z
+ );
+ }
+
+ /* A slot for the record has already been allocated in the
+ ** SQLITE_MASTER table. We just need to update that slot with all
+ ** the information we've collected.
+ */
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s "
+ "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
+ "WHERE rowid=#%d",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ zType,
+ p->zName,
+ p->zName,
+ pParse->regRoot,
+ zStmt,
+ pParse->regRowid
+ );
+ sqlite3DbFree(db, zStmt);
+ sqlite3ChangeCookie(pParse, iDb);
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* Check to see if we need to create an sqlite_sequence table for
+ ** keeping track of autoincrement keys.
+ */
+ if( p->tabFlags & TF_Autoincrement ){
+ Db *pDb = &db->aDb[iDb];
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ if( pDb->pSchema->pSeqTab==0 ){
+ sqlite3NestedParse(pParse,
+ "CREATE TABLE %Q.sqlite_sequence(name,seq)",
+ pDb->zName
+ );
+ }
+ }
+#endif
+
+ /* Reparse everything to update our internal data structures */
+ sqlite3VdbeAddParseSchemaOp(v, iDb,
+ sqlite3MPrintf(db, "tbl_name='%q'", p->zName));
+ }
+
+
+ /* Add the table to the in-memory representation of the database.
+ */
+ if( db->init.busy ){
+ Table *pOld;
+ Schema *pSchema = p->pSchema;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName,
+ sqlite3Strlen30(p->zName),p);
+ if( pOld ){
+ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
+ db->mallocFailed = 1;
+ return;
+ }
+ pParse->pNewTable = 0;
+ db->flags |= SQLITE_InternChanges;
+
+#ifndef SQLITE_OMIT_ALTERTABLE
+ if( !p->pSelect ){
+ const char *zName = (const char *)pParse->sNameToken.z;
+ int nName;
+ assert( !pSelect && pCons && pEnd );
+ if( pCons->z==0 ){
+ pCons = pEnd;
+ }
+ nName = (int)((const char *)pCons->z - zName);
+ p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
+ }
+#endif
+ }
+}
+
+#ifndef SQLITE_OMIT_VIEW
+/*
+** The parser calls this routine in order to create a new VIEW
+*/
+SQLITE_PRIVATE void sqlite3CreateView(
+ Parse *pParse, /* The parsing context */
+ Token *pBegin, /* The CREATE token that begins the statement */
+ Token *pName1, /* The token that holds the name of the view */
+ Token *pName2, /* The token that holds the name of the view */
+ Select *pSelect, /* A SELECT statement that will become the new view */
+ int isTemp, /* TRUE for a TEMPORARY view */
+ int noErr /* Suppress error messages if VIEW already exists */
+){
+ Table *p;
+ int n;
+ const char *z;
+ Token sEnd;
+ DbFixer sFix;
+ Token *pName = 0;
+ int iDb;
+ sqlite3 *db = pParse->db;
+
+ if( pParse->nVar>0 ){
+ sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
+ sqlite3SelectDelete(db, pSelect);
+ return;
+ }
+ sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
+ p = pParse->pNewTable;
+ if( p==0 || pParse->nErr ){
+ sqlite3SelectDelete(db, pSelect);
+ return;
+ }
+ sqlite3TwoPartName(pParse, pName1, pName2, &pName);
+ iDb = sqlite3SchemaToIndex(db, p->pSchema);
+ if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
+ && sqlite3FixSelect(&sFix, pSelect)
+ ){
+ sqlite3SelectDelete(db, pSelect);
+ return;
+ }
+
+ /* Make a copy of the entire SELECT statement that defines the view.
+ ** This will force all the Expr.token.z values to be dynamically
+ ** allocated rather than point to the input string - which means that
+ ** they will persist after the current sqlite3_exec() call returns.
+ */
+ p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ sqlite3SelectDelete(db, pSelect);
+ if( db->mallocFailed ){
+ return;
+ }
+ if( !db->init.busy ){
+ sqlite3ViewGetColumnNames(pParse, p);
+ }
+
+ /* Locate the end of the CREATE VIEW statement. Make sEnd point to
+ ** the end.
+ */
+ sEnd = pParse->sLastToken;
+ if( ALWAYS(sEnd.z[0]!=0) && sEnd.z[0]!=';' ){
+ sEnd.z += sEnd.n;
+ }
+ sEnd.n = 0;
+ n = (int)(sEnd.z - pBegin->z);
+ z = pBegin->z;
+ while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; }
+ sEnd.z = &z[n-1];
+ sEnd.n = 1;
+
+ /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
+ sqlite3EndTable(pParse, 0, &sEnd, 0);
+ return;
+}
+#endif /* SQLITE_OMIT_VIEW */
+
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
+/*
+** The Table structure pTable is really a VIEW. Fill in the names of
+** the columns of the view in the pTable structure. Return the number
+** of errors. If an error is seen leave an error message in pParse->zErrMsg.
+*/
+SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
+ Table *pSelTab; /* A fake table from which we get the result set */
+ Select *pSel; /* Copy of the SELECT that implements the view */
+ int nErr = 0; /* Number of errors encountered */
+ int n; /* Temporarily holds the number of cursors assigned */
+ sqlite3 *db = pParse->db; /* Database connection for malloc errors */
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
+
+ assert( pTable );
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( sqlite3VtabCallConnect(pParse, pTable) ){
+ return SQLITE_ERROR;
+ }
+ if( IsVirtual(pTable) ) return 0;
+#endif
+
+#ifndef SQLITE_OMIT_VIEW
+ /* A positive nCol means the columns names for this view are
+ ** already known.
+ */
+ if( pTable->nCol>0 ) return 0;
+
+ /* A negative nCol is a special marker meaning that we are currently
+ ** trying to compute the column names. If we enter this routine with
+ ** a negative nCol, it means two or more views form a loop, like this:
+ **
+ ** CREATE VIEW one AS SELECT * FROM two;
+ ** CREATE VIEW two AS SELECT * FROM one;
+ **
+ ** Actually, the error above is now caught prior to reaching this point.
+ ** But the following test is still important as it does come up
+ ** in the following:
+ **
+ ** CREATE TABLE main.ex1(a);
+ ** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
+ ** SELECT * FROM temp.ex1;
+ */
+ if( pTable->nCol<0 ){
+ sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
+ return 1;
+ }
+ assert( pTable->nCol>=0 );
+
+ /* If we get this far, it means we need to compute the table names.
+ ** Note that the call to sqlite3ResultSetOfSelect() will expand any
+ ** "*" elements in the results set of the view and will assign cursors
+ ** to the elements of the FROM clause. But we do not want these changes
+ ** to be permanent. So the computation is done on a copy of the SELECT
+ ** statement that defines the view.
+ */
+ assert( pTable->pSelect );
+ pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
+ if( pSel ){
+ u8 enableLookaside = db->lookaside.bEnabled;
+ n = pParse->nTab;
+ sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
+ pTable->nCol = -1;
+ db->lookaside.bEnabled = 0;
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ xAuth = db->xAuth;
+ db->xAuth = 0;
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
+ db->xAuth = xAuth;
+#else
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
+#endif
+ db->lookaside.bEnabled = enableLookaside;
+ pParse->nTab = n;
+ if( pSelTab ){
+ assert( pTable->aCol==0 );
+ pTable->nCol = pSelTab->nCol;
+ pTable->aCol = pSelTab->aCol;
+ pSelTab->nCol = 0;
+ pSelTab->aCol = 0;
+ sqlite3DeleteTable(db, pSelTab);
+ assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
+ pTable->pSchema->flags |= DB_UnresetViews;
+ }else{
+ pTable->nCol = 0;
+ nErr++;
+ }
+ sqlite3SelectDelete(db, pSel);
+ } else {
+ nErr++;
+ }
+#endif /* SQLITE_OMIT_VIEW */
+ return nErr;
+}
+#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
+
+#ifndef SQLITE_OMIT_VIEW
+/*
+** Clear the column names from every VIEW in database idx.
+*/
+static void sqliteViewResetAll(sqlite3 *db, int idx){
+ HashElem *i;
+ assert( sqlite3SchemaMutexHeld(db, idx, 0) );
+ if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
+ for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
+ Table *pTab = sqliteHashData(i);
+ if( pTab->pSelect ){
+ sqliteDeleteColumnNames(db, pTab);
+ pTab->aCol = 0;
+ pTab->nCol = 0;
+ }
+ }
+ DbClearProperty(db, idx, DB_UnresetViews);
+}
+#else
+# define sqliteViewResetAll(A,B)
+#endif /* SQLITE_OMIT_VIEW */
+
+/*
+** This function is called by the VDBE to adjust the internal schema
+** used by SQLite when the btree layer moves a table root page. The
+** root-page of a table or index in database iDb has changed from iFrom
+** to iTo.
+**
+** Ticket #1728: The symbol table might still contain information
+** on tables and/or indices that are the process of being deleted.
+** If you are unlucky, one of those deleted indices or tables might
+** have the same rootpage number as the real table or index that is
+** being moved. So we cannot stop searching after the first match
+** because the first match might be for one of the deleted indices
+** or tables and not the table/index that is actually being moved.
+** We must continue looping until all tables and indices with
+** rootpage==iFrom have been converted to have a rootpage of iTo
+** in order to be certain that we got the right one.
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
+ HashElem *pElem;
+ Hash *pHash;
+ Db *pDb;
+
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ pDb = &db->aDb[iDb];
+ pHash = &pDb->pSchema->tblHash;
+ for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
+ Table *pTab = sqliteHashData(pElem);
+ if( pTab->tnum==iFrom ){
+ pTab->tnum = iTo;
+ }
+ }
+ pHash = &pDb->pSchema->idxHash;
+ for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){
+ Index *pIdx = sqliteHashData(pElem);
+ if( pIdx->tnum==iFrom ){
+ pIdx->tnum = iTo;
+ }
+ }
+}
+#endif
+
+/*
+** Write code to erase the table with root-page iTable from database iDb.
+** Also write code to modify the sqlite_master table and internal schema
+** if a root-page of another table is moved by the btree-layer whilst
+** erasing iTable (this can happen with an auto-vacuum database).
+*/
+static void destroyRootPage(Parse *pParse, int iTable, int iDb){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
+ sqlite3MayAbort(pParse);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* OP_Destroy stores an in integer r1. If this integer
+ ** is non-zero, then it is the root page number of a table moved to
+ ** location iTable. The following code modifies the sqlite_master table to
+ ** reflect this.
+ **
+ ** The "#NNN" in the SQL is a special constant that means whatever value
+ ** is in register NNN. See grammar rules associated with the TK_REGISTER
+ ** token for additional information.
+ */
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
+ pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1);
+#endif
+ sqlite3ReleaseTempReg(pParse, r1);
+}
+
+/*
+** Write VDBE code to erase table pTab and all associated indices on disk.
+** Code to update the sqlite_master tables and internal schema definitions
+** in case a root-page belonging to another table is moved by the btree layer
+** is also added (this can happen with an auto-vacuum database).
+*/
+static void destroyTable(Parse *pParse, Table *pTab){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ Index *pIdx;
+ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ destroyRootPage(pParse, pTab->tnum, iDb);
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ destroyRootPage(pParse, pIdx->tnum, iDb);
+ }
+#else
+ /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
+ ** is not defined), then it is important to call OP_Destroy on the
+ ** table and index root-pages in order, starting with the numerically
+ ** largest root-page number. This guarantees that none of the root-pages
+ ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
+ ** following were coded:
+ **
+ ** OP_Destroy 4 0
+ ** ...
+ ** OP_Destroy 5 0
+ **
+ ** and root page 5 happened to be the largest root-page number in the
+ ** database, then root page 5 would be moved to page 4 by the
+ ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
+ ** a free-list page.
+ */
+ int iTab = pTab->tnum;
+ int iDestroyed = 0;
+
+ while( 1 ){
+ Index *pIdx;
+ int iLargest = 0;
+
+ if( iDestroyed==0 || iTab<iDestroyed ){
+ iLargest = iTab;
+ }
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int iIdx = pIdx->tnum;
+ assert( pIdx->pSchema==pTab->pSchema );
+ if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
+ iLargest = iIdx;
+ }
+ }
+ if( iLargest==0 ){
+ return;
+ }else{
+ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ assert( iDb>=0 && iDb<pParse->db->nDb );
+ destroyRootPage(pParse, iLargest, iDb);
+ iDestroyed = iLargest;
+ }
+ }
+#endif
+}
+
+/*
+** Remove entries from the sqlite_statN tables (for N in (1,2,3))
+** after a DROP INDEX or DROP TABLE command.
+*/
+static void sqlite3ClearStatTables(
+ Parse *pParse, /* The parsing context */
+ int iDb, /* The database number */
+ const char *zType, /* "idx" or "tbl" */
+ const char *zName /* Name of index or table */
+){
+ int i;
+ const char *zDbName = pParse->db->aDb[iDb].zName;
+ for(i=1; i<=3; i++){
+ char zTab[24];
+ sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
+ if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE %s=%Q",
+ zDbName, zTab, zType, zName
+ );
+ }
+ }
+}
+
+/*
+** Generate code to drop a table.
+*/
+SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
+ Vdbe *v;
+ sqlite3 *db = pParse->db;
+ Trigger *pTrigger;
+ Db *pDb = &db->aDb[iDb];
+
+ v = sqlite3GetVdbe(pParse);
+ assert( v!=0 );
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp0(v, OP_VBegin);
+ }
+#endif
+
+ /* Drop all triggers associated with the table being dropped. Code
+ ** is generated to remove entries from sqlite_master and/or
+ ** sqlite_temp_master if required.
+ */
+ pTrigger = sqlite3TriggerList(pParse, pTab);
+ while( pTrigger ){
+ assert( pTrigger->pSchema==pTab->pSchema ||
+ pTrigger->pSchema==db->aDb[1].pSchema );
+ sqlite3DropTriggerPtr(pParse, pTrigger);
+ pTrigger = pTrigger->pNext;
+ }
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* Remove any entries of the sqlite_sequence table associated with
+ ** the table being dropped. This is done before the table is dropped
+ ** at the btree level, in case the sqlite_sequence table needs to
+ ** move as a result of the drop (can happen in auto-vacuum mode).
+ */
+ if( pTab->tabFlags & TF_Autoincrement ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.sqlite_sequence WHERE name=%Q",
+ pDb->zName, pTab->zName
+ );
+ }
+#endif
+
+ /* Drop all SQLITE_MASTER table and index entries that refer to the
+ ** table. The program name loops through the master table and deletes
+ ** every row that refers to a table of the same name as the one being
+ ** dropped. Triggers are handled separately because a trigger can be
+ ** created in the temp database that refers to a table in another
+ ** database.
+ */
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
+ pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
+ if( !isView && !IsVirtual(pTab) ){
+ destroyTable(pParse, pTab);
+ }
+
+ /* Remove the table entry from SQLite's internal schema and modify
+ ** the schema cookie.
+ */
+ if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
+ }
+ sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
+ sqlite3ChangeCookie(pParse, iDb);
+ sqliteViewResetAll(db, iDb);
+}
+
+/*
+** This routine is called to do the work of a DROP TABLE statement.
+** pName is the name of the table to be dropped.
+*/
+SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
+ Table *pTab;
+ Vdbe *v;
+ sqlite3 *db = pParse->db;
+ int iDb;
+
+ if( db->mallocFailed ){
+ goto exit_drop_table;
+ }
+ assert( pParse->nErr==0 );
+ assert( pName->nSrc==1 );
+ if( noErr ) db->suppressErr++;
+ pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
+ if( noErr ) db->suppressErr--;
+
+ if( pTab==0 ){
+ if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ goto exit_drop_table;
+ }
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb>=0 && iDb<db->nDb );
+
+ /* If pTab is a virtual table, call ViewGetColumnNames() to ensure
+ ** it is initialized.
+ */
+ if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){
+ goto exit_drop_table;
+ }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ {
+ int code;
+ const char *zTab = SCHEMA_TABLE(iDb);
+ const char *zDb = db->aDb[iDb].zName;
+ const char *zArg2 = 0;
+ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
+ goto exit_drop_table;
+ }
+ if( isView ){
+ if( !OMIT_TEMPDB && iDb==1 ){
+ code = SQLITE_DROP_TEMP_VIEW;
+ }else{
+ code = SQLITE_DROP_VIEW;
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ }else if( IsVirtual(pTab) ){
+ code = SQLITE_DROP_VTABLE;
+ zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName;
+#endif
+ }else{
+ if( !OMIT_TEMPDB && iDb==1 ){
+ code = SQLITE_DROP_TEMP_TABLE;
+ }else{
+ code = SQLITE_DROP_TABLE;
+ }
+ }
+ if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){
+ goto exit_drop_table;
+ }
+ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
+ goto exit_drop_table;
+ }
+ }
+#endif
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
+ && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
+ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
+ goto exit_drop_table;
+ }
+
+#ifndef SQLITE_OMIT_VIEW
+ /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
+ ** on a table.
+ */
+ if( isView && pTab->pSelect==0 ){
+ sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
+ goto exit_drop_table;
+ }
+ if( !isView && pTab->pSelect ){
+ sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
+ goto exit_drop_table;
+ }
+#endif
+
+ /* Generate code to remove the table from the master table
+ ** on disk.
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+ sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
+ sqlite3FkDropTable(pParse, pName, pTab);
+ sqlite3CodeDropTable(pParse, pTab, iDb, isView);
+ }
+
+exit_drop_table:
+ sqlite3SrcListDelete(db, pName);
+}
+
+/*
+** This routine is called to create a new foreign key on the table
+** currently under construction. pFromCol determines which columns
+** in the current table point to the foreign key. If pFromCol==0 then
+** connect the key to the last column inserted. pTo is the name of
+** the table referred to. pToCol is a list of tables in the other
+** pTo table that the foreign key points to. flags contains all
+** information about the conflict resolution algorithms specified
+** in the ON DELETE, ON UPDATE and ON INSERT clauses.
+**
+** An FKey structure is created and added to the table currently
+** under construction in the pParse->pNewTable field.
+**
+** The foreign key is set for IMMEDIATE processing. A subsequent call
+** to sqlite3DeferForeignKey() might change this to DEFERRED.
+*/
+SQLITE_PRIVATE void sqlite3CreateForeignKey(
+ Parse *pParse, /* Parsing context */
+ ExprList *pFromCol, /* Columns in this table that point to other table */
+ Token *pTo, /* Name of the other table */
+ ExprList *pToCol, /* Columns in the other table */
+ int flags /* Conflict resolution algorithms. */
+){
+ sqlite3 *db = pParse->db;
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ FKey *pFKey = 0;
+ FKey *pNextTo;
+ Table *p = pParse->pNewTable;
+ int nByte;
+ int i;
+ int nCol;
+ char *z;
+
+ assert( pTo!=0 );
+ if( p==0 || IN_DECLARE_VTAB ) goto fk_end;
+ if( pFromCol==0 ){
+ int iCol = p->nCol-1;
+ if( NEVER(iCol<0) ) goto fk_end;
+ if( pToCol && pToCol->nExpr!=1 ){
+ sqlite3ErrorMsg(pParse, "foreign key on %s"
+ " should reference only one column of table %T",
+ p->aCol[iCol].zName, pTo);
+ goto fk_end;
+ }
+ nCol = 1;
+ }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){
+ sqlite3ErrorMsg(pParse,
+ "number of columns in foreign key does not match the number of "
+ "columns in the referenced table");
+ goto fk_end;
+ }else{
+ nCol = pFromCol->nExpr;
+ }
+ nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
+ if( pToCol ){
+ for(i=0; i<pToCol->nExpr; i++){
+ nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
+ }
+ }
+ pFKey = sqlite3DbMallocZero(db, nByte );
+ if( pFKey==0 ){
+ goto fk_end;
+ }
+ pFKey->pFrom = p;
+ pFKey->pNextFrom = p->pFKey;
+ z = (char*)&pFKey->aCol[nCol];
+ pFKey->zTo = z;
+ memcpy(z, pTo->z, pTo->n);
+ z[pTo->n] = 0;
+ sqlite3Dequote(z);
+ z += pTo->n+1;
+ pFKey->nCol = nCol;
+ if( pFromCol==0 ){
+ pFKey->aCol[0].iFrom = p->nCol-1;
+ }else{
+ for(i=0; i<nCol; i++){
+ int j;
+ for(j=0; j<p->nCol; j++){
+ if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
+ pFKey->aCol[i].iFrom = j;
+ break;
+ }
+ }
+ if( j>=p->nCol ){
+ sqlite3ErrorMsg(pParse,
+ "unknown column \"%s\" in foreign key definition",
+ pFromCol->a[i].zName);
+ goto fk_end;
+ }
+ }
+ }
+ if( pToCol ){
+ for(i=0; i<nCol; i++){
+ int n = sqlite3Strlen30(pToCol->a[i].zName);
+ pFKey->aCol[i].zCol = z;
+ memcpy(z, pToCol->a[i].zName, n);
+ z[n] = 0;
+ z += n+1;
+ }
+ }
+ pFKey->isDeferred = 0;
+ pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */
+ pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */
+
+ assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
+ pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
+ pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey
+ );
+ if( pNextTo==pFKey ){
+ db->mallocFailed = 1;
+ goto fk_end;
+ }
+ if( pNextTo ){
+ assert( pNextTo->pPrevTo==0 );
+ pFKey->pNextTo = pNextTo;
+ pNextTo->pPrevTo = pFKey;
+ }
+
+ /* Link the foreign key to the table as the last step.
+ */
+ p->pFKey = pFKey;
+ pFKey = 0;
+
+fk_end:
+ sqlite3DbFree(db, pFKey);
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
+ sqlite3ExprListDelete(db, pFromCol);
+ sqlite3ExprListDelete(db, pToCol);
+}
+
+/*
+** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
+** clause is seen as part of a foreign key definition. The isDeferred
+** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
+** The behavior of the most recently created foreign key is adjusted
+** accordingly.
+*/
+SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ Table *pTab;
+ FKey *pFKey;
+ if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
+ assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
+ pFKey->isDeferred = (u8)isDeferred;
+#endif
+}
+
+/*
+** Generate code that will erase and refill index *pIdx. This is
+** used to initialize a newly created index or to recompute the
+** content of an index in response to a REINDEX command.
+**
+** if memRootPage is not negative, it means that the index is newly
+** created. The register specified by memRootPage contains the
+** root page number of the index. If memRootPage is negative, then
+** the index already exists and must be cleared before being refilled and
+** the root page number of the index is taken from pIndex->tnum.
+*/
+static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
+ Table *pTab = pIndex->pTable; /* The table that is indexed */
+ int iTab = pParse->nTab++; /* Btree cursor used for pTab */
+ int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
+ int iSorter; /* Cursor opened by OpenSorter (if in use) */
+ int addr1; /* Address of top of loop */
+ int addr2; /* Address to jump to for next iteration */
+ int tnum; /* Root page of index */
+ Vdbe *v; /* Generate code into this virtual machine */
+ KeyInfo *pKey; /* KeyInfo for index */
+ int regRecord; /* Register holding assemblied index record */
+ sqlite3 *db = pParse->db; /* The database connection */
+ int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
+ db->aDb[iDb].zName ) ){
+ return;
+ }
+#endif
+
+ /* Require a write-lock on the table to perform this operation */
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
+
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) return;
+ if( memRootPage>=0 ){
+ tnum = memRootPage;
+ }else{
+ tnum = pIndex->tnum;
+ sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
+ }
+ pKey = sqlite3IndexKeyinfo(pParse, pIndex);
+ sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
+ (char *)pKey, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
+
+ /* Open the sorter cursor if we are to use one. */
+ iSorter = pParse->nTab++;
+ sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
+
+ /* Open the table. Loop through all rows of the table, inserting index
+ ** records into the sorter. */
+ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
+ regRecord = sqlite3GetTempReg(pParse);
+
+ sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
+ sqlite3VdbeJumpHere(v, addr1);
+ addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
+ if( pIndex->onError!=OE_None ){
+ int j2 = sqlite3VdbeCurrentAddr(v) + 3;
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
+ addr2 = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+ OE_Abort, "indexed columns are not unique", P4_STATIC
+ );
+ }else{
+ addr2 = sqlite3VdbeCurrentAddr(v);
+ }
+ sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ sqlite3ReleaseTempReg(pParse, regRecord);
+ sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
+ sqlite3VdbeJumpHere(v, addr1);
+
+ sqlite3VdbeAddOp1(v, OP_Close, iTab);
+ sqlite3VdbeAddOp1(v, OP_Close, iIdx);
+ sqlite3VdbeAddOp1(v, OP_Close, iSorter);
+}
+
+/*
+** Create a new index for an SQL table. pName1.pName2 is the name of the index
+** and pTblList is the name of the table that is to be indexed. Both will
+** be NULL for a primary key or an index that is created to satisfy a
+** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
+** as the table to be indexed. pParse->pNewTable is a table that is
+** currently being constructed by a CREATE TABLE statement.
+**
+** pList is a list of columns to be indexed. pList will be NULL if this
+** is a primary key or unique-constraint on the most recent column added
+** to the table currently under construction.
+**
+** If the index is created successfully, return a pointer to the new Index
+** structure. This is used by sqlite3AddPrimaryKey() to mark the index
+** as the tables primary key (Index.autoIndex==2).
+*/
+SQLITE_PRIVATE Index *sqlite3CreateIndex(
+ Parse *pParse, /* All information about this parse */
+ Token *pName1, /* First part of index name. May be NULL */
+ Token *pName2, /* Second part of index name. May be NULL */
+ SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */
+ ExprList *pList, /* A list of columns to be indexed */
+ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
+ Token *pStart, /* The CREATE token that begins this statement */
+ Token *pEnd, /* The ")" that closes the CREATE INDEX statement */
+ int sortOrder, /* Sort order of primary key when pList==NULL */
+ int ifNotExist /* Omit error if index already exists */
+){
+ Index *pRet = 0; /* Pointer to return */
+ Table *pTab = 0; /* Table to be indexed */
+ Index *pIndex = 0; /* The index to be created */
+ char *zName = 0; /* Name of the index */
+ int nName; /* Number of characters in zName */
+ int i, j;
+ Token nullId; /* Fake token for an empty ID list */
+ DbFixer sFix; /* For assigning database names to pTable */
+ int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */
+ sqlite3 *db = pParse->db;
+ Db *pDb; /* The specific table containing the indexed database */
+ int iDb; /* Index of the database that is being written */
+ Token *pName = 0; /* Unqualified name of the index to create */
+ struct ExprList_item *pListItem; /* For looping over pList */
+ int nCol;
+ int nExtra = 0;
+ char *zExtra;
+
+ assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */
+ assert( pParse->nErr==0 ); /* Never called with prior errors */
+ if( db->mallocFailed || IN_DECLARE_VTAB ){
+ goto exit_create_index;
+ }
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ goto exit_create_index;
+ }
+
+ /*
+ ** Find the table that is to be indexed. Return early if not found.
+ */
+ if( pTblName!=0 ){
+
+ /* Use the two-part index name to determine the database
+ ** to search for the table. 'Fix' the table name to this db
+ ** before looking up the table.
+ */
+ assert( pName1 && pName2 );
+ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
+ if( iDb<0 ) goto exit_create_index;
+ assert( pName && pName->z );
+
+#ifndef SQLITE_OMIT_TEMPDB
+ /* If the index name was unqualified, check if the table
+ ** is a temp table. If so, set the database to 1. Do not do this
+ ** if initialising a database schema.
+ */
+ if( !db->init.busy ){
+ pTab = sqlite3SrcListLookup(pParse, pTblName);
+ if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
+ iDb = 1;
+ }
+ }
+#endif
+
+ if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
+ sqlite3FixSrcList(&sFix, pTblName)
+ ){
+ /* Because the parser constructs pTblName from a single identifier,
+ ** sqlite3FixSrcList can never fail. */
+ assert(0);
+ }
+ pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
+ assert( db->mallocFailed==0 || pTab==0 );
+ if( pTab==0 ) goto exit_create_index;
+ assert( db->aDb[iDb].pSchema==pTab->pSchema );
+ }else{
+ assert( pName==0 );
+ assert( pStart==0 );
+ pTab = pParse->pNewTable;
+ if( !pTab ) goto exit_create_index;
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ }
+ pDb = &db->aDb[iDb];
+
+ assert( pTab!=0 );
+ assert( pParse->nErr==0 );
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
+ && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
+ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
+ goto exit_create_index;
+ }
+#ifndef SQLITE_OMIT_VIEW
+ if( pTab->pSelect ){
+ sqlite3ErrorMsg(pParse, "views may not be indexed");
+ goto exit_create_index;
+ }
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be indexed");
+ goto exit_create_index;
+ }
+#endif
+
+ /*
+ ** Find the name of the index. Make sure there is not already another
+ ** index or table with the same name.
+ **
+ ** Exception: If we are reading the names of permanent indices from the
+ ** sqlite_master table (because some other process changed the schema) and
+ ** one of the index names collides with the name of a temporary table or
+ ** index, then we will continue to process this index.
+ **
+ ** If pName==0 it means that we are
+ ** dealing with a primary key or UNIQUE constraint. We have to invent our
+ ** own name.
+ */
+ if( pName ){
+ zName = sqlite3NameFromToken(db, pName);
+ if( zName==0 ) goto exit_create_index;
+ assert( pName->z!=0 );
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+ goto exit_create_index;
+ }
+ if( !db->init.busy ){
+ if( sqlite3FindTable(db, zName, 0)!=0 ){
+ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
+ goto exit_create_index;
+ }
+ }
+ if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){
+ if( !ifNotExist ){
+ sqlite3ErrorMsg(pParse, "index %s already exists", zName);
+ }else{
+ assert( !db->init.busy );
+ sqlite3CodeVerifySchema(pParse, iDb);
+ }
+ goto exit_create_index;
+ }
+ }else{
+ int n;
+ Index *pLoop;
+ for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
+ zName = sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName, n);
+ if( zName==0 ){
+ goto exit_create_index;
+ }
+ }
+
+ /* Check for authorization to create an index.
+ */
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ {
+ const char *zDb = pDb->zName;
+ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
+ goto exit_create_index;
+ }
+ i = SQLITE_CREATE_INDEX;
+ if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX;
+ if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){
+ goto exit_create_index;
+ }
+ }
+#endif
+
+ /* If pList==0, it means this routine was called to make a primary
+ ** key out of the last column added to the table under construction.
+ ** So create a fake list to simulate this.
+ */
+ if( pList==0 ){
+ nullId.z = pTab->aCol[pTab->nCol-1].zName;
+ nullId.n = sqlite3Strlen30((char*)nullId.z);
+ pList = sqlite3ExprListAppend(pParse, 0, 0);
+ if( pList==0 ) goto exit_create_index;
+ sqlite3ExprListSetName(pParse, pList, &nullId, 0);
+ pList->a[0].sortOrder = (u8)sortOrder;
+ }
+
+ /* Figure out how many bytes of space are required to store explicitly
+ ** specified collation sequence names.
+ */
+ for(i=0; i<pList->nExpr; i++){
+ Expr *pExpr = pList->a[i].pExpr;
+ if( pExpr ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
+ if( pColl ){
+ nExtra += (1 + sqlite3Strlen30(pColl->zName));
+ }
+ }
+ }
+
+ /*
+ ** Allocate the index structure.
+ */
+ nName = sqlite3Strlen30(zName);
+ nCol = pList->nExpr;
+ pIndex = sqlite3DbMallocZero(db,
+ ROUND8(sizeof(Index)) + /* Index structure */
+ ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */
+ sizeof(char *)*nCol + /* Index.azColl */
+ sizeof(int)*nCol + /* Index.aiColumn */
+ sizeof(u8)*nCol + /* Index.aSortOrder */
+ nName + 1 + /* Index.zName */
+ nExtra /* Collation sequence names */
+ );
+ if( db->mallocFailed ){
+ goto exit_create_index;
+ }
+ zExtra = (char*)pIndex;
+ pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))];
+ pIndex->azColl = (char**)
+ ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1));
+ assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
+ assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
+ pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
+ pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]);
+ pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
+ zExtra = (char *)(&pIndex->zName[nName+1]);
+ memcpy(pIndex->zName, zName, nName+1);
+ pIndex->pTable = pTab;
+ pIndex->nColumn = pList->nExpr;
+ pIndex->onError = (u8)onError;
+ pIndex->autoIndex = (u8)(pName==0);
+ pIndex->pSchema = db->aDb[iDb].pSchema;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+
+ /* Check to see if we should honor DESC requests on index columns
+ */
+ if( pDb->pSchema->file_format>=4 ){
+ sortOrderMask = -1; /* Honor DESC */
+ }else{
+ sortOrderMask = 0; /* Ignore DESC */
+ }
+
+ /* Scan the names of the columns of the table to be indexed and
+ ** load the column indices into the Index structure. Report an error
+ ** if any column is not found.
+ **
+ ** TODO: Add a test to make sure that the same column is not named
+ ** more than once within the same index. Only the first instance of
+ ** the column will ever be used by the optimizer. Note that using the
+ ** same column more than once cannot be an error because that would
+ ** break backwards compatibility - it needs to be a warning.
+ */
+ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
+ const char *zColName = pListItem->zName;
+ Column *pTabCol;
+ int requestedSortOrder;
+ CollSeq *pColl; /* Collating sequence */
+ char *zColl; /* Collation sequence name */
+
+ for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
+ if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
+ }
+ if( j>=pTab->nCol ){
+ sqlite3ErrorMsg(pParse, "table %s has no column named %s",
+ pTab->zName, zColName);
+ pParse->checkSchema = 1;
+ goto exit_create_index;
+ }
+ pIndex->aiColumn[i] = j;
+ if( pListItem->pExpr
+ && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
+ ){
+ int nColl;
+ zColl = pColl->zName;
+ nColl = sqlite3Strlen30(zColl) + 1;
+ assert( nExtra>=nColl );
+ memcpy(zExtra, zColl, nColl);
+ zColl = zExtra;
+ zExtra += nColl;
+ nExtra -= nColl;
+ }else{
+ zColl = pTab->aCol[j].zColl;
+ if( !zColl ){
+ zColl = "BINARY";
+ }
+ }
+ if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
+ goto exit_create_index;
+ }
+ pIndex->azColl[i] = zColl;
+ requestedSortOrder = pListItem->sortOrder & sortOrderMask;
+ pIndex->aSortOrder[i] = (u8)requestedSortOrder;
+ }
+ sqlite3DefaultRowEst(pIndex);
+
+ if( pTab==pParse->pNewTable ){
+ /* This routine has been called to create an automatic index as a
+ ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
+ ** a PRIMARY KEY or UNIQUE clause following the column definitions.
+ ** i.e. one of:
+ **
+ ** CREATE TABLE t(x PRIMARY KEY, y);
+ ** CREATE TABLE t(x, y, UNIQUE(x, y));
+ **
+ ** Either way, check to see if the table already has such an index. If
+ ** so, don't bother creating this one. This only applies to
+ ** automatically created indices. Users can do as they wish with
+ ** explicit indices.
+ **
+ ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent
+ ** (and thus suppressing the second one) even if they have different
+ ** sort orders.
+ **
+ ** If there are different collating sequences or if the columns of
+ ** the constraint occur in different orders, then the constraints are
+ ** considered distinct and both result in separate indices.
+ */
+ Index *pIdx;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int k;
+ assert( pIdx->onError!=OE_None );
+ assert( pIdx->autoIndex );
+ assert( pIndex->onError!=OE_None );
+
+ if( pIdx->nColumn!=pIndex->nColumn ) continue;
+ for(k=0; k<pIdx->nColumn; k++){
+ const char *z1;
+ const char *z2;
+ if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
+ z1 = pIdx->azColl[k];
+ z2 = pIndex->azColl[k];
+ if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break;
+ }
+ if( k==pIdx->nColumn ){
+ if( pIdx->onError!=pIndex->onError ){
+ /* This constraint creates the same index as a previous
+ ** constraint specified somewhere in the CREATE TABLE statement.
+ ** However the ON CONFLICT clauses are different. If both this
+ ** constraint and the previous equivalent constraint have explicit
+ ** ON CONFLICT clauses this is an error. Otherwise, use the
+ ** explicitly specified behavior for the index.
+ */
+ if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
+ sqlite3ErrorMsg(pParse,
+ "conflicting ON CONFLICT clauses specified", 0);
+ }
+ if( pIdx->onError==OE_Default ){
+ pIdx->onError = pIndex->onError;
+ }
+ }
+ goto exit_create_index;
+ }
+ }
+ }
+
+ /* Link the new Index structure to its table and to the other
+ ** in-memory database structures.
+ */
+ if( db->init.busy ){
+ Index *p;
+ assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
+ p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
+ pIndex->zName, sqlite3Strlen30(pIndex->zName),
+ pIndex);
+ if( p ){
+ assert( p==pIndex ); /* Malloc must have failed */
+ db->mallocFailed = 1;
+ goto exit_create_index;
+ }
+ db->flags |= SQLITE_InternChanges;
+ if( pTblName!=0 ){
+ pIndex->tnum = db->init.newTnum;
+ }
+ }
+
+ /* If the db->init.busy is 0 then create the index on disk. This
+ ** involves writing the index into the master table and filling in the
+ ** index with the current table contents.
+ **
+ ** The db->init.busy is 0 when the user first enters a CREATE INDEX
+ ** command. db->init.busy is 1 when a database is opened and
+ ** CREATE INDEX statements are read out of the master table. In
+ ** the latter case the index already exists on disk, which is why
+ ** we don't want to recreate it.
+ **
+ ** If pTblName==0 it means this index is generated as a primary key
+ ** or UNIQUE constraint of a CREATE TABLE statement. Since the table
+ ** has just been created, it contains no data and the index initialization
+ ** step can be skipped.
+ */
+ else{ /* if( db->init.busy==0 ) */
+ Vdbe *v;
+ char *zStmt;
+ int iMem = ++pParse->nMem;
+
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto exit_create_index;
+
+
+ /* Create the rootpage for the index
+ */
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+ sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);
+
+ /* Gather the complete text of the CREATE INDEX statement into
+ ** the zStmt variable
+ */
+ if( pStart ){
+ assert( pEnd!=0 );
+ /* A named index with an explicit CREATE INDEX statement */
+ zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
+ onError==OE_None ? "" : " UNIQUE",
+ (int)(pEnd->z - pName->z) + 1,
+ pName->z);
+ }else{
+ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
+ /* zStmt = sqlite3MPrintf(""); */
+ zStmt = 0;
+ }
+
+ /* Add an entry in sqlite_master for this index
+ */
+ sqlite3NestedParse(pParse,
+ "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ pIndex->zName,
+ pTab->zName,
+ iMem,
+ zStmt
+ );
+ sqlite3DbFree(db, zStmt);
+
+ /* Fill the index with data and reparse the schema. Code an OP_Expire
+ ** to invalidate all pre-compiled statements.
+ */
+ if( pTblName ){
+ sqlite3RefillIndex(pParse, pIndex, iMem);
+ sqlite3ChangeCookie(pParse, iDb);
+ sqlite3VdbeAddParseSchemaOp(v, iDb,
+ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
+ sqlite3VdbeAddOp1(v, OP_Expire, 0);
+ }
+ }
+
+ /* When adding an index to the list of indices for a table, make
+ ** sure all indices labeled OE_Replace come after all those labeled
+ ** OE_Ignore. This is necessary for the correct constraint check
+ ** processing (in sqlite3GenerateConstraintChecks()) as part of
+ ** UPDATE and INSERT statements.
+ */
+ if( db->init.busy || pTblName==0 ){
+ if( onError!=OE_Replace || pTab->pIndex==0
+ || pTab->pIndex->onError==OE_Replace){
+ pIndex->pNext = pTab->pIndex;
+ pTab->pIndex = pIndex;
+ }else{
+ Index *pOther = pTab->pIndex;
+ while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
+ pOther = pOther->pNext;
+ }
+ pIndex->pNext = pOther->pNext;
+ pOther->pNext = pIndex;
+ }
+ pRet = pIndex;
+ pIndex = 0;
+ }
+
+ /* Clean up before exiting */
+exit_create_index:
+ if( pIndex ){
+ sqlite3DbFree(db, pIndex->zColAff);
+ sqlite3DbFree(db, pIndex);
+ }
+ sqlite3ExprListDelete(db, pList);
+ sqlite3SrcListDelete(db, pTblName);
+ sqlite3DbFree(db, zName);
+ return pRet;
+}
+
+/*
+** Fill the Index.aiRowEst[] array with default information - information
+** to be used when we have not run the ANALYZE command.
+**
+** aiRowEst[0] is suppose to contain the number of elements in the index.
+** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
+** number of rows in the table that match any particular value of the
+** first column of the index. aiRowEst[2] is an estimate of the number
+** of rows that match any particular combiniation of the first 2 columns
+** of the index. And so forth. It must always be the case that
+*
+** aiRowEst[N]<=aiRowEst[N-1]
+** aiRowEst[N]>=1
+**
+** Apart from that, we have little to go on besides intuition as to
+** how aiRowEst[] should be initialized. The numbers generated here
+** are based on typical values found in actual indices.
+*/
+SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
+ tRowcnt *a = pIdx->aiRowEst;
+ int i;
+ tRowcnt n;
+ assert( a!=0 );
+ a[0] = pIdx->pTable->nRowEst;
+ if( a[0]<10 ) a[0] = 10;
+ n = 10;
+ for(i=1; i<=pIdx->nColumn; i++){
+ a[i] = n;
+ if( n>5 ) n--;
+ }
+ if( pIdx->onError!=OE_None ){
+ a[pIdx->nColumn] = 1;
+ }
+}
+
+/*
+** This routine will drop an existing named index. This routine
+** implements the DROP INDEX statement.
+*/
+SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
+ Index *pIndex;
+ Vdbe *v;
+ sqlite3 *db = pParse->db;
+ int iDb;
+
+ assert( pParse->nErr==0 ); /* Never called with prior errors */
+ if( db->mallocFailed ){
+ goto exit_drop_index;
+ }
+ assert( pName->nSrc==1 );
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ goto exit_drop_index;
+ }
+ pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
+ if( pIndex==0 ){
+ if( !ifExists ){
+ sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
+ }else{
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ }
+ pParse->checkSchema = 1;
+ goto exit_drop_index;
+ }
+ if( pIndex->autoIndex ){
+ sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
+ "or PRIMARY KEY constraint cannot be dropped", 0);
+ goto exit_drop_index;
+ }
+ iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ {
+ int code = SQLITE_DROP_INDEX;
+ Table *pTab = pIndex->pTable;
+ const char *zDb = db->aDb[iDb].zName;
+ const char *zTab = SCHEMA_TABLE(iDb);
+ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
+ goto exit_drop_index;
+ }
+ if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX;
+ if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
+ goto exit_drop_index;
+ }
+ }
+#endif
+
+ /* Generate code to remove the index and from the master table */
+ v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName
+ );
+ sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
+ sqlite3ChangeCookie(pParse, iDb);
+ destroyRootPage(pParse, pIndex->tnum, iDb);
+ sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
+ }
+
+exit_drop_index:
+ sqlite3SrcListDelete(db, pName);
+}
+
+/*
+** pArray is a pointer to an array of objects. Each object in the
+** array is szEntry bytes in size. This routine uses sqlite3DbRealloc()
+** to extend the array so that there is space for a new object at the end.
+**
+** When this function is called, *pnEntry contains the current size of
+** the array (in entries - so the allocation is ((*pnEntry) * szEntry) bytes
+** in total).
+**
+** If the realloc() is successful (i.e. if no OOM condition occurs), the
+** space allocated for the new object is zeroed, *pnEntry updated to
+** reflect the new size of the array and a pointer to the new allocation
+** returned. *pIdx is set to the index of the new array entry in this case.
+**
+** Otherwise, if the realloc() fails, *pIdx is set to -1, *pnEntry remains
+** unchanged and a copy of pArray returned.
+*/
+SQLITE_PRIVATE void *sqlite3ArrayAllocate(
+ sqlite3 *db, /* Connection to notify of malloc failures */
+ void *pArray, /* Array of objects. Might be reallocated */
+ int szEntry, /* Size of each object in the array */
+ int *pnEntry, /* Number of objects currently in use */
+ int *pIdx /* Write the index of a new slot here */
+){
+ char *z;
+ int n = *pnEntry;
+ if( (n & (n-1))==0 ){
+ int sz = (n==0) ? 1 : 2*n;
+ void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry);
+ if( pNew==0 ){
+ *pIdx = -1;
+ return pArray;
+ }
+ pArray = pNew;
+ }
+ z = (char*)pArray;
+ memset(&z[n * szEntry], 0, szEntry);
+ *pIdx = n;
+ ++*pnEntry;
+ return pArray;
+}
+
+/*
+** Append a new element to the given IdList. Create a new IdList if
+** need be.
+**
+** A new IdList is returned, or NULL if malloc() fails.
+*/
+SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){
+ int i;
+ if( pList==0 ){
+ pList = sqlite3DbMallocZero(db, sizeof(IdList) );
+ if( pList==0 ) return 0;
+ }
+ pList->a = sqlite3ArrayAllocate(
+ db,
+ pList->a,
+ sizeof(pList->a[0]),
+ &pList->nId,
+ &i
+ );
+ if( i<0 ){
+ sqlite3IdListDelete(db, pList);
+ return 0;
+ }
+ pList->a[i].zName = sqlite3NameFromToken(db, pToken);
+ return pList;
+}
+
+/*
+** Delete an IdList.
+*/
+SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
+ int i;
+ if( pList==0 ) return;
+ for(i=0; i<pList->nId; i++){
+ sqlite3DbFree(db, pList->a[i].zName);
+ }
+ sqlite3DbFree(db, pList->a);
+ sqlite3DbFree(db, pList);
+}
+
+/*
+** Return the index in pList of the identifier named zId. Return -1
+** if not found.
+*/
+SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){
+ int i;
+ if( pList==0 ) return -1;
+ for(i=0; i<pList->nId; i++){
+ if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
+ }
+ return -1;
+}
+
+/*
+** Expand the space allocated for the given SrcList object by
+** creating nExtra new slots beginning at iStart. iStart is zero based.
+** New slots are zeroed.
+**
+** For example, suppose a SrcList initially contains two entries: A,B.
+** To append 3 new entries onto the end, do this:
+**
+** sqlite3SrcListEnlarge(db, pSrclist, 3, 2);
+**
+** After the call above it would contain: A, B, nil, nil, nil.
+** If the iStart argument had been 1 instead of 2, then the result
+** would have been: A, nil, nil, nil, B. To prepend the new slots,
+** the iStart value would be 0. The result then would
+** be: nil, nil, nil, A, B.
+**
+** If a memory allocation fails the SrcList is unchanged. The
+** db->mallocFailed flag will be set to true.
+*/
+SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
+ sqlite3 *db, /* Database connection to notify of OOM errors */
+ SrcList *pSrc, /* The SrcList to be enlarged */
+ int nExtra, /* Number of new slots to add to pSrc->a[] */
+ int iStart /* Index in pSrc->a[] of first new slot */
+){
+ int i;
+
+ /* Sanity checking on calling parameters */
+ assert( iStart>=0 );
+ assert( nExtra>=1 );
+ assert( pSrc!=0 );
+ assert( iStart<=pSrc->nSrc );
+
+ /* Allocate additional space if needed */
+ if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
+ SrcList *pNew;
+ int nAlloc = pSrc->nSrc+nExtra;
+ int nGot;
+ pNew = sqlite3DbRealloc(db, pSrc,
+ sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
+ if( pNew==0 ){
+ assert( db->mallocFailed );
+ return pSrc;
+ }
+ pSrc = pNew;
+ nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
+ pSrc->nAlloc = (u16)nGot;
+ }
+
+ /* Move existing slots that come after the newly inserted slots
+ ** out of the way */
+ for(i=pSrc->nSrc-1; i>=iStart; i--){
+ pSrc->a[i+nExtra] = pSrc->a[i];
+ }
+ pSrc->nSrc += (i16)nExtra;
+
+ /* Zero the newly allocated slots */
+ memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
+ for(i=iStart; i<iStart+nExtra; i++){
+ pSrc->a[i].iCursor = -1;
+ }
+
+ /* Return a pointer to the enlarged SrcList */
+ return pSrc;
+}
+
+
+/*
+** Append a new table name to the given SrcList. Create a new SrcList if
+** need be. A new entry is created in the SrcList even if pTable is NULL.
+**
+** A SrcList is returned, or NULL if there is an OOM error. The returned
+** SrcList might be the same as the SrcList that was input or it might be
+** a new one. If an OOM error does occurs, then the prior value of pList
+** that is input to this routine is automatically freed.
+**
+** If pDatabase is not null, it means that the table has an optional
+** database name prefix. Like this: "database.table". The pDatabase
+** points to the table name and the pTable points to the database name.
+** The SrcList.a[].zName field is filled with the table name which might
+** come from pTable (if pDatabase is NULL) or from pDatabase.
+** SrcList.a[].zDatabase is filled with the database name from pTable,
+** or with NULL if no database is specified.
+**
+** In other words, if call like this:
+**
+** sqlite3SrcListAppend(D,A,B,0);
+**
+** Then B is a table name and the database name is unspecified. If called
+** like this:
+**
+** sqlite3SrcListAppend(D,A,B,C);
+**
+** Then C is the table name and B is the database name. If C is defined
+** then so is B. In other words, we never have a case where:
+**
+** sqlite3SrcListAppend(D,A,0,C);
+**
+** Both pTable and pDatabase are assumed to be quoted. They are dequoted
+** before being added to the SrcList.
+*/
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
+ sqlite3 *db, /* Connection to notify of malloc failures */
+ SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */
+ Token *pTable, /* Table to append */
+ Token *pDatabase /* Database of the table */
+){
+ struct SrcList_item *pItem;
+ assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
+ if( pList==0 ){
+ pList = sqlite3DbMallocZero(db, sizeof(SrcList) );
+ if( pList==0 ) return 0;
+ pList->nAlloc = 1;
+ }
+ pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
+ if( db->mallocFailed ){
+ sqlite3SrcListDelete(db, pList);
+ return 0;
+ }
+ pItem = &pList->a[pList->nSrc-1];
+ if( pDatabase && pDatabase->z==0 ){
+ pDatabase = 0;
+ }
+ if( pDatabase ){
+ Token *pTemp = pDatabase;
+ pDatabase = pTable;
+ pTable = pTemp;
+ }
+ pItem->zName = sqlite3NameFromToken(db, pTable);
+ pItem->zDatabase = sqlite3NameFromToken(db, pDatabase);
+ return pList;
+}
+
+/*
+** Assign VdbeCursor index numbers to all tables in a SrcList
+*/
+SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
+ int i;
+ struct SrcList_item *pItem;
+ assert(pList || pParse->db->mallocFailed );
+ if( pList ){
+ for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+ if( pItem->iCursor>=0 ) break;
+ pItem->iCursor = pParse->nTab++;
+ if( pItem->pSelect ){
+ sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
+ }
+ }
+ }
+}
+
+/*
+** Delete an entire SrcList including all its substructure.
+*/
+SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
+ int i;
+ struct SrcList_item *pItem;
+ if( pList==0 ) return;
+ for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
+ sqlite3DbFree(db, pItem->zDatabase);
+ sqlite3DbFree(db, pItem->zName);
+ sqlite3DbFree(db, pItem->zAlias);
+ sqlite3DbFree(db, pItem->zIndex);
+ sqlite3DeleteTable(db, pItem->pTab);
+ sqlite3SelectDelete(db, pItem->pSelect);
+ sqlite3ExprDelete(db, pItem->pOn);
+ sqlite3IdListDelete(db, pItem->pUsing);
+ }
+ sqlite3DbFree(db, pList);
+}
+
+/*
+** This routine is called by the parser to add a new term to the
+** end of a growing FROM clause. The "p" parameter is the part of
+** the FROM clause that has already been constructed. "p" is NULL
+** if this is the first term of the FROM clause. pTable and pDatabase
+** are the name of the table and database named in the FROM clause term.
+** pDatabase is NULL if the database name qualifier is missing - the
+** usual case. If the term has a alias, then pAlias points to the
+** alias token. If the term is a subquery, then pSubquery is the
+** SELECT statement that the subquery encodes. The pTable and
+** pDatabase parameters are NULL for subqueries. The pOn and pUsing
+** parameters are the content of the ON and USING clauses.
+**
+** Return a new SrcList which encodes is the FROM with the new
+** term added.
+*/
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
+ Parse *pParse, /* Parsing context */
+ SrcList *p, /* The left part of the FROM clause already seen */
+ Token *pTable, /* Name of the table to add to the FROM clause */
+ Token *pDatabase, /* Name of the database containing pTable */
+ Token *pAlias, /* The right-hand side of the AS subexpression */
+ Select *pSubquery, /* A subquery used in place of a table name */
+ Expr *pOn, /* The ON clause of a join */
+ IdList *pUsing /* The USING clause of a join */
+){
+ struct SrcList_item *pItem;
+ sqlite3 *db = pParse->db;
+ if( !p && (pOn || pUsing) ){
+ sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
+ (pOn ? "ON" : "USING")
+ );
+ goto append_from_error;
+ }
+ p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
+ if( p==0 || NEVER(p->nSrc==0) ){
+ goto append_from_error;
+ }
+ pItem = &p->a[p->nSrc-1];
+ assert( pAlias!=0 );
+ if( pAlias->n ){
+ pItem->zAlias = sqlite3NameFromToken(db, pAlias);
+ }
+ pItem->pSelect = pSubquery;
+ pItem->pOn = pOn;
+ pItem->pUsing = pUsing;
+ return p;
+
+ append_from_error:
+ assert( p==0 );
+ sqlite3ExprDelete(db, pOn);
+ sqlite3IdListDelete(db, pUsing);
+ sqlite3SelectDelete(db, pSubquery);
+ return 0;
+}
+
+/*
+** Add an INDEXED BY or NOT INDEXED clause to the most recently added
+** element of the source-list passed as the second argument.
+*/
+SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
+ assert( pIndexedBy!=0 );
+ if( p && ALWAYS(p->nSrc>0) ){
+ struct SrcList_item *pItem = &p->a[p->nSrc-1];
+ assert( pItem->notIndexed==0 && pItem->zIndex==0 );
+ if( pIndexedBy->n==1 && !pIndexedBy->z ){
+ /* A "NOT INDEXED" clause was supplied. See parse.y
+ ** construct "indexed_opt" for details. */
+ pItem->notIndexed = 1;
+ }else{
+ pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy);
+ }
+ }
+}
+
+/*
+** When building up a FROM clause in the parser, the join operator
+** is initially attached to the left operand. But the code generator
+** expects the join operator to be on the right operand. This routine
+** Shifts all join operators from left to right for an entire FROM
+** clause.
+**
+** Example: Suppose the join is like this:
+**
+** A natural cross join B
+**
+** The operator is "natural cross join". The A and B operands are stored
+** in p->a[0] and p->a[1], respectively. The parser initially stores the
+** operator with A. This routine shifts that operator over to B.
+*/
+SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
+ if( p ){
+ int i;
+ assert( p->a || p->nSrc==0 );
+ for(i=p->nSrc-1; i>0; i--){
+ p->a[i].jointype = p->a[i-1].jointype;
+ }
+ p->a[0].jointype = 0;
+ }
+}
+
+/*
+** Begin a transaction
+*/
+SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){
+ sqlite3 *db;
+ Vdbe *v;
+ int i;
+
+ assert( pParse!=0 );
+ db = pParse->db;
+ assert( db!=0 );
+/* if( db->aDb[0].pBt==0 ) return; */
+ if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){
+ return;
+ }
+ v = sqlite3GetVdbe(pParse);
+ if( !v ) return;
+ if( type!=TK_DEFERRED ){
+ for(i=0; i<db->nDb; i++){
+ sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
+ sqlite3VdbeUsesBtree(v, i);
+ }
+ }
+ sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0);
+}
+
+/*
+** Commit a transaction
+*/
+SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){
+ Vdbe *v;
+
+ assert( pParse!=0 );
+ assert( pParse->db!=0 );
+ if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){
+ return;
+ }
+ v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0);
+ }
+}
+
+/*
+** Rollback a transaction
+*/
+SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){
+ Vdbe *v;
+
+ assert( pParse!=0 );
+ assert( pParse->db!=0 );
+ if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){
+ return;
+ }
+ v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1);
+ }
+}
+
+/*
+** This function is called by the parser when it parses a command to create,
+** release or rollback an SQL savepoint.
+*/
+SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){
+ char *zName = sqlite3NameFromToken(pParse->db, pName);
+ if( zName ){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ static const char * const az[] = { "BEGIN", "RELEASE", "ROLLBACK" };
+ assert( !SAVEPOINT_BEGIN && SAVEPOINT_RELEASE==1 && SAVEPOINT_ROLLBACK==2 );
+#endif
+ if( !v || sqlite3AuthCheck(pParse, SQLITE_SAVEPOINT, az[op], zName, 0) ){
+ sqlite3DbFree(pParse->db, zName);
+ return;
+ }
+ sqlite3VdbeAddOp4(v, OP_Savepoint, op, 0, 0, zName, P4_DYNAMIC);
+ }
+}
+
+/*
+** Make sure the TEMP database is open and available for use. Return
+** the number of errors. Leave any error messages in the pParse structure.
+*/
+SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
+ sqlite3 *db = pParse->db;
+ if( db->aDb[1].pBt==0 && !pParse->explain ){
+ int rc;
+ Btree *pBt;
+ static const int flags =
+ SQLITE_OPEN_READWRITE |
+ SQLITE_OPEN_CREATE |
+ SQLITE_OPEN_EXCLUSIVE |
+ SQLITE_OPEN_DELETEONCLOSE |
+ SQLITE_OPEN_TEMP_DB;
+
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
+ if( rc!=SQLITE_OK ){
+ sqlite3ErrorMsg(pParse, "unable to open a temporary database "
+ "file for storing temporary tables");
+ pParse->rc = rc;
+ return 1;
+ }
+ db->aDb[1].pBt = pBt;
+ assert( db->aDb[1].pSchema );
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
+ db->mallocFailed = 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+** Generate VDBE code that will verify the schema cookie and start
+** a read-transaction for all named database files.
+**
+** It is important that all schema cookies be verified and all
+** read transactions be started before anything else happens in
+** the VDBE program. But this routine can be called after much other
+** code has been generated. So here is what we do:
+**
+** The first time this routine is called, we code an OP_Goto that
+** will jump to a subroutine at the end of the program. Then we
+** record every database that needs its schema verified in the
+** pParse->cookieMask field. Later, after all other code has been
+** generated, the subroutine that does the cookie verifications and
+** starts the transactions will be coded and the OP_Goto P2 value
+** will be made to point to that subroutine. The generation of the
+** cookie verification subroutine code happens in sqlite3FinishCoding().
+**
+** If iDb<0 then code the OP_Goto only - don't set flag to verify the
+** schema on any databases. This can be used to position the OP_Goto
+** early in the code, before we know if any database tables will be used.
+*/
+SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+
+#ifndef SQLITE_OMIT_TRIGGER
+ if( pToplevel!=pParse ){
+ /* This branch is taken if a trigger is currently being coded. In this
+ ** case, set cookieGoto to a non-zero value to show that this function
+ ** has been called. This is used by the sqlite3ExprCodeConstants()
+ ** function. */
+ pParse->cookieGoto = -1;
+ }
+#endif
+ if( pToplevel->cookieGoto==0 ){
+ Vdbe *v = sqlite3GetVdbe(pToplevel);
+ if( v==0 ) return; /* This only happens if there was a prior error */
+ pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
+ }
+ if( iDb>=0 ){
+ sqlite3 *db = pToplevel->db;
+ yDbMask mask;
+
+ assert( iDb<db->nDb );
+ assert( db->aDb[iDb].pBt!=0 || iDb==1 );
+ assert( iDb<SQLITE_MAX_ATTACHED+2 );
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ mask = ((yDbMask)1)<<iDb;
+ if( (pToplevel->cookieMask & mask)==0 ){
+ pToplevel->cookieMask |= mask;
+ pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
+ if( !OMIT_TEMPDB && iDb==1 ){
+ sqlite3OpenTempDatabase(pToplevel);
+ }
+ }
+ }
+}
+
+/*
+** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
+** attached database. Otherwise, invoke it for the database named zDb only.
+*/
+SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
+ sqlite3 *db = pParse->db;
+ int i;
+ for(i=0; i<db->nDb; i++){
+ Db *pDb = &db->aDb[i];
+ if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zName)) ){
+ sqlite3CodeVerifySchema(pParse, i);
+ }
+ }
+}
+
+/*
+** Generate VDBE code that prepares for doing an operation that
+** might change the database.
+**
+** This routine starts a new transaction if we are not already within
+** a transaction. If we are already within a transaction, then a checkpoint
+** is set if the setStatement parameter is true. A checkpoint should
+** be set for operations that might fail (due to a constraint) part of
+** the way through and which will need to undo some writes without having to
+** rollback the whole transaction. For operations where all constraints
+** can be checked before any changes are made to the database, it is never
+** necessary to undo a write and the checkpoint should not be set.
+*/
+SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ sqlite3CodeVerifySchema(pParse, iDb);
+ pToplevel->writeMask |= ((yDbMask)1)<<iDb;
+ pToplevel->isMultiWrite |= setStatement;
+}
+
+/*
+** Indicate that the statement currently under construction might write
+** more than one entry (example: deleting one row then inserting another,
+** inserting multiple rows in a table, or inserting a row and index entries.)
+** If an abort occurs after some of these writes have completed, then it will
+** be necessary to undo the completed writes.
+*/
+SQLITE_PRIVATE void sqlite3MultiWrite(Parse *pParse){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ pToplevel->isMultiWrite = 1;
+}
+
+/*
+** The code generator calls this routine if is discovers that it is
+** possible to abort a statement prior to completion. In order to
+** perform this abort without corrupting the database, we need to make
+** sure that the statement is protected by a statement transaction.
+**
+** Technically, we only need to set the mayAbort flag if the
+** isMultiWrite flag was previously set. There is a time dependency
+** such that the abort must occur after the multiwrite. This makes
+** some statements involving the REPLACE conflict resolution algorithm
+** go a little faster. But taking advantage of this time dependency
+** makes it more difficult to prove that the code is correct (in
+** particular, it prevents us from writing an effective
+** implementation of sqlite3AssertMayAbort()) and so we have chosen
+** to take the safe route and skip the optimization.
+*/
+SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ pToplevel->mayAbort = 1;
+}
+
+/*
+** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT
+** error. The onError parameter determines which (if any) of the statement
+** and/or current transaction is rolled back.
+*/
+SQLITE_PRIVATE void sqlite3HaltConstraint(
+ Parse *pParse, /* Parsing context */
+ int errCode, /* extended error code */
+ int onError, /* Constraint type */
+ char *p4, /* Error message */
+ int p4type /* P4_STATIC or P4_TRANSIENT */
+){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ assert( (errCode&0xff)==SQLITE_CONSTRAINT );
+ if( onError==OE_Abort ){
+ sqlite3MayAbort(pParse);
+ }
+ sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
+}
+
+/*
+** Check to see if pIndex uses the collating sequence pColl. Return
+** true if it does and false if it does not.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+static int collationMatch(const char *zColl, Index *pIndex){
+ int i;
+ assert( zColl!=0 );
+ for(i=0; i<pIndex->nColumn; i++){
+ const char *z = pIndex->azColl[i];
+ assert( z!=0 );
+ if( 0==sqlite3StrICmp(z, zColl) ){
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+/*
+** Recompute all indices of pTab that use the collating sequence pColl.
+** If pColl==0 then recompute all indices of pTab.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
+ Index *pIndex; /* An index associated with pTab */
+
+ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
+ if( zColl==0 || collationMatch(zColl, pIndex) ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3RefillIndex(pParse, pIndex, -1);
+ }
+ }
+}
+#endif
+
+/*
+** Recompute all indices of all tables in all databases where the
+** indices use the collating sequence pColl. If pColl==0 then recompute
+** all indices everywhere.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+static void reindexDatabases(Parse *pParse, char const *zColl){
+ Db *pDb; /* A single database */
+ int iDb; /* The database index number */
+ sqlite3 *db = pParse->db; /* The database connection */
+ HashElem *k; /* For looping over tables in pDb */
+ Table *pTab; /* A table in the database */
+
+ assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */
+ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
+ assert( pDb!=0 );
+ for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
+ pTab = (Table*)sqliteHashData(k);
+ reindexTable(pParse, pTab, zColl);
+ }
+ }
+}
+#endif
+
+/*
+** Generate code for the REINDEX command.
+**
+** REINDEX -- 1
+** REINDEX <collation> -- 2
+** REINDEX ?<database>.?<tablename> -- 3
+** REINDEX ?<database>.?<indexname> -- 4
+**
+** Form 1 causes all indices in all attached databases to be rebuilt.
+** Form 2 rebuilds all indices in all databases that use the named
+** collating function. Forms 3 and 4 rebuild the named index or all
+** indices associated with the named table.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
+ CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */
+ char *z; /* Name of a table or index */
+ const char *zDb; /* Name of the database */
+ Table *pTab; /* A table in the database */
+ Index *pIndex; /* An index associated with pTab */
+ int iDb; /* The database index number */
+ sqlite3 *db = pParse->db; /* The database connection */
+ Token *pObjName; /* Name of the table or index to be reindexed */
+
+ /* Read the database schema. If an error occurs, leave an error message
+ ** and code in pParse and return NULL. */
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ return;
+ }
+
+ if( pName1==0 ){
+ reindexDatabases(pParse, 0);
+ return;
+ }else if( NEVER(pName2==0) || pName2->z==0 ){
+ char *zColl;
+ assert( pName1->z );
+ zColl = sqlite3NameFromToken(pParse->db, pName1);
+ if( !zColl ) return;
+ pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
+ if( pColl ){
+ reindexDatabases(pParse, zColl);
+ sqlite3DbFree(db, zColl);
+ return;
+ }
+ sqlite3DbFree(db, zColl);
+ }
+ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
+ if( iDb<0 ) return;
+ z = sqlite3NameFromToken(db, pObjName);
+ if( z==0 ) return;
+ zDb = db->aDb[iDb].zName;
+ pTab = sqlite3FindTable(db, z, zDb);
+ if( pTab ){
+ reindexTable(pParse, pTab, 0);
+ sqlite3DbFree(db, z);
+ return;
+ }
+ pIndex = sqlite3FindIndex(db, z, zDb);
+ sqlite3DbFree(db, z);
+ if( pIndex ){
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3RefillIndex(pParse, pIndex, -1);
+ return;
+ }
+ sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
+}
+#endif
+
+/*
+** Return a dynamicly allocated KeyInfo structure that can be used
+** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
+**
+** If successful, a pointer to the new structure is returned. In this case
+** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
+** pointer. If an error occurs (out of memory or missing collation
+** sequence), NULL is returned and the state of pParse updated to reflect
+** the error.
+*/
+SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
+ int i;
+ int nCol = pIdx->nColumn;
+ int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
+ sqlite3 *db = pParse->db;
+ KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes);
+
+ if( pKey ){
+ pKey->db = pParse->db;
+ pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
+ assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );
+ for(i=0; i<nCol; i++){
+ char *zColl = pIdx->azColl[i];
+ assert( zColl );
+ pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
+ pKey->aSortOrder[i] = pIdx->aSortOrder[i];
+ }
+ pKey->nField = (u16)nCol;
+ }
+
+ if( pParse->nErr ){
+ sqlite3DbFree(db, pKey);
+ pKey = 0;
+ }
+ return pKey;
+}
+
+/************** End of build.c ***********************************************/
+/************** Begin file callback.c ****************************************/
+/*
+** 2005 May 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains functions used to access the internal hash tables
+** of user defined functions and collation sequences.
+*/
+
+
+/*
+** Invoke the 'collation needed' callback to request a collation sequence
+** in the encoding enc of name zName, length nName.
+*/
+static void callCollNeeded(sqlite3 *db, int enc, const char *zName){
+ assert( !db->xCollNeeded || !db->xCollNeeded16 );
+ if( db->xCollNeeded ){
+ char *zExternal = sqlite3DbStrDup(db, zName);
+ if( !zExternal ) return;
+ db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal);
+ sqlite3DbFree(db, zExternal);
+ }
+#ifndef SQLITE_OMIT_UTF16
+ if( db->xCollNeeded16 ){
+ char const *zExternal;
+ sqlite3_value *pTmp = sqlite3ValueNew(db);
+ sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC);
+ zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
+ if( zExternal ){
+ db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);
+ }
+ sqlite3ValueFree(pTmp);
+ }
+#endif
+}
+
+/*
+** This routine is called if the collation factory fails to deliver a
+** collation function in the best encoding but there may be other versions
+** of this collation function (for other text encodings) available. Use one
+** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if
+** possible.
+*/
+static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
+ CollSeq *pColl2;
+ char *z = pColl->zName;
+ int i;
+ static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
+ for(i=0; i<3; i++){
+ pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0);
+ if( pColl2->xCmp!=0 ){
+ memcpy(pColl, pColl2, sizeof(CollSeq));
+ pColl->xDel = 0; /* Do not copy the destructor */
+ return SQLITE_OK;
+ }
+ }
+ return SQLITE_ERROR;
+}
+
+/*
+** This function is responsible for invoking the collation factory callback
+** or substituting a collation sequence of a different encoding when the
+** requested collation sequence is not available in the desired encoding.
+**
+** If it is not NULL, then pColl must point to the database native encoding
+** collation sequence with name zName, length nName.
+**
+** The return value is either the collation sequence to be used in database
+** db for collation type name zName, length nName, or NULL, if no collation
+** sequence can be found. If no collation is found, leave an error message.
+**
+** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
+*/
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
+ Parse *pParse, /* Parsing context */
+ u8 enc, /* The desired encoding for the collating sequence */
+ CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
+ const char *zName /* Collating sequence name */
+){
+ CollSeq *p;
+ sqlite3 *db = pParse->db;
+
+ p = pColl;
+ if( !p ){
+ p = sqlite3FindCollSeq(db, enc, zName, 0);
+ }
+ if( !p || !p->xCmp ){
+ /* No collation sequence of this type for this encoding is registered.
+ ** Call the collation factory to see if it can supply us with one.
+ */
+ callCollNeeded(db, enc, zName);
+ p = sqlite3FindCollSeq(db, enc, zName, 0);
+ }
+ if( p && !p->xCmp && synthCollSeq(db, p) ){
+ p = 0;
+ }
+ assert( !p || p->xCmp );
+ if( p==0 ){
+ sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
+ }
+ return p;
+}
+
+/*
+** This routine is called on a collation sequence before it is used to
+** check that it is defined. An undefined collation sequence exists when
+** a database is loaded that contains references to collation sequences
+** that have not been defined by sqlite3_create_collation() etc.
+**
+** If required, this routine calls the 'collation needed' callback to
+** request a definition of the collating sequence. If this doesn't work,
+** an equivalent collating sequence that uses a text encoding different
+** from the main database is substituted, if one is available.
+*/
+SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
+ if( pColl ){
+ const char *zName = pColl->zName;
+ sqlite3 *db = pParse->db;
+ CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
+ if( !p ){
+ return SQLITE_ERROR;
+ }
+ assert( p==pColl );
+ }
+ return SQLITE_OK;
+}
+
+
+
+/*
+** Locate and return an entry from the db.aCollSeq hash table. If the entry
+** specified by zName and nName is not found and parameter 'create' is
+** true, then create a new entry. Otherwise return NULL.
+**
+** Each pointer stored in the sqlite3.aCollSeq hash table contains an
+** array of three CollSeq structures. The first is the collation sequence
+** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
+**
+** Stored immediately after the three collation sequences is a copy of
+** the collation sequence name. A pointer to this string is stored in
+** each collation sequence structure.
+*/
+static CollSeq *findCollSeqEntry(
+ sqlite3 *db, /* Database connection */
+ const char *zName, /* Name of the collating sequence */
+ int create /* Create a new entry if true */
+){
+ CollSeq *pColl;
+ int nName = sqlite3Strlen30(zName);
+ pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
+
+ if( 0==pColl && create ){
+ pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 );
+ if( pColl ){
+ CollSeq *pDel = 0;
+ pColl[0].zName = (char*)&pColl[3];
+ pColl[0].enc = SQLITE_UTF8;
+ pColl[1].zName = (char*)&pColl[3];
+ pColl[1].enc = SQLITE_UTF16LE;
+ pColl[2].zName = (char*)&pColl[3];
+ pColl[2].enc = SQLITE_UTF16BE;
+ memcpy(pColl[0].zName, zName, nName);
+ pColl[0].zName[nName] = 0;
+ pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
+
+ /* If a malloc() failure occurred in sqlite3HashInsert(), it will
+ ** return the pColl pointer to be deleted (because it wasn't added
+ ** to the hash table).
+ */
+ assert( pDel==0 || pDel==pColl );
+ if( pDel!=0 ){
+ db->mallocFailed = 1;
+ sqlite3DbFree(db, pDel);
+ pColl = 0;
+ }
+ }
+ }
+ return pColl;
+}
+
+/*
+** Parameter zName points to a UTF-8 encoded string nName bytes long.
+** Return the CollSeq* pointer for the collation sequence named zName
+** for the encoding 'enc' from the database 'db'.
+**
+** If the entry specified is not found and 'create' is true, then create a
+** new entry. Otherwise return NULL.
+**
+** A separate function sqlite3LocateCollSeq() is a wrapper around
+** this routine. sqlite3LocateCollSeq() invokes the collation factory
+** if necessary and generates an error message if the collating sequence
+** cannot be found.
+**
+** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
+*/
+SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(
+ sqlite3 *db,
+ u8 enc,
+ const char *zName,
+ int create
+){
+ CollSeq *pColl;
+ if( zName ){
+ pColl = findCollSeqEntry(db, zName, create);
+ }else{
+ pColl = db->pDfltColl;
+ }
+ assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+ assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
+ if( pColl ) pColl += enc-1;
+ return pColl;
+}
+
+/* During the search for the best function definition, this procedure
+** is called to test how well the function passed as the first argument
+** matches the request for a function with nArg arguments in a system
+** that uses encoding enc. The value returned indicates how well the
+** request is matched. A higher value indicates a better match.
+**
+** If nArg is -1 that means to only return a match (non-zero) if p->nArg
+** is also -1. In other words, we are searching for a function that
+** takes a variable number of arguments.
+**
+** If nArg is -2 that means that we are searching for any function
+** regardless of the number of arguments it uses, so return a positive
+** match score for any
+**
+** The returned value is always between 0 and 6, as follows:
+**
+** 0: Not a match.
+** 1: UTF8/16 conversion required and function takes any number of arguments.
+** 2: UTF16 byte order change required and function takes any number of args.
+** 3: encoding matches and function takes any number of arguments
+** 4: UTF8/16 conversion required - argument count matches exactly
+** 5: UTF16 byte order conversion required - argument count matches exactly
+** 6: Perfect match: encoding and argument count match exactly.
+**
+** If nArg==(-2) then any function with a non-null xStep or xFunc is
+** a perfect match and any function with both xStep and xFunc NULL is
+** a non-match.
+*/
+#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */
+static int matchQuality(
+ FuncDef *p, /* The function we are evaluating for match quality */
+ int nArg, /* Desired number of arguments. (-1)==any */
+ u8 enc /* Desired text encoding */
+){
+ int match;
+
+ /* nArg of -2 is a special case */
+ if( nArg==(-2) ) return (p->xFunc==0 && p->xStep==0) ? 0 : FUNC_PERFECT_MATCH;
+
+ /* Wrong number of arguments means "no match" */
+ if( p->nArg!=nArg && p->nArg>=0 ) return 0;
+
+ /* Give a better score to a function with a specific number of arguments
+ ** than to function that accepts any number of arguments. */
+ if( p->nArg==nArg ){
+ match = 4;
+ }else{
+ match = 1;
+ }
+
+ /* Bonus points if the text encoding matches */
+ if( enc==p->iPrefEnc ){
+ match += 2; /* Exact encoding match */
+ }else if( (enc & p->iPrefEnc & 2)!=0 ){
+ match += 1; /* Both are UTF16, but with different byte orders */
+ }
+
+ return match;
+}
+
+/*
+** Search a FuncDefHash for a function with the given name. Return
+** a pointer to the matching FuncDef if found, or 0 if there is no match.
+*/
+static FuncDef *functionSearch(
+ FuncDefHash *pHash, /* Hash table to search */
+ int h, /* Hash of the name */
+ const char *zFunc, /* Name of function */
+ int nFunc /* Number of bytes in zFunc */
+){
+ FuncDef *p;
+ for(p=pHash->a[h]; p; p=p->pHash){
+ if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){
+ return p;
+ }
+ }
+ return 0;
+}
+
+/*
+** Insert a new FuncDef into a FuncDefHash hash table.
+*/
+SQLITE_PRIVATE void sqlite3FuncDefInsert(
+ FuncDefHash *pHash, /* The hash table into which to insert */
+ FuncDef *pDef /* The function definition to insert */
+){
+ FuncDef *pOther;
+ int nName = sqlite3Strlen30(pDef->zName);
+ u8 c1 = (u8)pDef->zName[0];
+ int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a);
+ pOther = functionSearch(pHash, h, pDef->zName, nName);
+ if( pOther ){
+ assert( pOther!=pDef && pOther->pNext!=pDef );
+ pDef->pNext = pOther->pNext;
+ pOther->pNext = pDef;
+ }else{
+ pDef->pNext = 0;
+ pDef->pHash = pHash->a[h];
+ pHash->a[h] = pDef;
+ }
+}
+
+
+
+/*
+** Locate a user function given a name, a number of arguments and a flag
+** indicating whether the function prefers UTF-16 over UTF-8. Return a
+** pointer to the FuncDef structure that defines that function, or return
+** NULL if the function does not exist.
+**
+** If the createFlag argument is true, then a new (blank) FuncDef
+** structure is created and liked into the "db" structure if a
+** no matching function previously existed.
+**
+** If nArg is -2, then the first valid function found is returned. A
+** function is valid if either xFunc or xStep is non-zero. The nArg==(-2)
+** case is used to see if zName is a valid function name for some number
+** of arguments. If nArg is -2, then createFlag must be 0.
+**
+** If createFlag is false, then a function with the required name and
+** number of arguments may be returned even if the eTextRep flag does not
+** match that requested.
+*/
+SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
+ sqlite3 *db, /* An open database */
+ const char *zName, /* Name of the function. Not null-terminated */
+ int nName, /* Number of characters in the name */
+ int nArg, /* Number of arguments. -1 means any number */
+ u8 enc, /* Preferred text encoding */
+ u8 createFlag /* Create new entry if true and does not otherwise exist */
+){
+ FuncDef *p; /* Iterator variable */
+ FuncDef *pBest = 0; /* Best match found so far */
+ int bestScore = 0; /* Score of best match */
+ int h; /* Hash value */
+
+ assert( nArg>=(-2) );
+ assert( nArg>=(-1) || createFlag==0 );
+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+ h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
+
+ /* First search for a match amongst the application-defined functions.
+ */
+ p = functionSearch(&db->aFunc, h, zName, nName);
+ while( p ){
+ int score = matchQuality(p, nArg, enc);
+ if( score>bestScore ){
+ pBest = p;
+ bestScore = score;
+ }
+ p = p->pNext;
+ }
+
+ /* If no match is found, search the built-in functions.
+ **
+ ** If the SQLITE_PreferBuiltin flag is set, then search the built-in
+ ** functions even if a prior app-defined function was found. And give
+ ** priority to built-in functions.
+ **
+ ** Except, if createFlag is true, that means that we are trying to
+ ** install a new function. Whatever FuncDef structure is returned it will
+ ** have fields overwritten with new information appropriate for the
+ ** new function. But the FuncDefs for built-in functions are read-only.
+ ** So we must not search for built-ins when creating a new function.
+ */
+ if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ bestScore = 0;
+ p = functionSearch(pHash, h, zName, nName);
+ while( p ){
+ int score = matchQuality(p, nArg, enc);
+ if( score>bestScore ){
+ pBest = p;
+ bestScore = score;
+ }
+ p = p->pNext;
+ }
+ }
+
+ /* If the createFlag parameter is true and the search did not reveal an
+ ** exact match for the name, number of arguments and encoding, then add a
+ ** new entry to the hash table and return it.
+ */
+ if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
+ (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
+ pBest->zName = (char *)&pBest[1];
+ pBest->nArg = (u16)nArg;
+ pBest->iPrefEnc = enc;
+ memcpy(pBest->zName, zName, nName);
+ pBest->zName[nName] = 0;
+ sqlite3FuncDefInsert(&db->aFunc, pBest);
+ }
+
+ if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
+ return pBest;
+ }
+ return 0;
+}
+
+/*
+** Free all resources held by the schema structure. The void* argument points
+** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
+** pointer itself, it just cleans up subsidiary resources (i.e. the contents
+** of the schema hash tables).
+**
+** The Schema.cache_size variable is not cleared.
+*/
+SQLITE_PRIVATE void sqlite3SchemaClear(void *p){
+ Hash temp1;
+ Hash temp2;
+ HashElem *pElem;
+ Schema *pSchema = (Schema *)p;
+
+ temp1 = pSchema->tblHash;
+ temp2 = pSchema->trigHash;
+ sqlite3HashInit(&pSchema->trigHash);
+ sqlite3HashClear(&pSchema->idxHash);
+ for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
+ sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
+ }
+ sqlite3HashClear(&temp2);
+ sqlite3HashInit(&pSchema->tblHash);
+ for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
+ Table *pTab = sqliteHashData(pElem);
+ sqlite3DeleteTable(0, pTab);
+ }
+ sqlite3HashClear(&temp1);
+ sqlite3HashClear(&pSchema->fkeyHash);
+ pSchema->pSeqTab = 0;
+ if( pSchema->flags & DB_SchemaLoaded ){
+ pSchema->iGeneration++;
+ pSchema->flags &= ~DB_SchemaLoaded;
+ }
+}
+
+/*
+** Find and return the schema associated with a BTree. Create
+** a new one if necessary.
+*/
+SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
+ Schema * p;
+ if( pBt ){
+ p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
+ }else{
+ p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
+ }
+ if( !p ){
+ db->mallocFailed = 1;
+ }else if ( 0==p->file_format ){
+ sqlite3HashInit(&p->tblHash);
+ sqlite3HashInit(&p->idxHash);
+ sqlite3HashInit(&p->trigHash);
+ sqlite3HashInit(&p->fkeyHash);
+ p->enc = SQLITE_UTF8;
+ }
+ return p;
+}
+
+/************** End of callback.c ********************************************/
+/************** Begin file delete.c ******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that are called by the parser
+** in order to generate code for DELETE FROM statements.
+*/
+
+/*
+** While a SrcList can in general represent multiple tables and subqueries
+** (as in the FROM clause of a SELECT statement) in this case it contains
+** the name of a single table, as one might find in an INSERT, DELETE,
+** or UPDATE statement. Look up that table in the symbol table and
+** return a pointer. Set an error message and return NULL if the table
+** name is not found or if any other error occurs.
+**
+** The following fields are initialized appropriate in pSrc:
+**
+** pSrc->a[0].pTab Pointer to the Table object
+** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
+**
+*/
+SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
+ struct SrcList_item *pItem = pSrc->a;
+ Table *pTab;
+ assert( pItem && pSrc->nSrc==1 );
+ pTab = sqlite3LocateTableItem(pParse, 0, pItem);
+ sqlite3DeleteTable(pParse->db, pItem->pTab);
+ pItem->pTab = pTab;
+ if( pTab ){
+ pTab->nRef++;
+ }
+ if( sqlite3IndexedByLookup(pParse, pItem) ){
+ pTab = 0;
+ }
+ return pTab;
+}
+
+/*
+** Check to make sure the given table is writable. If it is not
+** writable, generate an error message and return 1. If it is
+** writable return 0;
+*/
+SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
+ /* A table is not writable under the following circumstances:
+ **
+ ** 1) It is a virtual table and no implementation of the xUpdate method
+ ** has been provided, or
+ ** 2) It is a system table (i.e. sqlite_master), this call is not
+ ** part of a nested parse and writable_schema pragma has not
+ ** been specified.
+ **
+ ** In either case leave an error message in pParse and return non-zero.
+ */
+ if( ( IsVirtual(pTab)
+ && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
+ || ( (pTab->tabFlags & TF_Readonly)!=0
+ && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && pParse->nested==0 )
+ ){
+ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
+ return 1;
+ }
+
+#ifndef SQLITE_OMIT_VIEW
+ if( !viewOk && pTab->pSelect ){
+ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
+/*
+** Evaluate a view and store its result in an ephemeral table. The
+** pWhere argument is an optional WHERE clause that restricts the
+** set of rows in the view that are to be added to the ephemeral table.
+*/
+SQLITE_PRIVATE void sqlite3MaterializeView(
+ Parse *pParse, /* Parsing context */
+ Table *pView, /* View definition */
+ Expr *pWhere, /* Optional WHERE clause to be added */
+ int iCur /* Cursor number for ephemerial table */
+){
+ SelectDest dest;
+ Select *pSel;
+ SrcList *pFrom;
+ sqlite3 *db = pParse->db;
+ int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
+
+ pWhere = sqlite3ExprDup(db, pWhere, 0);
+ pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
+
+ if( pFrom ){
+ assert( pFrom->nSrc==1 );
+ pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
+ pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
+ assert( pFrom->a[0].pOn==0 );
+ assert( pFrom->a[0].pUsing==0 );
+ }
+
+ pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+ if( pSel ) pSel->selFlags |= SF_Materialize;
+
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
+ sqlite3Select(pParse, pSel, &dest);
+ sqlite3SelectDelete(db, pSel);
+}
+#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
+
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
+/*
+** Generate an expression tree to implement the WHERE, ORDER BY,
+** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
+**
+** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
+** \__________________________/
+** pLimitWhere (pInClause)
+*/
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(
+ Parse *pParse, /* The parser context */
+ SrcList *pSrc, /* the FROM clause -- which tables to scan */
+ Expr *pWhere, /* The WHERE clause. May be null */
+ ExprList *pOrderBy, /* The ORDER BY clause. May be null */
+ Expr *pLimit, /* The LIMIT clause. May be null */
+ Expr *pOffset, /* The OFFSET clause. May be null */
+ char *zStmtType /* Either DELETE or UPDATE. For error messages. */
+){
+ Expr *pWhereRowid = NULL; /* WHERE rowid .. */
+ Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
+ Expr *pSelectRowid = NULL; /* SELECT rowid ... */
+ ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */
+ SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */
+ Select *pSelect = NULL; /* Complete SELECT tree */
+
+ /* Check that there isn't an ORDER BY without a LIMIT clause.
+ */
+ if( pOrderBy && (pLimit == 0) ) {
+ sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
+ goto limit_where_cleanup_2;
+ }
+
+ /* We only need to generate a select expression if there
+ ** is a limit/offset term to enforce.
+ */
+ if( pLimit == 0 ) {
+ /* if pLimit is null, pOffset will always be null as well. */
+ assert( pOffset == 0 );
+ return pWhere;
+ }
+
+ /* Generate a select expression tree to enforce the limit/offset
+ ** term for the DELETE or UPDATE statement. For example:
+ ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
+ ** becomes:
+ ** DELETE FROM table_a WHERE rowid IN (
+ ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
+ ** );
+ */
+
+ pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
+ if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
+ pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
+ if( pEList == 0 ) goto limit_where_cleanup_2;
+
+ /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
+ ** and the SELECT subtree. */
+ pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
+ if( pSelectSrc == 0 ) {
+ sqlite3ExprListDelete(pParse->db, pEList);
+ goto limit_where_cleanup_2;
+ }
+
+ /* generate the SELECT expression tree. */
+ pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
+ pOrderBy,0,pLimit,pOffset);
+ if( pSelect == 0 ) return 0;
+
+ /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
+ pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
+ if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
+ pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
+ if( pInClause == 0 ) goto limit_where_cleanup_1;
+
+ pInClause->x.pSelect = pSelect;
+ pInClause->flags |= EP_xIsSelect;
+ sqlite3ExprSetHeight(pParse, pInClause);
+ return pInClause;
+
+ /* something went wrong. clean up anything allocated. */
+limit_where_cleanup_1:
+ sqlite3SelectDelete(pParse->db, pSelect);
+ return 0;
+
+limit_where_cleanup_2:
+ sqlite3ExprDelete(pParse->db, pWhere);
+ sqlite3ExprListDelete(pParse->db, pOrderBy);
+ sqlite3ExprDelete(pParse->db, pLimit);
+ sqlite3ExprDelete(pParse->db, pOffset);
+ return 0;
+}
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+
+/*
+** Generate code for a DELETE FROM statement.
+**
+** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
+** \________/ \________________/
+** pTabList pWhere
+*/
+SQLITE_PRIVATE void sqlite3DeleteFrom(
+ Parse *pParse, /* The parser context */
+ SrcList *pTabList, /* The table from which we should delete things */
+ Expr *pWhere /* The WHERE clause. May be null */
+){
+ Vdbe *v; /* The virtual database engine */
+ Table *pTab; /* The table from which records will be deleted */
+ const char *zDb; /* Name of database holding pTab */
+ int end, addr = 0; /* A couple addresses of generated code */
+ int i; /* Loop counter */
+ WhereInfo *pWInfo; /* Information about the WHERE clause */
+ Index *pIdx; /* For looping over indices of the table */
+ int iCur; /* VDBE Cursor number for pTab */
+ sqlite3 *db; /* Main database structure */
+ AuthContext sContext; /* Authorization context */
+ NameContext sNC; /* Name context to resolve expressions in */
+ int iDb; /* Database number */
+ int memCnt = -1; /* Memory cell used for change counting */
+ int rcauth; /* Value returned by authorization callback */
+
+#ifndef SQLITE_OMIT_TRIGGER
+ int isView; /* True if attempting to delete from a view */
+ Trigger *pTrigger; /* List of table triggers, if required */
+#endif
+
+ memset(&sContext, 0, sizeof(sContext));
+ db = pParse->db;
+ if( pParse->nErr || db->mallocFailed ){
+ goto delete_from_cleanup;
+ }
+ assert( pTabList->nSrc==1 );
+
+ /* Locate the table which we want to delete. This table has to be
+ ** put in an SrcList structure because some of the subroutines we
+ ** will be calling are designed to work with multiple tables and expect
+ ** an SrcList* parameter instead of just a Table* parameter.
+ */
+ pTab = sqlite3SrcListLookup(pParse, pTabList);
+ if( pTab==0 ) goto delete_from_cleanup;
+
+ /* Figure out if we have any triggers and if the table being
+ ** deleted from is a view
+ */
+#ifndef SQLITE_OMIT_TRIGGER
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
+ isView = pTab->pSelect!=0;
+#else
+# define pTrigger 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
+ /* If pTab is really a view, make sure it has been initialized.
+ */
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+ goto delete_from_cleanup;
+ }
+
+ if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
+ goto delete_from_cleanup;
+ }
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb<db->nDb );
+ zDb = db->aDb[iDb].zName;
+ rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
+ assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
+ if( rcauth==SQLITE_DENY ){
+ goto delete_from_cleanup;
+ }
+ assert(!isView || pTrigger);
+
+ /* Assign cursor number to the table and all its indices.
+ */
+ assert( pTabList->nSrc==1 );
+ iCur = pTabList->a[0].iCursor = pParse->nTab++;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ pParse->nTab++;
+ }
+
+ /* Start the view context
+ */
+ if( isView ){
+ sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
+ }
+
+ /* Begin generating code.
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ){
+ goto delete_from_cleanup;
+ }
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+
+ /* If we are trying to delete from a view, realize that view into
+ ** a ephemeral table.
+ */
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
+ if( isView ){
+ sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ }
+#endif
+
+ /* Resolve the column names in the WHERE clause.
+ */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+ if( sqlite3ResolveExprNames(&sNC, pWhere) ){
+ goto delete_from_cleanup;
+ }
+
+ /* Initialize the counter of the number of rows deleted, if
+ ** we are counting rows.
+ */
+ if( db->flags & SQLITE_CountRows ){
+ memCnt = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
+ }
+
+#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
+ /* Special case: A DELETE without a WHERE clause deletes everything.
+ ** It is easier just to erase the whole table. Prior to version 3.6.5,
+ ** this optimization caused the row change count (the value returned by
+ ** API function sqlite3_count_changes) to be set incorrectly. */
+ if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
+ && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
+ ){
+ assert( !isView );
+ sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
+ pTab->zName, P4_STATIC);
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ assert( pIdx->pSchema==pTab->pSchema );
+ sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
+ }
+ }else
+#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
+ /* The usual case: There is a WHERE clause so we have to scan through
+ ** the table and pick which records to delete.
+ */
+ {
+ int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
+ int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
+ int regRowid; /* Actual register containing rowids */
+
+ /* Collect rowids of every row to be deleted.
+ */
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
+ pWInfo = sqlite3WhereBegin(
+ pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
+ );
+ if( pWInfo==0 ) goto delete_from_cleanup;
+ regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
+ if( db->flags & SQLITE_CountRows ){
+ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
+ }
+ sqlite3WhereEnd(pWInfo);
+
+ /* Delete every item whose key was written to the list during the
+ ** database scan. We have to delete items after the scan is complete
+ ** because deleting an item can change the scan order. */
+ end = sqlite3VdbeMakeLabel(v);
+
+ /* Unless this is a view, open cursors for the table we are
+ ** deleting from and all its indices. If this is a view, then the
+ ** only effect this statement has is to fire the INSTEAD OF
+ ** triggers. */
+ if( !isView ){
+ sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
+ }
+
+ addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
+
+ /* Delete the row */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
+ sqlite3VtabMakeWritable(pParse, pTab);
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
+ sqlite3VdbeChangeP5(v, OE_Abort);
+ sqlite3MayAbort(pParse);
+ }else
+#endif
+ {
+ int count = (pParse->nested==0); /* True to count changes */
+ sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default);
+ }
+
+ /* End of the delete loop */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
+ sqlite3VdbeResolveLabel(v, end);
+
+ /* Close the cursors open on the table and its indexes. */
+ if( !isView && !IsVirtual(pTab) ){
+ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+ sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum);
+ }
+ sqlite3VdbeAddOp1(v, OP_Close, iCur);
+ }
+ }
+
+ /* Update the sqlite_sequence table by storing the content of the
+ ** maximum rowid counter values recorded while inserting into
+ ** autoincrement tables.
+ */
+ if( pParse->nested==0 && pParse->pTriggerTab==0 ){
+ sqlite3AutoincrementEnd(pParse);
+ }
+
+ /* Return the number of rows that were deleted. If this routine is
+ ** generating code because of a call to sqlite3NestedParse(), do not
+ ** invoke the callback function.
+ */
+ if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){
+ sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
+ }
+
+delete_from_cleanup:
+ sqlite3AuthContextPop(&sContext);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprDelete(db, pWhere);
+ return;
+}
+/* Make sure "isView" and other macros defined above are undefined. Otherwise
+** thely may interfere with compilation of other functions in this file
+** (or in another file, if this file becomes part of the amalgamation). */
+#ifdef isView
+ #undef isView
+#endif
+#ifdef pTrigger
+ #undef pTrigger
+#endif
+
+/*
+** This routine generates VDBE code that causes a single row of a
+** single table to be deleted.
+**
+** The VDBE must be in a particular state when this routine is called.
+** These are the requirements:
+**
+** 1. A read/write cursor pointing to pTab, the table containing the row
+** to be deleted, must be opened as cursor number $iCur.
+**
+** 2. Read/write cursors for all indices of pTab must be open as
+** cursor number base+i for the i-th index.
+**
+** 3. The record number of the row to be deleted must be stored in
+** memory cell iRowid.
+**
+** This routine generates code to remove both the table record and all
+** index entries that point to that record.
+*/
+SQLITE_PRIVATE void sqlite3GenerateRowDelete(
+ Parse *pParse, /* Parsing context */
+ Table *pTab, /* Table containing the row to be deleted */
+ int iCur, /* Cursor number for the table */
+ int iRowid, /* Memory cell that contains the rowid to delete */
+ int count, /* If non-zero, increment the row change counter */
+ Trigger *pTrigger, /* List of triggers to (potentially) fire */
+ int onconf /* Default ON CONFLICT policy for triggers */
+){
+ Vdbe *v = pParse->pVdbe; /* Vdbe */
+ int iOld = 0; /* First register in OLD.* array */
+ int iLabel; /* Label resolved to end of generated code */
+
+ /* Vdbe is guaranteed to have been allocated by this stage. */
+ assert( v );
+
+ /* Seek cursor iCur to the row to delete. If this row no longer exists
+ ** (this can happen if a trigger program has already deleted it), do
+ ** not attempt to delete it or fire any DELETE triggers. */
+ iLabel = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
+
+ /* If there are any triggers to fire, allocate a range of registers to
+ ** use for the old.* references in the triggers. */
+ if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
+ u32 mask; /* Mask of OLD.* columns in use */
+ int iCol; /* Iterator used while populating OLD.* */
+
+ /* TODO: Could use temporary registers here. Also could attempt to
+ ** avoid copying the contents of the rowid register. */
+ mask = sqlite3TriggerColmask(
+ pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
+ );
+ mask |= sqlite3FkOldmask(pParse, pTab);
+ iOld = pParse->nMem+1;
+ pParse->nMem += (1 + pTab->nCol);
+
+ /* Populate the OLD.* pseudo-table register array. These values will be
+ ** used by any BEFORE and AFTER triggers that exist. */
+ sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
+ for(iCol=0; iCol<pTab->nCol; iCol++){
+ if( mask==0xffffffff || mask&(1<<iCol) ){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
+ }
+ }
+
+ /* Invoke BEFORE DELETE trigger programs. */
+ sqlite3CodeRowTrigger(pParse, pTrigger,
+ TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
+ );
+
+ /* Seek the cursor to the row to be deleted again. It may be that
+ ** the BEFORE triggers coded above have already removed the row
+ ** being deleted. Do not attempt to delete the row a second time, and
+ ** do not fire AFTER triggers. */
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
+
+ /* Do FK processing. This call checks that any FK constraints that
+ ** refer to this table (i.e. constraints attached to other tables)
+ ** are not violated by deleting this row. */
+ sqlite3FkCheck(pParse, pTab, iOld, 0);
+ }
+
+ /* Delete the index and table entries. Skip this step if pTab is really
+ ** a view (in which case the only effect of the DELETE statement is to
+ ** fire the INSTEAD OF triggers). */
+ if( pTab->pSelect==0 ){
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
+ sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
+ if( count ){
+ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
+ }
+ }
+
+ /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
+ ** handle rows (possibly in other tables) that refer via a foreign key
+ ** to the row just deleted. */
+ sqlite3FkActions(pParse, pTab, 0, iOld);
+
+ /* Invoke AFTER DELETE trigger programs. */
+ sqlite3CodeRowTrigger(pParse, pTrigger,
+ TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
+ );
+
+ /* Jump here if the row had already been deleted before any BEFORE
+ ** trigger programs were invoked. Or if a trigger program throws a
+ ** RAISE(IGNORE) exception. */
+ sqlite3VdbeResolveLabel(v, iLabel);
+}
+
+/*
+** This routine generates VDBE code that causes the deletion of all
+** index entries associated with a single row of a single table.
+**
+** The VDBE must be in a particular state when this routine is called.
+** These are the requirements:
+**
+** 1. A read/write cursor pointing to pTab, the table containing the row
+** to be deleted, must be opened as cursor number "iCur".
+**
+** 2. Read/write cursors for all indices of pTab must be open as
+** cursor number iCur+i for the i-th index.
+**
+** 3. The "iCur" cursor must be pointing to the row that is to be
+** deleted.
+*/
+SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
+ Parse *pParse, /* Parsing and code generating context */
+ Table *pTab, /* Table containing the row to be deleted */
+ int iCur, /* Cursor number for the table */
+ int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
+){
+ int i;
+ Index *pIdx;
+ int r1;
+
+ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+ if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
+ }
+}
+
+/*
+** Generate code that will assemble an index key and put it in register
+** regOut. The key with be for index pIdx which is an index on pTab.
+** iCur is the index of a cursor open on the pTab table and pointing to
+** the entry that needs indexing.
+**
+** Return a register number which is the first in a block of
+** registers that holds the elements of the index key. The
+** block of registers has already been deallocated by the time
+** this routine returns.
+*/
+SQLITE_PRIVATE int sqlite3GenerateIndexKey(
+ Parse *pParse, /* Parsing context */
+ Index *pIdx, /* The index for which to generate a key */
+ int iCur, /* Cursor number for the pIdx->pTable table */
+ int regOut, /* Write the new index key to this register */
+ int doMakeRec /* Run the OP_MakeRecord instruction if true */
+){
+ Vdbe *v = pParse->pVdbe;
+ int j;
+ Table *pTab = pIdx->pTable;
+ int regBase;
+ int nCol;
+
+ nCol = pIdx->nColumn;
+ regBase = sqlite3GetTempRange(pParse, nCol+1);
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
+ for(j=0; j<nCol; j++){
+ int idx = pIdx->aiColumn[j];
+ if( idx==pTab->iPKey ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
+ sqlite3ColumnDefault(v, pTab, idx, -1);
+ }
+ }
+ if( doMakeRec ){
+ const char *zAff;
+ if( pTab->pSelect
+ || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
+ ){
+ zAff = 0;
+ }else{
+ zAff = sqlite3IndexAffinityStr(v, pIdx);
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
+ sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
+ }
+ sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
+ return regBase;
+}
+
+/************** End of delete.c **********************************************/
+/************** Begin file func.c ********************************************/
+/*
+** 2002 February 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement various SQL
+** functions of SQLite.
+**
+** There is only one exported symbol in this file - the function
+** sqliteRegisterBuildinFunctions() found at the bottom of the file.
+** All other code has file scope.
+*/
+/* #include <stdlib.h> */
+/* #include <assert.h> */
+
+/*
+** Return the collating function associated with a function.
+*/
+static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
+ return context->pColl;
+}
+
+/*
+** Indicate that the accumulator load should be skipped on this
+** iteration of the aggregate loop.
+*/
+static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){
+ context->skipFlag = 1;
+}
+
+/*
+** Implementation of the non-aggregate min() and max() functions
+*/
+static void minmaxFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int i;
+ int mask; /* 0 for min() or 0xffffffff for max() */
+ int iBest;
+ CollSeq *pColl;
+
+ assert( argc>1 );
+ mask = sqlite3_user_data(context)==0 ? 0 : -1;
+ pColl = sqlite3GetFuncCollSeq(context);
+ assert( pColl );
+ assert( mask==-1 || mask==0 );
+ iBest = 0;
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
+ for(i=1; i<argc; i++){
+ if( sqlite3_value_type(argv[i])==SQLITE_NULL ) return;
+ if( (sqlite3MemCompare(argv[iBest], argv[i], pColl)^mask)>=0 ){
+ testcase( mask==0 );
+ iBest = i;
+ }
+ }
+ sqlite3_result_value(context, argv[iBest]);
+}
+
+/*
+** Return the type of the argument.
+*/
+static void typeofFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ const char *z = 0;
+ UNUSED_PARAMETER(NotUsed);
+ switch( sqlite3_value_type(argv[0]) ){
+ case SQLITE_INTEGER: z = "integer"; break;
+ case SQLITE_TEXT: z = "text"; break;
+ case SQLITE_FLOAT: z = "real"; break;
+ case SQLITE_BLOB: z = "blob"; break;
+ default: z = "null"; break;
+ }
+ sqlite3_result_text(context, z, -1, SQLITE_STATIC);
+}
+
+
+/*
+** Implementation of the length() function
+*/
+static void lengthFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int len;
+
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ switch( sqlite3_value_type(argv[0]) ){
+ case SQLITE_BLOB:
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT: {
+ sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
+ break;
+ }
+ case SQLITE_TEXT: {
+ const unsigned char *z = sqlite3_value_text(argv[0]);
+ if( z==0 ) return;
+ len = 0;
+ while( *z ){
+ len++;
+ SQLITE_SKIP_UTF8(z);
+ }
+ sqlite3_result_int(context, len);
+ break;
+ }
+ default: {
+ sqlite3_result_null(context);
+ break;
+ }
+ }
+}
+
+/*
+** Implementation of the abs() function.
+**
+** IMP: R-23979-26855 The abs(X) function returns the absolute value of
+** the numeric argument X.
+*/
+static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ switch( sqlite3_value_type(argv[0]) ){
+ case SQLITE_INTEGER: {
+ i64 iVal = sqlite3_value_int64(argv[0]);
+ if( iVal<0 ){
+ if( (iVal<<1)==0 ){
+ /* IMP: R-35460-15084 If X is the integer -9223372036854775807 then
+ ** abs(X) throws an integer overflow error since there is no
+ ** equivalent positive 64-bit two complement value. */
+ sqlite3_result_error(context, "integer overflow", -1);
+ return;
+ }
+ iVal = -iVal;
+ }
+ sqlite3_result_int64(context, iVal);
+ break;
+ }
+ case SQLITE_NULL: {
+ /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */
+ sqlite3_result_null(context);
+ break;
+ }
+ default: {
+ /* Because sqlite3_value_double() returns 0.0 if the argument is not
+ ** something that can be converted into a number, we have:
+ ** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that
+ ** cannot be converted to a numeric value.
+ */
+ double rVal = sqlite3_value_double(argv[0]);
+ if( rVal<0 ) rVal = -rVal;
+ sqlite3_result_double(context, rVal);
+ break;
+ }
+ }
+}
+
+/*
+** Implementation of the instr() function.
+**
+** instr(haystack,needle) finds the first occurrence of needle
+** in haystack and returns the number of previous characters plus 1,
+** or 0 if needle does not occur within haystack.
+**
+** If both haystack and needle are BLOBs, then the result is one more than
+** the number of bytes in haystack prior to the first occurrence of needle,
+** or 0 if needle never occurs in haystack.
+*/
+static void instrFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *zHaystack;
+ const unsigned char *zNeedle;
+ int nHaystack;
+ int nNeedle;
+ int typeHaystack, typeNeedle;
+ int N = 1;
+ int isText;
+
+ UNUSED_PARAMETER(argc);
+ typeHaystack = sqlite3_value_type(argv[0]);
+ typeNeedle = sqlite3_value_type(argv[1]);
+ if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
+ nHaystack = sqlite3_value_bytes(argv[0]);
+ nNeedle = sqlite3_value_bytes(argv[1]);
+ if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
+ zHaystack = sqlite3_value_blob(argv[0]);
+ zNeedle = sqlite3_value_blob(argv[1]);
+ isText = 0;
+ }else{
+ zHaystack = sqlite3_value_text(argv[0]);
+ zNeedle = sqlite3_value_text(argv[1]);
+ isText = 1;
+ }
+ while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+ N++;
+ do{
+ nHaystack--;
+ zHaystack++;
+ }while( isText && (zHaystack[0]&0xc0)==0x80 );
+ }
+ if( nNeedle>nHaystack ) N = 0;
+ sqlite3_result_int(context, N);
+}
+
+/*
+** Implementation of the substr() function.
+**
+** substr(x,p1,p2) returns p2 characters of x[] beginning with p1.
+** p1 is 1-indexed. So substr(x,1,1) returns the first character
+** of x. If x is text, then we actually count UTF-8 characters.
+** If x is a blob, then we count bytes.
+**
+** If p1 is negative, then we begin abs(p1) from the end of x[].
+**
+** If p2 is negative, return the p2 characters preceeding p1.
+*/
+static void substrFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *z;
+ const unsigned char *z2;
+ int len;
+ int p0type;
+ i64 p1, p2;
+ int negP2 = 0;
+
+ assert( argc==3 || argc==2 );
+ if( sqlite3_value_type(argv[1])==SQLITE_NULL
+ || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
+ ){
+ return;
+ }
+ p0type = sqlite3_value_type(argv[0]);
+ p1 = sqlite3_value_int(argv[1]);
+ if( p0type==SQLITE_BLOB ){
+ len = sqlite3_value_bytes(argv[0]);
+ z = sqlite3_value_blob(argv[0]);
+ if( z==0 ) return;
+ assert( len==sqlite3_value_bytes(argv[0]) );
+ }else{
+ z = sqlite3_value_text(argv[0]);
+ if( z==0 ) return;
+ len = 0;
+ if( p1<0 ){
+ for(z2=z; *z2; len++){
+ SQLITE_SKIP_UTF8(z2);
+ }
+ }
+ }
+ if( argc==3 ){
+ p2 = sqlite3_value_int(argv[2]);
+ if( p2<0 ){
+ p2 = -p2;
+ negP2 = 1;
+ }
+ }else{
+ p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
+ }
+ if( p1<0 ){
+ p1 += len;
+ if( p1<0 ){
+ p2 += p1;
+ if( p2<0 ) p2 = 0;
+ p1 = 0;
+ }
+ }else if( p1>0 ){
+ p1--;
+ }else if( p2>0 ){
+ p2--;
+ }
+ if( negP2 ){
+ p1 -= p2;
+ if( p1<0 ){
+ p2 += p1;
+ p1 = 0;
+ }
+ }
+ assert( p1>=0 && p2>=0 );
+ if( p0type!=SQLITE_BLOB ){
+ while( *z && p1 ){
+ SQLITE_SKIP_UTF8(z);
+ p1--;
+ }
+ for(z2=z; *z2 && p2; p2--){
+ SQLITE_SKIP_UTF8(z2);
+ }
+ sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT);
+ }else{
+ if( p1+p2>len ){
+ p2 = len-p1;
+ if( p2<0 ) p2 = 0;
+ }
+ sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT);
+ }
+}
+
+/*
+** Implementation of the round() function
+*/
+#ifndef SQLITE_OMIT_FLOATING_POINT
+static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+ int n = 0;
+ double r;
+ char *zBuf;
+ assert( argc==1 || argc==2 );
+ if( argc==2 ){
+ if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
+ n = sqlite3_value_int(argv[1]);
+ if( n>30 ) n = 30;
+ if( n<0 ) n = 0;
+ }
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
+ r = sqlite3_value_double(argv[0]);
+ /* If Y==0 and X will fit in a 64-bit int,
+ ** handle the rounding directly,
+ ** otherwise use printf.
+ */
+ if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
+ r = (double)((sqlite_int64)(r+0.5));
+ }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
+ r = -(double)((sqlite_int64)((-r)+0.5));
+ }else{
+ zBuf = sqlite3_mprintf("%.*f",n,r);
+ if( zBuf==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
+ sqlite3_free(zBuf);
+ }
+ sqlite3_result_double(context, r);
+}
+#endif
+
+/*
+** Allocate nByte bytes of space using sqlite3_malloc(). If the
+** allocation fails, call sqlite3_result_error_nomem() to notify
+** the database handle that malloc() has failed and return NULL.
+** If nByte is larger than the maximum string or blob length, then
+** raise an SQLITE_TOOBIG exception and return NULL.
+*/
+static void *contextMalloc(sqlite3_context *context, i64 nByte){
+ char *z;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ assert( nByte>0 );
+ testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] );
+ testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
+ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ sqlite3_result_error_toobig(context);
+ z = 0;
+ }else{
+ z = sqlite3Malloc((int)nByte);
+ if( !z ){
+ sqlite3_result_error_nomem(context);
+ }
+ }
+ return z;
+}
+
+/*
+** Implementation of the upper() and lower() SQL functions.
+*/
+static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+ char *z1;
+ const char *z2;
+ int i, n;
+ UNUSED_PARAMETER(argc);
+ z2 = (char*)sqlite3_value_text(argv[0]);
+ n = sqlite3_value_bytes(argv[0]);
+ /* Verify that the call to _bytes() does not invalidate the _text() pointer */
+ assert( z2==(char*)sqlite3_value_text(argv[0]) );
+ if( z2 ){
+ z1 = contextMalloc(context, ((i64)n)+1);
+ if( z1 ){
+ for(i=0; i<n; i++){
+ z1[i] = (char)sqlite3Toupper(z2[i]);
+ }
+ sqlite3_result_text(context, z1, n, sqlite3_free);
+ }
+ }
+}
+static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+ char *z1;
+ const char *z2;
+ int i, n;
+ UNUSED_PARAMETER(argc);
+ z2 = (char*)sqlite3_value_text(argv[0]);
+ n = sqlite3_value_bytes(argv[0]);
+ /* Verify that the call to _bytes() does not invalidate the _text() pointer */
+ assert( z2==(char*)sqlite3_value_text(argv[0]) );
+ if( z2 ){
+ z1 = contextMalloc(context, ((i64)n)+1);
+ if( z1 ){
+ for(i=0; i<n; i++){
+ z1[i] = sqlite3Tolower(z2[i]);
+ }
+ sqlite3_result_text(context, z1, n, sqlite3_free);
+ }
+ }
+}
+
+/*
+** The COALESCE() and IFNULL() functions are implemented as VDBE code so
+** that unused argument values do not have to be computed. However, we
+** still need some kind of function implementation for this routines in
+** the function table. That function implementation will never be called
+** so it doesn't matter what the implementation is. We might as well use
+** the "version()" function as a substitute.
+*/
+#define ifnullFunc versionFunc /* Substitute function - never called */
+
+/*
+** Implementation of random(). Return a random integer.
+*/
+static void randomFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ sqlite_int64 r;
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ sqlite3_randomness(sizeof(r), &r);
+ if( r<0 ){
+ /* We need to prevent a random number of 0x8000000000000000
+ ** (or -9223372036854775808) since when you do abs() of that
+ ** number of you get the same value back again. To do this
+ ** in a way that is testable, mask the sign bit off of negative
+ ** values, resulting in a positive value. Then take the
+ ** 2s complement of that positive value. The end result can
+ ** therefore be no less than -9223372036854775807.
+ */
+ r = -(r & LARGEST_INT64);
+ }
+ sqlite3_result_int64(context, r);
+}
+
+/*
+** Implementation of randomblob(N). Return a random blob
+** that is N bytes long.
+*/
+static void randomBlob(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int n;
+ unsigned char *p;
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ n = sqlite3_value_int(argv[0]);
+ if( n<1 ){
+ n = 1;
+ }
+ p = contextMalloc(context, n);
+ if( p ){
+ sqlite3_randomness(n, p);
+ sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
+ }
+}
+
+/*
+** Implementation of the last_insert_rowid() SQL function. The return
+** value is the same as the sqlite3_last_insert_rowid() API function.
+*/
+static void last_insert_rowid(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a
+ ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface
+ ** function. */
+ sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
+}
+
+/*
+** Implementation of the changes() SQL function.
+**
+** IMP: R-62073-11209 The changes() SQL function is a wrapper
+** around the sqlite3_changes() C/C++ function and hence follows the same
+** rules for counting changes.
+*/
+static void changes(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ sqlite3_result_int(context, sqlite3_changes(db));
+}
+
+/*
+** Implementation of the total_changes() SQL function. The return value is
+** the same as the sqlite3_total_changes() API function.
+*/
+static void total_changes(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ /* IMP: R-52756-41993 This function is a wrapper around the
+ ** sqlite3_total_changes() C/C++ interface. */
+ sqlite3_result_int(context, sqlite3_total_changes(db));
+}
+
+/*
+** A structure defining how to do GLOB-style comparisons.
+*/
+struct compareInfo {
+ u8 matchAll;
+ u8 matchOne;
+ u8 matchSet;
+ u8 noCase;
+};
+
+/*
+** For LIKE and GLOB matching on EBCDIC machines, assume that every
+** character is exactly one byte in size. Also, all characters are
+** able to participate in upper-case-to-lower-case mappings in EBCDIC
+** whereas only characters less than 0x80 do in ASCII.
+*/
+#if defined(SQLITE_EBCDIC)
+# define sqlite3Utf8Read(A) (*((*A)++))
+# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
+#else
+# define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
+#endif
+
+static const struct compareInfo globInfo = { '*', '?', '[', 0 };
+/* The correct SQL-92 behavior is for the LIKE operator to ignore
+** case. Thus 'a' LIKE 'A' would be true. */
+static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
+/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
+** is case sensitive causing 'a' LIKE 'A' to be false */
+static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
+
+/*
+** Compare two UTF-8 strings for equality where the first string can
+** potentially be a "glob" expression. Return true (1) if they
+** are the same and false (0) if they are different.
+**
+** Globbing rules:
+**
+** '*' Matches any sequence of zero or more characters.
+**
+** '?' Matches exactly one character.
+**
+** [...] Matches one character from the enclosed list of
+** characters.
+**
+** [^...] Matches one character not in the enclosed list.
+**
+** With the [...] and [^...] matching, a ']' character can be included
+** in the list by making it the first character after '[' or '^'. A
+** range of characters can be specified using '-'. Example:
+** "[a-z]" matches any single lower-case letter. To match a '-', make
+** it the last character in the list.
+**
+** This routine is usually quick, but can be N**2 in the worst case.
+**
+** Hints: to match '*' or '?', put them in "[]". Like this:
+**
+** abc[*]xyz Matches "abc*xyz" only
+*/
+static int patternCompare(
+ const u8 *zPattern, /* The glob pattern */
+ const u8 *zString, /* The string to compare against the glob */
+ const struct compareInfo *pInfo, /* Information about how to do the compare */
+ u32 esc /* The escape character */
+){
+ u32 c, c2;
+ int invert;
+ int seen;
+ u8 matchOne = pInfo->matchOne;
+ u8 matchAll = pInfo->matchAll;
+ u8 matchSet = pInfo->matchSet;
+ u8 noCase = pInfo->noCase;
+ int prevEscape = 0; /* True if the previous character was 'escape' */
+
+ while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
+ if( c==matchAll && !prevEscape ){
+ while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
+ || c == matchOne ){
+ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
+ return 0;
+ }
+ }
+ if( c==0 ){
+ return 1;
+ }else if( c==esc ){
+ c = sqlite3Utf8Read(&zPattern);
+ if( c==0 ){
+ return 0;
+ }
+ }else if( c==matchSet ){
+ assert( esc==0 ); /* This is GLOB, not LIKE */
+ assert( matchSet<0x80 ); /* '[' is a single-byte character */
+ while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
+ SQLITE_SKIP_UTF8(zString);
+ }
+ return *zString!=0;
+ }
+ while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
+ if( noCase ){
+ GlogUpperToLower(c2);
+ GlogUpperToLower(c);
+ while( c2 != 0 && c2 != c ){
+ c2 = sqlite3Utf8Read(&zString);
+ GlogUpperToLower(c2);
+ }
+ }else{
+ while( c2 != 0 && c2 != c ){
+ c2 = sqlite3Utf8Read(&zString);
+ }
+ }
+ if( c2==0 ) return 0;
+ if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
+ }
+ return 0;
+ }else if( c==matchOne && !prevEscape ){
+ if( sqlite3Utf8Read(&zString)==0 ){
+ return 0;
+ }
+ }else if( c==matchSet ){
+ u32 prior_c = 0;
+ assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
+ seen = 0;
+ invert = 0;
+ c = sqlite3Utf8Read(&zString);
+ if( c==0 ) return 0;
+ c2 = sqlite3Utf8Read(&zPattern);
+ if( c2=='^' ){
+ invert = 1;
+ c2 = sqlite3Utf8Read(&zPattern);
+ }
+ if( c2==']' ){
+ if( c==']' ) seen = 1;
+ c2 = sqlite3Utf8Read(&zPattern);
+ }
+ while( c2 && c2!=']' ){
+ if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
+ c2 = sqlite3Utf8Read(&zPattern);
+ if( c>=prior_c && c<=c2 ) seen = 1;
+ prior_c = 0;
+ }else{
+ if( c==c2 ){
+ seen = 1;
+ }
+ prior_c = c2;
+ }
+ c2 = sqlite3Utf8Read(&zPattern);
+ }
+ if( c2==0 || (seen ^ invert)==0 ){
+ return 0;
+ }
+ }else if( esc==c && !prevEscape ){
+ prevEscape = 1;
+ }else{
+ c2 = sqlite3Utf8Read(&zString);
+ if( noCase ){
+ GlogUpperToLower(c);
+ GlogUpperToLower(c2);
+ }
+ if( c!=c2 ){
+ return 0;
+ }
+ prevEscape = 0;
+ }
+ }
+ return *zString==0;
+}
+
+/*
+** Count the number of times that the LIKE operator (or GLOB which is
+** just a variation of LIKE) gets called. This is used for testing
+** only.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_like_count = 0;
+#endif
+
+
+/*
+** Implementation of the like() SQL function. This function implements
+** the build-in LIKE operator. The first argument to the function is the
+** pattern and the second argument is the string. So, the SQL statements:
+**
+** A LIKE B
+**
+** is implemented as like(B,A).
+**
+** This same function (with a different compareInfo structure) computes
+** the GLOB operator.
+*/
+static void likeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *zA, *zB;
+ u32 escape = 0;
+ int nPat;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+
+ zB = sqlite3_value_text(argv[0]);
+ zA = sqlite3_value_text(argv[1]);
+
+ /* Limit the length of the LIKE or GLOB pattern to avoid problems
+ ** of deep recursion and N*N behavior in patternCompare().
+ */
+ nPat = sqlite3_value_bytes(argv[0]);
+ testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] );
+ testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 );
+ if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
+ sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
+ return;
+ }
+ assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */
+
+ if( argc==3 ){
+ /* The escape character string must consist of a single UTF-8 character.
+ ** Otherwise, return an error.
+ */
+ const unsigned char *zEsc = sqlite3_value_text(argv[2]);
+ if( zEsc==0 ) return;
+ if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
+ sqlite3_result_error(context,
+ "ESCAPE expression must be a single character", -1);
+ return;
+ }
+ escape = sqlite3Utf8Read(&zEsc);
+ }
+ if( zA && zB ){
+ struct compareInfo *pInfo = sqlite3_user_data(context);
+#ifdef SQLITE_TEST
+ sqlite3_like_count++;
+#endif
+
+ sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
+ }
+}
+
+/*
+** Implementation of the NULLIF(x,y) function. The result is the first
+** argument if the arguments are different. The result is NULL if the
+** arguments are equal to each other.
+*/
+static void nullifFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ CollSeq *pColl = sqlite3GetFuncCollSeq(context);
+ UNUSED_PARAMETER(NotUsed);
+ if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){
+ sqlite3_result_value(context, argv[0]);
+ }
+}
+
+/*
+** Implementation of the sqlite_version() function. The result is the version
+** of the SQLite library that is running.
+*/
+static void versionFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ /* IMP: R-48699-48617 This function is an SQL wrapper around the
+ ** sqlite3_libversion() C-interface. */
+ sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC);
+}
+
+/*
+** Implementation of the sqlite_source_id() function. The result is a string
+** that identifies the particular version of the source code used to build
+** SQLite.
+*/
+static void sourceidFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **NotUsed2
+){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ /* IMP: R-24470-31136 This function is an SQL wrapper around the
+ ** sqlite3_sourceid() C interface. */
+ sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
+}
+
+/*
+** Implementation of the sqlite_log() function. This is a wrapper around
+** sqlite3_log(). The return value is NULL. The function exists purely for
+** its side-effects.
+*/
+static void errlogFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(context);
+ sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1]));
+}
+
+/*
+** Implementation of the sqlite_compileoption_used() function.
+** The result is an integer that identifies if the compiler option
+** was used to build SQLite.
+*/
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+static void compileoptionusedFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const char *zOptName;
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL
+ ** function is a wrapper around the sqlite3_compileoption_used() C/C++
+ ** function.
+ */
+ if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
+ sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
+ }
+}
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+
+/*
+** Implementation of the sqlite_compileoption_get() function.
+** The result is a string that identifies the compiler options
+** used to build SQLite.
+*/
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+static void compileoptiongetFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int n;
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
+ ** is a wrapper around the sqlite3_compileoption_get() C/C++ function.
+ */
+ n = sqlite3_value_int(argv[0]);
+ sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
+}
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+
+/* Array for converting from half-bytes (nybbles) into ASCII hex
+** digits. */
+static const char hexdigits[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+/*
+** EXPERIMENTAL - This is not an official function. The interface may
+** change. This function may disappear. Do not write code that depends
+** on this function.
+**
+** Implementation of the QUOTE() function. This function takes a single
+** argument. If the argument is numeric, the return value is the same as
+** the argument. If the argument is NULL, the return value is the string
+** "NULL". Otherwise, the argument is enclosed in single quotes with
+** single-quote escapes.
+*/
+static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ switch( sqlite3_value_type(argv[0]) ){
+ case SQLITE_FLOAT: {
+ double r1, r2;
+ char zBuf[50];
+ r1 = sqlite3_value_double(argv[0]);
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
+ sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
+ if( r1!=r2 ){
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
+ }
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ break;
+ }
+ case SQLITE_INTEGER: {
+ sqlite3_result_value(context, argv[0]);
+ break;
+ }
+ case SQLITE_BLOB: {
+ char *zText = 0;
+ char const *zBlob = sqlite3_value_blob(argv[0]);
+ int nBlob = sqlite3_value_bytes(argv[0]);
+ assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
+ zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
+ if( zText ){
+ int i;
+ for(i=0; i<nBlob; i++){
+ zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
+ zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F];
+ }
+ zText[(nBlob*2)+2] = '\'';
+ zText[(nBlob*2)+3] = '\0';
+ zText[0] = 'X';
+ zText[1] = '\'';
+ sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
+ sqlite3_free(zText);
+ }
+ break;
+ }
+ case SQLITE_TEXT: {
+ int i,j;
+ u64 n;
+ const unsigned char *zArg = sqlite3_value_text(argv[0]);
+ char *z;
+
+ if( zArg==0 ) return;
+ for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
+ z = contextMalloc(context, ((i64)i)+((i64)n)+3);
+ if( z ){
+ z[0] = '\'';
+ for(i=0, j=1; zArg[i]; i++){
+ z[j++] = zArg[i];
+ if( zArg[i]=='\'' ){
+ z[j++] = '\'';
+ }
+ }
+ z[j++] = '\'';
+ z[j] = 0;
+ sqlite3_result_text(context, z, j, sqlite3_free);
+ }
+ break;
+ }
+ default: {
+ assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
+ sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
+ break;
+ }
+ }
+}
+
+/*
+** The unicode() function. Return the integer unicode code-point value
+** for the first character of the input string.
+*/
+static void unicodeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *z = sqlite3_value_text(argv[0]);
+ (void)argc;
+ if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z));
+}
+
+/*
+** The char() function takes zero or more arguments, each of which is
+** an integer. It constructs a string where each character of the string
+** is the unicode character for the corresponding integer argument.
+*/
+static void charFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ unsigned char *z, *zOut;
+ int i;
+ zOut = z = sqlite3_malloc( argc*4 );
+ if( z==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ for(i=0; i<argc; i++){
+ sqlite3_int64 x;
+ unsigned c;
+ x = sqlite3_value_int64(argv[i]);
+ if( x<0 || x>0x10ffff ) x = 0xfffd;
+ c = (unsigned)(x & 0x1fffff);
+ if( c<0x00080 ){
+ *zOut++ = (u8)(c&0xFF);
+ }else if( c<0x00800 ){
+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);
+ *zOut++ = 0x80 + (u8)(c & 0x3F);
+ }else if( c<0x10000 ){
+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+ *zOut++ = 0x80 + (u8)(c & 0x3F);
+ }else{
+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);
+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+ *zOut++ = 0x80 + (u8)(c & 0x3F);
+ } \
+ }
+ sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free);
+}
+
+/*
+** The hex() function. Interpret the argument as a blob. Return
+** a hexadecimal rendering as text.
+*/
+static void hexFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int i, n;
+ const unsigned char *pBlob;
+ char *zHex, *z;
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ pBlob = sqlite3_value_blob(argv[0]);
+ n = sqlite3_value_bytes(argv[0]);
+ assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
+ z = zHex = contextMalloc(context, ((i64)n)*2 + 1);
+ if( zHex ){
+ for(i=0; i<n; i++, pBlob++){
+ unsigned char c = *pBlob;
+ *(z++) = hexdigits[(c>>4)&0xf];
+ *(z++) = hexdigits[c&0xf];
+ }
+ *z = 0;
+ sqlite3_result_text(context, zHex, n*2, sqlite3_free);
+ }
+}
+
+/*
+** The zeroblob(N) function returns a zero-filled blob of size N bytes.
+*/
+static void zeroblobFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ i64 n;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ n = sqlite3_value_int64(argv[0]);
+ testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] );
+ testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
+ if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ sqlite3_result_error_toobig(context);
+ }else{
+ sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */
+ }
+}
+
+/*
+** The replace() function. Three arguments are all strings: call
+** them A, B, and C. The result is also a string which is derived
+** from A by replacing every occurance of B with C. The match
+** must be exact. Collating sequences are not used.
+*/
+static void replaceFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *zStr; /* The input string A */
+ const unsigned char *zPattern; /* The pattern string B */
+ const unsigned char *zRep; /* The replacement string C */
+ unsigned char *zOut; /* The output */
+ int nStr; /* Size of zStr */
+ int nPattern; /* Size of zPattern */
+ int nRep; /* Size of zRep */
+ i64 nOut; /* Maximum size of zOut */
+ int loopLimit; /* Last zStr[] that might match zPattern[] */
+ int i, j; /* Loop counters */
+
+ assert( argc==3 );
+ UNUSED_PARAMETER(argc);
+ zStr = sqlite3_value_text(argv[0]);
+ if( zStr==0 ) return;
+ nStr = sqlite3_value_bytes(argv[0]);
+ assert( zStr==sqlite3_value_text(argv[0]) ); /* No encoding change */
+ zPattern = sqlite3_value_text(argv[1]);
+ if( zPattern==0 ){
+ assert( sqlite3_value_type(argv[1])==SQLITE_NULL
+ || sqlite3_context_db_handle(context)->mallocFailed );
+ return;
+ }
+ if( zPattern[0]==0 ){
+ assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
+ sqlite3_result_value(context, argv[0]);
+ return;
+ }
+ nPattern = sqlite3_value_bytes(argv[1]);
+ assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */
+ zRep = sqlite3_value_text(argv[2]);
+ if( zRep==0 ) return;
+ nRep = sqlite3_value_bytes(argv[2]);
+ assert( zRep==sqlite3_value_text(argv[2]) );
+ nOut = nStr + 1;
+ assert( nOut<SQLITE_MAX_LENGTH );
+ zOut = contextMalloc(context, (i64)nOut);
+ if( zOut==0 ){
+ return;
+ }
+ loopLimit = nStr - nPattern;
+ for(i=j=0; i<=loopLimit; i++){
+ if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
+ zOut[j++] = zStr[i];
+ }else{
+ u8 *zOld;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ nOut += nRep - nPattern;
+ testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
+ testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
+ if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ sqlite3_result_error_toobig(context);
+ sqlite3_free(zOut);
+ return;
+ }
+ zOld = zOut;
+ zOut = sqlite3_realloc(zOut, (int)nOut);
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(context);
+ sqlite3_free(zOld);
+ return;
+ }
+ memcpy(&zOut[j], zRep, nRep);
+ j += nRep;
+ i += nPattern-1;
+ }
+ }
+ assert( j+nStr-i+1==nOut );
+ memcpy(&zOut[j], &zStr[i], nStr-i);
+ j += nStr - i;
+ assert( j<=nOut );
+ zOut[j] = 0;
+ sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);
+}
+
+/*
+** Implementation of the TRIM(), LTRIM(), and RTRIM() functions.
+** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both.
+*/
+static void trimFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *zIn; /* Input string */
+ const unsigned char *zCharSet; /* Set of characters to trim */
+ int nIn; /* Number of bytes in input */
+ int flags; /* 1: trimleft 2: trimright 3: trim */
+ int i; /* Loop counter */
+ unsigned char *aLen = 0; /* Length of each character in zCharSet */
+ unsigned char **azChar = 0; /* Individual characters in zCharSet */
+ int nChar; /* Number of characters in zCharSet */
+
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
+ return;
+ }
+ zIn = sqlite3_value_text(argv[0]);
+ if( zIn==0 ) return;
+ nIn = sqlite3_value_bytes(argv[0]);
+ assert( zIn==sqlite3_value_text(argv[0]) );
+ if( argc==1 ){
+ static const unsigned char lenOne[] = { 1 };
+ static unsigned char * const azOne[] = { (u8*)" " };
+ nChar = 1;
+ aLen = (u8*)lenOne;
+ azChar = (unsigned char **)azOne;
+ zCharSet = 0;
+ }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
+ return;
+ }else{
+ const unsigned char *z;
+ for(z=zCharSet, nChar=0; *z; nChar++){
+ SQLITE_SKIP_UTF8(z);
+ }
+ if( nChar>0 ){
+ azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
+ if( azChar==0 ){
+ return;
+ }
+ aLen = (unsigned char*)&azChar[nChar];
+ for(z=zCharSet, nChar=0; *z; nChar++){
+ azChar[nChar] = (unsigned char *)z;
+ SQLITE_SKIP_UTF8(z);
+ aLen[nChar] = (u8)(z - azChar[nChar]);
+ }
+ }
+ }
+ if( nChar>0 ){
+ flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
+ if( flags & 1 ){
+ while( nIn>0 ){
+ int len = 0;
+ for(i=0; i<nChar; i++){
+ len = aLen[i];
+ if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
+ }
+ if( i>=nChar ) break;
+ zIn += len;
+ nIn -= len;
+ }
+ }
+ if( flags & 2 ){
+ while( nIn>0 ){
+ int len = 0;
+ for(i=0; i<nChar; i++){
+ len = aLen[i];
+ if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
+ }
+ if( i>=nChar ) break;
+ nIn -= len;
+ }
+ }
+ if( zCharSet ){
+ sqlite3_free(azChar);
+ }
+ }
+ sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
+}
+
+
+/* IMP: R-25361-16150 This function is omitted from SQLite by default. It
+** is only available if the SQLITE_SOUNDEX compile-time option is used
+** when SQLite is built.
+*/
+#ifdef SQLITE_SOUNDEX
+/*
+** Compute the soundex encoding of a word.
+**
+** IMP: R-59782-00072 The soundex(X) function returns a string that is the
+** soundex encoding of the string X.
+*/
+static void soundexFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ char zResult[8];
+ const u8 *zIn;
+ int i, j;
+ static const unsigned char iCode[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
+ 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
+ 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
+ };
+ assert( argc==1 );
+ zIn = (u8*)sqlite3_value_text(argv[0]);
+ if( zIn==0 ) zIn = (u8*)"";
+ for(i=0; zIn[i] && !sqlite3Isalpha(zIn[i]); i++){}
+ if( zIn[i] ){
+ u8 prevcode = iCode[zIn[i]&0x7f];
+ zResult[0] = sqlite3Toupper(zIn[i]);
+ for(j=1; j<4 && zIn[i]; i++){
+ int code = iCode[zIn[i]&0x7f];
+ if( code>0 ){
+ if( code!=prevcode ){
+ prevcode = code;
+ zResult[j++] = code + '0';
+ }
+ }else{
+ prevcode = 0;
+ }
+ }
+ while( j<4 ){
+ zResult[j++] = '0';
+ }
+ zResult[j] = 0;
+ sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT);
+ }else{
+ /* IMP: R-64894-50321 The string "?000" is returned if the argument
+ ** is NULL or contains no ASCII alphabetic characters. */
+ sqlite3_result_text(context, "?000", 4, SQLITE_STATIC);
+ }
+}
+#endif /* SQLITE_SOUNDEX */
+
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+/*
+** A function that loads a shared-library extension then returns NULL.
+*/
+static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
+ const char *zFile = (const char *)sqlite3_value_text(argv[0]);
+ const char *zProc;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ char *zErrMsg = 0;
+
+ if( argc==2 ){
+ zProc = (const char *)sqlite3_value_text(argv[1]);
+ }else{
+ zProc = 0;
+ }
+ if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){
+ sqlite3_result_error(context, zErrMsg, -1);
+ sqlite3_free(zErrMsg);
+ }
+}
+#endif
+
+
+/*
+** An instance of the following structure holds the context of a
+** sum() or avg() aggregate computation.
+*/
+typedef struct SumCtx SumCtx;
+struct SumCtx {
+ double rSum; /* Floating point sum */
+ i64 iSum; /* Integer sum */
+ i64 cnt; /* Number of elements summed */
+ u8 overflow; /* True if integer overflow seen */
+ u8 approx; /* True if non-integer value was input to the sum */
+};
+
+/*
+** Routines used to compute the sum, average, and total.
+**
+** The SUM() function follows the (broken) SQL standard which means
+** that it returns NULL if it sums over no inputs. TOTAL returns
+** 0.0 in that case. In addition, TOTAL always returns a float where
+** SUM might return an integer if it never encounters a floating point
+** value. TOTAL never fails, but SUM might through an exception if
+** it overflows an integer.
+*/
+static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
+ SumCtx *p;
+ int type;
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ p = sqlite3_aggregate_context(context, sizeof(*p));
+ type = sqlite3_value_numeric_type(argv[0]);
+ if( p && type!=SQLITE_NULL ){
+ p->cnt++;
+ if( type==SQLITE_INTEGER ){
+ i64 v = sqlite3_value_int64(argv[0]);
+ p->rSum += v;
+ if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){
+ p->overflow = 1;
+ }
+ }else{
+ p->rSum += sqlite3_value_double(argv[0]);
+ p->approx = 1;
+ }
+ }
+}
+static void sumFinalize(sqlite3_context *context){
+ SumCtx *p;
+ p = sqlite3_aggregate_context(context, 0);
+ if( p && p->cnt>0 ){
+ if( p->overflow ){
+ sqlite3_result_error(context,"integer overflow",-1);
+ }else if( p->approx ){
+ sqlite3_result_double(context, p->rSum);
+ }else{
+ sqlite3_result_int64(context, p->iSum);
+ }
+ }
+}
+static void avgFinalize(sqlite3_context *context){
+ SumCtx *p;
+ p = sqlite3_aggregate_context(context, 0);
+ if( p && p->cnt>0 ){
+ sqlite3_result_double(context, p->rSum/(double)p->cnt);
+ }
+}
+static void totalFinalize(sqlite3_context *context){
+ SumCtx *p;
+ p = sqlite3_aggregate_context(context, 0);
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ sqlite3_result_double(context, p ? p->rSum : (double)0);
+}
+
+/*
+** The following structure keeps track of state information for the
+** count() aggregate function.
+*/
+typedef struct CountCtx CountCtx;
+struct CountCtx {
+ i64 n;
+};
+
+/*
+** Routines to implement the count() aggregate function.
+*/
+static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
+ CountCtx *p;
+ p = sqlite3_aggregate_context(context, sizeof(*p));
+ if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){
+ p->n++;
+ }
+
+#ifndef SQLITE_OMIT_DEPRECATED
+ /* The sqlite3_aggregate_count() function is deprecated. But just to make
+ ** sure it still operates correctly, verify that its count agrees with our
+ ** internal count when using count(*) and when the total count can be
+ ** expressed as a 32-bit integer. */
+ assert( argc==1 || p==0 || p->n>0x7fffffff
+ || p->n==sqlite3_aggregate_count(context) );
+#endif
+}
+static void countFinalize(sqlite3_context *context){
+ CountCtx *p;
+ p = sqlite3_aggregate_context(context, 0);
+ sqlite3_result_int64(context, p ? p->n : 0);
+}
+
+/*
+** Routines to implement min() and max() aggregate functions.
+*/
+static void minmaxStep(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ Mem *pArg = (Mem *)argv[0];
+ Mem *pBest;
+ UNUSED_PARAMETER(NotUsed);
+
+ pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
+ if( !pBest ) return;
+
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
+ if( pBest->flags ) sqlite3SkipAccumulatorLoad(context);
+ }else if( pBest->flags ){
+ int max;
+ int cmp;
+ CollSeq *pColl = sqlite3GetFuncCollSeq(context);
+ /* This step function is used for both the min() and max() aggregates,
+ ** the only difference between the two being that the sense of the
+ ** comparison is inverted. For the max() aggregate, the
+ ** sqlite3_user_data() function returns (void *)-1. For min() it
+ ** returns (void *)db, where db is the sqlite3* database pointer.
+ ** Therefore the next statement sets variable 'max' to 1 for the max()
+ ** aggregate, or 0 for min().
+ */
+ max = sqlite3_user_data(context)!=0;
+ cmp = sqlite3MemCompare(pBest, pArg, pColl);
+ if( (max && cmp<0) || (!max && cmp>0) ){
+ sqlite3VdbeMemCopy(pBest, pArg);
+ }else{
+ sqlite3SkipAccumulatorLoad(context);
+ }
+ }else{
+ sqlite3VdbeMemCopy(pBest, pArg);
+ }
+}
+static void minMaxFinalize(sqlite3_context *context){
+ sqlite3_value *pRes;
+ pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
+ if( pRes ){
+ if( pRes->flags ){
+ sqlite3_result_value(context, pRes);
+ }
+ sqlite3VdbeMemRelease(pRes);
+ }
+}
+
+/*
+** group_concat(EXPR, ?SEPARATOR?)
+*/
+static void groupConcatStep(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const char *zVal;
+ StrAccum *pAccum;
+ const char *zSep;
+ int nVal, nSep;
+ assert( argc==1 || argc==2 );
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
+ pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
+
+ if( pAccum ){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ int firstTerm = pAccum->useMalloc==0;
+ pAccum->useMalloc = 2;
+ pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
+ if( !firstTerm ){
+ if( argc==2 ){
+ zSep = (char*)sqlite3_value_text(argv[1]);
+ nSep = sqlite3_value_bytes(argv[1]);
+ }else{
+ zSep = ",";
+ nSep = 1;
+ }
+ sqlite3StrAccumAppend(pAccum, zSep, nSep);
+ }
+ zVal = (char*)sqlite3_value_text(argv[0]);
+ nVal = sqlite3_value_bytes(argv[0]);
+ sqlite3StrAccumAppend(pAccum, zVal, nVal);
+ }
+}
+static void groupConcatFinalize(sqlite3_context *context){
+ StrAccum *pAccum;
+ pAccum = sqlite3_aggregate_context(context, 0);
+ if( pAccum ){
+ if( pAccum->tooBig ){
+ sqlite3_result_error_toobig(context);
+ }else if( pAccum->mallocFailed ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
+ sqlite3_free);
+ }
+ }
+}
+
+/*
+** This routine does per-connection function registration. Most
+** of the built-in functions above are part of the global function set.
+** This routine only deals with those that are not global.
+*/
+SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
+ int rc = sqlite3_overload_function(db, "MATCH", 2);
+ assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
+ if( rc==SQLITE_NOMEM ){
+ db->mallocFailed = 1;
+ }
+}
+
+/*
+** Set the LIKEOPT flag on the 2-argument function with the given name.
+*/
+static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
+ FuncDef *pDef;
+ pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName),
+ 2, SQLITE_UTF8, 0);
+ if( ALWAYS(pDef) ){
+ pDef->flags = flagVal;
+ }
+}
+
+/*
+** Register the built-in LIKE and GLOB functions. The caseSensitive
+** parameter determines whether or not the LIKE operator is case
+** sensitive. GLOB is always case sensitive.
+*/
+SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
+ struct compareInfo *pInfo;
+ if( caseSensitive ){
+ pInfo = (struct compareInfo*)&likeInfoAlt;
+ }else{
+ pInfo = (struct compareInfo*)&likeInfoNorm;
+ }
+ sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
+ sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
+ sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
+ (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0);
+ setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
+ setLikeOptFlag(db, "like",
+ caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
+}
+
+/*
+** pExpr points to an expression which implements a function. If
+** it is appropriate to apply the LIKE optimization to that function
+** then set aWc[0] through aWc[2] to the wildcard characters and
+** return TRUE. If the function is not a LIKE-style function then
+** return FALSE.
+*/
+SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
+ FuncDef *pDef;
+ if( pExpr->op!=TK_FUNCTION
+ || !pExpr->x.pList
+ || pExpr->x.pList->nExpr!=2
+ ){
+ return 0;
+ }
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken,
+ sqlite3Strlen30(pExpr->u.zToken),
+ 2, SQLITE_UTF8, 0);
+ if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
+ return 0;
+ }
+
+ /* The memcpy() statement assumes that the wildcard characters are
+ ** the first three statements in the compareInfo structure. The
+ ** asserts() that follow verify that assumption
+ */
+ memcpy(aWc, pDef->pUserData, 3);
+ assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
+ assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
+ assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
+ *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
+ return 1;
+}
+
+/*
+** All all of the FuncDef structures in the aBuiltinFunc[] array above
+** to the global function hash table. This occurs at start-time (as
+** a consequence of calling sqlite3_initialize()).
+**
+** After this routine runs
+*/
+SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
+ /*
+ ** The following array holds FuncDef structures for all of the functions
+ ** defined in this file.
+ **
+ ** The array cannot be constant since changes are made to the
+ ** FuncDef.pHash elements at start-time. The elements of this array
+ ** are read-only after initialization is complete.
+ */
+ static SQLITE_WSD FuncDef aBuiltinFunc[] = {
+ FUNCTION(ltrim, 1, 1, 0, trimFunc ),
+ FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+ FUNCTION(rtrim, 1, 2, 0, trimFunc ),
+ FUNCTION(rtrim, 2, 2, 0, trimFunc ),
+ FUNCTION(trim, 1, 3, 0, trimFunc ),
+ FUNCTION(trim, 2, 3, 0, trimFunc ),
+ FUNCTION(min, -1, 0, 1, minmaxFunc ),
+ FUNCTION(min, 0, 0, 1, 0 ),
+ AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(max, -1, 1, 1, minmaxFunc ),
+ FUNCTION(max, 0, 1, 1, 0 ),
+ AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
+ FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
+ FUNCTION(instr, 2, 0, 0, instrFunc ),
+ FUNCTION(substr, 2, 0, 0, substrFunc ),
+ FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
+ FUNCTION(char, -1, 0, 0, charFunc ),
+ FUNCTION(abs, 1, 0, 0, absFunc ),
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ FUNCTION(round, 1, 0, 0, roundFunc ),
+ FUNCTION(round, 2, 0, 0, roundFunc ),
+#endif
+ FUNCTION(upper, 1, 0, 0, upperFunc ),
+ FUNCTION(lower, 1, 0, 0, lowerFunc ),
+ FUNCTION(coalesce, 1, 0, 0, 0 ),
+ FUNCTION(coalesce, 0, 0, 0, 0 ),
+ FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
+ FUNCTION(hex, 1, 0, 0, hexFunc ),
+ FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
+ FUNCTION(random, 0, 0, 0, randomFunc ),
+ FUNCTION(randomblob, 1, 0, 0, randomBlob ),
+ FUNCTION(nullif, 2, 0, 1, nullifFunc ),
+ FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
+ FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
+ FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+ FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
+ FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+ FUNCTION(quote, 1, 0, 0, quoteFunc ),
+ FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
+ FUNCTION(changes, 0, 0, 0, changes ),
+ FUNCTION(total_changes, 0, 0, 0, total_changes ),
+ FUNCTION(replace, 3, 0, 0, replaceFunc ),
+ FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
+ #ifdef SQLITE_SOUNDEX
+ FUNCTION(soundex, 1, 0, 0, soundexFunc ),
+ #endif
+ #ifndef SQLITE_OMIT_LOAD_EXTENSION
+ FUNCTION(load_extension, 1, 0, 0, loadExt ),
+ FUNCTION(load_extension, 2, 0, 0, loadExt ),
+ #endif
+ AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
+ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
+ AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
+ /* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */
+ {0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
+ AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
+ AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
+ AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
+
+ LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #ifdef SQLITE_CASE_SENSITIVE_LIKE
+ LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #else
+ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ #endif
+ };
+
+ int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
+
+ for(i=0; i<ArraySize(aBuiltinFunc); i++){
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
+ }
+ sqlite3RegisterDateTimeFunctions();
+#ifndef SQLITE_OMIT_ALTERTABLE
+ sqlite3AlterFunctions();
+#endif
+}
+
+/************** End of func.c ************************************************/
+/************** Begin file fkey.c ********************************************/
+/*
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used by the compiler to add foreign key
+** support to compiled SQL statements.
+*/
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+#ifndef SQLITE_OMIT_TRIGGER
+
+/*
+** Deferred and Immediate FKs
+** --------------------------
+**
+** Foreign keys in SQLite come in two flavours: deferred and immediate.
+** If an immediate foreign key constraint is violated,
+** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
+** statement transaction rolled back. If a
+** deferred foreign key constraint is violated, no action is taken
+** immediately. However if the application attempts to commit the
+** transaction before fixing the constraint violation, the attempt fails.
+**
+** Deferred constraints are implemented using a simple counter associated
+** with the database handle. The counter is set to zero each time a
+** database transaction is opened. Each time a statement is executed
+** that causes a foreign key violation, the counter is incremented. Each
+** time a statement is executed that removes an existing violation from
+** the database, the counter is decremented. When the transaction is
+** committed, the commit fails if the current value of the counter is
+** greater than zero. This scheme has two big drawbacks:
+**
+** * When a commit fails due to a deferred foreign key constraint,
+** there is no way to tell which foreign constraint is not satisfied,
+** or which row it is not satisfied for.
+**
+** * If the database contains foreign key violations when the
+** transaction is opened, this may cause the mechanism to malfunction.
+**
+** Despite these problems, this approach is adopted as it seems simpler
+** than the alternatives.
+**
+** INSERT operations:
+**
+** I.1) For each FK for which the table is the child table, search
+** the parent table for a match. If none is found increment the
+** constraint counter.
+**
+** I.2) For each FK for which the table is the parent table,
+** search the child table for rows that correspond to the new
+** row in the parent table. Decrement the counter for each row
+** found (as the constraint is now satisfied).
+**
+** DELETE operations:
+**
+** D.1) For each FK for which the table is the child table,
+** search the parent table for a row that corresponds to the
+** deleted row in the child table. If such a row is not found,
+** decrement the counter.
+**
+** D.2) For each FK for which the table is the parent table, search
+** the child table for rows that correspond to the deleted row
+** in the parent table. For each found increment the counter.
+**
+** UPDATE operations:
+**
+** An UPDATE command requires that all 4 steps above are taken, but only
+** for FK constraints for which the affected columns are actually
+** modified (values must be compared at runtime).
+**
+** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2.
+** This simplifies the implementation a bit.
+**
+** For the purposes of immediate FK constraints, the OR REPLACE conflict
+** resolution is considered to delete rows before the new row is inserted.
+** If a delete caused by OR REPLACE violates an FK constraint, an exception
+** is thrown, even if the FK constraint would be satisfied after the new
+** row is inserted.
+**
+** Immediate constraints are usually handled similarly. The only difference
+** is that the counter used is stored as part of each individual statement
+** object (struct Vdbe). If, after the statement has run, its immediate
+** constraint counter is greater than zero,
+** it returns SQLITE_CONSTRAINT_FOREIGNKEY
+** and the statement transaction is rolled back. An exception is an INSERT
+** statement that inserts a single row only (no triggers). In this case,
+** instead of using a counter, an exception is thrown immediately if the
+** INSERT violates a foreign key constraint. This is necessary as such
+** an INSERT does not open a statement transaction.
+**
+** TODO: How should dropping a table be handled? How should renaming a
+** table be handled?
+**
+**
+** Query API Notes
+** ---------------
+**
+** Before coding an UPDATE or DELETE row operation, the code-generator
+** for those two operations needs to know whether or not the operation
+** requires any FK processing and, if so, which columns of the original
+** row are required by the FK processing VDBE code (i.e. if FKs were
+** implemented using triggers, which of the old.* columns would be
+** accessed). No information is required by the code-generator before
+** coding an INSERT operation. The functions used by the UPDATE/DELETE
+** generation code to query for this information are:
+**
+** sqlite3FkRequired() - Test to see if FK processing is required.
+** sqlite3FkOldmask() - Query for the set of required old.* columns.
+**
+**
+** Externally accessible module functions
+** --------------------------------------
+**
+** sqlite3FkCheck() - Check for foreign key violations.
+** sqlite3FkActions() - Code triggers for ON UPDATE/ON DELETE actions.
+** sqlite3FkDelete() - Delete an FKey structure.
+*/
+
+/*
+** VDBE Calling Convention
+** -----------------------
+**
+** Example:
+**
+** For the following INSERT statement:
+**
+** CREATE TABLE t1(a, b INTEGER PRIMARY KEY, c);
+** INSERT INTO t1 VALUES(1, 2, 3.1);
+**
+** Register (x): 2 (type integer)
+** Register (x+1): 1 (type integer)
+** Register (x+2): NULL (type NULL)
+** Register (x+3): 3.1 (type real)
+*/
+
+/*
+** A foreign key constraint requires that the key columns in the parent
+** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
+** Given that pParent is the parent table for foreign key constraint pFKey,
+** search the schema for a unique index on the parent key columns.
+**
+** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
+** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
+** is set to point to the unique index.
+**
+** If the parent key consists of a single column (the foreign key constraint
+** is not a composite foreign key), output variable *paiCol is set to NULL.
+** Otherwise, it is set to point to an allocated array of size N, where
+** N is the number of columns in the parent key. The first element of the
+** array is the index of the child table column that is mapped by the FK
+** constraint to the parent table column stored in the left-most column
+** of index *ppIdx. The second element of the array is the index of the
+** child table column that corresponds to the second left-most column of
+** *ppIdx, and so on.
+**
+** If the required index cannot be found, either because:
+**
+** 1) The named parent key columns do not exist, or
+**
+** 2) The named parent key columns do exist, but are not subject to a
+** UNIQUE or PRIMARY KEY constraint, or
+**
+** 3) No parent key columns were provided explicitly as part of the
+** foreign key definition, and the parent table does not have a
+** PRIMARY KEY, or
+**
+** 4) No parent key columns were provided explicitly as part of the
+** foreign key definition, and the PRIMARY KEY of the parent table
+** consists of a a different number of columns to the child key in
+** the child table.
+**
+** then non-zero is returned, and a "foreign key mismatch" error loaded
+** into pParse. If an OOM error occurs, non-zero is returned and the
+** pParse->db->mallocFailed flag is set.
+*/
+SQLITE_PRIVATE int sqlite3FkLocateIndex(
+ Parse *pParse, /* Parse context to store any error in */
+ Table *pParent, /* Parent table of FK constraint pFKey */
+ FKey *pFKey, /* Foreign key to find index for */
+ Index **ppIdx, /* OUT: Unique index on parent table */
+ int **paiCol /* OUT: Map of index columns in pFKey */
+){
+ Index *pIdx = 0; /* Value to return via *ppIdx */
+ int *aiCol = 0; /* Value to return via *paiCol */
+ int nCol = pFKey->nCol; /* Number of columns in parent key */
+ char *zKey = pFKey->aCol[0].zCol; /* Name of left-most parent key column */
+
+ /* The caller is responsible for zeroing output parameters. */
+ assert( ppIdx && *ppIdx==0 );
+ assert( !paiCol || *paiCol==0 );
+ assert( pParse );
+
+ /* If this is a non-composite (single column) foreign key, check if it
+ ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx
+ ** and *paiCol set to zero and return early.
+ **
+ ** Otherwise, for a composite foreign key (more than one column), allocate
+ ** space for the aiCol array (returned via output parameter *paiCol).
+ ** Non-composite foreign keys do not require the aiCol array.
+ */
+ if( nCol==1 ){
+ /* The FK maps to the IPK if any of the following are true:
+ **
+ ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly
+ ** mapped to the primary key of table pParent, or
+ ** 2) The FK is explicitly mapped to a column declared as INTEGER
+ ** PRIMARY KEY.
+ */
+ if( pParent->iPKey>=0 ){
+ if( !zKey ) return 0;
+ if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
+ }
+ }else if( paiCol ){
+ assert( nCol>1 );
+ aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int));
+ if( !aiCol ) return 1;
+ *paiCol = aiCol;
+ }
+
+ for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){
+ /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
+ ** of columns. If each indexed column corresponds to a foreign key
+ ** column of pFKey, then this index is a winner. */
+
+ if( zKey==0 ){
+ /* If zKey is NULL, then this foreign key is implicitly mapped to
+ ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
+ ** identified by the test (Index.autoIndex==2). */
+ if( pIdx->autoIndex==2 ){
+ if( aiCol ){
+ int i;
+ for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
+ }
+ break;
+ }
+ }else{
+ /* If zKey is non-NULL, then this foreign key was declared to
+ ** map to an explicit list of columns in table pParent. Check if this
+ ** index matches those columns. Also, check that the index uses
+ ** the default collation sequences for each column. */
+ int i, j;
+ for(i=0; i<nCol; i++){
+ int iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
+ char *zDfltColl; /* Def. collation for column */
+ char *zIdxCol; /* Name of indexed column */
+
+ /* If the index uses a collation sequence that is different from
+ ** the default collation sequence for the column, this index is
+ ** unusable. Bail out early in this case. */
+ zDfltColl = pParent->aCol[iCol].zColl;
+ if( !zDfltColl ){
+ zDfltColl = "BINARY";
+ }
+ if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
+
+ zIdxCol = pParent->aCol[iCol].zName;
+ for(j=0; j<nCol; j++){
+ if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
+ if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
+ break;
+ }
+ }
+ if( j==nCol ) break;
+ }
+ if( i==nCol ) break; /* pIdx is usable */
+ }
+ }
+ }
+
+ if( !pIdx ){
+ if( !pParse->disableTriggers ){
+ sqlite3ErrorMsg(pParse,
+ "foreign key mismatch - \"%w\" referencing \"%w\"",
+ pFKey->pFrom->zName, pFKey->zTo);
+ }
+ sqlite3DbFree(pParse->db, aiCol);
+ return 1;
+ }
+
+ *ppIdx = pIdx;
+ return 0;
+}
+
+/*
+** This function is called when a row is inserted into or deleted from the
+** child table of foreign key constraint pFKey. If an SQL UPDATE is executed
+** on the child table of pFKey, this function is invoked twice for each row
+** affected - once to "delete" the old row, and then again to "insert" the
+** new row.
+**
+** Each time it is called, this function generates VDBE code to locate the
+** row in the parent table that corresponds to the row being inserted into
+** or deleted from the child table. If the parent row can be found, no
+** special action is taken. Otherwise, if the parent row can *not* be
+** found in the parent table:
+**
+** Operation | FK type | Action taken
+** --------------------------------------------------------------------------
+** INSERT immediate Increment the "immediate constraint counter".
+**
+** DELETE immediate Decrement the "immediate constraint counter".
+**
+** INSERT deferred Increment the "deferred constraint counter".
+**
+** DELETE deferred Decrement the "deferred constraint counter".
+**
+** These operations are identified in the comment at the top of this file
+** (fkey.c) as "I.1" and "D.1".
+*/
+static void fkLookupParent(
+ Parse *pParse, /* Parse context */
+ int iDb, /* Index of database housing pTab */
+ Table *pTab, /* Parent table of FK pFKey */
+ Index *pIdx, /* Unique index on parent key columns in pTab */
+ FKey *pFKey, /* Foreign key constraint */
+ int *aiCol, /* Map from parent key columns to child table columns */
+ int regData, /* Address of array containing child table row */
+ int nIncr, /* Increment constraint counter by this */
+ int isIgnore /* If true, pretend pTab contains all NULL values */
+){
+ int i; /* Iterator variable */
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */
+ int iCur = pParse->nTab - 1; /* Cursor number to use */
+ int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */
+
+ /* If nIncr is less than zero, then check at runtime if there are any
+ ** outstanding constraints to resolve. If there are not, there is no need
+ ** to check if deleting this row resolves any outstanding violations.
+ **
+ ** Check if any of the key columns in the child table row are NULL. If
+ ** any are, then the constraint is considered satisfied. No need to
+ ** search for a matching row in the parent table. */
+ if( nIncr<0 ){
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
+ }
+ for(i=0; i<pFKey->nCol; i++){
+ int iReg = aiCol[i] + regData + 1;
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk);
+ }
+
+ if( isIgnore==0 ){
+ if( pIdx==0 ){
+ /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY
+ ** column of the parent table (table pTab). */
+ int iMustBeInt; /* Address of MustBeInt instruction */
+ int regTemp = sqlite3GetTempReg(pParse);
+
+ /* Invoke MustBeInt to coerce the child key value to an integer (i.e.
+ ** apply the affinity of the parent key). If this fails, then there
+ ** is no matching parent key. Before using MustBeInt, make a copy of
+ ** the value. Otherwise, the value inserted into the child key column
+ ** will have INTEGER affinity applied to it, which may not be correct. */
+ sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
+ iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
+
+ /* If the parent table is the same as the child table, and we are about
+ ** to increment the constraint-counter (i.e. this is an INSERT operation),
+ ** then check if the row being inserted matches itself. If so, do not
+ ** increment the constraint-counter. */
+ if( pTab==pFKey->pFrom && nIncr==1 ){
+ sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp);
+ }
+
+ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+ sqlite3VdbeJumpHere(v, iMustBeInt);
+ sqlite3ReleaseTempReg(pParse, regTemp);
+ }else{
+ int nCol = pFKey->nCol;
+ int regTemp = sqlite3GetTempRange(pParse, nCol);
+ int regRec = sqlite3GetTempReg(pParse);
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
+ sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+ for(i=0; i<nCol; i++){
+ sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
+ }
+
+ /* If the parent table is the same as the child table, and we are about
+ ** to increment the constraint-counter (i.e. this is an INSERT operation),
+ ** then check if the row being inserted matches itself. If so, do not
+ ** increment the constraint-counter.
+ **
+ ** If any of the parent-key values are NULL, then the row cannot match
+ ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
+ ** of the parent-key values are NULL (at this point it is known that
+ ** none of the child key values are).
+ */
+ if( pTab==pFKey->pFrom && nIncr==1 ){
+ int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
+ for(i=0; i<nCol; i++){
+ int iChild = aiCol[i]+1+regData;
+ int iParent = pIdx->aiColumn[i]+1+regData;
+ assert( aiCol[i]!=pTab->iPKey );
+ if( pIdx->aiColumn[i]==pTab->iPKey ){
+ /* The parent key is a composite key that includes the IPK column */
+ iParent = regData;
+ }
+ sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
+ sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
+ }
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
+ }
+
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
+ sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
+ sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
+
+ sqlite3ReleaseTempReg(pParse, regRec);
+ sqlite3ReleaseTempRange(pParse, regTemp, nCol);
+ }
+ }
+
+ if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+ /* Special case: If this is an INSERT statement that will insert exactly
+ ** one row into the table, raise a constraint immediately instead of
+ ** incrementing a counter. This is necessary as the VM code is being
+ ** generated for will not open a statement transaction. */
+ assert( nIncr==1 );
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+ OE_Abort, "foreign key constraint failed", P4_STATIC
+ );
+ }else{
+ if( nIncr>0 && pFKey->isDeferred==0 ){
+ sqlite3ParseToplevel(pParse)->mayAbort = 1;
+ }
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
+ }
+
+ sqlite3VdbeResolveLabel(v, iOk);
+ sqlite3VdbeAddOp1(v, OP_Close, iCur);
+}
+
+/*
+** This function is called to generate code executed when a row is deleted
+** from the parent table of foreign key constraint pFKey and, if pFKey is
+** deferred, when a row is inserted into the same table. When generating
+** code for an SQL UPDATE operation, this function may be called twice -
+** once to "delete" the old row and once to "insert" the new row.
+**
+** The code generated by this function scans through the rows in the child
+** table that correspond to the parent table row being deleted or inserted.
+** For each child row found, one of the following actions is taken:
+**
+** Operation | FK type | Action taken
+** --------------------------------------------------------------------------
+** DELETE immediate Increment the "immediate constraint counter".
+** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
+** throw a "foreign key constraint failed" exception.
+**
+** INSERT immediate Decrement the "immediate constraint counter".
+**
+** DELETE deferred Increment the "deferred constraint counter".
+** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
+** throw a "foreign key constraint failed" exception.
+**
+** INSERT deferred Decrement the "deferred constraint counter".
+**
+** These operations are identified in the comment at the top of this file
+** (fkey.c) as "I.2" and "D.2".
+*/
+static void fkScanChildren(
+ Parse *pParse, /* Parse context */
+ SrcList *pSrc, /* SrcList containing the table to scan */
+ Table *pTab,
+ Index *pIdx, /* Foreign key index */
+ FKey *pFKey, /* Foreign key relationship */
+ int *aiCol, /* Map from pIdx cols to child table cols */
+ int regData, /* Referenced table data starts here */
+ int nIncr /* Amount to increment deferred counter by */
+){
+ sqlite3 *db = pParse->db; /* Database handle */
+ int i; /* Iterator variable */
+ Expr *pWhere = 0; /* WHERE clause to scan with */
+ NameContext sNameContext; /* Context used to resolve WHERE clause */
+ WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */
+ int iFkIfZero = 0; /* Address of OP_FkIfZero */
+ Vdbe *v = sqlite3GetVdbe(pParse);
+
+ assert( !pIdx || pIdx->pTable==pTab );
+
+ if( nIncr<0 ){
+ iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
+ }
+
+ /* Create an Expr object representing an SQL expression like:
+ **
+ ** <parent-key1> = <child-key1> AND <parent-key2> = <child-key2> ...
+ **
+ ** The collation sequence used for the comparison should be that of
+ ** the parent key columns. The affinity of the parent key column should
+ ** be applied to each child key value before the comparison takes place.
+ */
+ for(i=0; i<pFKey->nCol; i++){
+ Expr *pLeft; /* Value from parent table row */
+ Expr *pRight; /* Column ref to child table */
+ Expr *pEq; /* Expression (pLeft = pRight) */
+ int iCol; /* Index of column in child table */
+ const char *zCol; /* Name of column in child table */
+
+ pLeft = sqlite3Expr(db, TK_REGISTER, 0);
+ if( pLeft ){
+ /* Set the collation sequence and affinity of the LHS of each TK_EQ
+ ** expression to the parent key column defaults. */
+ if( pIdx ){
+ Column *pCol;
+ const char *zColl;
+ iCol = pIdx->aiColumn[i];
+ pCol = &pTab->aCol[iCol];
+ if( pTab->iPKey==iCol ) iCol = -1;
+ pLeft->iTable = regData+iCol+1;
+ pLeft->affinity = pCol->affinity;
+ zColl = pCol->zColl;
+ if( zColl==0 ) zColl = db->pDfltColl->zName;
+ pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
+ }else{
+ pLeft->iTable = regData;
+ pLeft->affinity = SQLITE_AFF_INTEGER;
+ }
+ }
+ iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
+ assert( iCol>=0 );
+ zCol = pFKey->pFrom->aCol[iCol].zName;
+ pRight = sqlite3Expr(db, TK_ID, zCol);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
+ pWhere = sqlite3ExprAnd(db, pWhere, pEq);
+ }
+
+ /* If the child table is the same as the parent table, and this scan
+ ** is taking place as part of a DELETE operation (operation D.2), omit the
+ ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE
+ ** clause, where $rowid is the rowid of the row being deleted. */
+ if( pTab==pFKey->pFrom && nIncr>0 ){
+ Expr *pEq; /* Expression (pLeft = pRight) */
+ Expr *pLeft; /* Value from parent table row */
+ Expr *pRight; /* Column ref to child table */
+ pLeft = sqlite3Expr(db, TK_REGISTER, 0);
+ pRight = sqlite3Expr(db, TK_COLUMN, 0);
+ if( pLeft && pRight ){
+ pLeft->iTable = regData;
+ pLeft->affinity = SQLITE_AFF_INTEGER;
+ pRight->iTable = pSrc->a[0].iCursor;
+ pRight->iColumn = -1;
+ }
+ pEq = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
+ pWhere = sqlite3ExprAnd(db, pWhere, pEq);
+ }
+
+ /* Resolve the references in the WHERE clause. */
+ memset(&sNameContext, 0, sizeof(NameContext));
+ sNameContext.pSrcList = pSrc;
+ sNameContext.pParse = pParse;
+ sqlite3ResolveExprNames(&sNameContext, pWhere);
+
+ /* Create VDBE to loop through the entries in pSrc that match the WHERE
+ ** clause. If the constraint is not deferred, throw an exception for
+ ** each row found. Otherwise, for deferred constraints, increment the
+ ** deferred constraint counter by nIncr for each row selected. */
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
+ if( nIncr>0 && pFKey->isDeferred==0 ){
+ sqlite3ParseToplevel(pParse)->mayAbort = 1;
+ }
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
+ if( pWInfo ){
+ sqlite3WhereEnd(pWInfo);
+ }
+
+ /* Clean up the WHERE clause constructed above. */
+ sqlite3ExprDelete(db, pWhere);
+ if( iFkIfZero ){
+ sqlite3VdbeJumpHere(v, iFkIfZero);
+ }
+}
+
+/*
+** This function returns a pointer to the head of a linked list of FK
+** constraints for which table pTab is the parent table. For example,
+** given the following schema:
+**
+** CREATE TABLE t1(a PRIMARY KEY);
+** CREATE TABLE t2(b REFERENCES t1(a);
+**
+** Calling this function with table "t1" as an argument returns a pointer
+** to the FKey structure representing the foreign key constraint on table
+** "t2". Calling this function with "t2" as the argument would return a
+** NULL pointer (as there are no FK constraints for which t2 is the parent
+** table).
+*/
+SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){
+ int nName = sqlite3Strlen30(pTab->zName);
+ return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName);
+}
+
+/*
+** The second argument is a Trigger structure allocated by the
+** fkActionTrigger() routine. This function deletes the Trigger structure
+** and all of its sub-components.
+**
+** The Trigger structure or any of its sub-components may be allocated from
+** the lookaside buffer belonging to database handle dbMem.
+*/
+static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
+ if( p ){
+ TriggerStep *pStep = p->step_list;
+ sqlite3ExprDelete(dbMem, pStep->pWhere);
+ sqlite3ExprListDelete(dbMem, pStep->pExprList);
+ sqlite3SelectDelete(dbMem, pStep->pSelect);
+ sqlite3ExprDelete(dbMem, p->pWhen);
+ sqlite3DbFree(dbMem, p);
+ }
+}
+
+/*
+** This function is called to generate code that runs when table pTab is
+** being dropped from the database. The SrcList passed as the second argument
+** to this function contains a single entry guaranteed to resolve to
+** table pTab.
+**
+** Normally, no code is required. However, if either
+**
+** (a) The table is the parent table of a FK constraint, or
+** (b) The table is the child table of a deferred FK constraint and it is
+** determined at runtime that there are outstanding deferred FK
+** constraint violations in the database,
+**
+** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
+** the table from the database. Triggers are disabled while running this
+** DELETE, but foreign key actions are not.
+*/
+SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
+ sqlite3 *db = pParse->db;
+ if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){
+ int iSkip = 0;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+
+ assert( v ); /* VDBE has already been allocated */
+ if( sqlite3FkReferences(pTab)==0 ){
+ /* Search for a deferred foreign key constraint for which this table
+ ** is the child table. If one cannot be found, return without
+ ** generating any VDBE code. If one can be found, then jump over
+ ** the entire DELETE if there are no outstanding deferred constraints
+ ** when this statement is run. */
+ FKey *p;
+ for(p=pTab->pFKey; p; p=p->pNextFrom){
+ if( p->isDeferred ) break;
+ }
+ if( !p ) return;
+ iSkip = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip);
+ }
+
+ pParse->disableTriggers = 1;
+ sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0);
+ pParse->disableTriggers = 0;
+
+ /* If the DELETE has generated immediate foreign key constraint
+ ** violations, halt the VDBE and return an error at this point, before
+ ** any modifications to the schema are made. This is because statement
+ ** transactions are not able to rollback schema changes. */
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+ OE_Abort, "foreign key constraint failed", P4_STATIC
+ );
+
+ if( iSkip ){
+ sqlite3VdbeResolveLabel(v, iSkip);
+ }
+ }
+}
+
+/*
+** This function is called when inserting, deleting or updating a row of
+** table pTab to generate VDBE code to perform foreign key constraint
+** processing for the operation.
+**
+** For a DELETE operation, parameter regOld is passed the index of the
+** first register in an array of (pTab->nCol+1) registers containing the
+** rowid of the row being deleted, followed by each of the column values
+** of the row being deleted, from left to right. Parameter regNew is passed
+** zero in this case.
+**
+** For an INSERT operation, regOld is passed zero and regNew is passed the
+** first register of an array of (pTab->nCol+1) registers containing the new
+** row data.
+**
+** For an UPDATE operation, this function is called twice. Once before
+** the original record is deleted from the table using the calling convention
+** described for DELETE. Then again after the original record is deleted
+** but before the new record is inserted using the INSERT convention.
+*/
+SQLITE_PRIVATE void sqlite3FkCheck(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Row is being deleted from this table */
+ int regOld, /* Previous row data is stored here */
+ int regNew /* New row data is stored here */
+){
+ sqlite3 *db = pParse->db; /* Database handle */
+ FKey *pFKey; /* Used to iterate through FKs */
+ int iDb; /* Index of database containing pTab */
+ const char *zDb; /* Name of database containing pTab */
+ int isIgnoreErrors = pParse->disableTriggers;
+
+ /* Exactly one of regOld and regNew should be non-zero. */
+ assert( (regOld==0)!=(regNew==0) );
+
+ /* If foreign-keys are disabled, this function is a no-op. */
+ if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
+
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ zDb = db->aDb[iDb].zName;
+
+ /* Loop through all the foreign key constraints for which pTab is the
+ ** child table (the table that the foreign key definition is part of). */
+ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ Table *pTo; /* Parent table of foreign key pFKey */
+ Index *pIdx = 0; /* Index on key columns in pTo */
+ int *aiFree = 0;
+ int *aiCol;
+ int iCol;
+ int i;
+ int isIgnore = 0;
+
+ /* Find the parent table of this foreign key. Also find a unique index
+ ** on the parent key columns in the parent table. If either of these
+ ** schema items cannot be located, set an error in pParse and return
+ ** early. */
+ if( pParse->disableTriggers ){
+ pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
+ }else{
+ pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
+ }
+ if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
+ assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
+ if( !isIgnoreErrors || db->mallocFailed ) return;
+ if( pTo==0 ){
+ /* If isIgnoreErrors is true, then a table is being dropped. In this
+ ** case SQLite runs a "DELETE FROM xxx" on the table being dropped
+ ** before actually dropping it in order to check FK constraints.
+ ** If the parent table of an FK constraint on the current table is
+ ** missing, behave as if it is empty. i.e. decrement the relevant
+ ** FK counter for each row of the current table with non-NULL keys.
+ */
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
+ for(i=0; i<pFKey->nCol; i++){
+ int iReg = pFKey->aCol[i].iFrom + regOld + 1;
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump);
+ }
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
+ }
+ continue;
+ }
+ assert( pFKey->nCol==1 || (aiFree && pIdx) );
+
+ if( aiFree ){
+ aiCol = aiFree;
+ }else{
+ iCol = pFKey->aCol[0].iFrom;
+ aiCol = &iCol;
+ }
+ for(i=0; i<pFKey->nCol; i++){
+ if( aiCol[i]==pTab->iPKey ){
+ aiCol[i] = -1;
+ }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Request permission to read the parent key columns. If the
+ ** authorization callback returns SQLITE_IGNORE, behave as if any
+ ** values read from the parent table are NULL. */
+ if( db->xAuth ){
+ int rcauth;
+ char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
+ rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
+ isIgnore = (rcauth==SQLITE_IGNORE);
+ }
+#endif
+ }
+
+ /* Take a shared-cache advisory read-lock on the parent table. Allocate
+ ** a cursor to use to search the unique index on the parent key columns
+ ** in the parent table. */
+ sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName);
+ pParse->nTab++;
+
+ if( regOld!=0 ){
+ /* A row is being removed from the child table. Search for the parent.
+ ** If the parent does not exist, removing the child row resolves an
+ ** outstanding foreign key constraint violation. */
+ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
+ }
+ if( regNew!=0 ){
+ /* A row is being added to the child table. If a parent row cannot
+ ** be found, adding the child row has violated the FK constraint. */
+ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
+ }
+
+ sqlite3DbFree(db, aiFree);
+ }
+
+ /* Loop through all the foreign key constraints that refer to this table */
+ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
+ Index *pIdx = 0; /* Foreign key index for pFKey */
+ SrcList *pSrc;
+ int *aiCol = 0;
+
+ if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+ assert( regOld==0 && regNew!=0 );
+ /* Inserting a single row into a parent table cannot cause an immediate
+ ** foreign key violation. So do nothing in this case. */
+ continue;
+ }
+
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
+ if( !isIgnoreErrors || db->mallocFailed ) return;
+ continue;
+ }
+ assert( aiCol || pFKey->nCol==1 );
+
+ /* Create a SrcList structure containing a single table (the table
+ ** the foreign key that refers to this table is attached to). This
+ ** is required for the sqlite3WhereXXX() interface. */
+ pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
+ if( pSrc ){
+ struct SrcList_item *pItem = pSrc->a;
+ pItem->pTab = pFKey->pFrom;
+ pItem->zName = pFKey->pFrom->zName;
+ pItem->pTab->nRef++;
+ pItem->iCursor = pParse->nTab++;
+
+ if( regNew!=0 ){
+ fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
+ }
+ if( regOld!=0 ){
+ /* If there is a RESTRICT action configured for the current operation
+ ** on the parent table of this FK, then throw an exception
+ ** immediately if the FK constraint is violated, even if this is a
+ ** deferred trigger. That's what RESTRICT means. To defer checking
+ ** the constraint, the FK should specify NO ACTION (represented
+ ** using OE_None). NO ACTION is the default. */
+ fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
+ }
+ pItem->zName = 0;
+ sqlite3SrcListDelete(db, pSrc);
+ }
+ sqlite3DbFree(db, aiCol);
+ }
+}
+
+#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x)))
+
+/*
+** This function is called before generating code to update or delete a
+** row contained in table pTab.
+*/
+SQLITE_PRIVATE u32 sqlite3FkOldmask(
+ Parse *pParse, /* Parse context */
+ Table *pTab /* Table being modified */
+){
+ u32 mask = 0;
+ if( pParse->db->flags&SQLITE_ForeignKeys ){
+ FKey *p;
+ int i;
+ for(p=pTab->pFKey; p; p=p->pNextFrom){
+ for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
+ }
+ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
+ Index *pIdx = 0;
+ sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
+ if( pIdx ){
+ for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
+ }
+ }
+ }
+ return mask;
+}
+
+/*
+** This function is called before generating code to update or delete a
+** row contained in table pTab. If the operation is a DELETE, then
+** parameter aChange is passed a NULL value. For an UPDATE, aChange points
+** to an array of size N, where N is the number of columns in table pTab.
+** If the i'th column is not modified by the UPDATE, then the corresponding
+** entry in the aChange[] array is set to -1. If the column is modified,
+** the value is 0 or greater. Parameter chngRowid is set to true if the
+** UPDATE statement modifies the rowid fields of the table.
+**
+** If any foreign key processing will be required, this function returns
+** true. If there is no foreign key related processing, this function
+** returns false.
+*/
+SQLITE_PRIVATE int sqlite3FkRequired(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Table being modified */
+ int *aChange, /* Non-NULL for UPDATE operations */
+ int chngRowid /* True for UPDATE that affects rowid */
+){
+ if( pParse->db->flags&SQLITE_ForeignKeys ){
+ if( !aChange ){
+ /* A DELETE operation. Foreign key processing is required if the
+ ** table in question is either the child or parent table for any
+ ** foreign key constraint. */
+ return (sqlite3FkReferences(pTab) || pTab->pFKey);
+ }else{
+ /* This is an UPDATE. Foreign key processing is only required if the
+ ** operation modifies one or more child or parent key columns. */
+ int i;
+ FKey *p;
+
+ /* Check if any child key columns are being modified. */
+ for(p=pTab->pFKey; p; p=p->pNextFrom){
+ for(i=0; i<p->nCol; i++){
+ int iChildKey = p->aCol[i].iFrom;
+ if( aChange[iChildKey]>=0 ) return 1;
+ if( iChildKey==pTab->iPKey && chngRowid ) return 1;
+ }
+ }
+
+ /* Check if any parent key columns are being modified. */
+ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
+ for(i=0; i<p->nCol; i++){
+ char *zKey = p->aCol[i].zCol;
+ int iKey;
+ for(iKey=0; iKey<pTab->nCol; iKey++){
+ Column *pCol = &pTab->aCol[iKey];
+ if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey)
+ : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){
+ if( aChange[iKey]>=0 ) return 1;
+ if( iKey==pTab->iPKey && chngRowid ) return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** This function is called when an UPDATE or DELETE operation is being
+** compiled on table pTab, which is the parent table of foreign-key pFKey.
+** If the current operation is an UPDATE, then the pChanges parameter is
+** passed a pointer to the list of columns being modified. If it is a
+** DELETE, pChanges is passed a NULL pointer.
+**
+** It returns a pointer to a Trigger structure containing a trigger
+** equivalent to the ON UPDATE or ON DELETE action specified by pFKey.
+** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is
+** returned (these actions require no special handling by the triggers
+** sub-system, code for them is created by fkScanChildren()).
+**
+** For example, if pFKey is the foreign key and pTab is table "p" in
+** the following schema:
+**
+** CREATE TABLE p(pk PRIMARY KEY);
+** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE);
+**
+** then the returned trigger structure is equivalent to:
+**
+** CREATE TRIGGER ... DELETE ON p BEGIN
+** DELETE FROM c WHERE ck = old.pk;
+** END;
+**
+** The returned pointer is cached as part of the foreign key object. It
+** is eventually freed along with the rest of the foreign key object by
+** sqlite3FkDelete().
+*/
+static Trigger *fkActionTrigger(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Table being updated or deleted from */
+ FKey *pFKey, /* Foreign key to get action for */
+ ExprList *pChanges /* Change-list for UPDATE, NULL for DELETE */
+){
+ sqlite3 *db = pParse->db; /* Database handle */
+ int action; /* One of OE_None, OE_Cascade etc. */
+ Trigger *pTrigger; /* Trigger definition to return */
+ int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */
+
+ action = pFKey->aAction[iAction];
+ pTrigger = pFKey->apTrigger[iAction];
+
+ if( action!=OE_None && !pTrigger ){
+ u8 enableLookaside; /* Copy of db->lookaside.bEnabled */
+ char const *zFrom; /* Name of child table */
+ int nFrom; /* Length in bytes of zFrom */
+ Index *pIdx = 0; /* Parent key index for this FK */
+ int *aiCol = 0; /* child table cols -> parent key cols */
+ TriggerStep *pStep = 0; /* First (only) step of trigger program */
+ Expr *pWhere = 0; /* WHERE clause of trigger step */
+ ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
+ Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */
+ int i; /* Iterator variable */
+ Expr *pWhen = 0; /* WHEN clause for the trigger */
+
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
+ assert( aiCol || pFKey->nCol==1 );
+
+ for(i=0; i<pFKey->nCol; i++){
+ Token tOld = { "old", 3 }; /* Literal "old" token */
+ Token tNew = { "new", 3 }; /* Literal "new" token */
+ Token tFromCol; /* Name of column in child table */
+ Token tToCol; /* Name of column in parent table */
+ int iFromCol; /* Idx of column in child table */
+ Expr *pEq; /* tFromCol = OLD.tToCol */
+
+ iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
+ assert( iFromCol>=0 );
+ tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid";
+ tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName;
+
+ tToCol.n = sqlite3Strlen30(tToCol.z);
+ tFromCol.n = sqlite3Strlen30(tFromCol.z);
+
+ /* Create the expression "OLD.zToCol = zFromCol". It is important
+ ** that the "OLD.zToCol" term is on the LHS of the = operator, so
+ ** that the affinity and collation sequence associated with the
+ ** parent table are used for the comparison. */
+ pEq = sqlite3PExpr(pParse, TK_EQ,
+ sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
+ , 0),
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol)
+ , 0);
+ pWhere = sqlite3ExprAnd(db, pWhere, pEq);
+
+ /* For ON UPDATE, construct the next term of the WHEN clause.
+ ** The final WHEN clause will be like this:
+ **
+ ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
+ */
+ if( pChanges ){
+ pEq = sqlite3PExpr(pParse, TK_IS,
+ sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
+ 0),
+ sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
+ 0),
+ 0);
+ pWhen = sqlite3ExprAnd(db, pWhen, pEq);
+ }
+
+ if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){
+ Expr *pNew;
+ if( action==OE_Cascade ){
+ pNew = sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
+ sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
+ , 0);
+ }else if( action==OE_SetDflt ){
+ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
+ if( pDflt ){
+ pNew = sqlite3ExprDup(db, pDflt, 0);
+ }else{
+ pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
+ }
+ }else{
+ pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
+ }
+ pList = sqlite3ExprListAppend(pParse, pList, pNew);
+ sqlite3ExprListSetName(pParse, pList, &tFromCol, 0);
+ }
+ }
+ sqlite3DbFree(db, aiCol);
+
+ zFrom = pFKey->pFrom->zName;
+ nFrom = sqlite3Strlen30(zFrom);
+
+ if( action==OE_Restrict ){
+ Token tFrom;
+ Expr *pRaise;
+
+ tFrom.z = zFrom;
+ tFrom.n = nFrom;
+ pRaise = sqlite3Expr(db, TK_RAISE, "foreign key constraint failed");
+ if( pRaise ){
+ pRaise->affinity = OE_Abort;
+ }
+ pSelect = sqlite3SelectNew(pParse,
+ sqlite3ExprListAppend(pParse, 0, pRaise),
+ sqlite3SrcListAppend(db, 0, &tFrom, 0),
+ pWhere,
+ 0, 0, 0, 0, 0, 0
+ );
+ pWhere = 0;
+ }
+
+ /* Disable lookaside memory allocation */
+ enableLookaside = db->lookaside.bEnabled;
+ db->lookaside.bEnabled = 0;
+
+ pTrigger = (Trigger *)sqlite3DbMallocZero(db,
+ sizeof(Trigger) + /* struct Trigger */
+ sizeof(TriggerStep) + /* Single step in trigger program */
+ nFrom + 1 /* Space for pStep->target.z */
+ );
+ if( pTrigger ){
+ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
+ pStep->target.z = (char *)&pStep[1];
+ pStep->target.n = nFrom;
+ memcpy((char *)pStep->target.z, zFrom, nFrom);
+
+ pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
+ pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
+ pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ if( pWhen ){
+ pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0);
+ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
+ }
+ }
+
+ /* Re-enable the lookaside buffer, if it was disabled earlier. */
+ db->lookaside.bEnabled = enableLookaside;
+
+ sqlite3ExprDelete(db, pWhere);
+ sqlite3ExprDelete(db, pWhen);
+ sqlite3ExprListDelete(db, pList);
+ sqlite3SelectDelete(db, pSelect);
+ if( db->mallocFailed==1 ){
+ fkTriggerDelete(db, pTrigger);
+ return 0;
+ }
+ assert( pStep!=0 );
+
+ switch( action ){
+ case OE_Restrict:
+ pStep->op = TK_SELECT;
+ break;
+ case OE_Cascade:
+ if( !pChanges ){
+ pStep->op = TK_DELETE;
+ break;
+ }
+ default:
+ pStep->op = TK_UPDATE;
+ }
+ pStep->pTrig = pTrigger;
+ pTrigger->pSchema = pTab->pSchema;
+ pTrigger->pTabSchema = pTab->pSchema;
+ pFKey->apTrigger[iAction] = pTrigger;
+ pTrigger->op = (pChanges ? TK_UPDATE : TK_DELETE);
+ }
+
+ return pTrigger;
+}
+
+/*
+** This function is called when deleting or updating a row to implement
+** any required CASCADE, SET NULL or SET DEFAULT actions.
+*/
+SQLITE_PRIVATE void sqlite3FkActions(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Table being updated or deleted from */
+ ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */
+ int regOld /* Address of array containing old row */
+){
+ /* If foreign-key support is enabled, iterate through all FKs that
+ ** refer to table pTab. If there is an action associated with the FK
+ ** for this operation (either update or delete), invoke the associated
+ ** trigger sub-program. */
+ if( pParse->db->flags&SQLITE_ForeignKeys ){
+ FKey *pFKey; /* Iterator variable */
+ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
+ Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges);
+ if( pAction ){
+ sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0);
+ }
+ }
+ }
+}
+
+#endif /* ifndef SQLITE_OMIT_TRIGGER */
+
+/*
+** Free all memory associated with foreign key definitions attached to
+** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
+** hash table.
+*/
+SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
+ FKey *pFKey; /* Iterator variable */
+ FKey *pNext; /* Copy of pFKey->pNextFrom */
+
+ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
+ for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
+
+ /* Remove the FK from the fkeyHash hash table. */
+ if( !db || db->pnBytesFreed==0 ){
+ if( pFKey->pPrevTo ){
+ pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
+ }else{
+ void *p = (void *)pFKey->pNextTo;
+ const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo);
+ sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p);
+ }
+ if( pFKey->pNextTo ){
+ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
+ }
+ }
+
+ /* EV: R-30323-21917 Each foreign key constraint in SQLite is
+ ** classified as either immediate or deferred.
+ */
+ assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 );
+
+ /* Delete any triggers created to implement actions for this FK. */
+#ifndef SQLITE_OMIT_TRIGGER
+ fkTriggerDelete(db, pFKey->apTrigger[0]);
+ fkTriggerDelete(db, pFKey->apTrigger[1]);
+#endif
+
+ pNext = pFKey->pNextFrom;
+ sqlite3DbFree(db, pFKey);
+ }
+}
+#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */
+
+/************** End of fkey.c ************************************************/
+/************** Begin file insert.c ******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that are called by the parser
+** to handle INSERT statements in SQLite.
+*/
+
+/*
+** Generate code that will open a table for reading.
+*/
+SQLITE_PRIVATE void sqlite3OpenTable(
+ Parse *p, /* Generate code into this VDBE */
+ int iCur, /* The cursor number of the table */
+ int iDb, /* The database index in sqlite3.aDb[] */
+ Table *pTab, /* The table to be opened */
+ int opcode /* OP_OpenRead or OP_OpenWrite */
+){
+ Vdbe *v;
+ assert( !IsVirtual(pTab) );
+ v = sqlite3GetVdbe(p);
+ assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
+ sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
+ sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
+ sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
+ VdbeComment((v, "%s", pTab->zName));
+}
+
+/*
+** Return a pointer to the column affinity string associated with index
+** pIdx. A column affinity string has one character for each column in
+** the table, according to the affinity of the column:
+**
+** Character Column affinity
+** ------------------------------
+** 'a' TEXT
+** 'b' NONE
+** 'c' NUMERIC
+** 'd' INTEGER
+** 'e' REAL
+**
+** An extra 'd' is appended to the end of the string to cover the
+** rowid that appears as the last column in every index.
+**
+** Memory for the buffer containing the column index affinity string
+** is managed along with the rest of the Index structure. It will be
+** released when sqlite3DeleteIndex() is called.
+*/
+SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
+ if( !pIdx->zColAff ){
+ /* The first time a column affinity string for a particular index is
+ ** required, it is allocated and populated here. It is then stored as
+ ** a member of the Index structure for subsequent use.
+ **
+ ** The column affinity string will eventually be deleted by
+ ** sqliteDeleteIndex() when the Index structure itself is cleaned
+ ** up.
+ */
+ int n;
+ Table *pTab = pIdx->pTable;
+ sqlite3 *db = sqlite3VdbeDb(v);
+ pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+2);
+ if( !pIdx->zColAff ){
+ db->mallocFailed = 1;
+ return 0;
+ }
+ for(n=0; n<pIdx->nColumn; n++){
+ pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
+ }
+ pIdx->zColAff[n++] = SQLITE_AFF_INTEGER;
+ pIdx->zColAff[n] = 0;
+ }
+
+ return pIdx->zColAff;
+}
+
+/*
+** Set P4 of the most recently inserted opcode to a column affinity
+** string for table pTab. A column affinity string has one character
+** for each column indexed by the index, according to the affinity of the
+** column:
+**
+** Character Column affinity
+** ------------------------------
+** 'a' TEXT
+** 'b' NONE
+** 'c' NUMERIC
+** 'd' INTEGER
+** 'e' REAL
+*/
+SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
+ /* The first time a column affinity string for a particular table
+ ** is required, it is allocated and populated here. It is then
+ ** stored as a member of the Table structure for subsequent use.
+ **
+ ** The column affinity string will eventually be deleted by
+ ** sqlite3DeleteTable() when the Table structure itself is cleaned up.
+ */
+ if( !pTab->zColAff ){
+ char *zColAff;
+ int i;
+ sqlite3 *db = sqlite3VdbeDb(v);
+
+ zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
+ if( !zColAff ){
+ db->mallocFailed = 1;
+ return;
+ }
+
+ for(i=0; i<pTab->nCol; i++){
+ zColAff[i] = pTab->aCol[i].affinity;
+ }
+ zColAff[pTab->nCol] = '\0';
+
+ pTab->zColAff = zColAff;
+ }
+
+ sqlite3VdbeChangeP4(v, -1, pTab->zColAff, P4_TRANSIENT);
+}
+
+/*
+** Return non-zero if the table pTab in database iDb or any of its indices
+** have been opened at any point in the VDBE program beginning at location
+** iStartAddr throught the end of the program. This is used to see if
+** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
+** run without using temporary table for the results of the SELECT.
+*/
+static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){
+ Vdbe *v = sqlite3GetVdbe(p);
+ int i;
+ int iEnd = sqlite3VdbeCurrentAddr(v);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0;
+#endif
+
+ for(i=iStartAddr; i<iEnd; i++){
+ VdbeOp *pOp = sqlite3VdbeGetOp(v, i);
+ assert( pOp!=0 );
+ if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){
+ Index *pIndex;
+ int tnum = pOp->p2;
+ if( tnum==pTab->tnum ){
+ return 1;
+ }
+ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
+ if( tnum==pIndex->tnum ){
+ return 1;
+ }
+ }
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pVTab ){
+ assert( pOp->p4.pVtab!=0 );
+ assert( pOp->p4type==P4_VTAB );
+ return 1;
+ }
+#endif
+ }
+ return 0;
+}
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+/*
+** Locate or create an AutoincInfo structure associated with table pTab
+** which is in database iDb. Return the register number for the register
+** that holds the maximum rowid.
+**
+** There is at most one AutoincInfo structure per table even if the
+** same table is autoincremented multiple times due to inserts within
+** triggers. A new AutoincInfo structure is created if this is the
+** first use of table pTab. On 2nd and subsequent uses, the original
+** AutoincInfo structure is used.
+**
+** Three memory locations are allocated:
+**
+** (1) Register to hold the name of the pTab table.
+** (2) Register to hold the maximum ROWID of pTab.
+** (3) Register to hold the rowid in sqlite_sequence of pTab
+**
+** The 2nd register is the one that is returned. That is all the
+** insert routine needs to know about.
+*/
+static int autoIncBegin(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* Index of the database holding pTab */
+ Table *pTab /* The table we are writing to */
+){
+ int memId = 0; /* Register holding maximum rowid */
+ if( pTab->tabFlags & TF_Autoincrement ){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ AutoincInfo *pInfo;
+
+ pInfo = pToplevel->pAinc;
+ while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
+ if( pInfo==0 ){
+ pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo));
+ if( pInfo==0 ) return 0;
+ pInfo->pNext = pToplevel->pAinc;
+ pToplevel->pAinc = pInfo;
+ pInfo->pTab = pTab;
+ pInfo->iDb = iDb;
+ pToplevel->nMem++; /* Register to hold name of table */
+ pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */
+ pToplevel->nMem++; /* Rowid in sqlite_sequence */
+ }
+ memId = pInfo->regCtr;
+ }
+ return memId;
+}
+
+/*
+** This routine generates code that will initialize all of the
+** register used by the autoincrement tracker.
+*/
+SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
+ AutoincInfo *p; /* Information about an AUTOINCREMENT */
+ sqlite3 *db = pParse->db; /* The database connection */
+ Db *pDb; /* Database only autoinc table */
+ int memId; /* Register holding max rowid */
+ int addr; /* A VDBE address */
+ Vdbe *v = pParse->pVdbe; /* VDBE under construction */
+
+ /* This routine is never called during trigger-generation. It is
+ ** only called from the top-level */
+ assert( pParse->pTriggerTab==0 );
+ assert( pParse==sqlite3ParseToplevel(pParse) );
+
+ assert( v ); /* We failed long ago if this is not so */
+ for(p = pParse->pAinc; p; p = p->pNext){
+ pDb = &db->aDb[p->iDb];
+ memId = p->regCtr;
+ assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
+ sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1);
+ addr = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9);
+ sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId);
+ sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId);
+ sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
+ sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9);
+ sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, memId);
+ sqlite3VdbeAddOp0(v, OP_Close);
+ }
+}
+
+/*
+** Update the maximum rowid for an autoincrement calculation.
+**
+** This routine should be called when the top of the stack holds a
+** new rowid that is about to be inserted. If that new rowid is
+** larger than the maximum rowid in the memId memory cell, then the
+** memory cell is updated. The stack is unchanged.
+*/
+static void autoIncStep(Parse *pParse, int memId, int regRowid){
+ if( memId>0 ){
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid);
+ }
+}
+
+/*
+** This routine generates the code needed to write autoincrement
+** maximum rowid values back into the sqlite_sequence register.
+** Every statement that might do an INSERT into an autoincrement
+** table (either directly or through triggers) needs to call this
+** routine just before the "exit" code.
+*/
+SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
+ AutoincInfo *p;
+ Vdbe *v = pParse->pVdbe;
+ sqlite3 *db = pParse->db;
+
+ assert( v );
+ for(p = pParse->pAinc; p; p = p->pNext){
+ Db *pDb = &db->aDb[p->iDb];
+ int j1, j2, j3, j4, j5;
+ int iRec;
+ int memId = p->regCtr;
+
+ iRec = sqlite3GetTempReg(pParse);
+ assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
+ sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
+ j2 = sqlite3VdbeAddOp0(v, OP_Rewind);
+ j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec);
+ j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec);
+ sqlite3VdbeAddOp2(v, OP_Next, 0, j3);
+ sqlite3VdbeJumpHere(v, j2);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
+ j5 = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, j4);
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
+ sqlite3VdbeJumpHere(v, j1);
+ sqlite3VdbeJumpHere(v, j5);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
+ sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ sqlite3VdbeAddOp0(v, OP_Close);
+ sqlite3ReleaseTempReg(pParse, iRec);
+ }
+}
+#else
+/*
+** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines
+** above are all no-ops
+*/
+# define autoIncBegin(A,B,C) (0)
+# define autoIncStep(A,B,C)
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
+
+
+/*
+** Generate code for a co-routine that will evaluate a subquery one
+** row at a time.
+**
+** The pSelect parameter is the subquery that the co-routine will evaluation.
+** Information about the location of co-routine and the registers it will use
+** is returned by filling in the pDest object.
+**
+** Registers are allocated as follows:
+**
+** pDest->iSDParm The register holding the next entry-point of the
+** co-routine. Run the co-routine to its next breakpoint
+** by calling "OP_Yield $X" where $X is pDest->iSDParm.
+**
+** pDest->iSDParm+1 The register holding the "completed" flag for the
+** co-routine. This register is 0 if the previous Yield
+** generated a new result row, or 1 if the subquery
+** has completed. If the Yield is called again
+** after this register becomes 1, then the VDBE will
+** halt with an SQLITE_INTERNAL error.
+**
+** pDest->iSdst First result register.
+**
+** pDest->nSdst Number of result registers.
+**
+** This routine handles all of the register allocation and fills in the
+** pDest structure appropriately.
+**
+** Here is a schematic of the generated code assuming that X is the
+** co-routine entry-point register reg[pDest->iSDParm], that EOF is the
+** completed flag reg[pDest->iSDParm+1], and R and S are the range of
+** registers that hold the result set, reg[pDest->iSdst] through
+** reg[pDest->iSdst+pDest->nSdst-1]:
+**
+** X <- A
+** EOF <- 0
+** goto B
+** A: setup for the SELECT
+** loop rows in the SELECT
+** load results into registers R..S
+** yield X
+** end loop
+** cleanup after the SELECT
+** EOF <- 1
+** yield X
+** halt-error
+** B:
+**
+** To use this subroutine, the caller generates code as follows:
+**
+** [ Co-routine generated by this subroutine, shown above ]
+** S: yield X
+** if EOF goto E
+** if skip this row, goto C
+** if terminate loop, goto E
+** deal with this row
+** C: goto S
+** E:
+*/
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
+ int regYield; /* Register holding co-routine entry-point */
+ int regEof; /* Register holding co-routine completion flag */
+ int addrTop; /* Top of the co-routine */
+ int j1; /* Jump instruction */
+ int rc; /* Result code */
+ Vdbe *v; /* VDBE under construction */
+
+ regYield = ++pParse->nMem;
+ regEof = ++pParse->nMem;
+ v = sqlite3GetVdbe(pParse);
+ addrTop = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
+ VdbeComment((v, "Co-routine entry point"));
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */
+ VdbeComment((v, "Co-routine completion flag"));
+ sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
+ j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
+ rc = sqlite3Select(pParse, pSelect, pDest);
+ assert( pParse->nErr==0 || rc );
+ if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
+ if( rc ) return rc;
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
+ sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
+ VdbeComment((v, "End of coroutine"));
+ sqlite3VdbeJumpHere(v, j1); /* label B: */
+ return rc;
+}
+
+
+
+/* Forward declaration */
+static int xferOptimization(
+ Parse *pParse, /* Parser context */
+ Table *pDest, /* The table we are inserting into */
+ Select *pSelect, /* A SELECT statement to use as the data source */
+ int onError, /* How to handle constraint errors */
+ int iDbDest /* The database of pDest */
+);
+
+/*
+** This routine is call to handle SQL of the following forms:
+**
+** insert into TABLE (IDLIST) values(EXPRLIST)
+** insert into TABLE (IDLIST) select
+**
+** The IDLIST following the table name is always optional. If omitted,
+** then a list of all columns for the table is substituted. The IDLIST
+** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted.
+**
+** The pList parameter holds EXPRLIST in the first form of the INSERT
+** statement above, and pSelect is NULL. For the second form, pList is
+** NULL and pSelect is a pointer to the select statement used to generate
+** data for the insert.
+**
+** The code generated follows one of four templates. For a simple
+** select with data coming from a VALUES clause, the code executes
+** once straight down through. Pseudo-code follows (we call this
+** the "1st template"):
+**
+** open write cursor to <table> and its indices
+** puts VALUES clause expressions onto the stack
+** write the resulting record into <table>
+** cleanup
+**
+** The three remaining templates assume the statement is of the form
+**
+** INSERT INTO <table> SELECT ...
+**
+** If the SELECT clause is of the restricted form "SELECT * FROM <table2>" -
+** in other words if the SELECT pulls all columns from a single table
+** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and
+** if <table2> and <table1> are distinct tables but have identical
+** schemas, including all the same indices, then a special optimization
+** is invoked that copies raw records from <table2> over to <table1>.
+** See the xferOptimization() function for the implementation of this
+** template. This is the 2nd template.
+**
+** open a write cursor to <table>
+** open read cursor on <table2>
+** transfer all records in <table2> over to <table>
+** close cursors
+** foreach index on <table>
+** open a write cursor on the <table> index
+** open a read cursor on the corresponding <table2> index
+** transfer all records from the read to the write cursors
+** close cursors
+** end foreach
+**
+** The 3rd template is for when the second template does not apply
+** and the SELECT clause does not read from <table> at any time.
+** The generated code follows this template:
+**
+** EOF <- 0
+** X <- A
+** goto B
+** A: setup for the SELECT
+** loop over the rows in the SELECT
+** load values into registers R..R+n
+** yield X
+** end loop
+** cleanup after the SELECT
+** EOF <- 1
+** yield X
+** goto A
+** B: open write cursor to <table> and its indices
+** C: yield X
+** if EOF goto D
+** insert the select result into <table> from R..R+n
+** goto C
+** D: cleanup
+**
+** The 4th template is used if the insert statement takes its
+** values from a SELECT but the data is being inserted into a table
+** that is also read as part of the SELECT. In the third form,
+** we have to use a intermediate table to store the results of
+** the select. The template is like this:
+**
+** EOF <- 0
+** X <- A
+** goto B
+** A: setup for the SELECT
+** loop over the tables in the SELECT
+** load value into register R..R+n
+** yield X
+** end loop
+** cleanup after the SELECT
+** EOF <- 1
+** yield X
+** halt-error
+** B: open temp table
+** L: yield X
+** if EOF goto M
+** insert row from R..R+n into temp table
+** goto L
+** M: open write cursor to <table> and its indices
+** rewind temp table
+** C: loop over rows of intermediate table
+** transfer values form intermediate table into <table>
+** end loop
+** D: cleanup
+*/
+SQLITE_PRIVATE void sqlite3Insert(
+ Parse *pParse, /* Parser context */
+ SrcList *pTabList, /* Name of table into which we are inserting */
+ ExprList *pList, /* List of values to be inserted */
+ Select *pSelect, /* A SELECT statement to use as the data source */
+ IdList *pColumn, /* Column names corresponding to IDLIST. */
+ int onError /* How to handle constraint errors */
+){
+ sqlite3 *db; /* The main database structure */
+ Table *pTab; /* The table to insert into. aka TABLE */
+ char *zTab; /* Name of the table into which we are inserting */
+ const char *zDb; /* Name of the database holding this table */
+ int i, j, idx; /* Loop counters */
+ Vdbe *v; /* Generate code into this virtual machine */
+ Index *pIdx; /* For looping over indices of the table */
+ int nColumn; /* Number of columns in the data */
+ int nHidden = 0; /* Number of hidden columns if TABLE is virtual */
+ int baseCur = 0; /* VDBE Cursor number for pTab */
+ int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
+ int endOfLoop; /* Label for the end of the insertion loop */
+ int useTempTable = 0; /* Store SELECT results in intermediate table */
+ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */
+ int addrInsTop = 0; /* Jump to label "D" */
+ int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */
+ int addrSelect = 0; /* Address of coroutine that implements the SELECT */
+ SelectDest dest; /* Destination for SELECT on rhs of INSERT */
+ int iDb; /* Index of database holding TABLE */
+ Db *pDb; /* The database containing table being inserted into */
+ int appendFlag = 0; /* True if the insert is likely to be an append */
+
+ /* Register allocations */
+ int regFromSelect = 0;/* Base register for data coming from SELECT */
+ int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */
+ int regRowCount = 0; /* Memory cell used for the row counter */
+ int regIns; /* Block of regs holding rowid+data being inserted */
+ int regRowid; /* registers holding insert rowid */
+ int regData; /* register holding first column to insert */
+ int regEof = 0; /* Register recording end of SELECT data */
+ int *aRegIdx = 0; /* One register allocated to each index */
+
+#ifndef SQLITE_OMIT_TRIGGER
+ int isView; /* True if attempting to insert into a view */
+ Trigger *pTrigger; /* List of triggers on pTab, if required */
+ int tmask; /* Mask of trigger times */
+#endif
+
+ db = pParse->db;
+ memset(&dest, 0, sizeof(dest));
+ if( pParse->nErr || db->mallocFailed ){
+ goto insert_cleanup;
+ }
+
+ /* Locate the table into which we will be inserting new information.
+ */
+ assert( pTabList->nSrc==1 );
+ zTab = pTabList->a[0].zName;
+ if( NEVER(zTab==0) ) goto insert_cleanup;
+ pTab = sqlite3SrcListLookup(pParse, pTabList);
+ if( pTab==0 ){
+ goto insert_cleanup;
+ }
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb<db->nDb );
+ pDb = &db->aDb[iDb];
+ zDb = pDb->zName;
+ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
+ goto insert_cleanup;
+ }
+
+ /* Figure out if we have any triggers and if the table being
+ ** inserted into is a view
+ */
+#ifndef SQLITE_OMIT_TRIGGER
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
+ isView = pTab->pSelect!=0;
+#else
+# define pTrigger 0
+# define tmask 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+ assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
+
+ /* If pTab is really a view, make sure it has been initialized.
+ ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
+ ** module table).
+ */
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+ goto insert_cleanup;
+ }
+
+ /* Ensure that:
+ * (a) the table is not read-only,
+ * (b) that if it is a view then ON INSERT triggers exist
+ */
+ if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
+ goto insert_cleanup;
+ }
+
+ /* Allocate a VDBE
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto insert_cleanup;
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+ sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb);
+
+#ifndef SQLITE_OMIT_XFER_OPT
+ /* If the statement is of the form
+ **
+ ** INSERT INTO <table1> SELECT * FROM <table2>;
+ **
+ ** Then special optimizations can be applied that make the transfer
+ ** very fast and which reduce fragmentation of indices.
+ **
+ ** This is the 2nd template.
+ */
+ if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
+ assert( !pTrigger );
+ assert( pList==0 );
+ goto insert_end;
+ }
+#endif /* SQLITE_OMIT_XFER_OPT */
+
+ /* If this is an AUTOINCREMENT table, look up the sequence number in the
+ ** sqlite_sequence table and store it in memory cell regAutoinc.
+ */
+ regAutoinc = autoIncBegin(pParse, iDb, pTab);
+
+ /* Figure out how many columns of data are supplied. If the data
+ ** is coming from a SELECT statement, then generate a co-routine that
+ ** produces a single row of the SELECT on each invocation. The
+ ** co-routine is the common header to the 3rd and 4th templates.
+ */
+ if( pSelect ){
+ /* Data is coming from a SELECT. Generate a co-routine to run that
+ ** SELECT. */
+ int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
+ if( rc ) goto insert_cleanup;
+
+ regEof = dest.iSDParm + 1;
+ regFromSelect = dest.iSdst;
+ assert( pSelect->pEList );
+ nColumn = pSelect->pEList->nExpr;
+ assert( dest.nSdst==nColumn );
+
+ /* Set useTempTable to TRUE if the result of the SELECT statement
+ ** should be written into a temporary table (template 4). Set to
+ ** FALSE if each* row of the SELECT can be written directly into
+ ** the destination table (template 3).
+ **
+ ** A temp table must be used if the table being updated is also one
+ ** of the tables being read by the SELECT statement. Also use a
+ ** temp table in the case of row triggers.
+ */
+ if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){
+ useTempTable = 1;
+ }
+
+ if( useTempTable ){
+ /* Invoke the coroutine to extract information from the SELECT
+ ** and add it to a transient table srcTab. The code generated
+ ** here is from the 4th template:
+ **
+ ** B: open temp table
+ ** L: yield X
+ ** if EOF goto M
+ ** insert row from R..R+n into temp table
+ ** goto L
+ ** M: ...
+ */
+ int regRec; /* Register to hold packed record */
+ int regTempRowid; /* Register to hold temp table ROWID */
+ int addrTop; /* Label "L" */
+ int addrIf; /* Address of jump to M */
+
+ srcTab = pParse->nTab++;
+ regRec = sqlite3GetTempReg(pParse);
+ regTempRowid = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
+ addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
+ addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
+ sqlite3VdbeJumpHere(v, addrIf);
+ sqlite3ReleaseTempReg(pParse, regRec);
+ sqlite3ReleaseTempReg(pParse, regTempRowid);
+ }
+ }else{
+ /* This is the case if the data for the INSERT is coming from a VALUES
+ ** clause
+ */
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ srcTab = -1;
+ assert( useTempTable==0 );
+ nColumn = pList ? pList->nExpr : 0;
+ for(i=0; i<nColumn; i++){
+ if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+ goto insert_cleanup;
+ }
+ }
+ }
+
+ /* Make sure the number of columns in the source data matches the number
+ ** of columns to be inserted into the table.
+ */
+ if( IsVirtual(pTab) ){
+ for(i=0; i<pTab->nCol; i++){
+ nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
+ }
+ }
+ if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
+ sqlite3ErrorMsg(pParse,
+ "table %S has %d columns but %d values were supplied",
+ pTabList, 0, pTab->nCol-nHidden, nColumn);
+ goto insert_cleanup;
+ }
+ if( pColumn!=0 && nColumn!=pColumn->nId ){
+ sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
+ goto insert_cleanup;
+ }
+
+ /* If the INSERT statement included an IDLIST term, then make sure
+ ** all elements of the IDLIST really are columns of the table and
+ ** remember the column indices.
+ **
+ ** If the table has an INTEGER PRIMARY KEY column and that column
+ ** is named in the IDLIST, then record in the keyColumn variable
+ ** the index into IDLIST of the primary key column. keyColumn is
+ ** the index of the primary key as it appears in IDLIST, not as
+ ** is appears in the original table. (The index of the primary
+ ** key in the original table is pTab->iPKey.)
+ */
+ if( pColumn ){
+ for(i=0; i<pColumn->nId; i++){
+ pColumn->a[i].idx = -1;
+ }
+ for(i=0; i<pColumn->nId; i++){
+ for(j=0; j<pTab->nCol; j++){
+ if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
+ pColumn->a[i].idx = j;
+ if( j==pTab->iPKey ){
+ keyColumn = i;
+ }
+ break;
+ }
+ }
+ if( j>=pTab->nCol ){
+ if( sqlite3IsRowid(pColumn->a[i].zName) ){
+ keyColumn = i;
+ }else{
+ sqlite3ErrorMsg(pParse, "table %S has no column named %s",
+ pTabList, 0, pColumn->a[i].zName);
+ pParse->checkSchema = 1;
+ goto insert_cleanup;
+ }
+ }
+ }
+ }
+
+ /* If there is no IDLIST term but the table has an integer primary
+ ** key, the set the keyColumn variable to the primary key column index
+ ** in the original table definition.
+ */
+ if( pColumn==0 && nColumn>0 ){
+ keyColumn = pTab->iPKey;
+ }
+
+ /* Initialize the count of rows to be inserted
+ */
+ if( db->flags & SQLITE_CountRows ){
+ regRowCount = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
+ }
+
+ /* If this is not a view, open the table and and all indices */
+ if( !isView ){
+ int nIdx;
+
+ baseCur = pParse->nTab;
+ nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);
+ aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
+ if( aRegIdx==0 ){
+ goto insert_cleanup;
+ }
+ for(i=0; i<nIdx; i++){
+ aRegIdx[i] = ++pParse->nMem;
+ }
+ }
+
+ /* This is the top of the main insertion loop */
+ if( useTempTable ){
+ /* This block codes the top of loop only. The complete loop is the
+ ** following pseudocode (template 4):
+ **
+ ** rewind temp table
+ ** C: loop over rows of intermediate table
+ ** transfer values form intermediate table into <table>
+ ** end loop
+ ** D: ...
+ */
+ addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab);
+ addrCont = sqlite3VdbeCurrentAddr(v);
+ }else if( pSelect ){
+ /* This block codes the top of loop only. The complete loop is the
+ ** following pseudocode (template 3):
+ **
+ ** C: yield X
+ ** if EOF goto D
+ ** insert the select result into <table> from R..R+n
+ ** goto C
+ ** D: ...
+ */
+ addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
+ addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);
+ }
+
+ /* Allocate registers for holding the rowid of the new row,
+ ** the content of the new row, and the assemblied row record.
+ */
+ regRowid = regIns = pParse->nMem+1;
+ pParse->nMem += pTab->nCol + 1;
+ if( IsVirtual(pTab) ){
+ regRowid++;
+ pParse->nMem++;
+ }
+ regData = regRowid+1;
+
+ /* Run the BEFORE and INSTEAD OF triggers, if there are any
+ */
+ endOfLoop = sqlite3VdbeMakeLabel(v);
+ if( tmask & TRIGGER_BEFORE ){
+ int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1);
+
+ /* build the NEW.* reference row. Note that if there is an INTEGER
+ ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
+ ** translated into a unique ID for the row. But on a BEFORE trigger,
+ ** we do not know what the unique ID will be (because the insert has
+ ** not happened yet) so we substitute a rowid of -1
+ */
+ if( keyColumn<0 ){
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
+ }else{
+ int j1;
+ if( useTempTable ){
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols);
+ }else{
+ assert( pSelect==0 ); /* Otherwise useTempTable is true */
+ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols);
+ }
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
+ sqlite3VdbeJumpHere(v, j1);
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols);
+ }
+
+ /* Cannot have triggers on a virtual table. If it were possible,
+ ** this block would have to account for hidden column.
+ */
+ assert( !IsVirtual(pTab) );
+
+ /* Create the new column data
+ */
+ for(i=0; i<pTab->nCol; i++){
+ if( pColumn==0 ){
+ j = i;
+ }else{
+ for(j=0; j<pColumn->nId; j++){
+ if( pColumn->a[j].idx==i ) break;
+ }
+ }
+ if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
+ }else if( useTempTable ){
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
+ }else{
+ assert( pSelect==0 ); /* Otherwise useTempTable is true */
+ sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
+ }
+ }
+
+ /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
+ ** do not attempt any conversions before assembling the record.
+ ** If this is a real table, attempt conversions as required by the
+ ** table column affinities.
+ */
+ if( !isView ){
+ sqlite3VdbeAddOp2(v, OP_Affinity, regCols+1, pTab->nCol);
+ sqlite3TableAffinityStr(v, pTab);
+ }
+
+ /* Fire BEFORE or INSTEAD OF triggers */
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
+ pTab, regCols-pTab->nCol-1, onError, endOfLoop);
+
+ sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
+ }
+
+ /* Push the record number for the new entry onto the stack. The
+ ** record number is a randomly generate integer created by NewRowid
+ ** except when the table has an INTEGER PRIMARY KEY column, in which
+ ** case the record number is the same as that column.
+ */
+ if( !isView ){
+ if( IsVirtual(pTab) ){
+ /* The row that the VUpdate opcode will delete: none */
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
+ }
+ if( keyColumn>=0 ){
+ if( useTempTable ){
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
+ }else if( pSelect ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);
+ }else{
+ VdbeOp *pOp;
+ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
+ pOp = sqlite3VdbeGetOp(v, -1);
+ if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
+ appendFlag = 1;
+ pOp->opcode = OP_NewRowid;
+ pOp->p1 = baseCur;
+ pOp->p2 = regRowid;
+ pOp->p3 = regAutoinc;
+ }
+ }
+ /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
+ ** to generate a unique primary key value.
+ */
+ if( !appendFlag ){
+ int j1;
+ if( !IsVirtual(pTab) ){
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);
+ sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
+ sqlite3VdbeJumpHere(v, j1);
+ }else{
+ j1 = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2);
+ }
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
+ }
+ }else if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
+ appendFlag = 1;
+ }
+ autoIncStep(pParse, regAutoinc, regRowid);
+
+ /* Push onto the stack, data for all columns of the new entry, beginning
+ ** with the first column.
+ */
+ nHidden = 0;
+ for(i=0; i<pTab->nCol; i++){
+ int iRegStore = regRowid+1+i;
+ if( i==pTab->iPKey ){
+ /* The value of the INTEGER PRIMARY KEY column is always a NULL.
+ ** Whenever this column is read, the record number will be substituted
+ ** in its place. So will fill this column with a NULL to avoid
+ ** taking up data space with information that will never be used. */
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore);
+ continue;
+ }
+ if( pColumn==0 ){
+ if( IsHiddenColumn(&pTab->aCol[i]) ){
+ assert( IsVirtual(pTab) );
+ j = -1;
+ nHidden++;
+ }else{
+ j = i - nHidden;
+ }
+ }else{
+ for(j=0; j<pColumn->nId; j++){
+ if( pColumn->a[j].idx==i ) break;
+ }
+ }
+ if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);
+ }else if( useTempTable ){
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
+ }else if( pSelect ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
+ }else{
+ sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
+ }
+ }
+
+ /* Generate code to check constraints and generate index keys and
+ ** do the insertion.
+ */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
+ sqlite3VtabMakeWritable(pParse, pTab);
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
+ sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
+ sqlite3MayAbort(pParse);
+ }else
+#endif
+ {
+ int isReplace; /* Set to true if constraints may cause a replace */
+ sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx,
+ keyColumn>=0, 0, onError, endOfLoop, &isReplace
+ );
+ sqlite3FkCheck(pParse, pTab, 0, regIns);
+ sqlite3CompleteInsertion(
+ pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0
+ );
+ }
+ }
+
+ /* Update the count of rows that are inserted
+ */
+ if( (db->flags & SQLITE_CountRows)!=0 ){
+ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
+ }
+
+ if( pTrigger ){
+ /* Code AFTER triggers */
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
+ pTab, regData-2-pTab->nCol, onError, endOfLoop);
+ }
+
+ /* The bottom of the main insertion loop, if the data source
+ ** is a SELECT statement.
+ */
+ sqlite3VdbeResolveLabel(v, endOfLoop);
+ if( useTempTable ){
+ sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont);
+ sqlite3VdbeJumpHere(v, addrInsTop);
+ sqlite3VdbeAddOp1(v, OP_Close, srcTab);
+ }else if( pSelect ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont);
+ sqlite3VdbeJumpHere(v, addrInsTop);
+ }
+
+ if( !IsVirtual(pTab) && !isView ){
+ /* Close all tables opened */
+ sqlite3VdbeAddOp1(v, OP_Close, baseCur);
+ for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
+ sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur);
+ }
+ }
+
+insert_end:
+ /* Update the sqlite_sequence table by storing the content of the
+ ** maximum rowid counter values recorded while inserting into
+ ** autoincrement tables.
+ */
+ if( pParse->nested==0 && pParse->pTriggerTab==0 ){
+ sqlite3AutoincrementEnd(pParse);
+ }
+
+ /*
+ ** Return the number of rows inserted. If this routine is
+ ** generating code because of a call to sqlite3NestedParse(), do not
+ ** invoke the callback function.
+ */
+ if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
+ }
+
+insert_cleanup:
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprListDelete(db, pList);
+ sqlite3SelectDelete(db, pSelect);
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3DbFree(db, aRegIdx);
+}
+
+/* Make sure "isView" and other macros defined above are undefined. Otherwise
+** thely may interfere with compilation of other functions in this file
+** (or in another file, if this file becomes part of the amalgamation). */
+#ifdef isView
+ #undef isView
+#endif
+#ifdef pTrigger
+ #undef pTrigger
+#endif
+#ifdef tmask
+ #undef tmask
+#endif
+
+
+/*
+** Generate code to do constraint checks prior to an INSERT or an UPDATE.
+**
+** The input is a range of consecutive registers as follows:
+**
+** 1. The rowid of the row after the update.
+**
+** 2. The data in the first column of the entry after the update.
+**
+** i. Data from middle columns...
+**
+** N. The data in the last column of the entry after the update.
+**
+** The regRowid parameter is the index of the register containing (1).
+**
+** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
+** the address of a register containing the rowid before the update takes
+** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
+** is false, indicating an INSERT statement, then a non-zero rowidChng
+** indicates that the rowid was explicitly specified as part of the
+** INSERT statement. If rowidChng is false, it means that the rowid is
+** computed automatically in an insert or that the rowid value is not
+** modified by an update.
+**
+** The code generated by this routine store new index entries into
+** registers identified by aRegIdx[]. No index entry is created for
+** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
+** the same as the order of indices on the linked list of indices
+** attached to the table.
+**
+** This routine also generates code to check constraints. NOT NULL,
+** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
+** then the appropriate action is performed. There are five possible
+** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
+**
+** Constraint type Action What Happens
+** --------------- ---------- ----------------------------------------
+** any ROLLBACK The current transaction is rolled back and
+** sqlite3_exec() returns immediately with a
+** return code of SQLITE_CONSTRAINT.
+**
+** any ABORT Back out changes from the current command
+** only (do not do a complete rollback) then
+** cause sqlite3_exec() to return immediately
+** with SQLITE_CONSTRAINT.
+**
+** any FAIL Sqlite3_exec() returns immediately with a
+** return code of SQLITE_CONSTRAINT. The
+** transaction is not rolled back and any
+** prior changes are retained.
+**
+** any IGNORE The record number and data is popped from
+** the stack and there is an immediate jump
+** to label ignoreDest.
+**
+** NOT NULL REPLACE The NULL value is replace by the default
+** value for that column. If the default value
+** is NULL, the action is the same as ABORT.
+**
+** UNIQUE REPLACE The other row that conflicts with the row
+** being inserted is removed.
+**
+** CHECK REPLACE Illegal. The results in an exception.
+**
+** Which action to take is determined by the overrideError parameter.
+** Or if overrideError==OE_Default, then the pParse->onError parameter
+** is used. Or if pParse->onError==OE_Default then the onError value
+** for the constraint is used.
+**
+** The calling routine must open a read/write cursor for pTab with
+** cursor number "baseCur". All indices of pTab must also have open
+** read/write cursors with cursor number baseCur+i for the i-th cursor.
+** Except, if there is no possibility of a REPLACE action then
+** cursors do not need to be open for indices where aRegIdx[i]==0.
+*/
+SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
+ Parse *pParse, /* The parser context */
+ Table *pTab, /* the table into which we are inserting */
+ int baseCur, /* Index of a read/write cursor pointing at pTab */
+ int regRowid, /* Index of the range of input registers */
+ int *aRegIdx, /* Register used by each index. 0 for unused indices */
+ int rowidChng, /* True if the rowid might collide with existing entry */
+ int isUpdate, /* True for UPDATE, False for INSERT */
+ int overrideError, /* Override onError to this if not OE_Default */
+ int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
+ int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */
+){
+ int i; /* loop counter */
+ Vdbe *v; /* VDBE under constrution */
+ int nCol; /* Number of columns */
+ int onError; /* Conflict resolution strategy */
+ int j1; /* Addresss of jump instruction */
+ int j2 = 0, j3; /* Addresses of jump instructions */
+ int regData; /* Register containing first data column */
+ int iCur; /* Table cursor number */
+ Index *pIdx; /* Pointer to one of the indices */
+ sqlite3 *db; /* Database connection */
+ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
+ int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
+
+ db = pParse->db;
+ v = sqlite3GetVdbe(pParse);
+ assert( v!=0 );
+ assert( pTab->pSelect==0 ); /* This table is not a VIEW */
+ nCol = pTab->nCol;
+ regData = regRowid + 1;
+
+ /* Test all NOT NULL constraints.
+ */
+ for(i=0; i<nCol; i++){
+ if( i==pTab->iPKey ){
+ continue;
+ }
+ onError = pTab->aCol[i].notNull;
+ if( onError==OE_None ) continue;
+ if( overrideError!=OE_Default ){
+ onError = overrideError;
+ }else if( onError==OE_Default ){
+ onError = OE_Abort;
+ }
+ if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
+ onError = OE_Abort;
+ }
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+ || onError==OE_Ignore || onError==OE_Replace );
+ switch( onError ){
+ case OE_Abort:
+ sqlite3MayAbort(pParse);
+ case OE_Rollback:
+ case OE_Fail: {
+ char *zMsg;
+ sqlite3VdbeAddOp3(v, OP_HaltIfNull,
+ SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
+ zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
+ pTab->zName, pTab->aCol[i].zName);
+ sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
+ break;
+ }
+ case OE_Ignore: {
+ sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
+ break;
+ }
+ default: {
+ assert( onError==OE_Replace );
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i);
+ sqlite3VdbeJumpHere(v, j1);
+ break;
+ }
+ }
+ }
+
+ /* Test all CHECK constraints
+ */
+#ifndef SQLITE_OMIT_CHECK
+ if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
+ ExprList *pCheck = pTab->pCheck;
+ pParse->ckBase = regData;
+ onError = overrideError!=OE_Default ? overrideError : OE_Abort;
+ for(i=0; i<pCheck->nExpr; i++){
+ int allOk = sqlite3VdbeMakeLabel(v);
+ sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL);
+ if( onError==OE_Ignore ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
+ }else{
+ char *zConsName = pCheck->a[i].zName;
+ if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
+ if( zConsName ){
+ zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
+ }else{
+ zConsName = 0;
+ }
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
+ onError, zConsName, P4_DYNAMIC);
+ }
+ sqlite3VdbeResolveLabel(v, allOk);
+ }
+ }
+#endif /* !defined(SQLITE_OMIT_CHECK) */
+
+ /* If we have an INTEGER PRIMARY KEY, make sure the primary key
+ ** of the new record does not previously exist. Except, if this
+ ** is an UPDATE and the primary key is not changing, that is OK.
+ */
+ if( rowidChng ){
+ onError = pTab->keyConf;
+ if( overrideError!=OE_Default ){
+ onError = overrideError;
+ }else if( onError==OE_Default ){
+ onError = OE_Abort;
+ }
+
+ if( isUpdate ){
+ j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
+ }
+ j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
+ switch( onError ){
+ default: {
+ onError = OE_Abort;
+ /* Fall thru into the next case */
+ }
+ case OE_Rollback:
+ case OE_Abort:
+ case OE_Fail: {
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+ onError, "PRIMARY KEY must be unique", P4_STATIC);
+ break;
+ }
+ case OE_Replace: {
+ /* If there are DELETE triggers on this table and the
+ ** recursive-triggers flag is set, call GenerateRowDelete() to
+ ** remove the conflicting row from the table. This will fire
+ ** the triggers and remove both the table and index b-tree entries.
+ **
+ ** Otherwise, if there are no triggers or the recursive-triggers
+ ** flag is not set, but the table has one or more indexes, call
+ ** GenerateRowIndexDelete(). This removes the index b-tree entries
+ ** only. The table b-tree entry will be replaced by the new entry
+ ** when it is inserted.
+ **
+ ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
+ ** also invoke MultiWrite() to indicate that this VDBE may require
+ ** statement rollback (if the statement is aborted after the delete
+ ** takes place). Earlier versions called sqlite3MultiWrite() regardless,
+ ** but being more selective here allows statements like:
+ **
+ ** REPLACE INTO t(rowid) VALUES($newrowid)
+ **
+ ** to run without a statement journal if there are no indexes on the
+ ** table.
+ */
+ Trigger *pTrigger = 0;
+ if( db->flags&SQLITE_RecTriggers ){
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
+ }
+ if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
+ sqlite3MultiWrite(pParse);
+ sqlite3GenerateRowDelete(
+ pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
+ );
+ }else if( pTab->pIndex ){
+ sqlite3MultiWrite(pParse);
+ sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
+ }
+ seenReplace = 1;
+ break;
+ }
+ case OE_Ignore: {
+ assert( seenReplace==0 );
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
+ break;
+ }
+ }
+ sqlite3VdbeJumpHere(v, j3);
+ if( isUpdate ){
+ sqlite3VdbeJumpHere(v, j2);
+ }
+ }
+
+ /* Test all UNIQUE constraints by creating entries for each UNIQUE
+ ** index and making sure that duplicate entries do not already exist.
+ ** Add the new records to the indices as we go.
+ */
+ for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
+ int regIdx;
+ int regR;
+
+ if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
+
+ /* Create a key for accessing the index entry */
+ regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
+ for(i=0; i<pIdx->nColumn; i++){
+ int idx = pIdx->aiColumn[i];
+ if( idx==pTab->iPKey ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
+ }
+ }
+ sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
+ sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
+ sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
+
+ /* Find out what action to take in case there is an indexing conflict */
+ onError = pIdx->onError;
+ if( onError==OE_None ){
+ sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+ continue; /* pIdx is not a UNIQUE index */
+ }
+ if( overrideError!=OE_Default ){
+ onError = overrideError;
+ }else if( onError==OE_Default ){
+ onError = OE_Abort;
+ }
+ if( seenReplace ){
+ if( onError==OE_Ignore ) onError = OE_Replace;
+ else if( onError==OE_Fail ) onError = OE_Abort;
+ }
+
+ /* Check to see if the new index entry will be unique */
+ regR = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
+ j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
+ regR, SQLITE_INT_TO_PTR(regIdx),
+ P4_INT32);
+ sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+
+ /* Generate code that executes if the new index entry is not unique */
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+ || onError==OE_Ignore || onError==OE_Replace );
+ switch( onError ){
+ case OE_Rollback:
+ case OE_Abort:
+ case OE_Fail: {
+ int j;
+ StrAccum errMsg;
+ const char *zSep;
+ char *zErr;
+
+ sqlite3StrAccumInit(&errMsg, 0, 0, 200);
+ errMsg.db = db;
+ zSep = pIdx->nColumn>1 ? "columns " : "column ";
+ for(j=0; j<pIdx->nColumn; j++){
+ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
+ sqlite3StrAccumAppend(&errMsg, zSep, -1);
+ zSep = ", ";
+ sqlite3StrAccumAppend(&errMsg, zCol, -1);
+ }
+ sqlite3StrAccumAppend(&errMsg,
+ pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
+ zErr = sqlite3StrAccumFinish(&errMsg);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+ onError, zErr, 0);
+ sqlite3DbFree(errMsg.db, zErr);
+ break;
+ }
+ case OE_Ignore: {
+ assert( seenReplace==0 );
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
+ break;
+ }
+ default: {
+ Trigger *pTrigger = 0;
+ assert( onError==OE_Replace );
+ sqlite3MultiWrite(pParse);
+ if( db->flags&SQLITE_RecTriggers ){
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
+ }
+ sqlite3GenerateRowDelete(
+ pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
+ );
+ seenReplace = 1;
+ break;
+ }
+ }
+ sqlite3VdbeJumpHere(v, j3);
+ sqlite3ReleaseTempReg(pParse, regR);
+ }
+
+ if( pbMayReplace ){
+ *pbMayReplace = seenReplace;
+ }
+}
+
+/*
+** This routine generates code to finish the INSERT or UPDATE operation
+** that was started by a prior call to sqlite3GenerateConstraintChecks.
+** A consecutive range of registers starting at regRowid contains the
+** rowid and the content to be inserted.
+**
+** The arguments to this routine should be the same as the first six
+** arguments to sqlite3GenerateConstraintChecks.
+*/
+SQLITE_PRIVATE void sqlite3CompleteInsertion(
+ Parse *pParse, /* The parser context */
+ Table *pTab, /* the table into which we are inserting */
+ int baseCur, /* Index of a read/write cursor pointing at pTab */
+ int regRowid, /* Range of content */
+ int *aRegIdx, /* Register used by each index. 0 for unused indices */
+ int isUpdate, /* True for UPDATE, False for INSERT */
+ int appendBias, /* True if this is likely to be an append */
+ int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
+){
+ int i;
+ Vdbe *v;
+ int nIdx;
+ Index *pIdx;
+ u8 pik_flags;
+ int regData;
+ int regRec;
+
+ v = sqlite3GetVdbe(pParse);
+ assert( v!=0 );
+ assert( pTab->pSelect==0 ); /* This table is not a VIEW */
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
+ for(i=nIdx-1; i>=0; i--){
+ if( aRegIdx[i]==0 ) continue;
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
+ if( useSeekResult ){
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ }
+ }
+ regData = regRowid + 1;
+ regRec = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
+ sqlite3TableAffinityStr(v, pTab);
+ sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
+ if( pParse->nested ){
+ pik_flags = 0;
+ }else{
+ pik_flags = OPFLAG_NCHANGE;
+ pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID);
+ }
+ if( appendBias ){
+ pik_flags |= OPFLAG_APPEND;
+ }
+ if( useSeekResult ){
+ pik_flags |= OPFLAG_USESEEKRESULT;
+ }
+ sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid);
+ if( !pParse->nested ){
+ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
+ }
+ sqlite3VdbeChangeP5(v, pik_flags);
+}
+
+/*
+** Generate code that will open cursors for a table and for all
+** indices of that table. The "baseCur" parameter is the cursor number used
+** for the table. Indices are opened on subsequent cursors.
+**
+** Return the number of indices on the table.
+*/
+SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
+ Parse *pParse, /* Parsing context */
+ Table *pTab, /* Table to be opened */
+ int baseCur, /* Cursor number assigned to the table */
+ int op /* OP_OpenRead or OP_OpenWrite */
+){
+ int i;
+ int iDb;
+ Index *pIdx;
+ Vdbe *v;
+
+ if( IsVirtual(pTab) ) return 0;
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ v = sqlite3GetVdbe(pParse);
+ assert( v!=0 );
+ sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);
+ for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+ assert( pIdx->pSchema==pTab->pSchema );
+ sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb,
+ (char*)pKey, P4_KEYINFO_HANDOFF);
+ VdbeComment((v, "%s", pIdx->zName));
+ }
+ if( pParse->nTab<baseCur+i ){
+ pParse->nTab = baseCur+i;
+ }
+ return i-1;
+}
+
+
+#ifdef SQLITE_TEST
+/*
+** The following global variable is incremented whenever the
+** transfer optimization is used. This is used for testing
+** purposes only - to make sure the transfer optimization really
+** is happening when it is suppose to.
+*/
+SQLITE_API int sqlite3_xferopt_count;
+#endif /* SQLITE_TEST */
+
+
+#ifndef SQLITE_OMIT_XFER_OPT
+/*
+** Check to collation names to see if they are compatible.
+*/
+static int xferCompatibleCollation(const char *z1, const char *z2){
+ if( z1==0 ){
+ return z2==0;
+ }
+ if( z2==0 ){
+ return 0;
+ }
+ return sqlite3StrICmp(z1, z2)==0;
+}
+
+
+/*
+** Check to see if index pSrc is compatible as a source of data
+** for index pDest in an insert transfer optimization. The rules
+** for a compatible index:
+**
+** * The index is over the same set of columns
+** * The same DESC and ASC markings occurs on all columns
+** * The same onError processing (OE_Abort, OE_Ignore, etc)
+** * The same collating sequence on each column
+*/
+static int xferCompatibleIndex(Index *pDest, Index *pSrc){
+ int i;
+ assert( pDest && pSrc );
+ assert( pDest->pTable!=pSrc->pTable );
+ if( pDest->nColumn!=pSrc->nColumn ){
+ return 0; /* Different number of columns */
+ }
+ if( pDest->onError!=pSrc->onError ){
+ return 0; /* Different conflict resolution strategies */
+ }
+ for(i=0; i<pSrc->nColumn; i++){
+ if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
+ return 0; /* Different columns indexed */
+ }
+ if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
+ return 0; /* Different sort orders */
+ }
+ if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){
+ return 0; /* Different collating sequences */
+ }
+ }
+
+ /* If no test above fails then the indices must be compatible */
+ return 1;
+}
+
+/*
+** Attempt the transfer optimization on INSERTs of the form
+**
+** INSERT INTO tab1 SELECT * FROM tab2;
+**
+** The xfer optimization transfers raw records from tab2 over to tab1.
+** Columns are not decoded and reassemblied, which greatly improves
+** performance. Raw index records are transferred in the same way.
+**
+** The xfer optimization is only attempted if tab1 and tab2 are compatible.
+** There are lots of rules for determining compatibility - see comments
+** embedded in the code for details.
+**
+** This routine returns TRUE if the optimization is guaranteed to be used.
+** Sometimes the xfer optimization will only work if the destination table
+** is empty - a factor that can only be determined at run-time. In that
+** case, this routine generates code for the xfer optimization but also
+** does a test to see if the destination table is empty and jumps over the
+** xfer optimization code if the test fails. In that case, this routine
+** returns FALSE so that the caller will know to go ahead and generate
+** an unoptimized transfer. This routine also returns FALSE if there
+** is no chance that the xfer optimization can be applied.
+**
+** This optimization is particularly useful at making VACUUM run faster.
+*/
+static int xferOptimization(
+ Parse *pParse, /* Parser context */
+ Table *pDest, /* The table we are inserting into */
+ Select *pSelect, /* A SELECT statement to use as the data source */
+ int onError, /* How to handle constraint errors */
+ int iDbDest /* The database of pDest */
+){
+ ExprList *pEList; /* The result set of the SELECT */
+ Table *pSrc; /* The table in the FROM clause of SELECT */
+ Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
+ struct SrcList_item *pItem; /* An element of pSelect->pSrc */
+ int i; /* Loop counter */
+ int iDbSrc; /* The database of pSrc */
+ int iSrc, iDest; /* Cursors from source and destination */
+ int addr1, addr2; /* Loop addresses */
+ int emptyDestTest; /* Address of test for empty pDest */
+ int emptySrcTest; /* Address of test for empty pSrc */
+ Vdbe *v; /* The VDBE we are building */
+ KeyInfo *pKey; /* Key information for an index */
+ int regAutoinc; /* Memory register used by AUTOINC */
+ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
+ int regData, regRowid; /* Registers holding data and rowid */
+
+ if( pSelect==0 ){
+ return 0; /* Must be of the form INSERT INTO ... SELECT ... */
+ }
+ if( sqlite3TriggerList(pParse, pDest) ){
+ return 0; /* tab1 must not have triggers */
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pDest->tabFlags & TF_Virtual ){
+ return 0; /* tab1 must not be a virtual table */
+ }
+#endif
+ if( onError==OE_Default ){
+ if( pDest->iPKey>=0 ) onError = pDest->keyConf;
+ if( onError==OE_Default ) onError = OE_Abort;
+ }
+ assert(pSelect->pSrc); /* allocated even if there is no FROM clause */
+ if( pSelect->pSrc->nSrc!=1 ){
+ return 0; /* FROM clause must have exactly one term */
+ }
+ if( pSelect->pSrc->a[0].pSelect ){
+ return 0; /* FROM clause cannot contain a subquery */
+ }
+ if( pSelect->pWhere ){
+ return 0; /* SELECT may not have a WHERE clause */
+ }
+ if( pSelect->pOrderBy ){
+ return 0; /* SELECT may not have an ORDER BY clause */
+ }
+ /* Do not need to test for a HAVING clause. If HAVING is present but
+ ** there is no ORDER BY, we will get an error. */
+ if( pSelect->pGroupBy ){
+ return 0; /* SELECT may not have a GROUP BY clause */
+ }
+ if( pSelect->pLimit ){
+ return 0; /* SELECT may not have a LIMIT clause */
+ }
+ assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */
+ if( pSelect->pPrior ){
+ return 0; /* SELECT may not be a compound query */
+ }
+ if( pSelect->selFlags & SF_Distinct ){
+ return 0; /* SELECT may not be DISTINCT */
+ }
+ pEList = pSelect->pEList;
+ assert( pEList!=0 );
+ if( pEList->nExpr!=1 ){
+ return 0; /* The result set must have exactly one column */
+ }
+ assert( pEList->a[0].pExpr );
+ if( pEList->a[0].pExpr->op!=TK_ALL ){
+ return 0; /* The result set must be the special operator "*" */
+ }
+
+ /* At this point we have established that the statement is of the
+ ** correct syntactic form to participate in this optimization. Now
+ ** we have to check the semantics.
+ */
+ pItem = pSelect->pSrc->a;
+ pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
+ if( pSrc==0 ){
+ return 0; /* FROM clause does not contain a real table */
+ }
+ if( pSrc==pDest ){
+ return 0; /* tab1 and tab2 may not be the same table */
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pSrc->tabFlags & TF_Virtual ){
+ return 0; /* tab2 must not be a virtual table */
+ }
+#endif
+ if( pSrc->pSelect ){
+ return 0; /* tab2 may not be a view */
+ }
+ if( pDest->nCol!=pSrc->nCol ){
+ return 0; /* Number of columns must be the same in tab1 and tab2 */
+ }
+ if( pDest->iPKey!=pSrc->iPKey ){
+ return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
+ }
+ for(i=0; i<pDest->nCol; i++){
+ if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
+ return 0; /* Affinity must be the same on all columns */
+ }
+ if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){
+ return 0; /* Collating sequence must be the same on all columns */
+ }
+ if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){
+ return 0; /* tab2 must be NOT NULL if tab1 is */
+ }
+ }
+ for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
+ if( pDestIdx->onError!=OE_None ){
+ destHasUniqueIdx = 1;
+ }
+ for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
+ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
+ }
+ if( pSrcIdx==0 ){
+ return 0; /* pDestIdx has no corresponding index in pSrc */
+ }
+ }
+#ifndef SQLITE_OMIT_CHECK
+ if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){
+ return 0; /* Tables have different CHECK constraints. Ticket #2252 */
+ }
+#endif
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ /* Disallow the transfer optimization if the destination table constains
+ ** any foreign key constraints. This is more restrictive than necessary.
+ ** But the main beneficiary of the transfer optimization is the VACUUM
+ ** command, and the VACUUM command disables foreign key constraints. So
+ ** the extra complication to make this rule less restrictive is probably
+ ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
+ */
+ if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
+ return 0;
+ }
+#endif
+ if( (pParse->db->flags & SQLITE_CountRows)!=0 ){
+ return 0; /* xfer opt does not play well with PRAGMA count_changes */
+ }
+
+ /* If we get this far, it means that the xfer optimization is at
+ ** least a possibility, though it might only work if the destination
+ ** table (tab1) is initially empty.
+ */
+#ifdef SQLITE_TEST
+ sqlite3_xferopt_count++;
+#endif
+ iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema);
+ v = sqlite3GetVdbe(pParse);
+ sqlite3CodeVerifySchema(pParse, iDbSrc);
+ iSrc = pParse->nTab++;
+ iDest = pParse->nTab++;
+ regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
+ sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
+ if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
+ || destHasUniqueIdx /* (2) */
+ || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
+ ){
+ /* In some circumstances, we are able to run the xfer optimization
+ ** only if the destination table is initially empty. This code makes
+ ** that determination. Conditions under which the destination must
+ ** be empty:
+ **
+ ** (1) There is no INTEGER PRIMARY KEY but there are indices.
+ ** (If the destination is not initially empty, the rowid fields
+ ** of index entries might need to change.)
+ **
+ ** (2) The destination has a unique index. (The xfer optimization
+ ** is unable to test uniqueness.)
+ **
+ ** (3) onError is something other than OE_Abort and OE_Rollback.
+ */
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0);
+ emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
+ sqlite3VdbeJumpHere(v, addr1);
+ }else{
+ emptyDestTest = 0;
+ }
+ sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
+ emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
+ regData = sqlite3GetTempReg(pParse);
+ regRowid = sqlite3GetTempReg(pParse);
+ if( pDest->iPKey>=0 ){
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
+ addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+ onError, "PRIMARY KEY must be unique", P4_STATIC);
+ sqlite3VdbeJumpHere(v, addr2);
+ autoIncStep(pParse, regAutoinc, regRowid);
+ }else if( pDest->pIndex==0 ){
+ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
+ }else{
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
+ assert( (pDest->tabFlags & TF_Autoincrement)==0 );
+ }
+ sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
+ sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
+ sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
+ for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
+ for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
+ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
+ }
+ assert( pSrcIdx );
+ sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
+ sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
+ pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx);
+ sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc,
+ (char*)pKey, P4_KEYINFO_HANDOFF);
+ VdbeComment((v, "%s", pSrcIdx->zName));
+ pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
+ sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
+ (char*)pKey, P4_KEYINFO_HANDOFF);
+ VdbeComment((v, "%s", pDestIdx->zName));
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
+ sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
+ sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
+ sqlite3VdbeJumpHere(v, addr1);
+ }
+ sqlite3VdbeJumpHere(v, emptySrcTest);
+ sqlite3ReleaseTempReg(pParse, regRowid);
+ sqlite3ReleaseTempReg(pParse, regData);
+ sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
+ sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
+ if( emptyDestTest ){
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
+ sqlite3VdbeJumpHere(v, emptyDestTest);
+ sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
+ return 0;
+ }else{
+ return 1;
+ }
+}
+#endif /* SQLITE_OMIT_XFER_OPT */
+
+/************** End of insert.c **********************************************/
+/************** Begin file legacy.c ******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Main file for the SQLite library. The routines in this file
+** implement the programmer interface to the library. Routines in
+** other files are for internal use by SQLite and should not be
+** accessed by users of the library.
+*/
+
+
+/*
+** Execute SQL code. Return one of the SQLITE_ success/failure
+** codes. Also write an error message into memory obtained from
+** malloc() and make *pzErrMsg point to that message.
+**
+** If the SQL is a query, then for each row in the query result
+** the xCallback() function is called. pArg becomes the first
+** argument to xCallback(). If xCallback=NULL then no callback
+** is invoked, even for queries.
+*/
+SQLITE_API int sqlite3_exec(
+ sqlite3 *db, /* The database on which the SQL executes */
+ const char *zSql, /* The SQL to be executed */
+ sqlite3_callback xCallback, /* Invoke this callback routine */
+ void *pArg, /* First argument to xCallback() */
+ char **pzErrMsg /* Write error messages here */
+){
+ int rc = SQLITE_OK; /* Return code */
+ const char *zLeftover; /* Tail of unprocessed SQL */
+ sqlite3_stmt *pStmt = 0; /* The current SQL statement */
+ char **azCols = 0; /* Names of result columns */
+ int nRetry = 0; /* Number of retry attempts */
+ int callbackIsInit; /* True if callback data is initialized */
+
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+ if( zSql==0 ) zSql = "";
+
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3Error(db, SQLITE_OK, 0);
+ while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
+ int nCol;
+ char **azVals = 0;
+
+ pStmt = 0;
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
+ assert( rc==SQLITE_OK || pStmt==0 );
+ if( rc!=SQLITE_OK ){
+ continue;
+ }
+ if( !pStmt ){
+ /* this happens for a comment or white-space */
+ zSql = zLeftover;
+ continue;
+ }
+
+ callbackIsInit = 0;
+ nCol = sqlite3_column_count(pStmt);
+
+ while( 1 ){
+ int i;
+ rc = sqlite3_step(pStmt);
+
+ /* Invoke the callback function if required */
+ if( xCallback && (SQLITE_ROW==rc ||
+ (SQLITE_DONE==rc && !callbackIsInit
+ && db->flags&SQLITE_NullCallback)) ){
+ if( !callbackIsInit ){
+ azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
+ if( azCols==0 ){
+ goto exec_out;
+ }
+ for(i=0; i<nCol; i++){
+ azCols[i] = (char *)sqlite3_column_name(pStmt, i);
+ /* sqlite3VdbeSetColName() installs column names as UTF8
+ ** strings so there is no way for sqlite3_column_name() to fail. */
+ assert( azCols[i]!=0 );
+ }
+ callbackIsInit = 1;
+ }
+ if( rc==SQLITE_ROW ){
+ azVals = &azCols[nCol];
+ for(i=0; i<nCol; i++){
+ azVals[i] = (char *)sqlite3_column_text(pStmt, i);
+ if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
+ db->mallocFailed = 1;
+ goto exec_out;
+ }
+ }
+ }
+ if( xCallback(pArg, nCol, azVals, azCols) ){
+ rc = SQLITE_ABORT;
+ sqlite3VdbeFinalize((Vdbe *)pStmt);
+ pStmt = 0;
+ sqlite3Error(db, SQLITE_ABORT, 0);
+ goto exec_out;
+ }
+ }
+
+ if( rc!=SQLITE_ROW ){
+ rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
+ pStmt = 0;
+ if( rc!=SQLITE_SCHEMA ){
+ nRetry = 0;
+ zSql = zLeftover;
+ while( sqlite3Isspace(zSql[0]) ) zSql++;
+ }
+ break;
+ }
+ }
+
+ sqlite3DbFree(db, azCols);
+ azCols = 0;
+ }
+
+exec_out:
+ if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
+ sqlite3DbFree(db, azCols);
+
+ rc = sqlite3ApiExit(db, rc);
+ if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
+ int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
+ *pzErrMsg = sqlite3Malloc(nErrMsg);
+ if( *pzErrMsg ){
+ memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
+ }else{
+ rc = SQLITE_NOMEM;
+ sqlite3Error(db, SQLITE_NOMEM, 0);
+ }
+ }else if( pzErrMsg ){
+ *pzErrMsg = 0;
+ }
+
+ assert( (rc&db->errMask)==rc );
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/************** End of legacy.c **********************************************/
+/************** Begin file loadext.c *****************************************/
+/*
+** 2006 June 7
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used to dynamically load extensions into
+** the SQLite library.
+*/
+
+#ifndef SQLITE_CORE
+ #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
+#endif
+/************** Include sqlite3ext.h in the middle of loadext.c **************/
+/************** Begin file sqlite3ext.h **************************************/
+/*
+** 2006 June 7
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the SQLite interface for use by
+** shared libraries that want to be imported as extensions into
+** an SQLite instance. Shared libraries that intend to be loaded
+** as extensions by SQLite should #include this file instead of
+** sqlite3.h.
+*/
+#ifndef _SQLITE3EXT_H_
+#define _SQLITE3EXT_H_
+
+typedef struct sqlite3_api_routines sqlite3_api_routines;
+
+/*
+** The following structure holds pointers to all of the SQLite API
+** routines.
+**
+** WARNING: In order to maintain backwards compatibility, add new
+** interfaces to the end of this structure only. If you insert new
+** interfaces in the middle of this structure, then older different
+** versions of SQLite will not be able to load each others' shared
+** libraries!
+*/
+struct sqlite3_api_routines {
+ void * (*aggregate_context)(sqlite3_context*,int nBytes);
+ int (*aggregate_count)(sqlite3_context*);
+ int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
+ int (*bind_double)(sqlite3_stmt*,int,double);
+ int (*bind_int)(sqlite3_stmt*,int,int);
+ int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
+ int (*bind_null)(sqlite3_stmt*,int);
+ int (*bind_parameter_count)(sqlite3_stmt*);
+ int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
+ const char * (*bind_parameter_name)(sqlite3_stmt*,int);
+ int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
+ int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
+ int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
+ int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
+ int (*busy_timeout)(sqlite3*,int ms);
+ int (*changes)(sqlite3*);
+ int (*close)(sqlite3*);
+ int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
+ int eTextRep,const char*));
+ int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
+ int eTextRep,const void*));
+ const void * (*column_blob)(sqlite3_stmt*,int iCol);
+ int (*column_bytes)(sqlite3_stmt*,int iCol);
+ int (*column_bytes16)(sqlite3_stmt*,int iCol);
+ int (*column_count)(sqlite3_stmt*pStmt);
+ const char * (*column_database_name)(sqlite3_stmt*,int);
+ const void * (*column_database_name16)(sqlite3_stmt*,int);
+ const char * (*column_decltype)(sqlite3_stmt*,int i);
+ const void * (*column_decltype16)(sqlite3_stmt*,int);
+ double (*column_double)(sqlite3_stmt*,int iCol);
+ int (*column_int)(sqlite3_stmt*,int iCol);
+ sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
+ const char * (*column_name)(sqlite3_stmt*,int);
+ const void * (*column_name16)(sqlite3_stmt*,int);
+ const char * (*column_origin_name)(sqlite3_stmt*,int);
+ const void * (*column_origin_name16)(sqlite3_stmt*,int);
+ const char * (*column_table_name)(sqlite3_stmt*,int);
+ const void * (*column_table_name16)(sqlite3_stmt*,int);
+ const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
+ const void * (*column_text16)(sqlite3_stmt*,int iCol);
+ int (*column_type)(sqlite3_stmt*,int iCol);
+ sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
+ void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
+ int (*complete)(const char*sql);
+ int (*complete16)(const void*sql);
+ int (*create_collation)(sqlite3*,const char*,int,void*,
+ int(*)(void*,int,const void*,int,const void*));
+ int (*create_collation16)(sqlite3*,const void*,int,void*,
+ int(*)(void*,int,const void*,int,const void*));
+ int (*create_function)(sqlite3*,const char*,int,int,void*,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*));
+ int (*create_function16)(sqlite3*,const void*,int,int,void*,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*));
+ int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
+ int (*data_count)(sqlite3_stmt*pStmt);
+ sqlite3 * (*db_handle)(sqlite3_stmt*);
+ int (*declare_vtab)(sqlite3*,const char*);
+ int (*enable_shared_cache)(int);
+ int (*errcode)(sqlite3*db);
+ const char * (*errmsg)(sqlite3*);
+ const void * (*errmsg16)(sqlite3*);
+ int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
+ int (*expired)(sqlite3_stmt*);
+ int (*finalize)(sqlite3_stmt*pStmt);
+ void (*free)(void*);
+ void (*free_table)(char**result);
+ int (*get_autocommit)(sqlite3*);
+ void * (*get_auxdata)(sqlite3_context*,int);
+ int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
+ int (*global_recover)(void);
+ void (*interruptx)(sqlite3*);
+ sqlite_int64 (*last_insert_rowid)(sqlite3*);
+ const char * (*libversion)(void);
+ int (*libversion_number)(void);
+ void *(*malloc)(int);
+ char * (*mprintf)(const char*,...);
+ int (*open)(const char*,sqlite3**);
+ int (*open16)(const void*,sqlite3**);
+ int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
+ int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
+ void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
+ void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
+ void *(*realloc)(void*,int);
+ int (*reset)(sqlite3_stmt*pStmt);
+ void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_double)(sqlite3_context*,double);
+ void (*result_error)(sqlite3_context*,const char*,int);
+ void (*result_error16)(sqlite3_context*,const void*,int);
+ void (*result_int)(sqlite3_context*,int);
+ void (*result_int64)(sqlite3_context*,sqlite_int64);
+ void (*result_null)(sqlite3_context*);
+ void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
+ void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_value)(sqlite3_context*,sqlite3_value*);
+ void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
+ int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
+ const char*,const char*),void*);
+ void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
+ char * (*snprintf)(int,char*,const char*,...);
+ int (*step)(sqlite3_stmt*);
+ int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
+ char const**,char const**,int*,int*,int*);
+ void (*thread_cleanup)(void);
+ int (*total_changes)(sqlite3*);
+ void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
+ int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
+ void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
+ sqlite_int64),void*);
+ void * (*user_data)(sqlite3_context*);
+ const void * (*value_blob)(sqlite3_value*);
+ int (*value_bytes)(sqlite3_value*);
+ int (*value_bytes16)(sqlite3_value*);
+ double (*value_double)(sqlite3_value*);
+ int (*value_int)(sqlite3_value*);
+ sqlite_int64 (*value_int64)(sqlite3_value*);
+ int (*value_numeric_type)(sqlite3_value*);
+ const unsigned char * (*value_text)(sqlite3_value*);
+ const void * (*value_text16)(sqlite3_value*);
+ const void * (*value_text16be)(sqlite3_value*);
+ const void * (*value_text16le)(sqlite3_value*);
+ int (*value_type)(sqlite3_value*);
+ char *(*vmprintf)(const char*,va_list);
+ /* Added ??? */
+ int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
+ /* Added by 3.3.13 */
+ int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
+ int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
+ int (*clear_bindings)(sqlite3_stmt*);
+ /* Added by 3.4.1 */
+ int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
+ void (*xDestroy)(void *));
+ /* Added by 3.5.0 */
+ int (*bind_zeroblob)(sqlite3_stmt*,int,int);
+ int (*blob_bytes)(sqlite3_blob*);
+ int (*blob_close)(sqlite3_blob*);
+ int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
+ int,sqlite3_blob**);
+ int (*blob_read)(sqlite3_blob*,void*,int,int);
+ int (*blob_write)(sqlite3_blob*,const void*,int,int);
+ int (*create_collation_v2)(sqlite3*,const char*,int,void*,
+ int(*)(void*,int,const void*,int,const void*),
+ void(*)(void*));
+ int (*file_control)(sqlite3*,const char*,int,void*);
+ sqlite3_int64 (*memory_highwater)(int);
+ sqlite3_int64 (*memory_used)(void);
+ sqlite3_mutex *(*mutex_alloc)(int);
+ void (*mutex_enter)(sqlite3_mutex*);
+ void (*mutex_free)(sqlite3_mutex*);
+ void (*mutex_leave)(sqlite3_mutex*);
+ int (*mutex_try)(sqlite3_mutex*);
+ int (*open_v2)(const char*,sqlite3**,int,const char*);
+ int (*release_memory)(int);
+ void (*result_error_nomem)(sqlite3_context*);
+ void (*result_error_toobig)(sqlite3_context*);
+ int (*sleep)(int);
+ void (*soft_heap_limit)(int);
+ sqlite3_vfs *(*vfs_find)(const char*);
+ int (*vfs_register)(sqlite3_vfs*,int);
+ int (*vfs_unregister)(sqlite3_vfs*);
+ int (*xthreadsafe)(void);
+ void (*result_zeroblob)(sqlite3_context*,int);
+ void (*result_error_code)(sqlite3_context*,int);
+ int (*test_control)(int, ...);
+ void (*randomness)(int,void*);
+ sqlite3 *(*context_db_handle)(sqlite3_context*);
+ int (*extended_result_codes)(sqlite3*,int);
+ int (*limit)(sqlite3*,int,int);
+ sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
+ const char *(*sql)(sqlite3_stmt*);
+ int (*status)(int,int*,int*,int);
+ int (*backup_finish)(sqlite3_backup*);
+ sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
+ int (*backup_pagecount)(sqlite3_backup*);
+ int (*backup_remaining)(sqlite3_backup*);
+ int (*backup_step)(sqlite3_backup*,int);
+ const char *(*compileoption_get)(int);
+ int (*compileoption_used)(const char*);
+ int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*),
+ void(*xDestroy)(void*));
+ int (*db_config)(sqlite3*,int,...);
+ sqlite3_mutex *(*db_mutex)(sqlite3*);
+ int (*db_status)(sqlite3*,int,int*,int*,int);
+ int (*extended_errcode)(sqlite3*);
+ void (*log)(int,const char*,...);
+ sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
+ const char *(*sourceid)(void);
+ int (*stmt_status)(sqlite3_stmt*,int,int);
+ int (*strnicmp)(const char*,const char*,int);
+ int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
+ int (*wal_autocheckpoint)(sqlite3*,int);
+ int (*wal_checkpoint)(sqlite3*,const char*);
+ void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
+ int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
+ int (*vtab_config)(sqlite3*,int op,...);
+ int (*vtab_on_conflict)(sqlite3*);
+ /* Version 3.7.16 and later */
+ int (*close_v2)(sqlite3*);
+ const char *(*db_filename)(sqlite3*,const char*);
+ int (*db_readonly)(sqlite3*,const char*);
+ int (*db_release_memory)(sqlite3*);
+ const char *(*errstr)(int);
+ int (*stmt_busy)(sqlite3_stmt*);
+ int (*stmt_readonly)(sqlite3_stmt*);
+ int (*stricmp)(const char*,const char*);
+ int (*uri_boolean)(const char*,const char*,int);
+ sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
+ const char *(*uri_parameter)(const char*,const char*);
+ char *(*vsnprintf)(int,char*,const char*,va_list);
+ int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
+};
+
+/*
+** The following macros redefine the API routines so that they are
+** redirected throught the global sqlite3_api structure.
+**
+** This header file is also used by the loadext.c source file
+** (part of the main SQLite library - not an extension) so that
+** it can get access to the sqlite3_api_routines structure
+** definition. But the main library does not want to redefine
+** the API. So the redefinition macros are only valid if the
+** SQLITE_CORE macros is undefined.
+*/
+#ifndef SQLITE_CORE
+#define sqlite3_aggregate_context sqlite3_api->aggregate_context
+#ifndef SQLITE_OMIT_DEPRECATED
+#define sqlite3_aggregate_count sqlite3_api->aggregate_count
+#endif
+#define sqlite3_bind_blob sqlite3_api->bind_blob
+#define sqlite3_bind_double sqlite3_api->bind_double
+#define sqlite3_bind_int sqlite3_api->bind_int
+#define sqlite3_bind_int64 sqlite3_api->bind_int64
+#define sqlite3_bind_null sqlite3_api->bind_null
+#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
+#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
+#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
+#define sqlite3_bind_text sqlite3_api->bind_text
+#define sqlite3_bind_text16 sqlite3_api->bind_text16
+#define sqlite3_bind_value sqlite3_api->bind_value
+#define sqlite3_busy_handler sqlite3_api->busy_handler
+#define sqlite3_busy_timeout sqlite3_api->busy_timeout
+#define sqlite3_changes sqlite3_api->changes
+#define sqlite3_close sqlite3_api->close
+#define sqlite3_collation_needed sqlite3_api->collation_needed
+#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
+#define sqlite3_column_blob sqlite3_api->column_blob
+#define sqlite3_column_bytes sqlite3_api->column_bytes
+#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
+#define sqlite3_column_count sqlite3_api->column_count
+#define sqlite3_column_database_name sqlite3_api->column_database_name
+#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
+#define sqlite3_column_decltype sqlite3_api->column_decltype
+#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
+#define sqlite3_column_double sqlite3_api->column_double
+#define sqlite3_column_int sqlite3_api->column_int
+#define sqlite3_column_int64 sqlite3_api->column_int64
+#define sqlite3_column_name sqlite3_api->column_name
+#define sqlite3_column_name16 sqlite3_api->column_name16
+#define sqlite3_column_origin_name sqlite3_api->column_origin_name
+#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
+#define sqlite3_column_table_name sqlite3_api->column_table_name
+#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
+#define sqlite3_column_text sqlite3_api->column_text
+#define sqlite3_column_text16 sqlite3_api->column_text16
+#define sqlite3_column_type sqlite3_api->column_type
+#define sqlite3_column_value sqlite3_api->column_value
+#define sqlite3_commit_hook sqlite3_api->commit_hook
+#define sqlite3_complete sqlite3_api->complete
+#define sqlite3_complete16 sqlite3_api->complete16
+#define sqlite3_create_collation sqlite3_api->create_collation
+#define sqlite3_create_collation16 sqlite3_api->create_collation16
+#define sqlite3_create_function sqlite3_api->create_function
+#define sqlite3_create_function16 sqlite3_api->create_function16
+#define sqlite3_create_module sqlite3_api->create_module
+#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
+#define sqlite3_data_count sqlite3_api->data_count
+#define sqlite3_db_handle sqlite3_api->db_handle
+#define sqlite3_declare_vtab sqlite3_api->declare_vtab
+#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
+#define sqlite3_errcode sqlite3_api->errcode
+#define sqlite3_errmsg sqlite3_api->errmsg
+#define sqlite3_errmsg16 sqlite3_api->errmsg16
+#define sqlite3_exec sqlite3_api->exec
+#ifndef SQLITE_OMIT_DEPRECATED
+#define sqlite3_expired sqlite3_api->expired
+#endif
+#define sqlite3_finalize sqlite3_api->finalize
+#define sqlite3_free sqlite3_api->free
+#define sqlite3_free_table sqlite3_api->free_table
+#define sqlite3_get_autocommit sqlite3_api->get_autocommit
+#define sqlite3_get_auxdata sqlite3_api->get_auxdata
+#define sqlite3_get_table sqlite3_api->get_table
+#ifndef SQLITE_OMIT_DEPRECATED
+#define sqlite3_global_recover sqlite3_api->global_recover
+#endif
+#define sqlite3_interrupt sqlite3_api->interruptx
+#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
+#define sqlite3_libversion sqlite3_api->libversion
+#define sqlite3_libversion_number sqlite3_api->libversion_number
+#define sqlite3_malloc sqlite3_api->malloc
+#define sqlite3_mprintf sqlite3_api->mprintf
+#define sqlite3_open sqlite3_api->open
+#define sqlite3_open16 sqlite3_api->open16
+#define sqlite3_prepare sqlite3_api->prepare
+#define sqlite3_prepare16 sqlite3_api->prepare16
+#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
+#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
+#define sqlite3_profile sqlite3_api->profile
+#define sqlite3_progress_handler sqlite3_api->progress_handler
+#define sqlite3_realloc sqlite3_api->realloc
+#define sqlite3_reset sqlite3_api->reset
+#define sqlite3_result_blob sqlite3_api->result_blob
+#define sqlite3_result_double sqlite3_api->result_double
+#define sqlite3_result_error sqlite3_api->result_error
+#define sqlite3_result_error16 sqlite3_api->result_error16
+#define sqlite3_result_int sqlite3_api->result_int
+#define sqlite3_result_int64 sqlite3_api->result_int64
+#define sqlite3_result_null sqlite3_api->result_null
+#define sqlite3_result_text sqlite3_api->result_text
+#define sqlite3_result_text16 sqlite3_api->result_text16
+#define sqlite3_result_text16be sqlite3_api->result_text16be
+#define sqlite3_result_text16le sqlite3_api->result_text16le
+#define sqlite3_result_value sqlite3_api->result_value
+#define sqlite3_rollback_hook sqlite3_api->rollback_hook
+#define sqlite3_set_authorizer sqlite3_api->set_authorizer
+#define sqlite3_set_auxdata sqlite3_api->set_auxdata
+#define sqlite3_snprintf sqlite3_api->snprintf
+#define sqlite3_step sqlite3_api->step
+#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
+#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
+#define sqlite3_total_changes sqlite3_api->total_changes
+#define sqlite3_trace sqlite3_api->trace
+#ifndef SQLITE_OMIT_DEPRECATED
+#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
+#endif
+#define sqlite3_update_hook sqlite3_api->update_hook
+#define sqlite3_user_data sqlite3_api->user_data
+#define sqlite3_value_blob sqlite3_api->value_blob
+#define sqlite3_value_bytes sqlite3_api->value_bytes
+#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
+#define sqlite3_value_double sqlite3_api->value_double
+#define sqlite3_value_int sqlite3_api->value_int
+#define sqlite3_value_int64 sqlite3_api->value_int64
+#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
+#define sqlite3_value_text sqlite3_api->value_text
+#define sqlite3_value_text16 sqlite3_api->value_text16
+#define sqlite3_value_text16be sqlite3_api->value_text16be
+#define sqlite3_value_text16le sqlite3_api->value_text16le
+#define sqlite3_value_type sqlite3_api->value_type
+#define sqlite3_vmprintf sqlite3_api->vmprintf
+#define sqlite3_overload_function sqlite3_api->overload_function
+#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
+#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
+#define sqlite3_clear_bindings sqlite3_api->clear_bindings
+#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
+#define sqlite3_blob_bytes sqlite3_api->blob_bytes
+#define sqlite3_blob_close sqlite3_api->blob_close
+#define sqlite3_blob_open sqlite3_api->blob_open
+#define sqlite3_blob_read sqlite3_api->blob_read
+#define sqlite3_blob_write sqlite3_api->blob_write
+#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
+#define sqlite3_file_control sqlite3_api->file_control
+#define sqlite3_memory_highwater sqlite3_api->memory_highwater
+#define sqlite3_memory_used sqlite3_api->memory_used
+#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
+#define sqlite3_mutex_enter sqlite3_api->mutex_enter
+#define sqlite3_mutex_free sqlite3_api->mutex_free
+#define sqlite3_mutex_leave sqlite3_api->mutex_leave
+#define sqlite3_mutex_try sqlite3_api->mutex_try
+#define sqlite3_open_v2 sqlite3_api->open_v2
+#define sqlite3_release_memory sqlite3_api->release_memory
+#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
+#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
+#define sqlite3_sleep sqlite3_api->sleep
+#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
+#define sqlite3_vfs_find sqlite3_api->vfs_find
+#define sqlite3_vfs_register sqlite3_api->vfs_register
+#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
+#define sqlite3_threadsafe sqlite3_api->xthreadsafe
+#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
+#define sqlite3_result_error_code sqlite3_api->result_error_code
+#define sqlite3_test_control sqlite3_api->test_control
+#define sqlite3_randomness sqlite3_api->randomness
+#define sqlite3_context_db_handle sqlite3_api->context_db_handle
+#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
+#define sqlite3_limit sqlite3_api->limit
+#define sqlite3_next_stmt sqlite3_api->next_stmt
+#define sqlite3_sql sqlite3_api->sql
+#define sqlite3_status sqlite3_api->status
+#define sqlite3_backup_finish sqlite3_api->backup_finish
+#define sqlite3_backup_init sqlite3_api->backup_init
+#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
+#define sqlite3_backup_remaining sqlite3_api->backup_remaining
+#define sqlite3_backup_step sqlite3_api->backup_step
+#define sqlite3_compileoption_get sqlite3_api->compileoption_get
+#define sqlite3_compileoption_used sqlite3_api->compileoption_used
+#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
+#define sqlite3_db_config sqlite3_api->db_config
+#define sqlite3_db_mutex sqlite3_api->db_mutex
+#define sqlite3_db_status sqlite3_api->db_status
+#define sqlite3_extended_errcode sqlite3_api->extended_errcode
+#define sqlite3_log sqlite3_api->log
+#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
+#define sqlite3_sourceid sqlite3_api->sourceid
+#define sqlite3_stmt_status sqlite3_api->stmt_status
+#define sqlite3_strnicmp sqlite3_api->strnicmp
+#define sqlite3_unlock_notify sqlite3_api->unlock_notify
+#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
+#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
+#define sqlite3_wal_hook sqlite3_api->wal_hook
+#define sqlite3_blob_reopen sqlite3_api->blob_reopen
+#define sqlite3_vtab_config sqlite3_api->vtab_config
+#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
+/* Version 3.7.16 and later */
+#define sqlite3_close_v2 sqlite3_api->close_v2
+#define sqlite3_db_filename sqlite3_api->db_filename
+#define sqlite3_db_readonly sqlite3_api->db_readonly
+#define sqlite3_db_release_memory sqlite3_api->db_release_memory
+#define sqlite3_errstr sqlite3_api->errstr
+#define sqlite3_stmt_busy sqlite3_api->stmt_busy
+#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
+#define sqlite3_stricmp sqlite3_api->stricmp
+#define sqlite3_uri_boolean sqlite3_api->uri_boolean
+#define sqlite3_uri_int64 sqlite3_api->uri_int64
+#define sqlite3_uri_parameter sqlite3_api->uri_parameter
+#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
+#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
+#endif /* SQLITE_CORE */
+
+#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
+#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
+
+#endif /* _SQLITE3EXT_H_ */
+
+/************** End of sqlite3ext.h ******************************************/
+/************** Continuing where we left off in loadext.c ********************/
+/* #include <string.h> */
+
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+
+/*
+** Some API routines are omitted when various features are
+** excluded from a build of SQLite. Substitute a NULL pointer
+** for any missing APIs.
+*/
+#ifndef SQLITE_ENABLE_COLUMN_METADATA
+# define sqlite3_column_database_name 0
+# define sqlite3_column_database_name16 0
+# define sqlite3_column_table_name 0
+# define sqlite3_column_table_name16 0
+# define sqlite3_column_origin_name 0
+# define sqlite3_column_origin_name16 0
+# define sqlite3_table_column_metadata 0
+#endif
+
+#ifdef SQLITE_OMIT_AUTHORIZATION
+# define sqlite3_set_authorizer 0
+#endif
+
+#ifdef SQLITE_OMIT_UTF16
+# define sqlite3_bind_text16 0
+# define sqlite3_collation_needed16 0
+# define sqlite3_column_decltype16 0
+# define sqlite3_column_name16 0
+# define sqlite3_column_text16 0
+# define sqlite3_complete16 0
+# define sqlite3_create_collation16 0
+# define sqlite3_create_function16 0
+# define sqlite3_errmsg16 0
+# define sqlite3_open16 0
+# define sqlite3_prepare16 0
+# define sqlite3_prepare16_v2 0
+# define sqlite3_result_error16 0
+# define sqlite3_result_text16 0
+# define sqlite3_result_text16be 0
+# define sqlite3_result_text16le 0
+# define sqlite3_value_text16 0
+# define sqlite3_value_text16be 0
+# define sqlite3_value_text16le 0
+# define sqlite3_column_database_name16 0
+# define sqlite3_column_table_name16 0
+# define sqlite3_column_origin_name16 0
+#endif
+
+#ifdef SQLITE_OMIT_COMPLETE
+# define sqlite3_complete 0
+# define sqlite3_complete16 0
+#endif
+
+#ifdef SQLITE_OMIT_DECLTYPE
+# define sqlite3_column_decltype16 0
+# define sqlite3_column_decltype 0
+#endif
+
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+# define sqlite3_progress_handler 0
+#endif
+
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+# define sqlite3_create_module 0
+# define sqlite3_create_module_v2 0
+# define sqlite3_declare_vtab 0
+# define sqlite3_vtab_config 0
+# define sqlite3_vtab_on_conflict 0
+#endif
+
+#ifdef SQLITE_OMIT_SHARED_CACHE
+# define sqlite3_enable_shared_cache 0
+#endif
+
+#ifdef SQLITE_OMIT_TRACE
+# define sqlite3_profile 0
+# define sqlite3_trace 0
+#endif
+
+#ifdef SQLITE_OMIT_GET_TABLE
+# define sqlite3_free_table 0
+# define sqlite3_get_table 0
+#endif
+
+#ifdef SQLITE_OMIT_INCRBLOB
+#define sqlite3_bind_zeroblob 0
+#define sqlite3_blob_bytes 0
+#define sqlite3_blob_close 0
+#define sqlite3_blob_open 0
+#define sqlite3_blob_read 0
+#define sqlite3_blob_write 0
+#define sqlite3_blob_reopen 0
+#endif
+
+/*
+** The following structure contains pointers to all SQLite API routines.
+** A pointer to this structure is passed into extensions when they are
+** loaded so that the extension can make calls back into the SQLite
+** library.
+**
+** When adding new APIs, add them to the bottom of this structure
+** in order to preserve backwards compatibility.
+**
+** Extensions that use newer APIs should first call the
+** sqlite3_libversion_number() to make sure that the API they
+** intend to use is supported by the library. Extensions should
+** also check to make sure that the pointer to the function is
+** not NULL before calling it.
+*/
+static const sqlite3_api_routines sqlite3Apis = {
+ sqlite3_aggregate_context,
+#ifndef SQLITE_OMIT_DEPRECATED
+ sqlite3_aggregate_count,
+#else
+ 0,
+#endif
+ sqlite3_bind_blob,
+ sqlite3_bind_double,
+ sqlite3_bind_int,
+ sqlite3_bind_int64,
+ sqlite3_bind_null,
+ sqlite3_bind_parameter_count,
+ sqlite3_bind_parameter_index,
+ sqlite3_bind_parameter_name,
+ sqlite3_bind_text,
+ sqlite3_bind_text16,
+ sqlite3_bind_value,
+ sqlite3_busy_handler,
+ sqlite3_busy_timeout,
+ sqlite3_changes,
+ sqlite3_close,
+ sqlite3_collation_needed,
+ sqlite3_collation_needed16,
+ sqlite3_column_blob,
+ sqlite3_column_bytes,
+ sqlite3_column_bytes16,
+ sqlite3_column_count,
+ sqlite3_column_database_name,
+ sqlite3_column_database_name16,
+ sqlite3_column_decltype,
+ sqlite3_column_decltype16,
+ sqlite3_column_double,
+ sqlite3_column_int,
+ sqlite3_column_int64,
+ sqlite3_column_name,
+ sqlite3_column_name16,
+ sqlite3_column_origin_name,
+ sqlite3_column_origin_name16,
+ sqlite3_column_table_name,
+ sqlite3_column_table_name16,
+ sqlite3_column_text,
+ sqlite3_column_text16,
+ sqlite3_column_type,
+ sqlite3_column_value,
+ sqlite3_commit_hook,
+ sqlite3_complete,
+ sqlite3_complete16,
+ sqlite3_create_collation,
+ sqlite3_create_collation16,
+ sqlite3_create_function,
+ sqlite3_create_function16,
+ sqlite3_create_module,
+ sqlite3_data_count,
+ sqlite3_db_handle,
+ sqlite3_declare_vtab,
+ sqlite3_enable_shared_cache,
+ sqlite3_errcode,
+ sqlite3_errmsg,
+ sqlite3_errmsg16,
+ sqlite3_exec,
+#ifndef SQLITE_OMIT_DEPRECATED
+ sqlite3_expired,
+#else
+ 0,
+#endif
+ sqlite3_finalize,
+ sqlite3_free,
+ sqlite3_free_table,
+ sqlite3_get_autocommit,
+ sqlite3_get_auxdata,
+ sqlite3_get_table,
+ 0, /* Was sqlite3_global_recover(), but that function is deprecated */
+ sqlite3_interrupt,
+ sqlite3_last_insert_rowid,
+ sqlite3_libversion,
+ sqlite3_libversion_number,
+ sqlite3_malloc,
+ sqlite3_mprintf,
+ sqlite3_open,
+ sqlite3_open16,
+ sqlite3_prepare,
+ sqlite3_prepare16,
+ sqlite3_profile,
+ sqlite3_progress_handler,
+ sqlite3_realloc,
+ sqlite3_reset,
+ sqlite3_result_blob,
+ sqlite3_result_double,
+ sqlite3_result_error,
+ sqlite3_result_error16,
+ sqlite3_result_int,
+ sqlite3_result_int64,
+ sqlite3_result_null,
+ sqlite3_result_text,
+ sqlite3_result_text16,
+ sqlite3_result_text16be,
+ sqlite3_result_text16le,
+ sqlite3_result_value,
+ sqlite3_rollback_hook,
+ sqlite3_set_authorizer,
+ sqlite3_set_auxdata,
+ sqlite3_snprintf,
+ sqlite3_step,
+ sqlite3_table_column_metadata,
+#ifndef SQLITE_OMIT_DEPRECATED
+ sqlite3_thread_cleanup,
+#else
+ 0,
+#endif
+ sqlite3_total_changes,
+ sqlite3_trace,
+#ifndef SQLITE_OMIT_DEPRECATED
+ sqlite3_transfer_bindings,
+#else
+ 0,
+#endif
+ sqlite3_update_hook,
+ sqlite3_user_data,
+ sqlite3_value_blob,
+ sqlite3_value_bytes,
+ sqlite3_value_bytes16,
+ sqlite3_value_double,
+ sqlite3_value_int,
+ sqlite3_value_int64,
+ sqlite3_value_numeric_type,
+ sqlite3_value_text,
+ sqlite3_value_text16,
+ sqlite3_value_text16be,
+ sqlite3_value_text16le,
+ sqlite3_value_type,
+ sqlite3_vmprintf,
+ /*
+ ** The original API set ends here. All extensions can call any
+ ** of the APIs above provided that the pointer is not NULL. But
+ ** before calling APIs that follow, extension should check the
+ ** sqlite3_libversion_number() to make sure they are dealing with
+ ** a library that is new enough to support that API.
+ *************************************************************************
+ */
+ sqlite3_overload_function,
+
+ /*
+ ** Added after 3.3.13
+ */
+ sqlite3_prepare_v2,
+ sqlite3_prepare16_v2,
+ sqlite3_clear_bindings,
+
+ /*
+ ** Added for 3.4.1
+ */
+ sqlite3_create_module_v2,
+
+ /*
+ ** Added for 3.5.0
+ */
+ sqlite3_bind_zeroblob,
+ sqlite3_blob_bytes,
+ sqlite3_blob_close,
+ sqlite3_blob_open,
+ sqlite3_blob_read,
+ sqlite3_blob_write,
+ sqlite3_create_collation_v2,
+ sqlite3_file_control,
+ sqlite3_memory_highwater,
+ sqlite3_memory_used,
+#ifdef SQLITE_MUTEX_OMIT
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+#else
+ sqlite3_mutex_alloc,
+ sqlite3_mutex_enter,
+ sqlite3_mutex_free,
+ sqlite3_mutex_leave,
+ sqlite3_mutex_try,
+#endif
+ sqlite3_open_v2,
+ sqlite3_release_memory,
+ sqlite3_result_error_nomem,
+ sqlite3_result_error_toobig,
+ sqlite3_sleep,
+ sqlite3_soft_heap_limit,
+ sqlite3_vfs_find,
+ sqlite3_vfs_register,
+ sqlite3_vfs_unregister,
+
+ /*
+ ** Added for 3.5.8
+ */
+ sqlite3_threadsafe,
+ sqlite3_result_zeroblob,
+ sqlite3_result_error_code,
+ sqlite3_test_control,
+ sqlite3_randomness,
+ sqlite3_context_db_handle,
+
+ /*
+ ** Added for 3.6.0
+ */
+ sqlite3_extended_result_codes,
+ sqlite3_limit,
+ sqlite3_next_stmt,
+ sqlite3_sql,
+ sqlite3_status,
+
+ /*
+ ** Added for 3.7.4
+ */
+ sqlite3_backup_finish,
+ sqlite3_backup_init,
+ sqlite3_backup_pagecount,
+ sqlite3_backup_remaining,
+ sqlite3_backup_step,
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+ sqlite3_compileoption_get,
+ sqlite3_compileoption_used,
+#else
+ 0,
+ 0,
+#endif
+ sqlite3_create_function_v2,
+ sqlite3_db_config,
+ sqlite3_db_mutex,
+ sqlite3_db_status,
+ sqlite3_extended_errcode,
+ sqlite3_log,
+ sqlite3_soft_heap_limit64,
+ sqlite3_sourceid,
+ sqlite3_stmt_status,
+ sqlite3_strnicmp,
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+ sqlite3_unlock_notify,
+#else
+ 0,
+#endif
+#ifndef SQLITE_OMIT_WAL
+ sqlite3_wal_autocheckpoint,
+ sqlite3_wal_checkpoint,
+ sqlite3_wal_hook,
+#else
+ 0,
+ 0,
+ 0,
+#endif
+ sqlite3_blob_reopen,
+ sqlite3_vtab_config,
+ sqlite3_vtab_on_conflict,
+ sqlite3_close_v2,
+ sqlite3_db_filename,
+ sqlite3_db_readonly,
+ sqlite3_db_release_memory,
+ sqlite3_errstr,
+ sqlite3_stmt_busy,
+ sqlite3_stmt_readonly,
+ sqlite3_stricmp,
+ sqlite3_uri_boolean,
+ sqlite3_uri_int64,
+ sqlite3_uri_parameter,
+ sqlite3_vsnprintf,
+ sqlite3_wal_checkpoint_v2
+};
+
+/*
+** Attempt to load an SQLite extension library contained in the file
+** zFile. The entry point is zProc. zProc may be 0 in which case a
+** default entry point name (sqlite3_extension_init) is used. Use
+** of the default name is recommended.
+**
+** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
+**
+** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
+** error message text. The calling function should free this memory
+** by calling sqlite3DbFree(db, ).
+*/
+static int sqlite3LoadExtension(
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
+){
+ sqlite3_vfs *pVfs = db->pVfs;
+ void *handle;
+ int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
+ char *zErrmsg = 0;
+ void **aHandle;
+ int nMsg = 300 + sqlite3Strlen30(zFile);
+
+ if( pzErrMsg ) *pzErrMsg = 0;
+
+ /* Ticket #1863. To avoid a creating security problems for older
+ ** applications that relink against newer versions of SQLite, the
+ ** ability to run load_extension is turned off by default. One
+ ** must call sqlite3_enable_load_extension() to turn on extension
+ ** loading. Otherwise you get the following error.
+ */
+ if( (db->flags & SQLITE_LoadExtension)==0 ){
+ if( pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("not authorized");
+ }
+ return SQLITE_ERROR;
+ }
+
+ if( zProc==0 ){
+ zProc = "sqlite3_extension_init";
+ }
+
+ handle = sqlite3OsDlOpen(pVfs, zFile);
+ if( handle==0 ){
+ if( pzErrMsg ){
+ *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
+ if( zErrmsg ){
+ sqlite3_snprintf(nMsg, zErrmsg,
+ "unable to open shared library [%s]", zFile);
+ sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
+ }
+ }
+ return SQLITE_ERROR;
+ }
+ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
+ sqlite3OsDlSym(pVfs, handle, zProc);
+ if( xInit==0 ){
+ if( pzErrMsg ){
+ nMsg += sqlite3Strlen30(zProc);
+ *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
+ if( zErrmsg ){
+ sqlite3_snprintf(nMsg, zErrmsg,
+ "no entry point [%s] in shared library [%s]", zProc,zFile);
+ sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
+ }
+ sqlite3OsDlClose(pVfs, handle);
+ }
+ return SQLITE_ERROR;
+ }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){
+ if( pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
+ }
+ sqlite3_free(zErrmsg);
+ sqlite3OsDlClose(pVfs, handle);
+ return SQLITE_ERROR;
+ }
+
+ /* Append the new shared library handle to the db->aExtension array. */
+ aHandle = sqlite3DbMallocZero(db, sizeof(handle)*(db->nExtension+1));
+ if( aHandle==0 ){
+ return SQLITE_NOMEM;
+ }
+ if( db->nExtension>0 ){
+ memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension);
+ }
+ sqlite3DbFree(db, db->aExtension);
+ db->aExtension = aHandle;
+
+ db->aExtension[db->nExtension++] = handle;
+ return SQLITE_OK;
+}
+SQLITE_API int sqlite3_load_extension(
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
+){
+ int rc;
+ sqlite3_mutex_enter(db->mutex);
+ rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** Call this routine when the database connection is closing in order
+** to clean up loaded extensions
+*/
+SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){
+ int i;
+ assert( sqlite3_mutex_held(db->mutex) );
+ for(i=0; i<db->nExtension; i++){
+ sqlite3OsDlClose(db->pVfs, db->aExtension[i]);
+ }
+ sqlite3DbFree(db, db->aExtension);
+}
+
+/*
+** Enable or disable extension loading. Extension loading is disabled by
+** default so as not to open security holes in older applications.
+*/
+SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
+ sqlite3_mutex_enter(db->mutex);
+ if( onoff ){
+ db->flags |= SQLITE_LoadExtension;
+ }else{
+ db->flags &= ~SQLITE_LoadExtension;
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+
+/*
+** The auto-extension code added regardless of whether or not extension
+** loading is supported. We need a dummy sqlite3Apis pointer for that
+** code if regular extension loading is not available. This is that
+** dummy pointer.
+*/
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+static const sqlite3_api_routines sqlite3Apis = { 0 };
+#endif
+
+
+/*
+** The following object holds the list of automatically loaded
+** extensions.
+**
+** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER
+** mutex must be held while accessing this list.
+*/
+typedef struct sqlite3AutoExtList sqlite3AutoExtList;
+static SQLITE_WSD struct sqlite3AutoExtList {
+ int nExt; /* Number of entries in aExt[] */
+ void (**aExt)(void); /* Pointers to the extension init functions */
+} sqlite3Autoext = { 0, 0 };
+
+/* The "wsdAutoext" macro will resolve to the autoextension
+** state vector. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdStat can refer directly
+** to the "sqlite3Autoext" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdAutoextInit \
+ sqlite3AutoExtList *x = &GLOBAL(sqlite3AutoExtList,sqlite3Autoext)
+# define wsdAutoext x[0]
+#else
+# define wsdAutoextInit
+# define wsdAutoext sqlite3Autoext
+#endif
+
+
+/*
+** Register a statically linked extension that is automatically
+** loaded by every new database connection.
+*/
+SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
+ int rc = SQLITE_OK;
+#ifndef SQLITE_OMIT_AUTOINIT
+ rc = sqlite3_initialize();
+ if( rc ){
+ return rc;
+ }else
+#endif
+ {
+ int i;
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ wsdAutoextInit;
+ sqlite3_mutex_enter(mutex);
+ for(i=0; i<wsdAutoext.nExt; i++){
+ if( wsdAutoext.aExt[i]==xInit ) break;
+ }
+ if( i==wsdAutoext.nExt ){
+ int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
+ void (**aNew)(void);
+ aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
+ if( aNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ wsdAutoext.aExt = aNew;
+ wsdAutoext.aExt[wsdAutoext.nExt] = xInit;
+ wsdAutoext.nExt++;
+ }
+ }
+ sqlite3_mutex_leave(mutex);
+ assert( (rc&0xff)==rc );
+ return rc;
+ }
+}
+
+/*
+** Reset the automatic extension loading mechanism.
+*/
+SQLITE_API void sqlite3_reset_auto_extension(void){
+#ifndef SQLITE_OMIT_AUTOINIT
+ if( sqlite3_initialize()==SQLITE_OK )
+#endif
+ {
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ wsdAutoextInit;
+ sqlite3_mutex_enter(mutex);
+ sqlite3_free(wsdAutoext.aExt);
+ wsdAutoext.aExt = 0;
+ wsdAutoext.nExt = 0;
+ sqlite3_mutex_leave(mutex);
+ }
+}
+
+/*
+** Load all automatic extensions.
+**
+** If anything goes wrong, set an error in the database connection.
+*/
+SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
+ int i;
+ int go = 1;
+ int rc;
+ int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
+
+ wsdAutoextInit;
+ if( wsdAutoext.nExt==0 ){
+ /* Common case: early out without every having to acquire a mutex */
+ return;
+ }
+ for(i=0; go; i++){
+ char *zErrmsg;
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ sqlite3_mutex_enter(mutex);
+ if( i>=wsdAutoext.nExt ){
+ xInit = 0;
+ go = 0;
+ }else{
+ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
+ wsdAutoext.aExt[i];
+ }
+ sqlite3_mutex_leave(mutex);
+ zErrmsg = 0;
+ if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){
+ sqlite3Error(db, rc,
+ "automatic extension loading failed: %s", zErrmsg);
+ go = 0;
+ }
+ sqlite3_free(zErrmsg);
+ }
+}
+
+/************** End of loadext.c *********************************************/
+/************** Begin file pragma.c ******************************************/
+/*
+** 2003 April 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used to implement the PRAGMA command.
+*/
+
+/*
+** Interpret the given string as a safety level. Return 0 for OFF,
+** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
+** unrecognized string argument. The FULL option is disallowed
+** if the omitFull parameter it 1.
+**
+** Note that the values returned are one less that the values that
+** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
+** to support legacy SQL code. The safety level used to be boolean
+** and older scripts may have used numbers 0 for OFF and 1 for ON.
+*/
+static u8 getSafetyLevel(const char *z, int omitFull, int dflt){
+ /* 123456789 123456789 */
+ static const char zText[] = "onoffalseyestruefull";
+ static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
+ static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
+ static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2};
+ int i, n;
+ if( sqlite3Isdigit(*z) ){
+ return (u8)sqlite3Atoi(z);
+ }
+ n = sqlite3Strlen30(z);
+ for(i=0; i<ArraySize(iLength)-omitFull; i++){
+ if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
+ return iValue[i];
+ }
+ }
+ return dflt;
+}
+
+/*
+** Interpret the given string as a boolean value.
+*/
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, int dflt){
+ return getSafetyLevel(z,1,dflt)!=0;
+}
+
+/* The sqlite3GetBoolean() function is used by other modules but the
+** remainder of this file is specific to PRAGMA processing. So omit
+** the rest of the file if PRAGMAs are omitted from the build.
+*/
+#if !defined(SQLITE_OMIT_PRAGMA)
+
+/*
+** Interpret the given string as a locking mode value.
+*/
+static int getLockingMode(const char *z){
+ if( z ){
+ if( 0==sqlite3StrICmp(z, "exclusive") ) return PAGER_LOCKINGMODE_EXCLUSIVE;
+ if( 0==sqlite3StrICmp(z, "normal") ) return PAGER_LOCKINGMODE_NORMAL;
+ }
+ return PAGER_LOCKINGMODE_QUERY;
+}
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Interpret the given string as an auto-vacuum mode value.
+**
+** The following strings, "none", "full" and "incremental" are
+** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively.
+*/
+static int getAutoVacuum(const char *z){
+ int i;
+ if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE;
+ if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL;
+ if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR;
+ i = sqlite3Atoi(z);
+ return (u8)((i>=0&&i<=2)?i:0);
+}
+#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/*
+** Interpret the given string as a temp db location. Return 1 for file
+** backed temporary databases, 2 for the Red-Black tree in memory database
+** and 0 to use the compile-time default.
+*/
+static int getTempStore(const char *z){
+ if( z[0]>='0' && z[0]<='2' ){
+ return z[0] - '0';
+ }else if( sqlite3StrICmp(z, "file")==0 ){
+ return 1;
+ }else if( sqlite3StrICmp(z, "memory")==0 ){
+ return 2;
+ }else{
+ return 0;
+ }
+}
+#endif /* SQLITE_PAGER_PRAGMAS */
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/*
+** Invalidate temp storage, either when the temp storage is changed
+** from default, or when 'file' and the temp_store_directory has changed
+*/
+static int invalidateTempStorage(Parse *pParse){
+ sqlite3 *db = pParse->db;
+ if( db->aDb[1].pBt!=0 ){
+ if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
+ sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
+ "from within a transaction");
+ return SQLITE_ERROR;
+ }
+ sqlite3BtreeClose(db->aDb[1].pBt);
+ db->aDb[1].pBt = 0;
+ sqlite3ResetAllSchemasOfConnection(db);
+ }
+ return SQLITE_OK;
+}
+#endif /* SQLITE_PAGER_PRAGMAS */
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/*
+** If the TEMP database is open, close it and mark the database schema
+** as needing reloading. This must be done when using the SQLITE_TEMP_STORE
+** or DEFAULT_TEMP_STORE pragmas.
+*/
+static int changeTempStorage(Parse *pParse, const char *zStorageType){
+ int ts = getTempStore(zStorageType);
+ sqlite3 *db = pParse->db;
+ if( db->temp_store==ts ) return SQLITE_OK;
+ if( invalidateTempStorage( pParse ) != SQLITE_OK ){
+ return SQLITE_ERROR;
+ }
+ db->temp_store = (u8)ts;
+ return SQLITE_OK;
+}
+#endif /* SQLITE_PAGER_PRAGMAS */
+
+/*
+** Generate code to return a single integer value.
+*/
+static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int mem = ++pParse->nMem;
+ i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value));
+ if( pI64 ){
+ memcpy(pI64, &value, sizeof(value));
+ }
+ sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
+}
+
+#ifndef SQLITE_OMIT_FLAG_PRAGMAS
+/*
+** Check to see if zRight and zLeft refer to a pragma that queries
+** or changes one of the flags in db->flags. Return 1 if so and 0 if not.
+** Also, implement the pragma.
+*/
+static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
+ static const struct sPragmaType {
+ const char *zName; /* Name of the pragma */
+ int mask; /* Mask for the db->flags value */
+ } aPragma[] = {
+ { "full_column_names", SQLITE_FullColNames },
+ { "short_column_names", SQLITE_ShortColNames },
+ { "count_changes", SQLITE_CountRows },
+ { "empty_result_callbacks", SQLITE_NullCallback },
+ { "legacy_file_format", SQLITE_LegacyFileFmt },
+ { "fullfsync", SQLITE_FullFSync },
+ { "checkpoint_fullfsync", SQLITE_CkptFullFSync },
+ { "reverse_unordered_selects", SQLITE_ReverseOrder },
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+ { "automatic_index", SQLITE_AutoIndex },
+#endif
+#ifdef SQLITE_DEBUG
+ { "sql_trace", SQLITE_SqlTrace },
+ { "vdbe_listing", SQLITE_VdbeListing },
+ { "vdbe_trace", SQLITE_VdbeTrace },
+ { "vdbe_addoptrace", SQLITE_VdbeAddopTrace},
+ { "vdbe_debug", SQLITE_SqlTrace | SQLITE_VdbeListing
+ | SQLITE_VdbeTrace },
+#endif
+#ifndef SQLITE_OMIT_CHECK
+ { "ignore_check_constraints", SQLITE_IgnoreChecks },
+#endif
+ /* The following is VERY experimental */
+ { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode },
+
+ /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
+ ** flag if there are any active statements. */
+ { "read_uncommitted", SQLITE_ReadUncommitted },
+ { "recursive_triggers", SQLITE_RecTriggers },
+
+ /* This flag may only be set if both foreign-key and trigger support
+ ** are present in the build. */
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+ { "foreign_keys", SQLITE_ForeignKeys },
+#endif
+ };
+ int i;
+ const struct sPragmaType *p;
+ for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){
+ if( sqlite3StrICmp(zLeft, p->zName)==0 ){
+ sqlite3 *db = pParse->db;
+ Vdbe *v;
+ v = sqlite3GetVdbe(pParse);
+ assert( v!=0 ); /* Already allocated by sqlite3Pragma() */
+ if( ALWAYS(v) ){
+ if( zRight==0 ){
+ returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
+ }else{
+ int mask = p->mask; /* Mask of bits to set or clear. */
+ if( db->autoCommit==0 ){
+ /* Foreign key support may not be enabled or disabled while not
+ ** in auto-commit mode. */
+ mask &= ~(SQLITE_ForeignKeys);
+ }
+
+ if( sqlite3GetBoolean(zRight, 0) ){
+ db->flags |= mask;
+ }else{
+ db->flags &= ~mask;
+ }
+
+ /* Many of the flag-pragmas modify the code generated by the SQL
+ ** compiler (eg. count_changes). So add an opcode to expire all
+ ** compiled SQL statements after modifying a pragma value.
+ */
+ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
+ }
+ }
+
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
+
+/*
+** Return a human-readable name for a constraint resolution action.
+*/
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+static const char *actionName(u8 action){
+ const char *zName;
+ switch( action ){
+ case OE_SetNull: zName = "SET NULL"; break;
+ case OE_SetDflt: zName = "SET DEFAULT"; break;
+ case OE_Cascade: zName = "CASCADE"; break;
+ case OE_Restrict: zName = "RESTRICT"; break;
+ default: zName = "NO ACTION";
+ assert( action==OE_None ); break;
+ }
+ return zName;
+}
+#endif
+
+
+/*
+** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants
+** defined in pager.h. This function returns the associated lowercase
+** journal-mode name.
+*/
+SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){
+ static char * const azModeName[] = {
+ "delete", "persist", "off", "truncate", "memory"
+#ifndef SQLITE_OMIT_WAL
+ , "wal"
+#endif
+ };
+ assert( PAGER_JOURNALMODE_DELETE==0 );
+ assert( PAGER_JOURNALMODE_PERSIST==1 );
+ assert( PAGER_JOURNALMODE_OFF==2 );
+ assert( PAGER_JOURNALMODE_TRUNCATE==3 );
+ assert( PAGER_JOURNALMODE_MEMORY==4 );
+ assert( PAGER_JOURNALMODE_WAL==5 );
+ assert( eMode>=0 && eMode<=ArraySize(azModeName) );
+
+ if( eMode==ArraySize(azModeName) ) return 0;
+ return azModeName[eMode];
+}
+
+/*
+** Process a pragma statement.
+**
+** Pragmas are of this form:
+**
+** PRAGMA [database.]id [= value]
+**
+** The identifier might also be a string. The value is a string, and
+** identifier, or a number. If minusFlag is true, then the value is
+** a number that was preceded by a minus sign.
+**
+** If the left side is "database.id" then pId1 is the database name
+** and pId2 is the id. If the left side is just "id" then pId1 is the
+** id and pId2 is any empty string.
+*/
+SQLITE_PRIVATE void sqlite3Pragma(
+ Parse *pParse,
+ Token *pId1, /* First part of [database.]id field */
+ Token *pId2, /* Second part of [database.]id field, or NULL */
+ Token *pValue, /* Token for <value>, or NULL */
+ int minusFlag /* True if a '-' sign preceded <value> */
+){
+ char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */
+ char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */
+ const char *zDb = 0; /* The database name */
+ Token *pId; /* Pointer to <id> token */
+ int iDb; /* Database index for <database> */
+ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
+ int rc; /* return value form SQLITE_FCNTL_PRAGMA */
+ sqlite3 *db = pParse->db; /* The database connection */
+ Db *pDb; /* The specific database being pragmaed */
+ Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); /* Prepared statement */
+
+ if( v==0 ) return;
+ sqlite3VdbeRunOnlyOnce(v);
+ pParse->nMem = 2;
+
+ /* Interpret the [database.] part of the pragma statement. iDb is the
+ ** index of the database this pragma is being applied to in db.aDb[]. */
+ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId);
+ if( iDb<0 ) return;
+ pDb = &db->aDb[iDb];
+
+ /* If the temp database has been explicitly named as part of the
+ ** pragma, make sure it is open.
+ */
+ if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){
+ return;
+ }
+
+ zLeft = sqlite3NameFromToken(db, pId);
+ if( !zLeft ) return;
+ if( minusFlag ){
+ zRight = sqlite3MPrintf(db, "-%T", pValue);
+ }else{
+ zRight = sqlite3NameFromToken(db, pValue);
+ }
+
+ assert( pId2 );
+ zDb = pId2->n>0 ? pDb->zName : 0;
+ if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
+ goto pragma_out;
+ }
+
+ /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
+ ** connection. If it returns SQLITE_OK, then assume that the VFS
+ ** handled the pragma and generate a no-op prepared statement.
+ */
+ aFcntl[0] = 0;
+ aFcntl[1] = zLeft;
+ aFcntl[2] = zRight;
+ aFcntl[3] = 0;
+ db->busyHandler.nBusy = 0;
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
+ if( rc==SQLITE_OK ){
+ if( aFcntl[0] ){
+ int mem = ++pParse->nMem;
+ sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
+ sqlite3_free(aFcntl[0]);
+ }
+ }else if( rc!=SQLITE_NOTFOUND ){
+ if( aFcntl[0] ){
+ sqlite3ErrorMsg(pParse, "%s", aFcntl[0]);
+ sqlite3_free(aFcntl[0]);
+ }
+ pParse->nErr++;
+ pParse->rc = rc;
+ }else
+
+
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
+ /*
+ ** PRAGMA [database.]default_cache_size
+ ** PRAGMA [database.]default_cache_size=N
+ **
+ ** The first form reports the current persistent setting for the
+ ** page cache size. The value returned is the maximum number of
+ ** pages in the page cache. The second form sets both the current
+ ** page cache size value and the persistent page cache size value
+ ** stored in the database file.
+ **
+ ** Older versions of SQLite would set the default cache size to a
+ ** negative number to indicate synchronous=OFF. These days, synchronous
+ ** is always on by default regardless of the sign of the default cache
+ ** size. But continue to take the absolute value of the default cache
+ ** size of historical compatibility.
+ */
+ if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
+ static const VdbeOpList getCacheSize[] = {
+ { OP_Transaction, 0, 0, 0}, /* 0 */
+ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */
+ { OP_IfPos, 1, 7, 0},
+ { OP_Integer, 0, 2, 0},
+ { OP_Subtract, 1, 2, 1},
+ { OP_IfPos, 1, 7, 0},
+ { OP_Integer, 0, 1, 0}, /* 6 */
+ { OP_ResultRow, 1, 1, 0},
+ };
+ int addr;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ sqlite3VdbeUsesBtree(v, iDb);
+ if( !zRight ){
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
+ pParse->nMem += 2;
+ addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
+ sqlite3VdbeChangeP1(v, addr, iDb);
+ sqlite3VdbeChangeP1(v, addr+1, iDb);
+ sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE);
+ }else{
+ int size = sqlite3AbsInt32(sqlite3Atoi(zRight));
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3VdbeAddOp2(v, OP_Integer, size, 1);
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1);
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ pDb->pSchema->cache_size = size;
+ sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
+ }
+ }else
+#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */
+
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ /*
+ ** PRAGMA [database.]page_size
+ ** PRAGMA [database.]page_size=N
+ **
+ ** The first form reports the current setting for the
+ ** database page size in bytes. The second form sets the
+ ** database page size value. The value can only be set if
+ ** the database has not yet been created.
+ */
+ if( sqlite3StrICmp(zLeft,"page_size")==0 ){
+ Btree *pBt = pDb->pBt;
+ assert( pBt!=0 );
+ if( !zRight ){
+ int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
+ returnSingleInt(pParse, "page_size", size);
+ }else{
+ /* Malloc may fail when setting the page-size, as there is an internal
+ ** buffer that the pager module resizes using sqlite3_realloc().
+ */
+ db->nextPagesize = sqlite3Atoi(zRight);
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
+ db->mallocFailed = 1;
+ }
+ }
+ }else
+
+ /*
+ ** PRAGMA [database.]secure_delete
+ ** PRAGMA [database.]secure_delete=ON/OFF
+ **
+ ** The first form reports the current setting for the
+ ** secure_delete flag. The second form changes the secure_delete
+ ** flag setting and reports thenew value.
+ */
+ if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
+ Btree *pBt = pDb->pBt;
+ int b = -1;
+ assert( pBt!=0 );
+ if( zRight ){
+ b = sqlite3GetBoolean(zRight, 0);
+ }
+ if( pId2->n==0 && b>=0 ){
+ int ii;
+ for(ii=0; ii<db->nDb; ii++){
+ sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
+ }
+ }
+ b = sqlite3BtreeSecureDelete(pBt, b);
+ returnSingleInt(pParse, "secure_delete", b);
+ }else
+
+ /*
+ ** PRAGMA [database.]max_page_count
+ ** PRAGMA [database.]max_page_count=N
+ **
+ ** The first form reports the current setting for the
+ ** maximum number of pages in the database file. The
+ ** second form attempts to change this setting. Both
+ ** forms return the current setting.
+ **
+ ** The absolute value of N is used. This is undocumented and might
+ ** change. The only purpose is to provide an easy way to test
+ ** the sqlite3AbsInt32() function.
+ **
+ ** PRAGMA [database.]page_count
+ **
+ ** Return the number of pages in the specified database.
+ */
+ if( sqlite3StrICmp(zLeft,"page_count")==0
+ || sqlite3StrICmp(zLeft,"max_page_count")==0
+ ){
+ int iReg;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ iReg = ++pParse->nMem;
+ if( sqlite3Tolower(zLeft[0])=='p' ){
+ sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg,
+ sqlite3AbsInt32(sqlite3Atoi(zRight)));
+ }
+ sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
+ }else
+
+ /*
+ ** PRAGMA [database.]locking_mode
+ ** PRAGMA [database.]locking_mode = (normal|exclusive)
+ */
+ if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){
+ const char *zRet = "normal";
+ int eMode = getLockingMode(zRight);
+
+ if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){
+ /* Simple "PRAGMA locking_mode;" statement. This is a query for
+ ** the current default locking mode (which may be different to
+ ** the locking-mode of the main database).
+ */
+ eMode = db->dfltLockMode;
+ }else{
+ Pager *pPager;
+ if( pId2->n==0 ){
+ /* This indicates that no database name was specified as part
+ ** of the PRAGMA command. In this case the locking-mode must be
+ ** set on all attached databases, as well as the main db file.
+ **
+ ** Also, the sqlite3.dfltLockMode variable is set so that
+ ** any subsequently attached databases also use the specified
+ ** locking mode.
+ */
+ int ii;
+ assert(pDb==&db->aDb[0]);
+ for(ii=2; ii<db->nDb; ii++){
+ pPager = sqlite3BtreePager(db->aDb[ii].pBt);
+ sqlite3PagerLockingMode(pPager, eMode);
+ }
+ db->dfltLockMode = (u8)eMode;
+ }
+ pPager = sqlite3BtreePager(pDb->pBt);
+ eMode = sqlite3PagerLockingMode(pPager, eMode);
+ }
+
+ assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE);
+ if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
+ zRet = "exclusive";
+ }
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }else
+
+ /*
+ ** PRAGMA [database.]journal_mode
+ ** PRAGMA [database.]journal_mode =
+ ** (delete|persist|off|truncate|memory|wal|off)
+ */
+ if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
+ int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
+ int ii; /* Loop counter */
+
+ /* Force the schema to be loaded on all databases. This causes all
+ ** database files to be opened and the journal_modes set. This is
+ ** necessary because subsequent processing must know if the databases
+ ** are in WAL mode. */
+ if( sqlite3ReadSchema(pParse) ){
+ goto pragma_out;
+ }
+
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
+
+ if( zRight==0 ){
+ /* If there is no "=MODE" part of the pragma, do a query for the
+ ** current mode */
+ eMode = PAGER_JOURNALMODE_QUERY;
+ }else{
+ const char *zMode;
+ int n = sqlite3Strlen30(zRight);
+ for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){
+ if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break;
+ }
+ if( !zMode ){
+ /* If the "=MODE" part does not match any known journal mode,
+ ** then do a query */
+ eMode = PAGER_JOURNALMODE_QUERY;
+ }
+ }
+ if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){
+ /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */
+ iDb = 0;
+ pId2->n = 1;
+ }
+ for(ii=db->nDb-1; ii>=0; ii--){
+ if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
+ sqlite3VdbeUsesBtree(v, ii);
+ sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode);
+ }
+ }
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }else
+
+ /*
+ ** PRAGMA [database.]journal_size_limit
+ ** PRAGMA [database.]journal_size_limit=N
+ **
+ ** Get or set the size limit on rollback journal files.
+ */
+ if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){
+ Pager *pPager = sqlite3BtreePager(pDb->pBt);
+ i64 iLimit = -2;
+ if( zRight ){
+ sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8);
+ if( iLimit<-1 ) iLimit = -1;
+ }
+ iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
+ returnSingleInt(pParse, "journal_size_limit", iLimit);
+ }else
+
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
+
+ /*
+ ** PRAGMA [database.]auto_vacuum
+ ** PRAGMA [database.]auto_vacuum=N
+ **
+ ** Get or set the value of the database 'auto-vacuum' parameter.
+ ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL
+ */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
+ Btree *pBt = pDb->pBt;
+ assert( pBt!=0 );
+ if( sqlite3ReadSchema(pParse) ){
+ goto pragma_out;
+ }
+ if( !zRight ){
+ int auto_vacuum;
+ if( ALWAYS(pBt) ){
+ auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
+ }else{
+ auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
+ }
+ returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
+ }else{
+ int eAuto = getAutoVacuum(zRight);
+ assert( eAuto>=0 && eAuto<=2 );
+ db->nextAutovac = (u8)eAuto;
+ if( ALWAYS(eAuto>=0) ){
+ /* Call SetAutoVacuum() to set initialize the internal auto and
+ ** incr-vacuum flags. This is required in case this connection
+ ** creates the database file. It is important that it is created
+ ** as an auto-vacuum capable db.
+ */
+ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
+ if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
+ /* When setting the auto_vacuum mode to either "full" or
+ ** "incremental", write the value of meta[6] in the database
+ ** file. Before writing to meta[6], check that meta[3] indicates
+ ** that this really is an auto-vacuum capable database.
+ */
+ static const VdbeOpList setMeta6[] = {
+ { OP_Transaction, 0, 1, 0}, /* 0 */
+ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
+ { OP_If, 1, 0, 0}, /* 2 */
+ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
+ { OP_Integer, 0, 1, 0}, /* 4 */
+ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
+ };
+ int iAddr;
+ iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
+ sqlite3VdbeChangeP1(v, iAddr, iDb);
+ sqlite3VdbeChangeP1(v, iAddr+1, iDb);
+ sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
+ sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
+ sqlite3VdbeChangeP1(v, iAddr+5, iDb);
+ sqlite3VdbeUsesBtree(v, iDb);
+ }
+ }
+ }
+ }else
+#endif
+
+ /*
+ ** PRAGMA [database.]incremental_vacuum(N)
+ **
+ ** Do N steps of incremental vacuuming on a database.
+ */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){
+ int iLimit, addr;
+ if( sqlite3ReadSchema(pParse) ){
+ goto pragma_out;
+ }
+ if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
+ iLimit = 0x7fffffff;
+ }
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
+ addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb);
+ sqlite3VdbeAddOp1(v, OP_ResultRow, 1);
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
+ sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr);
+ sqlite3VdbeJumpHere(v, addr);
+ }else
+#endif
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+ /*
+ ** PRAGMA [database.]cache_size
+ ** PRAGMA [database.]cache_size=N
+ **
+ ** The first form reports the current local setting for the
+ ** page cache size. The second form sets the local
+ ** page cache size value. If N is positive then that is the
+ ** number of pages in the cache. If N is negative, then the
+ ** number of pages is adjusted so that the cache uses -N kibibytes
+ ** of memory.
+ */
+ if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ if( !zRight ){
+ returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
+ }else{
+ int size = sqlite3Atoi(zRight);
+ pDb->pSchema->cache_size = size;
+ sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
+ }
+ }else
+
+ /*
+ ** PRAGMA temp_store
+ ** PRAGMA temp_store = "default"|"memory"|"file"
+ **
+ ** Return or set the local value of the temp_store flag. Changing
+ ** the local value does not make changes to the disk file and the default
+ ** value will be restored the next time the database is opened.
+ **
+ ** Note that it is possible for the library compile-time options to
+ ** override this setting
+ */
+ if( sqlite3StrICmp(zLeft, "temp_store")==0 ){
+ if( !zRight ){
+ returnSingleInt(pParse, "temp_store", db->temp_store);
+ }else{
+ changeTempStorage(pParse, zRight);
+ }
+ }else
+
+ /*
+ ** PRAGMA temp_store_directory
+ ** PRAGMA temp_store_directory = ""|"directory_name"
+ **
+ ** Return or set the local value of the temp_store_directory flag. Changing
+ ** the value sets a specific directory to be used for temporary files.
+ ** Setting to a null string reverts to the default temporary directory search.
+ ** If temporary directory is changed, then invalidateTempStorage.
+ **
+ */
+ if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){
+ if( !zRight ){
+ if( sqlite3_temp_directory ){
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ "temp_store_directory", SQLITE_STATIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+ }else{
+#ifndef SQLITE_OMIT_WSD
+ if( zRight[0] ){
+ int res;
+ rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
+ if( rc!=SQLITE_OK || res==0 ){
+ sqlite3ErrorMsg(pParse, "not a writable directory");
+ goto pragma_out;
+ }
+ }
+ if( SQLITE_TEMP_STORE==0
+ || (SQLITE_TEMP_STORE==1 && db->temp_store<=1)
+ || (SQLITE_TEMP_STORE==2 && db->temp_store==1)
+ ){
+ invalidateTempStorage(pParse);
+ }
+ sqlite3_free(sqlite3_temp_directory);
+ if( zRight[0] ){
+ sqlite3_temp_directory = sqlite3_mprintf("%s", zRight);
+ }else{
+ sqlite3_temp_directory = 0;
+ }
+#endif /* SQLITE_OMIT_WSD */
+ }
+ }else
+
+#if SQLITE_OS_WIN
+ /*
+ ** PRAGMA data_store_directory
+ ** PRAGMA data_store_directory = ""|"directory_name"
+ **
+ ** Return or set the local value of the data_store_directory flag. Changing
+ ** the value sets a specific directory to be used for database files that
+ ** were specified with a relative pathname. Setting to a null string reverts
+ ** to the default database directory, which for database files specified with
+ ** a relative path will probably be based on the current directory for the
+ ** process. Database file specified with an absolute path are not impacted
+ ** by this setting, regardless of its value.
+ **
+ */
+ if( sqlite3StrICmp(zLeft, "data_store_directory")==0 ){
+ if( !zRight ){
+ if( sqlite3_data_directory ){
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ "data_store_directory", SQLITE_STATIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+ }else{
+#ifndef SQLITE_OMIT_WSD
+ if( zRight[0] ){
+ int res;
+ rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
+ if( rc!=SQLITE_OK || res==0 ){
+ sqlite3ErrorMsg(pParse, "not a writable directory");
+ goto pragma_out;
+ }
+ }
+ sqlite3_free(sqlite3_data_directory);
+ if( zRight[0] ){
+ sqlite3_data_directory = sqlite3_mprintf("%s", zRight);
+ }else{
+ sqlite3_data_directory = 0;
+ }
+#endif /* SQLITE_OMIT_WSD */
+ }
+ }else
+#endif
+
+#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
+# if defined(__APPLE__)
+# define SQLITE_ENABLE_LOCKING_STYLE 1
+# else
+# define SQLITE_ENABLE_LOCKING_STYLE 0
+# endif
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE
+ /*
+ ** PRAGMA [database.]lock_proxy_file
+ ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
+ **
+ ** Return or set the value of the lock_proxy_file flag. Changing
+ ** the value sets a specific file to be used for database access locks.
+ **
+ */
+ if( sqlite3StrICmp(zLeft, "lock_proxy_file")==0 ){
+ if( !zRight ){
+ Pager *pPager = sqlite3BtreePager(pDb->pBt);
+ char *proxy_file_path = NULL;
+ sqlite3_file *pFile = sqlite3PagerFile(pPager);
+ sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE,
+ &proxy_file_path);
+
+ if( proxy_file_path ){
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ "lock_proxy_file", SQLITE_STATIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, proxy_file_path, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+ }else{
+ Pager *pPager = sqlite3BtreePager(pDb->pBt);
+ sqlite3_file *pFile = sqlite3PagerFile(pPager);
+ int res;
+ if( zRight[0] ){
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ zRight);
+ } else {
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ NULL);
+ }
+ if( res!=SQLITE_OK ){
+ sqlite3ErrorMsg(pParse, "failed to set lock proxy file");
+ goto pragma_out;
+ }
+ }
+ }else
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
+ /*
+ ** PRAGMA [database.]synchronous
+ ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
+ **
+ ** Return or set the local value of the synchronous flag. Changing
+ ** the local value does not make changes to the disk file and the
+ ** default value will be restored the next time the database is
+ ** opened.
+ */
+ if( sqlite3StrICmp(zLeft,"synchronous")==0 ){
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ if( !zRight ){
+ returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
+ }else{
+ if( !db->autoCommit ){
+ sqlite3ErrorMsg(pParse,
+ "Safety level may not be changed inside a transaction");
+ }else{
+ pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
+ }
+ }
+ }else
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
+
+#ifndef SQLITE_OMIT_FLAG_PRAGMAS
+ if( flagPragma(pParse, zLeft, zRight) ){
+ /* The flagPragma() subroutine also generates any necessary code
+ ** there is nothing more to do here */
+ }else
+#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
+
+#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
+ /*
+ ** PRAGMA table_info(<table>)
+ **
+ ** Return a single row for each column of the named table. The columns of
+ ** the returned data set are:
+ **
+ ** cid: Column id (numbered from left to right, starting at 0)
+ ** name: Column name
+ ** type: Column declaration type.
+ ** notnull: True if 'NOT NULL' is part of column declaration
+ ** dflt_value: The default value for the column, if any.
+ */
+ if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
+ Table *pTab;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ pTab = sqlite3FindTable(db, zRight, zDb);
+ if( pTab ){
+ int i, k;
+ int nHidden = 0;
+ Column *pCol;
+ Index *pPk;
+ for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
+ sqlite3VdbeSetNumCols(v, 6);
+ pParse->nMem = 6;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC);
+ sqlite3ViewGetColumnNames(pParse, pTab);
+ for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
+ if( IsHiddenColumn(pCol) ){
+ nHidden++;
+ continue;
+ }
+ sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
+ pCol->zType ? pCol->zType : "", 0);
+ sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4);
+ if( pCol->zDflt ){
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
+ }
+ if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
+ k = 0;
+ }else if( pPk==0 ){
+ k = 1;
+ }else{
+ for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
+ }
+ sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
+ }
+ }
+ }else
+
+ if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){
+ Index *pIdx;
+ Table *pTab;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ pIdx = sqlite3FindIndex(db, zRight, zDb);
+ if( pIdx ){
+ int i;
+ pTab = pIdx->pTable;
+ sqlite3VdbeSetNumCols(v, 3);
+ pParse->nMem = 3;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
+ for(i=0; i<pIdx->nColumn; i++){
+ int cnum = pIdx->aiColumn[i];
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
+ sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
+ assert( pTab->nCol>cnum );
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+ }
+ }
+ }else
+
+ if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){
+ Index *pIdx;
+ Table *pTab;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ pTab = sqlite3FindTable(db, zRight, zDb);
+ if( pTab ){
+ v = sqlite3GetVdbe(pParse);
+ pIdx = pTab->pIndex;
+ if( pIdx ){
+ int i = 0;
+ sqlite3VdbeSetNumCols(v, 3);
+ pParse->nMem = 3;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
+ while(pIdx){
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+ ++i;
+ pIdx = pIdx->pNext;
+ }
+ }
+ }
+ }else
+
+ if( sqlite3StrICmp(zLeft, "database_list")==0 ){
+ int i;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ sqlite3VdbeSetNumCols(v, 3);
+ pParse->nMem = 3;
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
+ for(i=0; i<db->nDb; i++){
+ if( db->aDb[i].pBt==0 ) continue;
+ assert( db->aDb[i].zName!=0 );
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
+ sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+ }
+ }else
+
+ if( sqlite3StrICmp(zLeft, "collation_list")==0 ){
+ int i = 0;
+ HashElem *p;
+ sqlite3VdbeSetNumCols(v, 2);
+ pParse->nMem = 2;
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
+ for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
+ CollSeq *pColl = (CollSeq *)sqliteHashData(p);
+ sqlite3VdbeAddOp2(v, OP_Integer, i++, 1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
+ }
+ }else
+#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
+ FKey *pFK;
+ Table *pTab;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ pTab = sqlite3FindTable(db, zRight, zDb);
+ if( pTab ){
+ v = sqlite3GetVdbe(pParse);
+ pFK = pTab->pFKey;
+ if( pFK ){
+ int i = 0;
+ sqlite3VdbeSetNumCols(v, 8);
+ pParse->nMem = 8;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 7, COLNAME_NAME, "match", SQLITE_STATIC);
+ while(pFK){
+ int j;
+ for(j=0; j<pFK->nCol; j++){
+ char *zCol = pFK->aCol[j].zCol;
+ char *zOnDelete = (char *)actionName(pFK->aAction[0]);
+ char *zOnUpdate = (char *)actionName(pFK->aAction[1]);
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
+ sqlite3VdbeAddOp2(v, OP_Integer, j, 2);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
+ pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
+ sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 6, 0, zOnUpdate, 0);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 7, 0, zOnDelete, 0);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 8, 0, "NONE", 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
+ }
+ ++i;
+ pFK = pFK->pNextFrom;
+ }
+ }
+ }
+ }else
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+#ifndef SQLITE_OMIT_TRIGGER
+ if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
+ FKey *pFK; /* A foreign key constraint */
+ Table *pTab; /* Child table contain "REFERENCES" keyword */
+ Table *pParent; /* Parent table that child points to */
+ Index *pIdx; /* Index in the parent table */
+ int i; /* Loop counter: Foreign key number for pTab */
+ int j; /* Loop counter: Field of the foreign key */
+ HashElem *k; /* Loop counter: Next table in schema */
+ int x; /* result variable */
+ int regResult; /* 3 registers to hold a result row */
+ int regKey; /* Register to hold key for checking the FK */
+ int regRow; /* Registers to hold a row from pTab */
+ int addrTop; /* Top of a loop checking foreign keys */
+ int addrOk; /* Jump here if the key is OK */
+ int *aiCols; /* child to parent column mapping */
+
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ regResult = pParse->nMem+1;
+ pParse->nMem += 4;
+ regKey = ++pParse->nMem;
+ regRow = ++pParse->nMem;
+ v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeSetNumCols(v, 4);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
+ sqlite3CodeVerifySchema(pParse, iDb);
+ k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
+ while( k ){
+ if( zRight ){
+ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
+ k = 0;
+ }else{
+ pTab = (Table*)sqliteHashData(k);
+ k = sqliteHashNext(k);
+ }
+ if( pTab==0 || pTab->pFKey==0 ) continue;
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+ if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
+ sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
+ P4_TRANSIENT);
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+ if( pParent==0 ) break;
+ pIdx = 0;
+ sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
+ if( x==0 ){
+ if( pIdx==0 ){
+ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
+ }else{
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
+ sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+ }
+ }else{
+ k = 0;
+ break;
+ }
+ }
+ if( pFK ) break;
+ if( pParse->nTab<i ) pParse->nTab = i;
+ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+ assert( pParent!=0 );
+ pIdx = 0;
+ aiCols = 0;
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
+ assert( x==0 );
+ addrOk = sqlite3VdbeMakeLabel(v);
+ if( pIdx==0 ){
+ int iKey = pFK->aCol[0].iFrom;
+ assert( iKey>=0 && iKey<pTab->nCol );
+ if( iKey!=pTab->iPKey ){
+ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
+ sqlite3ColumnDefault(v, pTab, iKey, regRow);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
+ sqlite3VdbeCurrentAddr(v)+3);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
+ }
+ sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+ }else{
+ for(j=0; j<pFK->nCol; j++){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
+ aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
+ sqlite3VdbeChangeP4(v, -1,
+ sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+ }
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
+ pFK->zTo, P4_TRANSIENT);
+ sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
+ sqlite3VdbeResolveLabel(v, addrOk);
+ sqlite3DbFree(db, aiCols);
+ }
+ sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
+ sqlite3VdbeJumpHere(v, addrTop);
+ }
+ }else
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
+
+#ifndef NDEBUG
+ if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
+ if( zRight ){
+ if( sqlite3GetBoolean(zRight, 0) ){
+ sqlite3ParserTrace(stderr, "parser: ");
+ }else{
+ sqlite3ParserTrace(0, 0);
+ }
+ }
+ }else
+#endif
+
+ /* Reinstall the LIKE and GLOB functions. The variant of LIKE
+ ** used will be case sensitive or not depending on the RHS.
+ */
+ if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
+ if( zRight ){
+ sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0));
+ }
+ }else
+
+#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
+# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
+#endif
+
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
+ /* Pragma "quick_check" is an experimental reduced version of
+ ** integrity_check designed to detect most database corruption
+ ** without most of the overhead of a full integrity-check.
+ */
+ if( sqlite3StrICmp(zLeft, "integrity_check")==0
+ || sqlite3StrICmp(zLeft, "quick_check")==0
+ ){
+ int i, j, addr, mxErr;
+
+ /* Code that appears at the end of the integrity check. If no error
+ ** messages have been generated, output OK. Otherwise output the
+ ** error message
+ */
+ static const VdbeOpList endCode[] = {
+ { OP_AddImm, 1, 0, 0}, /* 0 */
+ { OP_IfNeg, 1, 0, 0}, /* 1 */
+ { OP_String8, 0, 3, 0}, /* 2 */
+ { OP_ResultRow, 3, 1, 0},
+ };
+
+ int isQuick = (sqlite3Tolower(zLeft[0])=='q');
+
+ /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
+ ** then iDb is set to the index of the database identified by <db>.
+ ** In this case, the integrity of database iDb only is verified by
+ ** the VDBE created below.
+ **
+ ** Otherwise, if the command was simply "PRAGMA integrity_check" (or
+ ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb
+ ** to -1 here, to indicate that the VDBE should verify the integrity
+ ** of all attached databases. */
+ assert( iDb>=0 );
+ assert( iDb==0 || pId2->z );
+ if( pId2->z==0 ) iDb = -1;
+
+ /* Initialize the VDBE program */
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ pParse->nMem = 6;
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
+
+ /* Set the maximum error count */
+ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
+ if( zRight ){
+ sqlite3GetInt32(zRight, &mxErr);
+ if( mxErr<=0 ){
+ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
+ }
+ }
+ sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */
+
+ /* Do an integrity check on each database file */
+ for(i=0; i<db->nDb; i++){
+ HashElem *x;
+ Hash *pTbls;
+ int cnt = 0;
+
+ if( OMIT_TEMPDB && i==1 ) continue;
+ if( iDb>=0 && i!=iDb ) continue;
+
+ sqlite3CodeVerifySchema(pParse, i);
+ addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
+ sqlite3VdbeJumpHere(v, addr);
+
+ /* Do an integrity check of the B-Tree
+ **
+ ** Begin by filling registers 2, 3, ... with the root pages numbers
+ ** for all tables and indices in the database.
+ */
+ assert( sqlite3SchemaMutexHeld(db, i, 0) );
+ pTbls = &db->aDb[i].pSchema->tblHash;
+ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ Table *pTab = sqliteHashData(x);
+ Index *pIdx;
+ sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
+ cnt++;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt);
+ cnt++;
+ }
+ }
+
+ /* Make sure sufficient number of registers have been allocated */
+ if( pParse->nMem < cnt+4 ){
+ pParse->nMem = cnt+4;
+ }
+
+ /* Do the b-tree integrity checks */
+ sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
+ sqlite3VdbeChangeP5(v, (u8)i);
+ addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
+ sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
+ P4_DYNAMIC);
+ sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
+ sqlite3VdbeJumpHere(v, addr);
+
+ /* Make sure all the indices are constructed correctly.
+ */
+ for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
+ Table *pTab = sqliteHashData(x);
+ Index *pIdx;
+ int loopTop;
+
+ if( pTab->pIndex==0 ) continue;
+ addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
+ sqlite3VdbeJumpHere(v, addr);
+ sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */
+ loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0);
+ sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ int jmp2;
+ int r1;
+ static const VdbeOpList idxErr[] = {
+ { OP_AddImm, 1, -1, 0},
+ { OP_String8, 0, 3, 0}, /* 1 */
+ { OP_Rowid, 1, 4, 0},
+ { OP_String8, 0, 5, 0}, /* 3 */
+ { OP_String8, 0, 6, 0}, /* 4 */
+ { OP_Concat, 4, 3, 3},
+ { OP_Concat, 5, 3, 3},
+ { OP_Concat, 6, 3, 3},
+ { OP_ResultRow, 3, 1, 0},
+ { OP_IfPos, 1, 0, 0}, /* 9 */
+ { OP_Halt, 0, 0, 0},
+ };
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0);
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1);
+ addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
+ sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
+ sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);
+ sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_TRANSIENT);
+ sqlite3VdbeJumpHere(v, addr+9);
+ sqlite3VdbeJumpHere(v, jmp2);
+ }
+ sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1);
+ sqlite3VdbeJumpHere(v, loopTop);
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ static const VdbeOpList cntIdx[] = {
+ { OP_Integer, 0, 3, 0},
+ { OP_Rewind, 0, 0, 0}, /* 1 */
+ { OP_AddImm, 3, 1, 0},
+ { OP_Next, 0, 0, 0}, /* 3 */
+ { OP_Eq, 2, 0, 3}, /* 4 */
+ { OP_AddImm, 1, -1, 0},
+ { OP_String8, 0, 2, 0}, /* 6 */
+ { OP_String8, 0, 3, 0}, /* 7 */
+ { OP_Concat, 3, 2, 2},
+ { OP_ResultRow, 2, 1, 0},
+ };
+ addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
+ sqlite3VdbeJumpHere(v, addr);
+ addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
+ sqlite3VdbeChangeP1(v, addr+1, j+2);
+ sqlite3VdbeChangeP2(v, addr+1, addr+4);
+ sqlite3VdbeChangeP1(v, addr+3, j+2);
+ sqlite3VdbeChangeP2(v, addr+3, addr+2);
+ sqlite3VdbeJumpHere(v, addr+4);
+ sqlite3VdbeChangeP4(v, addr+6,
+ "wrong # of entries in index ", P4_STATIC);
+ sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_TRANSIENT);
+ }
+ }
+ }
+ addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
+ sqlite3VdbeChangeP2(v, addr, -mxErr);
+ sqlite3VdbeJumpHere(v, addr+1);
+ sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
+ }else
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+#ifndef SQLITE_OMIT_UTF16
+ /*
+ ** PRAGMA encoding
+ ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
+ **
+ ** In its first form, this pragma returns the encoding of the main
+ ** database. If the database is not initialized, it is initialized now.
+ **
+ ** The second form of this pragma is a no-op if the main database file
+ ** has not already been initialized. In this case it sets the default
+ ** encoding that will be used for the main database file if a new file
+ ** is created. If an existing main database file is opened, then the
+ ** default text encoding for the existing database is used.
+ **
+ ** In all cases new databases created using the ATTACH command are
+ ** created to use the same default text encoding as the main database. If
+ ** the main database has not been initialized and/or created when ATTACH
+ ** is executed, this is done before the ATTACH operation.
+ **
+ ** In the second form this pragma sets the text encoding to be used in
+ ** new database files created using this database handle. It is only
+ ** useful if invoked immediately after the main database i
+ */
+ if( sqlite3StrICmp(zLeft, "encoding")==0 ){
+ static const struct EncName {
+ char *zName;
+ u8 enc;
+ } encnames[] = {
+ { "UTF8", SQLITE_UTF8 },
+ { "UTF-8", SQLITE_UTF8 }, /* Must be element [1] */
+ { "UTF-16le", SQLITE_UTF16LE }, /* Must be element [2] */
+ { "UTF-16be", SQLITE_UTF16BE }, /* Must be element [3] */
+ { "UTF16le", SQLITE_UTF16LE },
+ { "UTF16be", SQLITE_UTF16BE },
+ { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */
+ { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */
+ { 0, 0 }
+ };
+ const struct EncName *pEnc;
+ if( !zRight ){ /* "PRAGMA encoding" */
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", SQLITE_STATIC);
+ sqlite3VdbeAddOp2(v, OP_String8, 0, 1);
+ assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 );
+ assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE );
+ assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE );
+ sqlite3VdbeChangeP4(v, -1, encnames[ENC(pParse->db)].zName, P4_STATIC);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }else{ /* "PRAGMA encoding = XXX" */
+ /* Only change the value of sqlite.enc if the database handle is not
+ ** initialized. If the main database exists, the new sqlite.enc value
+ ** will be overwritten when the schema is next loaded. If it does not
+ ** already exists, it will be created to use the new encoding value.
+ */
+ if(
+ !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
+ DbHasProperty(db, 0, DB_Empty)
+ ){
+ for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
+ if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
+ ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
+ break;
+ }
+ }
+ if( !pEnc->zName ){
+ sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
+ }
+ }
+ }
+ }else
+#endif /* SQLITE_OMIT_UTF16 */
+
+#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ /*
+ ** PRAGMA [database.]schema_version
+ ** PRAGMA [database.]schema_version = <integer>
+ **
+ ** PRAGMA [database.]user_version
+ ** PRAGMA [database.]user_version = <integer>
+ **
+ ** The pragma's schema_version and user_version are used to set or get
+ ** the value of the schema-version and user-version, respectively. Both
+ ** the schema-version and the user-version are 32-bit signed integers
+ ** stored in the database header.
+ **
+ ** The schema-cookie is usually only manipulated internally by SQLite. It
+ ** is incremented by SQLite whenever the database schema is modified (by
+ ** creating or dropping a table or index). The schema version is used by
+ ** SQLite each time a query is executed to ensure that the internal cache
+ ** of the schema used when compiling the SQL query matches the schema of
+ ** the database against which the compiled query is actually executed.
+ ** Subverting this mechanism by using "PRAGMA schema_version" to modify
+ ** the schema-version is potentially dangerous and may lead to program
+ ** crashes or database corruption. Use with caution!
+ **
+ ** The user-version is not used internally by SQLite. It may be used by
+ ** applications for any purpose.
+ */
+ if( sqlite3StrICmp(zLeft, "schema_version")==0
+ || sqlite3StrICmp(zLeft, "user_version")==0
+ || sqlite3StrICmp(zLeft, "freelist_count")==0
+ ){
+ int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
+ sqlite3VdbeUsesBtree(v, iDb);
+ switch( zLeft[0] ){
+ case 'f': case 'F':
+ iCookie = BTREE_FREE_PAGE_COUNT;
+ break;
+ case 's': case 'S':
+ iCookie = BTREE_SCHEMA_VERSION;
+ break;
+ default:
+ iCookie = BTREE_USER_VERSION;
+ break;
+ }
+
+ if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){
+ /* Write the specified cookie value */
+ static const VdbeOpList setCookie[] = {
+ { OP_Transaction, 0, 1, 0}, /* 0 */
+ { OP_Integer, 0, 1, 0}, /* 1 */
+ { OP_SetCookie, 0, 0, 1}, /* 2 */
+ };
+ int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
+ sqlite3VdbeChangeP1(v, addr, iDb);
+ sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight));
+ sqlite3VdbeChangeP1(v, addr+2, iDb);
+ sqlite3VdbeChangeP2(v, addr+2, iCookie);
+ }else{
+ /* Read the specified cookie value */
+ static const VdbeOpList readCookie[] = {
+ { OP_Transaction, 0, 0, 0}, /* 0 */
+ { OP_ReadCookie, 0, 1, 0}, /* 1 */
+ { OP_ResultRow, 1, 1, 0}
+ };
+ int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
+ sqlite3VdbeChangeP1(v, addr, iDb);
+ sqlite3VdbeChangeP1(v, addr+1, iDb);
+ sqlite3VdbeChangeP3(v, addr+1, iCookie);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
+ }
+ }else
+#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
+
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+ /*
+ ** PRAGMA compile_options
+ **
+ ** Return the names of all compile-time options used in this build,
+ ** one option per row.
+ */
+ if( sqlite3StrICmp(zLeft, "compile_options")==0 ){
+ int i = 0;
+ const char *zOpt;
+ sqlite3VdbeSetNumCols(v, 1);
+ pParse->nMem = 1;
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC);
+ while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+ }else
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+
+#ifndef SQLITE_OMIT_WAL
+ /*
+ ** PRAGMA [database.]wal_checkpoint = passive|full|restart
+ **
+ ** Checkpoint the database.
+ */
+ if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){
+ int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
+ int eMode = SQLITE_CHECKPOINT_PASSIVE;
+ if( zRight ){
+ if( sqlite3StrICmp(zRight, "full")==0 ){
+ eMode = SQLITE_CHECKPOINT_FULL;
+ }else if( sqlite3StrICmp(zRight, "restart")==0 ){
+ eMode = SQLITE_CHECKPOINT_RESTART;
+ }
+ }
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ sqlite3VdbeSetNumCols(v, 3);
+ pParse->nMem = 3;
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
+
+ sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+ }else
+
+ /*
+ ** PRAGMA wal_autocheckpoint
+ ** PRAGMA wal_autocheckpoint = N
+ **
+ ** Configure a database connection to automatically checkpoint a database
+ ** after accumulating N frames in the log. Or query for the current value
+ ** of N.
+ */
+ if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
+ if( zRight ){
+ sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
+ }
+ returnSingleInt(pParse, "wal_autocheckpoint",
+ db->xWalCallback==sqlite3WalDefaultHook ?
+ SQLITE_PTR_TO_INT(db->pWalArg) : 0);
+ }else
+#endif
+
+ /*
+ ** PRAGMA shrink_memory
+ **
+ ** This pragma attempts to free as much memory as possible from the
+ ** current database connection.
+ */
+ if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){
+ sqlite3_db_release_memory(db);
+ }else
+
+ /*
+ ** PRAGMA busy_timeout
+ ** PRAGMA busy_timeout = N
+ **
+ ** Call sqlite3_busy_timeout(db, N). Return the current timeout value
+ ** if one is set. If no busy handler or a different busy handler is set
+ ** then 0 is returned. Setting the busy_timeout to 0 or negative
+ ** disables the timeout.
+ */
+ if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){
+ if( zRight ){
+ sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
+ }
+ returnSingleInt(pParse, "timeout", db->busyTimeout);
+ }else
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+ /*
+ ** Report the current state of file logs for all databases
+ */
+ if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
+ static const char *const azLockName[] = {
+ "unlocked", "shared", "reserved", "pending", "exclusive"
+ };
+ int i;
+ sqlite3VdbeSetNumCols(v, 2);
+ pParse->nMem = 2;
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
+ for(i=0; i<db->nDb; i++){
+ Btree *pBt;
+ const char *zState = "unknown";
+ int j;
+ if( db->aDb[i].zName==0 ) continue;
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
+ pBt = db->aDb[i].pBt;
+ if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
+ zState = "closed";
+ }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
+ SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
+ zState = azLockName[j];
+ }
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
+ }
+
+ }else
+#endif
+
+#ifdef SQLITE_HAS_CODEC
+ if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
+ sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
+ }else
+ if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){
+ sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight));
+ }else
+ if( zRight && (sqlite3StrICmp(zLeft, "hexkey")==0 ||
+ sqlite3StrICmp(zLeft, "hexrekey")==0) ){
+ int i, h1, h2;
+ char zKey[40];
+ for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){
+ h1 += 9*(1&(h1>>6));
+ h2 += 9*(1&(h2>>6));
+ zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
+ }
+ if( (zLeft[3] & 0xf)==0xb ){
+ sqlite3_key(db, zKey, i/2);
+ }else{
+ sqlite3_rekey(db, zKey, i/2);
+ }
+ }else
+#endif
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
+ if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
+#ifdef SQLITE_HAS_CODEC
+ if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
+ sqlite3_activate_see(&zRight[4]);
+ }
+#endif
+#ifdef SQLITE_ENABLE_CEROD
+ if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
+ sqlite3_activate_cerod(&zRight[6]);
+ }
+#endif
+ }else
+#endif
+
+
+ {/* Empty ELSE clause */}
+
+ /*
+ ** Reset the safety level, in case the fullfsync flag or synchronous
+ ** setting changed.
+ */
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+ if( db->autoCommit ){
+ sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
+ (db->flags&SQLITE_FullFSync)!=0,
+ (db->flags&SQLITE_CkptFullFSync)!=0);
+ }
+#endif
+pragma_out:
+ sqlite3DbFree(db, zLeft);
+ sqlite3DbFree(db, zRight);
+}
+
+#endif /* SQLITE_OMIT_PRAGMA */
+
+/************** End of pragma.c **********************************************/
+/************** Begin file prepare.c *****************************************/
+/*
+** 2005 May 25
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the implementation of the sqlite3_prepare()
+** interface, and routines that contribute to loading the database schema
+** from disk.
+*/
+
+/*
+** Fill the InitData structure with an error message that indicates
+** that the database is corrupt.
+*/
+static void corruptSchema(
+ InitData *pData, /* Initialization context */
+ const char *zObj, /* Object being parsed at the point of error */
+ const char *zExtra /* Error information */
+){
+ sqlite3 *db = pData->db;
+ if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
+ if( zObj==0 ) zObj = "?";
+ sqlite3SetString(pData->pzErrMsg, db,
+ "malformed database schema (%s)", zObj);
+ if( zExtra ){
+ *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg,
+ "%s - %s", *pData->pzErrMsg, zExtra);
+ }
+ }
+ pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT;
+}
+
+/*
+** This is the callback routine for the code that initializes the
+** database. See sqlite3Init() below for additional information.
+** This routine is also called from the OP_ParseSchema opcode of the VDBE.
+**
+** Each callback contains the following information:
+**
+** argv[0] = name of thing being created
+** argv[1] = root page number for table or index. 0 for trigger or view.
+** argv[2] = SQL text for the CREATE statement.
+**
+*/
+SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
+ InitData *pData = (InitData*)pInit;
+ sqlite3 *db = pData->db;
+ int iDb = pData->iDb;
+
+ assert( argc==3 );
+ UNUSED_PARAMETER2(NotUsed, argc);
+ assert( sqlite3_mutex_held(db->mutex) );
+ DbClearProperty(db, iDb, DB_Empty);
+ if( db->mallocFailed ){
+ corruptSchema(pData, argv[0], 0);
+ return 1;
+ }
+
+ assert( iDb>=0 && iDb<db->nDb );
+ if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
+ if( argv[1]==0 ){
+ corruptSchema(pData, argv[0], 0);
+ }else if( argv[2] && argv[2][0] ){
+ /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
+ ** But because db->init.busy is set to 1, no VDBE code is generated
+ ** or executed. All the parser does is build the internal data
+ ** structures that describe the table, index, or view.
+ */
+ int rc;
+ sqlite3_stmt *pStmt;
+ TESTONLY(int rcp); /* Return code from sqlite3_prepare() */
+
+ assert( db->init.busy );
+ db->init.iDb = iDb;
+ db->init.newTnum = sqlite3Atoi(argv[1]);
+ db->init.orphanTrigger = 0;
+ TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
+ rc = db->errCode;
+ assert( (rc&0xFF)==(rcp&0xFF) );
+ db->init.iDb = 0;
+ if( SQLITE_OK!=rc ){
+ if( db->init.orphanTrigger ){
+ assert( iDb==1 );
+ }else{
+ pData->rc = rc;
+ if( rc==SQLITE_NOMEM ){
+ db->mallocFailed = 1;
+ }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
+ corruptSchema(pData, argv[0], sqlite3_errmsg(db));
+ }
+ }
+ }
+ sqlite3_finalize(pStmt);
+ }else if( argv[0]==0 ){
+ corruptSchema(pData, 0, 0);
+ }else{
+ /* If the SQL column is blank it means this is an index that
+ ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
+ ** constraint for a CREATE TABLE. The index should have already
+ ** been created when we processed the CREATE TABLE. All we have
+ ** to do here is record the root page number for that index.
+ */
+ Index *pIndex;
+ pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName);
+ if( pIndex==0 ){
+ /* This can occur if there exists an index on a TEMP table which
+ ** has the same name as another index on a permanent index. Since
+ ** the permanent table is hidden by the TEMP table, we can also
+ ** safely ignore the index on the permanent table.
+ */
+ /* Do Nothing */;
+ }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){
+ corruptSchema(pData, argv[0], "invalid rootpage");
+ }
+ }
+ return 0;
+}
+
+/*
+** Attempt to read the database schema and initialize internal
+** data structures for a single database file. The index of the
+** database file is given by iDb. iDb==0 is used for the main
+** database. iDb==1 should never be used. iDb>=2 is used for
+** auxiliary databases. Return one of the SQLITE_ error codes to
+** indicate success or failure.
+*/
+static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
+ int rc;
+ int i;
+#ifndef SQLITE_OMIT_DEPRECATED
+ int size;
+#endif
+ Table *pTab;
+ Db *pDb;
+ char const *azArg[4];
+ int meta[5];
+ InitData initData;
+ char const *zMasterSchema;
+ char const *zMasterName;
+ int openedTransaction = 0;
+
+ /*
+ ** The master database table has a structure like this
+ */
+ static const char master_schema[] =
+ "CREATE TABLE sqlite_master(\n"
+ " type text,\n"
+ " name text,\n"
+ " tbl_name text,\n"
+ " rootpage integer,\n"
+ " sql text\n"
+ ")"
+ ;
+#ifndef SQLITE_OMIT_TEMPDB
+ static const char temp_master_schema[] =
+ "CREATE TEMP TABLE sqlite_temp_master(\n"
+ " type text,\n"
+ " name text,\n"
+ " tbl_name text,\n"
+ " rootpage integer,\n"
+ " sql text\n"
+ ")"
+ ;
+#else
+ #define temp_master_schema 0
+#endif
+
+ assert( iDb>=0 && iDb<db->nDb );
+ assert( db->aDb[iDb].pSchema );
+ assert( sqlite3_mutex_held(db->mutex) );
+ assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
+
+ /* zMasterSchema and zInitScript are set to point at the master schema
+ ** and initialisation script appropriate for the database being
+ ** initialized. zMasterName is the name of the master table.
+ */
+ if( !OMIT_TEMPDB && iDb==1 ){
+ zMasterSchema = temp_master_schema;
+ }else{
+ zMasterSchema = master_schema;
+ }
+ zMasterName = SCHEMA_TABLE(iDb);
+
+ /* Construct the schema tables. */
+ azArg[0] = zMasterName;
+ azArg[1] = "1";
+ azArg[2] = zMasterSchema;
+ azArg[3] = 0;
+ initData.db = db;
+ initData.iDb = iDb;
+ initData.rc = SQLITE_OK;
+ initData.pzErrMsg = pzErrMsg;
+ sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
+ if( initData.rc ){
+ rc = initData.rc;
+ goto error_out;
+ }
+ pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
+ if( ALWAYS(pTab) ){
+ pTab->tabFlags |= TF_Readonly;
+ }
+
+ /* Create a cursor to hold the database open
+ */
+ pDb = &db->aDb[iDb];
+ if( pDb->pBt==0 ){
+ if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
+ DbSetProperty(db, 1, DB_SchemaLoaded);
+ }
+ return SQLITE_OK;
+ }
+
+ /* If there is not already a read-only (or read-write) transaction opened
+ ** on the b-tree database, open one now. If a transaction is opened, it
+ ** will be closed before this function returns. */
+ sqlite3BtreeEnter(pDb->pBt);
+ if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
+ rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
+ if( rc!=SQLITE_OK ){
+ sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
+ goto initone_error_out;
+ }
+ openedTransaction = 1;
+ }
+
+ /* Get the database meta information.
+ **
+ ** Meta values are as follows:
+ ** meta[0] Schema cookie. Changes with each schema change.
+ ** meta[1] File format of schema layer.
+ ** meta[2] Size of the page cache.
+ ** meta[3] Largest rootpage (auto/incr_vacuum mode)
+ ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE
+ ** meta[5] User version
+ ** meta[6] Incremental vacuum mode
+ ** meta[7] unused
+ ** meta[8] unused
+ ** meta[9] unused
+ **
+ ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
+ ** the possible values of meta[4].
+ */
+ for(i=0; i<ArraySize(meta); i++){
+ sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
+ }
+ pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1];
+
+ /* If opening a non-empty database, check the text encoding. For the
+ ** main database, set sqlite3.enc to the encoding of the main database.
+ ** For an attached db, it is an error if the encoding is not the same
+ ** as sqlite3.enc.
+ */
+ if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */
+ if( iDb==0 ){
+#ifndef SQLITE_OMIT_UTF16
+ u8 encoding;
+ /* If opening the main database, set ENC(db). */
+ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
+ if( encoding==0 ) encoding = SQLITE_UTF8;
+ ENC(db) = encoding;
+#else
+ ENC(db) = SQLITE_UTF8;
+#endif
+ }else{
+ /* If opening an attached database, the encoding much match ENC(db) */
+ if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
+ sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
+ " text encoding as main database");
+ rc = SQLITE_ERROR;
+ goto initone_error_out;
+ }
+ }
+ }else{
+ DbSetProperty(db, iDb, DB_Empty);
+ }
+ pDb->pSchema->enc = ENC(db);
+
+ if( pDb->pSchema->cache_size==0 ){
+#ifndef SQLITE_OMIT_DEPRECATED
+ size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]);
+ if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; }
+ pDb->pSchema->cache_size = size;
+#else
+ pDb->pSchema->cache_size = SQLITE_DEFAULT_CACHE_SIZE;
+#endif
+ sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
+ }
+
+ /*
+ ** file_format==1 Version 3.0.0.
+ ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN
+ ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults
+ ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants
+ */
+ pDb->pSchema->file_format = (u8)meta[BTREE_FILE_FORMAT-1];
+ if( pDb->pSchema->file_format==0 ){
+ pDb->pSchema->file_format = 1;
+ }
+ if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
+ sqlite3SetString(pzErrMsg, db, "unsupported file format");
+ rc = SQLITE_ERROR;
+ goto initone_error_out;
+ }
+
+ /* Ticket #2804: When we open a database in the newer file format,
+ ** clear the legacy_file_format pragma flag so that a VACUUM will
+ ** not downgrade the database and thus invalidate any descending
+ ** indices that the user might have created.
+ */
+ if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){
+ db->flags &= ~SQLITE_LegacyFileFmt;
+ }
+
+ /* Read the schema information out of the schema tables
+ */
+ assert( db->init.busy );
+ {
+ char *zSql;
+ zSql = sqlite3MPrintf(db,
+ "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
+ db->aDb[iDb].zName, zMasterName);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ {
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
+ xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+ rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+ }
+#endif
+ if( rc==SQLITE_OK ) rc = initData.rc;
+ sqlite3DbFree(db, zSql);
+#ifndef SQLITE_OMIT_ANALYZE
+ if( rc==SQLITE_OK ){
+ sqlite3AnalysisLoad(db, iDb);
+ }
+#endif
+ }
+ if( db->mallocFailed ){
+ rc = SQLITE_NOMEM;
+ sqlite3ResetAllSchemasOfConnection(db);
+ }
+ if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
+ /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
+ ** the schema loaded, even if errors occurred. In this situation the
+ ** current sqlite3_prepare() operation will fail, but the following one
+ ** will attempt to compile the supplied statement against whatever subset
+ ** of the schema was loaded before the error occurred. The primary
+ ** purpose of this is to allow access to the sqlite_master table
+ ** even when its contents have been corrupted.
+ */
+ DbSetProperty(db, iDb, DB_SchemaLoaded);
+ rc = SQLITE_OK;
+ }
+
+ /* Jump here for an error that occurs after successfully allocating
+ ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
+ ** before that point, jump to error_out.
+ */
+initone_error_out:
+ if( openedTransaction ){
+ sqlite3BtreeCommit(pDb->pBt);
+ }
+ sqlite3BtreeLeave(pDb->pBt);
+
+error_out:
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ db->mallocFailed = 1;
+ }
+ return rc;
+}
+
+/*
+** Initialize all database files - the main database file, the file
+** used to store temporary tables, and any additional database files
+** created using ATTACH statements. Return a success code. If an
+** error occurs, write an error message into *pzErrMsg.
+**
+** After a database is initialized, the DB_SchemaLoaded bit is set
+** bit is set in the flags field of the Db structure. If the database
+** file was of zero-length, then the DB_Empty flag is also set.
+*/
+SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
+ int i, rc;
+ int commit_internal = !(db->flags&SQLITE_InternChanges);
+
+ assert( sqlite3_mutex_held(db->mutex) );
+ rc = SQLITE_OK;
+ db->init.busy = 1;
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
+ rc = sqlite3InitOne(db, i, pzErrMsg);
+ if( rc ){
+ sqlite3ResetOneSchema(db, i);
+ }
+ }
+
+ /* Once all the other databases have been initialized, load the schema
+ ** for the TEMP database. This is loaded last, as the TEMP database
+ ** schema may contain references to objects in other databases.
+ */
+#ifndef SQLITE_OMIT_TEMPDB
+ if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
+ && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
+ rc = sqlite3InitOne(db, 1, pzErrMsg);
+ if( rc ){
+ sqlite3ResetOneSchema(db, 1);
+ }
+ }
+#endif
+
+ db->init.busy = 0;
+ if( rc==SQLITE_OK && commit_internal ){
+ sqlite3CommitInternalChanges(db);
+ }
+
+ return rc;
+}
+
+/*
+** This routine is a no-op if the database schema is already initialized.
+** Otherwise, the schema is loaded. An error code is returned.
+*/
+SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){
+ int rc = SQLITE_OK;
+ sqlite3 *db = pParse->db;
+ assert( sqlite3_mutex_held(db->mutex) );
+ if( !db->init.busy ){
+ rc = sqlite3Init(db, &pParse->zErrMsg);
+ }
+ if( rc!=SQLITE_OK ){
+ pParse->rc = rc;
+ pParse->nErr++;
+ }
+ return rc;
+}
+
+
+/*
+** Check schema cookies in all databases. If any cookie is out
+** of date set pParse->rc to SQLITE_SCHEMA. If all schema cookies
+** make no changes to pParse->rc.
+*/
+static void schemaIsValid(Parse *pParse){
+ sqlite3 *db = pParse->db;
+ int iDb;
+ int rc;
+ int cookie;
+
+ assert( pParse->checkSchema );
+ assert( sqlite3_mutex_held(db->mutex) );
+ for(iDb=0; iDb<db->nDb; iDb++){
+ int openedTransaction = 0; /* True if a transaction is opened */
+ Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */
+ if( pBt==0 ) continue;
+
+ /* If there is not already a read-only (or read-write) transaction opened
+ ** on the b-tree database, open one now. If a transaction is opened, it
+ ** will be closed immediately after reading the meta-value. */
+ if( !sqlite3BtreeIsInReadTrans(pBt) ){
+ rc = sqlite3BtreeBeginTrans(pBt, 0);
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ db->mallocFailed = 1;
+ }
+ if( rc!=SQLITE_OK ) return;
+ openedTransaction = 1;
+ }
+
+ /* Read the schema cookie from the database. If it does not match the
+ ** value stored as part of the in-memory schema representation,
+ ** set Parse.rc to SQLITE_SCHEMA. */
+ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
+ sqlite3ResetOneSchema(db, iDb);
+ pParse->rc = SQLITE_SCHEMA;
+ }
+
+ /* Close the transaction, if one was opened. */
+ if( openedTransaction ){
+ sqlite3BtreeCommit(pBt);
+ }
+ }
+}
+
+/*
+** Convert a schema pointer into the iDb index that indicates
+** which database file in db->aDb[] the schema refers to.
+**
+** If the same database is attached more than once, the first
+** attached database is returned.
+*/
+SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
+ int i = -1000000;
+
+ /* If pSchema is NULL, then return -1000000. This happens when code in
+ ** expr.c is trying to resolve a reference to a transient table (i.e. one
+ ** created by a sub-select). In this case the return value of this
+ ** function should never be used.
+ **
+ ** We return -1000000 instead of the more usual -1 simply because using
+ ** -1000000 as the incorrect index into db->aDb[] is much
+ ** more likely to cause a segfault than -1 (of course there are assert()
+ ** statements too, but it never hurts to play the odds).
+ */
+ assert( sqlite3_mutex_held(db->mutex) );
+ if( pSchema ){
+ for(i=0; ALWAYS(i<db->nDb); i++){
+ if( db->aDb[i].pSchema==pSchema ){
+ break;
+ }
+ }
+ assert( i>=0 && i<db->nDb );
+ }
+ return i;
+}
+
+/*
+** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
+*/
+static int sqlite3Prepare(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
+ Vdbe *pReprepare, /* VM being reprepared */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ Parse *pParse; /* Parsing context */
+ char *zErrMsg = 0; /* Error message */
+ int rc = SQLITE_OK; /* Result code */
+ int i; /* Loop counter */
+
+ /* Allocate the parsing context */
+ pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
+ if( pParse==0 ){
+ rc = SQLITE_NOMEM;
+ goto end_prepare;
+ }
+ pParse->pReprepare = pReprepare;
+ assert( ppStmt && *ppStmt==0 );
+ assert( !db->mallocFailed );
+ assert( sqlite3_mutex_held(db->mutex) );
+
+ /* Check to verify that it is possible to get a read lock on all
+ ** database schemas. The inability to get a read lock indicates that
+ ** some other database connection is holding a write-lock, which in
+ ** turn means that the other connection has made uncommitted changes
+ ** to the schema.
+ **
+ ** Were we to proceed and prepare the statement against the uncommitted
+ ** schema changes and if those schema changes are subsequently rolled
+ ** back and different changes are made in their place, then when this
+ ** prepared statement goes to run the schema cookie would fail to detect
+ ** the schema change. Disaster would follow.
+ **
+ ** This thread is currently holding mutexes on all Btrees (because
+ ** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it
+ ** is not possible for another thread to start a new schema change
+ ** while this routine is running. Hence, we do not need to hold
+ ** locks on the schema, we just need to make sure nobody else is
+ ** holding them.
+ **
+ ** Note that setting READ_UNCOMMITTED overrides most lock detection,
+ ** but it does *not* override schema lock detection, so this all still
+ ** works even if READ_UNCOMMITTED is set.
+ */
+ for(i=0; i<db->nDb; i++) {
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ assert( sqlite3BtreeHoldsMutex(pBt) );
+ rc = sqlite3BtreeSchemaLocked(pBt);
+ if( rc ){
+ const char *zDb = db->aDb[i].zName;
+ sqlite3Error(db, rc, "database schema is locked: %s", zDb);
+ testcase( db->flags & SQLITE_ReadUncommitted );
+ goto end_prepare;
+ }
+ }
+ }
+
+ sqlite3VtabUnlockList(db);
+
+ pParse->db = db;
+ pParse->nQueryLoop = (double)1;
+ if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
+ char *zSqlCopy;
+ int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
+ testcase( nBytes==mxLen );
+ testcase( nBytes==mxLen+1 );
+ if( nBytes>mxLen ){
+ sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
+ rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
+ goto end_prepare;
+ }
+ zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
+ if( zSqlCopy ){
+ sqlite3RunParser(pParse, zSqlCopy, &zErrMsg);
+ sqlite3DbFree(db, zSqlCopy);
+ pParse->zTail = &zSql[pParse->zTail-zSqlCopy];
+ }else{
+ pParse->zTail = &zSql[nBytes];
+ }
+ }else{
+ sqlite3RunParser(pParse, zSql, &zErrMsg);
+ }
+ assert( 1==(int)pParse->nQueryLoop );
+
+ if( db->mallocFailed ){
+ pParse->rc = SQLITE_NOMEM;
+ }
+ if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;
+ if( pParse->checkSchema ){
+ schemaIsValid(pParse);
+ }
+ if( db->mallocFailed ){
+ pParse->rc = SQLITE_NOMEM;
+ }
+ if( pzTail ){
+ *pzTail = pParse->zTail;
+ }
+ rc = pParse->rc;
+
+#ifndef SQLITE_OMIT_EXPLAIN
+ if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){
+ static const char * const azColName[] = {
+ "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
+ "selectid", "order", "from", "detail"
+ };
+ int iFirst, mx;
+ if( pParse->explain==2 ){
+ sqlite3VdbeSetNumCols(pParse->pVdbe, 4);
+ iFirst = 8;
+ mx = 12;
+ }else{
+ sqlite3VdbeSetNumCols(pParse->pVdbe, 8);
+ iFirst = 0;
+ mx = 8;
+ }
+ for(i=iFirst; i<mx; i++){
+ sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
+ azColName[i], SQLITE_STATIC);
+ }
+ }
+#endif
+
+ assert( db->init.busy==0 || saveSqlFlag==0 );
+ if( db->init.busy==0 ){
+ Vdbe *pVdbe = pParse->pVdbe;
+ sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
+ }
+ if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
+ sqlite3VdbeFinalize(pParse->pVdbe);
+ assert(!(*ppStmt));
+ }else{
+ *ppStmt = (sqlite3_stmt*)pParse->pVdbe;
+ }
+
+ if( zErrMsg ){
+ sqlite3Error(db, rc, "%s", zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
+ }else{
+ sqlite3Error(db, rc, 0);
+ }
+
+ /* Delete any TriggerPrg structures allocated while parsing this statement. */
+ while( pParse->pTriggerPrg ){
+ TriggerPrg *pT = pParse->pTriggerPrg;
+ pParse->pTriggerPrg = pT->pNext;
+ sqlite3DbFree(db, pT);
+ }
+
+end_prepare:
+
+ sqlite3StackFree(db, pParse);
+ rc = sqlite3ApiExit(db, rc);
+ assert( (rc&db->errMask)==rc );
+ return rc;
+}
+static int sqlite3LockAndPrepare(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
+ Vdbe *pOld, /* VM being reprepared */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ assert( ppStmt!=0 );
+ *ppStmt = 0;
+ if( !sqlite3SafetyCheckOk(db) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3BtreeEnterAll(db);
+ rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
+ if( rc==SQLITE_SCHEMA ){
+ sqlite3_finalize(*ppStmt);
+ rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
+ }
+ sqlite3BtreeLeaveAll(db);
+ sqlite3_mutex_leave(db->mutex);
+ assert( rc==SQLITE_OK || *ppStmt==0 );
+ return rc;
+}
+
+/*
+** Rerun the compilation of a statement after a schema change.
+**
+** If the statement is successfully recompiled, return SQLITE_OK. Otherwise,
+** if the statement cannot be recompiled because another connection has
+** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error
+** occurs, return SQLITE_SCHEMA.
+*/
+SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){
+ int rc;
+ sqlite3_stmt *pNew;
+ const char *zSql;
+ sqlite3 *db;
+
+ assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) );
+ zSql = sqlite3_sql((sqlite3_stmt *)p);
+ assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */
+ db = sqlite3VdbeDb(p);
+ assert( sqlite3_mutex_held(db->mutex) );
+ rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
+ if( rc ){
+ if( rc==SQLITE_NOMEM ){
+ db->mallocFailed = 1;
+ }
+ assert( pNew==0 );
+ return rc;
+ }else{
+ assert( pNew!=0 );
+ }
+ sqlite3VdbeSwap((Vdbe*)pNew, p);
+ sqlite3TransferBindings(pNew, (sqlite3_stmt*)p);
+ sqlite3VdbeResetStepResult((Vdbe*)pNew);
+ sqlite3VdbeFinalize((Vdbe*)pNew);
+ return SQLITE_OK;
+}
+
+
+/*
+** Two versions of the official API. Legacy and new use. In the legacy
+** version, the original SQL text is not saved in the prepared statement
+** and so if a schema change occurs, SQLITE_SCHEMA is returned by
+** sqlite3_step(). In the new version, the original SQL text is retained
+** and the statement is automatically recompiled if an schema change
+** occurs.
+*/
+SQLITE_API int sqlite3_prepare(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
+}
+SQLITE_API int sqlite3_prepare_v2(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
+}
+
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
+*/
+static int sqlite3Prepare16(
+ sqlite3 *db, /* Database handle. */
+ const void *zSql, /* UTF-16 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const void **pzTail /* OUT: End of parsed string */
+){
+ /* This function currently works by first transforming the UTF-16
+ ** encoded string to UTF-8, then invoking sqlite3_prepare(). The
+ ** tricky bit is figuring out the pointer to return in *pzTail.
+ */
+ char *zSql8;
+ const char *zTail8 = 0;
+ int rc = SQLITE_OK;
+
+ assert( ppStmt );
+ *ppStmt = 0;
+ if( !sqlite3SafetyCheckOk(db) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ sqlite3_mutex_enter(db->mutex);
+ zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
+ if( zSql8 ){
+ rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
+ }
+
+ if( zTail8 && pzTail ){
+ /* If sqlite3_prepare returns a tail pointer, we calculate the
+ ** equivalent pointer into the UTF-16 string by counting the unicode
+ ** characters between zSql8 and zTail8, and then returning a pointer
+ ** the same number of characters into the UTF-16 string.
+ */
+ int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
+ *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
+ }
+ sqlite3DbFree(db, zSql8);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** Two versions of the official API. Legacy and new use. In the legacy
+** version, the original SQL text is not saved in the prepared statement
+** and so if a schema change occurs, SQLITE_SCHEMA is returned by
+** sqlite3_step(). In the new version, the original SQL text is retained
+** and the statement is automatically recompiled if an schema change
+** occurs.
+*/
+SQLITE_API int sqlite3_prepare16(
+ sqlite3 *db, /* Database handle. */
+ const void *zSql, /* UTF-16 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const void **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
+}
+SQLITE_API int sqlite3_prepare16_v2(
+ sqlite3 *db, /* Database handle. */
+ const void *zSql, /* UTF-16 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const void **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
+}
+
+#endif /* SQLITE_OMIT_UTF16 */
+
+/************** End of prepare.c *********************************************/
+/************** Begin file select.c ******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that are called by the parser
+** to handle SELECT statements in SQLite.
+*/
+
+
+/*
+** Delete all the content of a Select structure but do not deallocate
+** the select structure itself.
+*/
+static void clearSelect(sqlite3 *db, Select *p){
+ sqlite3ExprListDelete(db, p->pEList);
+ sqlite3SrcListDelete(db, p->pSrc);
+ sqlite3ExprDelete(db, p->pWhere);
+ sqlite3ExprListDelete(db, p->pGroupBy);
+ sqlite3ExprDelete(db, p->pHaving);
+ sqlite3ExprListDelete(db, p->pOrderBy);
+ sqlite3SelectDelete(db, p->pPrior);
+ sqlite3ExprDelete(db, p->pLimit);
+ sqlite3ExprDelete(db, p->pOffset);
+}
+
+/*
+** Initialize a SelectDest structure.
+*/
+SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
+ pDest->eDest = (u8)eDest;
+ pDest->iSDParm = iParm;
+ pDest->affSdst = 0;
+ pDest->iSdst = 0;
+ pDest->nSdst = 0;
+}
+
+
+/*
+** Allocate a new Select structure and return a pointer to that
+** structure.
+*/
+SQLITE_PRIVATE Select *sqlite3SelectNew(
+ Parse *pParse, /* Parsing context */
+ ExprList *pEList, /* which columns to include in the result */
+ SrcList *pSrc, /* the FROM clause -- which tables to scan */
+ Expr *pWhere, /* the WHERE clause */
+ ExprList *pGroupBy, /* the GROUP BY clause */
+ Expr *pHaving, /* the HAVING clause */
+ ExprList *pOrderBy, /* the ORDER BY clause */
+ u16 selFlags, /* Flag parameters, such as SF_Distinct */
+ Expr *pLimit, /* LIMIT value. NULL means not used */
+ Expr *pOffset /* OFFSET value. NULL means no offset */
+){
+ Select *pNew;
+ Select standin;
+ sqlite3 *db = pParse->db;
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
+ assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */
+ if( pNew==0 ){
+ assert( db->mallocFailed );
+ pNew = &standin;
+ memset(pNew, 0, sizeof(*pNew));
+ }
+ if( pEList==0 ){
+ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0));
+ }
+ pNew->pEList = pEList;
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
+ pNew->pSrc = pSrc;
+ pNew->pWhere = pWhere;
+ pNew->pGroupBy = pGroupBy;
+ pNew->pHaving = pHaving;
+ pNew->pOrderBy = pOrderBy;
+ pNew->selFlags = selFlags;
+ pNew->op = TK_SELECT;
+ pNew->pLimit = pLimit;
+ pNew->pOffset = pOffset;
+ assert( pOffset==0 || pLimit!=0 );
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->addrOpenEphm[2] = -1;
+ if( db->mallocFailed ) {
+ clearSelect(db, pNew);
+ if( pNew!=&standin ) sqlite3DbFree(db, pNew);
+ pNew = 0;
+ }else{
+ assert( pNew->pSrc!=0 || pParse->nErr>0 );
+ }
+ assert( pNew!=&standin );
+ return pNew;
+}
+
+/*
+** Delete the given Select structure and all of its substructures.
+*/
+SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
+ if( p ){
+ clearSelect(db, p);
+ sqlite3DbFree(db, p);
+ }
+}
+
+/*
+** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
+** type of join. Return an integer constant that expresses that type
+** in terms of the following bit values:
+**
+** JT_INNER
+** JT_CROSS
+** JT_OUTER
+** JT_NATURAL
+** JT_LEFT
+** JT_RIGHT
+**
+** A full outer join is the combination of JT_LEFT and JT_RIGHT.
+**
+** If an illegal or unsupported join type is seen, then still return
+** a join type, but put an error in the pParse structure.
+*/
+SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
+ int jointype = 0;
+ Token *apAll[3];
+ Token *p;
+ /* 0123456789 123456789 123456789 123 */
+ static const char zKeyText[] = "naturaleftouterightfullinnercross";
+ static const struct {
+ u8 i; /* Beginning of keyword text in zKeyText[] */
+ u8 nChar; /* Length of the keyword in characters */
+ u8 code; /* Join type mask */
+ } aKeyword[] = {
+ /* natural */ { 0, 7, JT_NATURAL },
+ /* left */ { 6, 4, JT_LEFT|JT_OUTER },
+ /* outer */ { 10, 5, JT_OUTER },
+ /* right */ { 14, 5, JT_RIGHT|JT_OUTER },
+ /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
+ /* inner */ { 23, 5, JT_INNER },
+ /* cross */ { 28, 5, JT_INNER|JT_CROSS },
+ };
+ int i, j;
+ apAll[0] = pA;
+ apAll[1] = pB;
+ apAll[2] = pC;
+ for(i=0; i<3 && apAll[i]; i++){
+ p = apAll[i];
+ for(j=0; j<ArraySize(aKeyword); j++){
+ if( p->n==aKeyword[j].nChar
+ && sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){
+ jointype |= aKeyword[j].code;
+ break;
+ }
+ }
+ testcase( j==0 || j==1 || j==2 || j==3 || j==4 || j==5 || j==6 );
+ if( j>=ArraySize(aKeyword) ){
+ jointype |= JT_ERROR;
+ break;
+ }
+ }
+ if(
+ (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
+ (jointype & JT_ERROR)!=0
+ ){
+ const char *zSp = " ";
+ assert( pB!=0 );
+ if( pC==0 ){ zSp++; }
+ sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
+ "%T %T%s%T", pA, pB, zSp, pC);
+ jointype = JT_INNER;
+ }else if( (jointype & JT_OUTER)!=0
+ && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
+ sqlite3ErrorMsg(pParse,
+ "RIGHT and FULL OUTER JOINs are not currently supported");
+ jointype = JT_INNER;
+ }
+ return jointype;
+}
+
+/*
+** Return the index of a column in a table. Return -1 if the column
+** is not contained in the table.
+*/
+static int columnIndex(Table *pTab, const char *zCol){
+ int i;
+ for(i=0; i<pTab->nCol; i++){
+ if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
+ }
+ return -1;
+}
+
+/*
+** Search the first N tables in pSrc, from left to right, looking for a
+** table that has a column named zCol.
+**
+** When found, set *piTab and *piCol to the table index and column index
+** of the matching column and return TRUE.
+**
+** If not found, return FALSE.
+*/
+static int tableAndColumnIndex(
+ SrcList *pSrc, /* Array of tables to search */
+ int N, /* Number of tables in pSrc->a[] to search */
+ const char *zCol, /* Name of the column we are looking for */
+ int *piTab, /* Write index of pSrc->a[] here */
+ int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+){
+ int i; /* For looping over tables in pSrc */
+ int iCol; /* Index of column matching zCol */
+
+ assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
+ for(i=0; i<N; i++){
+ iCol = columnIndex(pSrc->a[i].pTab, zCol);
+ if( iCol>=0 ){
+ if( piTab ){
+ *piTab = i;
+ *piCol = iCol;
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+** This function is used to add terms implied by JOIN syntax to the
+** WHERE clause expression of a SELECT statement. The new term, which
+** is ANDed with the existing WHERE clause, is of the form:
+**
+** (tab1.col1 = tab2.col2)
+**
+** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
+** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
+** column iColRight of tab2.
+*/
+static void addWhereTerm(
+ Parse *pParse, /* Parsing context */
+ SrcList *pSrc, /* List of tables in FROM clause */
+ int iLeft, /* Index of first table to join in pSrc */
+ int iColLeft, /* Index of column in first table */
+ int iRight, /* Index of second table in pSrc */
+ int iColRight, /* Index of column in second table */
+ int isOuterJoin, /* True if this is an OUTER join */
+ Expr **ppWhere /* IN/OUT: The WHERE clause to add to */
+){
+ sqlite3 *db = pParse->db;
+ Expr *pE1;
+ Expr *pE2;
+ Expr *pEq;
+
+ assert( iLeft<iRight );
+ assert( pSrc->nSrc>iRight );
+ assert( pSrc->a[iLeft].pTab );
+ assert( pSrc->a[iRight].pTab );
+
+ pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
+ pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
+
+ pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
+ if( pEq && isOuterJoin ){
+ ExprSetProperty(pEq, EP_FromJoin);
+ assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) );
+ ExprSetIrreducible(pEq);
+ pEq->iRightJoinTable = (i16)pE2->iTable;
+ }
+ *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
+}
+
+/*
+** Set the EP_FromJoin property on all terms of the given expression.
+** And set the Expr.iRightJoinTable to iTable for every term in the
+** expression.
+**
+** The EP_FromJoin property is used on terms of an expression to tell
+** the LEFT OUTER JOIN processing logic that this term is part of the
+** join restriction specified in the ON or USING clause and not a part
+** of the more general WHERE clause. These terms are moved over to the
+** WHERE clause during join processing but we need to remember that they
+** originated in the ON or USING clause.
+**
+** The Expr.iRightJoinTable tells the WHERE clause processing that the
+** expression depends on table iRightJoinTable even if that table is not
+** explicitly mentioned in the expression. That information is needed
+** for cases like this:
+**
+** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
+**
+** The where clause needs to defer the handling of the t1.x=5
+** term until after the t2 loop of the join. In that way, a
+** NULL t2 row will be inserted whenever t1.x!=5. If we do not
+** defer the handling of t1.x=5, it will be processed immediately
+** after the t1 loop and rows with t1.x!=5 will never appear in
+** the output, which is incorrect.
+*/
+static void setJoinExpr(Expr *p, int iTable){
+ while( p ){
+ ExprSetProperty(p, EP_FromJoin);
+ assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
+ ExprSetIrreducible(p);
+ p->iRightJoinTable = (i16)iTable;
+ setJoinExpr(p->pLeft, iTable);
+ p = p->pRight;
+ }
+}
+
+/*
+** This routine processes the join information for a SELECT statement.
+** ON and USING clauses are converted into extra terms of the WHERE clause.
+** NATURAL joins also create extra WHERE clause terms.
+**
+** The terms of a FROM clause are contained in the Select.pSrc structure.
+** The left most table is the first entry in Select.pSrc. The right-most
+** table is the last entry. The join operator is held in the entry to
+** the left. Thus entry 0 contains the join operator for the join between
+** entries 0 and 1. Any ON or USING clauses associated with the join are
+** also attached to the left entry.
+**
+** This routine returns the number of errors encountered.
+*/
+static int sqliteProcessJoin(Parse *pParse, Select *p){
+ SrcList *pSrc; /* All tables in the FROM clause */
+ int i, j; /* Loop counters */
+ struct SrcList_item *pLeft; /* Left table being joined */
+ struct SrcList_item *pRight; /* Right table being joined */
+
+ pSrc = p->pSrc;
+ pLeft = &pSrc->a[0];
+ pRight = &pLeft[1];
+ for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
+ Table *pLeftTab = pLeft->pTab;
+ Table *pRightTab = pRight->pTab;
+ int isOuter;
+
+ if( NEVER(pLeftTab==0 || pRightTab==0) ) continue;
+ isOuter = (pRight->jointype & JT_OUTER)!=0;
+
+ /* When the NATURAL keyword is present, add WHERE clause terms for
+ ** every column that the two tables have in common.
+ */
+ if( pRight->jointype & JT_NATURAL ){
+ if( pRight->pOn || pRight->pUsing ){
+ sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
+ "an ON or USING clause", 0);
+ return 1;
+ }
+ for(j=0; j<pRightTab->nCol; j++){
+ char *zName; /* Name of column in the right table */
+ int iLeft; /* Matching left table */
+ int iLeftCol; /* Matching column in the left table */
+
+ zName = pRightTab->aCol[j].zName;
+ if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
+ addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
+ isOuter, &p->pWhere);
+ }
+ }
+ }
+
+ /* Disallow both ON and USING clauses in the same join
+ */
+ if( pRight->pOn && pRight->pUsing ){
+ sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
+ "clauses in the same join");
+ return 1;
+ }
+
+ /* Add the ON clause to the end of the WHERE clause, connected by
+ ** an AND operator.
+ */
+ if( pRight->pOn ){
+ if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
+ p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
+ pRight->pOn = 0;
+ }
+
+ /* Create extra terms on the WHERE clause for each column named
+ ** in the USING clause. Example: If the two tables to be joined are
+ ** A and B and the USING clause names X, Y, and Z, then add this
+ ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
+ ** Report an error if any column mentioned in the USING clause is
+ ** not contained in both tables to be joined.
+ */
+ if( pRight->pUsing ){
+ IdList *pList = pRight->pUsing;
+ for(j=0; j<pList->nId; j++){
+ char *zName; /* Name of the term in the USING clause */
+ int iLeft; /* Table on the left with matching column name */
+ int iLeftCol; /* Column number of matching column on the left */
+ int iRightCol; /* Column number of matching column on the right */
+
+ zName = pList->a[j].zName;
+ iRightCol = columnIndex(pRightTab, zName);
+ if( iRightCol<0
+ || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
+ ){
+ sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
+ "not present in both tables", zName);
+ return 1;
+ }
+ addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
+ isOuter, &p->pWhere);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Insert code into "v" that will push the record on the top of the
+** stack into the sorter.
+*/
+static void pushOntoSorter(
+ Parse *pParse, /* Parser context */
+ ExprList *pOrderBy, /* The ORDER BY clause */
+ Select *pSelect, /* The whole SELECT statement */
+ int regData /* Register holding data to be sorted */
+){
+ Vdbe *v = pParse->pVdbe;
+ int nExpr = pOrderBy->nExpr;
+ int regBase = sqlite3GetTempRange(pParse, nExpr+2);
+ int regRecord = sqlite3GetTempReg(pParse);
+ int op;
+ sqlite3ExprCacheClear(pParse);
+ sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
+ sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
+ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
+ if( pSelect->selFlags & SF_UseSorter ){
+ op = OP_SorterInsert;
+ }else{
+ op = OP_IdxInsert;
+ }
+ sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
+ sqlite3ReleaseTempReg(pParse, regRecord);
+ sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
+ if( pSelect->iLimit ){
+ int addr1, addr2;
+ int iLimit;
+ if( pSelect->iOffset ){
+ iLimit = pSelect->iOffset+1;
+ }else{
+ iLimit = pSelect->iLimit;
+ }
+ addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);
+ sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
+ addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, addr1);
+ sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
+ sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);
+ sqlite3VdbeJumpHere(v, addr2);
+ }
+}
+
+/*
+** Add code to implement the OFFSET
+*/
+static void codeOffset(
+ Vdbe *v, /* Generate code into this VM */
+ Select *p, /* The SELECT statement being coded */
+ int iContinue /* Jump here to skip the current record */
+){
+ if( p->iOffset && iContinue!=0 ){
+ int addr;
+ sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);
+ addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
+ VdbeComment((v, "skip OFFSET records"));
+ sqlite3VdbeJumpHere(v, addr);
+ }
+}
+
+/*
+** Add code that will check to make sure the N registers starting at iMem
+** form a distinct entry. iTab is a sorting index that holds previously
+** seen combinations of the N values. A new entry is made in iTab
+** if the current N values are new.
+**
+** A jump to addrRepeat is made and the N+1 values are popped from the
+** stack if the top N elements are not distinct.
+*/
+static void codeDistinct(
+ Parse *pParse, /* Parsing and code generating context */
+ int iTab, /* A sorting index used to test for distinctness */
+ int addrRepeat, /* Jump to here if not distinct */
+ int N, /* Number of elements */
+ int iMem /* First element */
+){
+ Vdbe *v;
+ int r1;
+
+ v = pParse->pVdbe;
+ r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
+ sqlite3ReleaseTempReg(pParse, r1);
+}
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** Generate an error message when a SELECT is used within a subexpression
+** (example: "a IN (SELECT * FROM table)") but it has more than 1 result
+** column. We do this in a subroutine because the error used to occur
+** in multiple places. (The error only occurs in one place now, but we
+** retain the subroutine to minimize code disruption.)
+*/
+static int checkForMultiColumnSelectError(
+ Parse *pParse, /* Parse context. */
+ SelectDest *pDest, /* Destination of SELECT results */
+ int nExpr /* Number of result columns returned by SELECT */
+){
+ int eDest = pDest->eDest;
+ if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){
+ sqlite3ErrorMsg(pParse, "only a single result allowed for "
+ "a SELECT that is part of an expression");
+ return 1;
+ }else{
+ return 0;
+ }
+}
+#endif
+
+/*
+** An instance of the following object is used to record information about
+** how to process the DISTINCT keyword, to simplify passing that information
+** into the selectInnerLoop() routine.
+*/
+typedef struct DistinctCtx DistinctCtx;
+struct DistinctCtx {
+ u8 isTnct; /* True if the DISTINCT keyword is present */
+ u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
+ int tabTnct; /* Ephemeral table used for DISTINCT processing */
+ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
+};
+
+/*
+** This routine generates the code for the inside of the inner loop
+** of a SELECT.
+**
+** If srcTab and nColumn are both zero, then the pEList expressions
+** are evaluated in order to get the data for this row. If nColumn>0
+** then data is pulled from srcTab and pEList is used only to get the
+** datatypes for each column.
+*/
+static void selectInnerLoop(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The complete select statement being coded */
+ ExprList *pEList, /* List of values being extracted */
+ int srcTab, /* Pull data from this table */
+ int nColumn, /* Number of columns in the source table */
+ ExprList *pOrderBy, /* If not NULL, sort results using this key */
+ DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
+ SelectDest *pDest, /* How to dispose of the results */
+ int iContinue, /* Jump here to continue with next row */
+ int iBreak /* Jump here to break out of the inner loop */
+){
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ int hasDistinct; /* True if the DISTINCT keyword is present */
+ int regResult; /* Start of memory holding result set */
+ int eDest = pDest->eDest; /* How to dispose of results */
+ int iParm = pDest->iSDParm; /* First argument to disposal method */
+ int nResultCol; /* Number of result columns */
+
+ assert( v );
+ if( NEVER(v==0) ) return;
+ assert( pEList!=0 );
+ hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
+ if( pOrderBy==0 && !hasDistinct ){
+ codeOffset(v, p, iContinue);
+ }
+
+ /* Pull the requested columns.
+ */
+ if( nColumn>0 ){
+ nResultCol = nColumn;
+ }else{
+ nResultCol = pEList->nExpr;
+ }
+ if( pDest->iSdst==0 ){
+ pDest->iSdst = pParse->nMem+1;
+ pDest->nSdst = nResultCol;
+ pParse->nMem += nResultCol;
+ }else{
+ assert( pDest->nSdst==nResultCol );
+ }
+ regResult = pDest->iSdst;
+ if( nColumn>0 ){
+ for(i=0; i<nColumn; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
+ }
+ }else if( eDest!=SRT_Exists ){
+ /* If the destination is an EXISTS(...) expression, the actual
+ ** values returned by the SELECT are not required.
+ */
+ sqlite3ExprCacheClear(pParse);
+ sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
+ }
+ nColumn = nResultCol;
+
+ /* If the DISTINCT keyword was present on the SELECT statement
+ ** and this row has been seen before, then do not make this row
+ ** part of the result.
+ */
+ if( hasDistinct ){
+ assert( pEList!=0 );
+ assert( pEList->nExpr==nColumn );
+ switch( pDistinct->eTnctType ){
+ case WHERE_DISTINCT_ORDERED: {
+ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
+ int iJump; /* Jump destination */
+ int regPrev; /* Previous row content */
+
+ /* Allocate space for the previous row */
+ regPrev = pParse->nMem+1;
+ pParse->nMem += nColumn;
+
+ /* Change the OP_OpenEphemeral coded earlier to an OP_Null
+ ** sets the MEM_Cleared bit on the first register of the
+ ** previous value. This will cause the OP_Ne below to always
+ ** fail on the first iteration of the loop even if the first
+ ** row is all NULLs.
+ */
+ sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
+ pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
+ pOp->opcode = OP_Null;
+ pOp->p1 = 1;
+ pOp->p2 = regPrev;
+
+ iJump = sqlite3VdbeCurrentAddr(v) + nColumn;
+ for(i=0; i<nColumn; i++){
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
+ if( i<nColumn-1 ){
+ sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
+ }
+ sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ }
+ assert( sqlite3VdbeCurrentAddr(v)==iJump );
+ sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nColumn-1);
+ break;
+ }
+
+ case WHERE_DISTINCT_UNIQUE: {
+ sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
+ break;
+ }
+
+ default: {
+ assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
+ codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult);
+ break;
+ }
+ }
+ if( pOrderBy==0 ){
+ codeOffset(v, p, iContinue);
+ }
+ }
+
+ switch( eDest ){
+ /* In this mode, write each query result to the key of the temporary
+ ** table iParm.
+ */
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
+ case SRT_Union: {
+ int r1;
+ r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3ReleaseTempReg(pParse, r1);
+ break;
+ }
+
+ /* Construct a record from the query result, but instead of
+ ** saving that record, use it as a key to delete elements from
+ ** the temporary table iParm.
+ */
+ case SRT_Except: {
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn);
+ break;
+ }
+#endif
+
+ /* Store the result as data using a unique key.
+ */
+ case SRT_Table:
+ case SRT_EphemTab: {
+ int r1 = sqlite3GetTempReg(pParse);
+ testcase( eDest==SRT_Table );
+ testcase( eDest==SRT_EphemTab );
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
+ if( pOrderBy ){
+ pushOntoSorter(pParse, pOrderBy, p, r1);
+ }else{
+ int r2 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
+ sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ sqlite3ReleaseTempReg(pParse, r2);
+ }
+ sqlite3ReleaseTempReg(pParse, r1);
+ break;
+ }
+
+#ifndef SQLITE_OMIT_SUBQUERY
+ /* If we are creating a set for an "expr IN (SELECT ...)" construct,
+ ** then there should be a single item on the stack. Write this
+ ** item into the set table with bogus data.
+ */
+ case SRT_Set: {
+ assert( nColumn==1 );
+ pDest->affSdst =
+ sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
+ if( pOrderBy ){
+ /* At first glance you would think we could optimize out the
+ ** ORDER BY in this case since the order of entries in the set
+ ** does not matter. But there might be a LIMIT clause, in which
+ ** case the order does matter */
+ pushOntoSorter(pParse, pOrderBy, p, regResult);
+ }else{
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
+ sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3ReleaseTempReg(pParse, r1);
+ }
+ break;
+ }
+
+ /* If any row exist in the result set, record that fact and abort.
+ */
+ case SRT_Exists: {
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);
+ /* The LIMIT clause will terminate the loop for us */
+ break;
+ }
+
+ /* If this is a scalar select that is part of an expression, then
+ ** store the results in the appropriate memory cell and break out
+ ** of the scan loop.
+ */
+ case SRT_Mem: {
+ assert( nColumn==1 );
+ if( pOrderBy ){
+ pushOntoSorter(pParse, pOrderBy, p, regResult);
+ }else{
+ sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
+ /* The LIMIT clause will jump out of the loop for us */
+ }
+ break;
+ }
+#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
+
+ /* Send the data to the callback function or to a subroutine. In the
+ ** case of a subroutine, the subroutine itself is responsible for
+ ** popping the data from the stack.
+ */
+ case SRT_Coroutine:
+ case SRT_Output: {
+ testcase( eDest==SRT_Coroutine );
+ testcase( eDest==SRT_Output );
+ if( pOrderBy ){
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
+ pushOntoSorter(pParse, pOrderBy, p, r1);
+ sqlite3ReleaseTempReg(pParse, r1);
+ }else if( eDest==SRT_Coroutine ){
+ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
+ sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
+ }
+ break;
+ }
+
+#if !defined(SQLITE_OMIT_TRIGGER)
+ /* Discard the results. This is used for SELECT statements inside
+ ** the body of a TRIGGER. The purpose of such selects is to call
+ ** user-defined functions that have side effects. We do not care
+ ** about the actual results of the select.
+ */
+ default: {
+ assert( eDest==SRT_Discard );
+ break;
+ }
+#endif
+ }
+
+ /* Jump to the end of the loop if the LIMIT is reached. Except, if
+ ** there is a sorter, in which case the sorter has already limited
+ ** the output for us.
+ */
+ if( pOrderBy==0 && p->iLimit ){
+ sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
+ }
+}
+
+/*
+** Given an expression list, generate a KeyInfo structure that records
+** the collating sequence for each expression in that expression list.
+**
+** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
+** KeyInfo structure is appropriate for initializing a virtual index to
+** implement that clause. If the ExprList is the result set of a SELECT
+** then the KeyInfo structure is appropriate for initializing a virtual
+** index to implement a DISTINCT test.
+**
+** Space to hold the KeyInfo structure is obtain from malloc. The calling
+** function is responsible for seeing that this structure is eventually
+** freed. Add the KeyInfo structure to the P4 field of an opcode using
+** P4_KEYINFO_HANDOFF is the usual way of dealing with this.
+*/
+static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
+ sqlite3 *db = pParse->db;
+ int nExpr;
+ KeyInfo *pInfo;
+ struct ExprList_item *pItem;
+ int i;
+
+ nExpr = pList->nExpr;
+ pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
+ if( pInfo ){
+ pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
+ pInfo->nField = (u16)nExpr;
+ pInfo->enc = ENC(db);
+ pInfo->db = db;
+ for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
+ CollSeq *pColl;
+ pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
+ if( !pColl ){
+ pColl = db->pDfltColl;
+ }
+ pInfo->aColl[i] = pColl;
+ pInfo->aSortOrder[i] = pItem->sortOrder;
+ }
+ }
+ return pInfo;
+}
+
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
+/*
+** Name of the connection operator, used for error messages.
+*/
+static const char *selectOpName(int id){
+ char *z;
+ switch( id ){
+ case TK_ALL: z = "UNION ALL"; break;
+ case TK_INTERSECT: z = "INTERSECT"; break;
+ case TK_EXCEPT: z = "EXCEPT"; break;
+ default: z = "UNION"; break;
+ }
+ return z;
+}
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
+
+#ifndef SQLITE_OMIT_EXPLAIN
+/*
+** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
+** is a no-op. Otherwise, it adds a single row of output to the EQP result,
+** where the caption is of the form:
+**
+** "USE TEMP B-TREE FOR xxx"
+**
+** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
+** is determined by the zUsage argument.
+*/
+static void explainTempTable(Parse *pParse, const char *zUsage){
+ if( pParse->explain==2 ){
+ Vdbe *v = pParse->pVdbe;
+ char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage);
+ sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
+ }
+}
+
+/*
+** Assign expression b to lvalue a. A second, no-op, version of this macro
+** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
+** in sqlite3Select() to assign values to structure member variables that
+** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
+** code with #ifndef directives.
+*/
+# define explainSetInteger(a, b) a = b
+
+#else
+/* No-op versions of the explainXXX() functions and macros. */
+# define explainTempTable(y,z)
+# define explainSetInteger(y,z)
+#endif
+
+#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT)
+/*
+** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
+** is a no-op. Otherwise, it adds a single row of output to the EQP result,
+** where the caption is of one of the two forms:
+**
+** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
+** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
+**
+** where iSub1 and iSub2 are the integers passed as the corresponding
+** function parameters, and op is the text representation of the parameter
+** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT,
+** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is
+** false, or the second form if it is true.
+*/
+static void explainComposite(
+ Parse *pParse, /* Parse context */
+ int op, /* One of TK_UNION, TK_EXCEPT etc. */
+ int iSub1, /* Subquery id 1 */
+ int iSub2, /* Subquery id 2 */
+ int bUseTmp /* True if a temp table was used */
+){
+ assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL );
+ if( pParse->explain==2 ){
+ Vdbe *v = pParse->pVdbe;
+ char *zMsg = sqlite3MPrintf(
+ pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
+ bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)
+ );
+ sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
+ }
+}
+#else
+/* No-op versions of the explainXXX() functions and macros. */
+# define explainComposite(v,w,x,y,z)
+#endif
+
+/*
+** If the inner loop was generated using a non-null pOrderBy argument,
+** then the results were placed in a sorter. After the loop is terminated
+** we need to run the sorter and output the results. The following
+** routine generates the code needed to do that.
+*/
+static void generateSortTail(
+ Parse *pParse, /* Parsing context */
+ Select *p, /* The SELECT statement */
+ Vdbe *v, /* Generate code into this VDBE */
+ int nColumn, /* Number of columns of data */
+ SelectDest *pDest /* Write the sorted results here */
+){
+ int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */
+ int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
+ int addr;
+ int iTab;
+ int pseudoTab = 0;
+ ExprList *pOrderBy = p->pOrderBy;
+
+ int eDest = pDest->eDest;
+ int iParm = pDest->iSDParm;
+
+ int regRow;
+ int regRowid;
+
+ iTab = pOrderBy->iECursor;
+ regRow = sqlite3GetTempReg(pParse);
+ if( eDest==SRT_Output || eDest==SRT_Coroutine ){
+ pseudoTab = pParse->nTab++;
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
+ regRowid = 0;
+ }else{
+ regRowid = sqlite3GetTempReg(pParse);
+ }
+ if( p->selFlags & SF_UseSorter ){
+ int regSortOut = ++pParse->nMem;
+ int ptab2 = pParse->nTab++;
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
+ codeOffset(v, p, addrContinue);
+ sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
+ sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
+ sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
+ }else{
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
+ codeOffset(v, p, addrContinue);
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
+ }
+ switch( eDest ){
+ case SRT_Table:
+ case SRT_EphemTab: {
+ testcase( eDest==SRT_Table );
+ testcase( eDest==SRT_EphemTab );
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ break;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case SRT_Set: {
+ assert( nColumn==1 );
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid,
+ &pDest->affSdst, 1);
+ sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
+ break;
+ }
+ case SRT_Mem: {
+ assert( nColumn==1 );
+ sqlite3ExprCodeMove(pParse, regRow, iParm, 1);
+ /* The LIMIT clause will terminate the loop for us */
+ break;
+ }
+#endif
+ default: {
+ int i;
+ assert( eDest==SRT_Output || eDest==SRT_Coroutine );
+ testcase( eDest==SRT_Output );
+ testcase( eDest==SRT_Coroutine );
+ for(i=0; i<nColumn; i++){
+ assert( regRow!=pDest->iSdst+i );
+ sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i);
+ if( i==0 ){
+ sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
+ }
+ }
+ if( eDest==SRT_Output ){
+ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
+ sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
+ }else{
+ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
+ }
+ break;
+ }
+ }
+ sqlite3ReleaseTempReg(pParse, regRow);
+ sqlite3ReleaseTempReg(pParse, regRowid);
+
+ /* The bottom of the loop
+ */
+ sqlite3VdbeResolveLabel(v, addrContinue);
+ if( p->selFlags & SF_UseSorter ){
+ sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
+ }
+ sqlite3VdbeResolveLabel(v, addrBreak);
+ if( eDest==SRT_Output || eDest==SRT_Coroutine ){
+ sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
+ }
+}
+
+/*
+** Return a pointer to a string containing the 'declaration type' of the
+** expression pExpr. The string may be treated as static by the caller.
+**
+** The declaration type is the exact datatype definition extracted from the
+** original CREATE TABLE statement if the expression is a column. The
+** declaration type for a ROWID field is INTEGER. Exactly when an expression
+** is considered a column can be complex in the presence of subqueries. The
+** result-set expression in all of the following SELECT statements is
+** considered a column by this function.
+**
+** SELECT col FROM tbl;
+** SELECT (SELECT col FROM tbl;
+** SELECT (SELECT col FROM tbl);
+** SELECT abc FROM (SELECT col AS abc FROM tbl);
+**
+** The declaration type for any expression other than a column is NULL.
+*/
+static const char *columnType(
+ NameContext *pNC,
+ Expr *pExpr,
+ const char **pzOriginDb,
+ const char **pzOriginTab,
+ const char **pzOriginCol
+){
+ char const *zType = 0;
+ char const *zOriginDb = 0;
+ char const *zOriginTab = 0;
+ char const *zOriginCol = 0;
+ int j;
+ if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
+
+ switch( pExpr->op ){
+ case TK_AGG_COLUMN:
+ case TK_COLUMN: {
+ /* The expression is a column. Locate the table the column is being
+ ** extracted from in NameContext.pSrcList. This table may be real
+ ** database table or a subquery.
+ */
+ Table *pTab = 0; /* Table structure column is extracted from */
+ Select *pS = 0; /* Select the column is extracted from */
+ int iCol = pExpr->iColumn; /* Index of column in pTab */
+ testcase( pExpr->op==TK_AGG_COLUMN );
+ testcase( pExpr->op==TK_COLUMN );
+ while( pNC && !pTab ){
+ SrcList *pTabList = pNC->pSrcList;
+ for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
+ if( j<pTabList->nSrc ){
+ pTab = pTabList->a[j].pTab;
+ pS = pTabList->a[j].pSelect;
+ }else{
+ pNC = pNC->pNext;
+ }
+ }
+
+ if( pTab==0 ){
+ /* At one time, code such as "SELECT new.x" within a trigger would
+ ** cause this condition to run. Since then, we have restructured how
+ ** trigger code is generated and so this condition is no longer
+ ** possible. However, it can still be true for statements like
+ ** the following:
+ **
+ ** CREATE TABLE t1(col INTEGER);
+ ** SELECT (SELECT t1.col) FROM FROM t1;
+ **
+ ** when columnType() is called on the expression "t1.col" in the
+ ** sub-select. In this case, set the column type to NULL, even
+ ** though it should really be "INTEGER".
+ **
+ ** This is not a problem, as the column type of "t1.col" is never
+ ** used. When columnType() is called on the expression
+ ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
+ ** branch below. */
+ break;
+ }
+
+ assert( pTab && pExpr->pTab==pTab );
+ if( pS ){
+ /* The "table" is actually a sub-select or a view in the FROM clause
+ ** of the SELECT statement. Return the declaration type and origin
+ ** data for the result-set column of the sub-select.
+ */
+ if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
+ /* If iCol is less than zero, then the expression requests the
+ ** rowid of the sub-select or view. This expression is legal (see
+ ** test case misc2.2.2) - it always evaluates to NULL.
+ */
+ NameContext sNC;
+ Expr *p = pS->pEList->a[iCol].pExpr;
+ sNC.pSrcList = pS->pSrc;
+ sNC.pNext = pNC;
+ sNC.pParse = pNC->pParse;
+ zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ }
+ }else if( ALWAYS(pTab->pSchema) ){
+ /* A real table */
+ assert( !pS );
+ if( iCol<0 ) iCol = pTab->iPKey;
+ assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
+ if( iCol<0 ){
+ zType = "INTEGER";
+ zOriginCol = "rowid";
+ }else{
+ zType = pTab->aCol[iCol].zType;
+ zOriginCol = pTab->aCol[iCol].zName;
+ }
+ zOriginTab = pTab->zName;
+ if( pNC->pParse ){
+ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
+ zOriginDb = pNC->pParse->db->aDb[iDb].zName;
+ }
+ }
+ break;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT: {
+ /* The expression is a sub-select. Return the declaration type and
+ ** origin info for the single column in the result set of the SELECT
+ ** statement.
+ */
+ NameContext sNC;
+ Select *pS = pExpr->x.pSelect;
+ Expr *p = pS->pEList->a[0].pExpr;
+ assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+ sNC.pSrcList = pS->pSrc;
+ sNC.pNext = pNC;
+ sNC.pParse = pNC->pParse;
+ zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ break;
+ }
+#endif
+ }
+
+ if( pzOriginDb ){
+ assert( pzOriginTab && pzOriginCol );
+ *pzOriginDb = zOriginDb;
+ *pzOriginTab = zOriginTab;
+ *pzOriginCol = zOriginCol;
+ }
+ return zType;
+}
+
+/*
+** Generate code that will tell the VDBE the declaration types of columns
+** in the result set.
+*/
+static void generateColumnTypes(
+ Parse *pParse, /* Parser context */
+ SrcList *pTabList, /* List of tables */
+ ExprList *pEList /* Expressions defining the result set */
+){
+#ifndef SQLITE_OMIT_DECLTYPE
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ NameContext sNC;
+ sNC.pSrcList = pTabList;
+ sNC.pParse = pParse;
+ for(i=0; i<pEList->nExpr; i++){
+ Expr *p = pEList->a[i].pExpr;
+ const char *zType;
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ const char *zOrigDb = 0;
+ const char *zOrigTab = 0;
+ const char *zOrigCol = 0;
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
+
+ /* The vdbe must make its own copy of the column-type and other
+ ** column specific strings, in case the schema is reset before this
+ ** virtual machine is deleted.
+ */
+ sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
+ sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
+ sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
+#else
+ zType = columnType(&sNC, p, 0, 0, 0);
+#endif
+ sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
+ }
+#endif /* SQLITE_OMIT_DECLTYPE */
+}
+
+/*
+** Generate code that will tell the VDBE the names of columns
+** in the result set. This information is used to provide the
+** azCol[] values in the callback.
+*/
+static void generateColumnNames(
+ Parse *pParse, /* Parser context */
+ SrcList *pTabList, /* List of tables */
+ ExprList *pEList /* Expressions defining the result set */
+){
+ Vdbe *v = pParse->pVdbe;
+ int i, j;
+ sqlite3 *db = pParse->db;
+ int fullNames, shortNames;
+
+#ifndef SQLITE_OMIT_EXPLAIN
+ /* If this is an EXPLAIN, skip this step */
+ if( pParse->explain ){
+ return;
+ }
+#endif
+
+ if( pParse->colNamesSet || NEVER(v==0) || db->mallocFailed ) return;
+ pParse->colNamesSet = 1;
+ fullNames = (db->flags & SQLITE_FullColNames)!=0;
+ shortNames = (db->flags & SQLITE_ShortColNames)!=0;
+ sqlite3VdbeSetNumCols(v, pEList->nExpr);
+ for(i=0; i<pEList->nExpr; i++){
+ Expr *p;
+ p = pEList->a[i].pExpr;
+ if( NEVER(p==0) ) continue;
+ if( pEList->a[i].zName ){
+ char *zName = pEList->a[i].zName;
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
+ }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){
+ Table *pTab;
+ char *zCol;
+ int iCol = p->iColumn;
+ for(j=0; ALWAYS(j<pTabList->nSrc); j++){
+ if( pTabList->a[j].iCursor==p->iTable ) break;
+ }
+ assert( j<pTabList->nSrc );
+ pTab = pTabList->a[j].pTab;
+ if( iCol<0 ) iCol = pTab->iPKey;
+ assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
+ if( iCol<0 ){
+ zCol = "rowid";
+ }else{
+ zCol = pTab->aCol[iCol].zName;
+ }
+ if( !shortNames && !fullNames ){
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME,
+ sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
+ }else if( fullNames ){
+ char *zName = 0;
+ zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
+ }else{
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
+ }
+ }else{
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME,
+ sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
+ }
+ }
+ generateColumnTypes(pParse, pTabList, pEList);
+}
+
+/*
+** Given a an expression list (which is really the list of expressions
+** that form the result set of a SELECT statement) compute appropriate
+** column names for a table that would hold the expression list.
+**
+** All column names will be unique.
+**
+** Only the column names are computed. Column.zType, Column.zColl,
+** and other fields of Column are zeroed.
+**
+** Return SQLITE_OK on success. If a memory allocation error occurs,
+** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
+*/
+static int selectColumnsFromExprList(
+ Parse *pParse, /* Parsing context */
+ ExprList *pEList, /* Expr list from which to derive column names */
+ i16 *pnCol, /* Write the number of columns here */
+ Column **paCol /* Write the new column list here */
+){
+ sqlite3 *db = pParse->db; /* Database connection */
+ int i, j; /* Loop counters */
+ int cnt; /* Index added to make the name unique */
+ Column *aCol, *pCol; /* For looping over result columns */
+ int nCol; /* Number of columns in the result set */
+ Expr *p; /* Expression for a single result column */
+ char *zName; /* Column name */
+ int nName; /* Size of name in zName[] */
+
+ if( pEList ){
+ nCol = pEList->nExpr;
+ aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
+ testcase( aCol==0 );
+ }else{
+ nCol = 0;
+ aCol = 0;
+ }
+ *pnCol = nCol;
+ *paCol = aCol;
+
+ for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+ /* Get an appropriate name for the column
+ */
+ p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
+ if( (zName = pEList->a[i].zName)!=0 ){
+ /* If the column contains an "AS <name>" phrase, use <name> as the name */
+ zName = sqlite3DbStrDup(db, zName);
+ }else{
+ Expr *pColExpr = p; /* The expression that is the result column name */
+ Table *pTab; /* Table associated with this expression */
+ while( pColExpr->op==TK_DOT ){
+ pColExpr = pColExpr->pRight;
+ assert( pColExpr!=0 );
+ }
+ if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){
+ /* For columns use the column name name */
+ int iCol = pColExpr->iColumn;
+ pTab = pColExpr->pTab;
+ if( iCol<0 ) iCol = pTab->iPKey;
+ zName = sqlite3MPrintf(db, "%s",
+ iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
+ }else if( pColExpr->op==TK_ID ){
+ assert( !ExprHasProperty(pColExpr, EP_IntValue) );
+ zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken);
+ }else{
+ /* Use the original text of the column expression as its name */
+ zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan);
+ }
+ }
+ if( db->mallocFailed ){
+ sqlite3DbFree(db, zName);
+ break;
+ }
+
+ /* Make sure the column name is unique. If the name is not unique,
+ ** append a integer to the name so that it becomes unique.
+ */
+ nName = sqlite3Strlen30(zName);
+ for(j=cnt=0; j<i; j++){
+ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
+ char *zNewName;
+ int k;
+ for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
+ if( zName[k]==':' ) nName = k;
+ zName[nName] = 0;
+ zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
+ sqlite3DbFree(db, zName);
+ zName = zNewName;
+ j = -1;
+ if( zName==0 ) break;
+ }
+ }
+ pCol->zName = zName;
+ }
+ if( db->mallocFailed ){
+ for(j=0; j<i; j++){
+ sqlite3DbFree(db, aCol[j].zName);
+ }
+ sqlite3DbFree(db, aCol);
+ *paCol = 0;
+ *pnCol = 0;
+ return SQLITE_NOMEM;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Add type and collation information to a column list based on
+** a SELECT statement.
+**
+** The column list presumably came from selectColumnNamesFromExprList().
+** The column list has only names, not types or collations. This
+** routine goes through and adds the types and collations.
+**
+** This routine requires that all identifiers in the SELECT
+** statement be resolved.
+*/
+static void selectAddColumnTypeAndCollation(
+ Parse *pParse, /* Parsing contexts */
+ int nCol, /* Number of columns */
+ Column *aCol, /* List of columns */
+ Select *pSelect /* SELECT used to determine types and collations */
+){
+ sqlite3 *db = pParse->db;
+ NameContext sNC;
+ Column *pCol;
+ CollSeq *pColl;
+ int i;
+ Expr *p;
+ struct ExprList_item *a;
+
+ assert( pSelect!=0 );
+ assert( (pSelect->selFlags & SF_Resolved)!=0 );
+ assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
+ if( db->mallocFailed ) return;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pSrcList = pSelect->pSrc;
+ a = pSelect->pEList->a;
+ for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+ p = a[i].pExpr;
+ pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
+ pCol->affinity = sqlite3ExprAffinity(p);
+ if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
+ pColl = sqlite3ExprCollSeq(pParse, p);
+ if( pColl ){
+ pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
+ }
+ }
+}
+
+/*
+** Given a SELECT statement, generate a Table structure that describes
+** the result set of that SELECT.
+*/
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
+ Table *pTab;
+ sqlite3 *db = pParse->db;
+ int savedFlags;
+
+ savedFlags = db->flags;
+ db->flags &= ~SQLITE_FullColNames;
+ db->flags |= SQLITE_ShortColNames;
+ sqlite3SelectPrep(pParse, pSelect, 0);
+ if( pParse->nErr ) return 0;
+ while( pSelect->pPrior ) pSelect = pSelect->pPrior;
+ db->flags = savedFlags;
+ pTab = sqlite3DbMallocZero(db, sizeof(Table) );
+ if( pTab==0 ){
+ return 0;
+ }
+ /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
+ ** is disabled */
+ assert( db->lookaside.bEnabled==0 );
+ pTab->nRef = 1;
+ pTab->zName = 0;
+ pTab->nRowEst = 1000000;
+ selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
+ selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+ pTab->iPKey = -1;
+ if( db->mallocFailed ){
+ sqlite3DeleteTable(db, pTab);
+ return 0;
+ }
+ return pTab;
+}
+
+/*
+** Get a VDBE for the given parser context. Create a new one if necessary.
+** If an error occurs, return NULL and leave a message in pParse.
+*/
+SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){
+ Vdbe *v = pParse->pVdbe;
+ if( v==0 ){
+ v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db);
+#ifndef SQLITE_OMIT_TRACE
+ if( v ){
+ sqlite3VdbeAddOp0(v, OP_Trace);
+ }
+#endif
+ }
+ return v;
+}
+
+
+/*
+** Compute the iLimit and iOffset fields of the SELECT based on the
+** pLimit and pOffset expressions. pLimit and pOffset hold the expressions
+** that appear in the original SQL statement after the LIMIT and OFFSET
+** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
+** are the integer memory register numbers for counters used to compute
+** the limit and offset. If there is no limit and/or offset, then
+** iLimit and iOffset are negative.
+**
+** This routine changes the values of iLimit and iOffset only if
+** a limit or offset is defined by pLimit and pOffset. iLimit and
+** iOffset should have been preset to appropriate default values
+** (usually but not always -1) prior to calling this routine.
+** Only if pLimit!=0 or pOffset!=0 do the limit registers get
+** redefined. The UNION ALL operator uses this property to force
+** the reuse of the same limit and offset registers across multiple
+** SELECT statements.
+*/
+static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
+ Vdbe *v = 0;
+ int iLimit = 0;
+ int iOffset;
+ int addr1, n;
+ if( p->iLimit ) return;
+
+ /*
+ ** "LIMIT -1" always shows all rows. There is some
+ ** contraversy about what the correct behavior should be.
+ ** The current implementation interprets "LIMIT 0" to mean
+ ** no rows.
+ */
+ sqlite3ExprCacheClear(pParse);
+ assert( p->pOffset==0 || p->pLimit!=0 );
+ if( p->pLimit ){
+ p->iLimit = iLimit = ++pParse->nMem;
+ v = sqlite3GetVdbe(pParse);
+ if( NEVER(v==0) ) return; /* VDBE should have already been allocated */
+ if( sqlite3ExprIsInteger(p->pLimit, &n) ){
+ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
+ VdbeComment((v, "LIMIT counter"));
+ if( n==0 ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
+ }else{
+ if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
+ }
+ }else{
+ sqlite3ExprCode(pParse, p->pLimit, iLimit);
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
+ VdbeComment((v, "LIMIT counter"));
+ sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
+ }
+ if( p->pOffset ){
+ p->iOffset = iOffset = ++pParse->nMem;
+ pParse->nMem++; /* Allocate an extra register for limit+offset */
+ sqlite3ExprCode(pParse, p->pOffset, iOffset);
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset);
+ VdbeComment((v, "OFFSET counter"));
+ addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
+ sqlite3VdbeJumpHere(v, addr1);
+ sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
+ VdbeComment((v, "LIMIT+OFFSET"));
+ addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
+ sqlite3VdbeJumpHere(v, addr1);
+ }
+ }
+}
+
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
+/*
+** Return the appropriate collating sequence for the iCol-th column of
+** the result set for the compound-select statement "p". Return NULL if
+** the column has no default collating sequence.
+**
+** The collating sequence for the compound select is taken from the
+** left-most term of the select that has a collating sequence.
+*/
+static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
+ CollSeq *pRet;
+ if( p->pPrior ){
+ pRet = multiSelectCollSeq(pParse, p->pPrior, iCol);
+ }else{
+ pRet = 0;
+ }
+ assert( iCol>=0 );
+ if( pRet==0 && iCol<p->pEList->nExpr ){
+ pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
+ }
+ return pRet;
+}
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
+
+/* Forward reference */
+static int multiSelectOrderBy(
+ Parse *pParse, /* Parsing context */
+ Select *p, /* The right-most of SELECTs to be coded */
+ SelectDest *pDest /* What to do with query results */
+);
+
+
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
+/*
+** This routine is called to process a compound query form from
+** two or more separate queries using UNION, UNION ALL, EXCEPT, or
+** INTERSECT
+**
+** "p" points to the right-most of the two queries. the query on the
+** left is p->pPrior. The left query could also be a compound query
+** in which case this routine will be called recursively.
+**
+** The results of the total query are to be written into a destination
+** of type eDest with parameter iParm.
+**
+** Example 1: Consider a three-way compound SQL statement.
+**
+** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3
+**
+** This statement is parsed up as follows:
+**
+** SELECT c FROM t3
+** |
+** `-----> SELECT b FROM t2
+** |
+** `------> SELECT a FROM t1
+**
+** The arrows in the diagram above represent the Select.pPrior pointer.
+** So if this routine is called with p equal to the t3 query, then
+** pPrior will be the t2 query. p->op will be TK_UNION in this case.
+**
+** Notice that because of the way SQLite parses compound SELECTs, the
+** individual selects always group from left to right.
+*/
+static int multiSelect(
+ Parse *pParse, /* Parsing context */
+ Select *p, /* The right-most of SELECTs to be coded */
+ SelectDest *pDest /* What to do with query results */
+){
+ int rc = SQLITE_OK; /* Success code from a subroutine */
+ Select *pPrior; /* Another SELECT immediately to our left */
+ Vdbe *v; /* Generate code to this VDBE */
+ SelectDest dest; /* Alternative data destination */
+ Select *pDelete = 0; /* Chain of simple selects to delete */
+ sqlite3 *db; /* Database connection */
+#ifndef SQLITE_OMIT_EXPLAIN
+ int iSub1; /* EQP id of left-hand query */
+ int iSub2; /* EQP id of right-hand query */
+#endif
+
+ /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
+ ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
+ */
+ assert( p && p->pPrior ); /* Calling function guarantees this much */
+ db = pParse->db;
+ pPrior = p->pPrior;
+ assert( pPrior->pRightmost!=pPrior );
+ assert( pPrior->pRightmost==p->pRightmost );
+ dest = *pDest;
+ if( pPrior->pOrderBy ){
+ sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
+ selectOpName(p->op));
+ rc = 1;
+ goto multi_select_end;
+ }
+ if( pPrior->pLimit ){
+ sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before",
+ selectOpName(p->op));
+ rc = 1;
+ goto multi_select_end;
+ }
+
+ v = sqlite3GetVdbe(pParse);
+ assert( v!=0 ); /* The VDBE already created by calling function */
+
+ /* Create the destination temporary table if necessary
+ */
+ if( dest.eDest==SRT_EphemTab ){
+ assert( p->pEList );
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
+ sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
+ dest.eDest = SRT_Table;
+ }
+
+ /* Make sure all SELECTs in the statement have the same number of elements
+ ** in their result sets.
+ */
+ assert( p->pEList && pPrior->pEList );
+ if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
+ if( p->selFlags & SF_Values ){
+ sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
+ }else{
+ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
+ " do not have the same number of result columns", selectOpName(p->op));
+ }
+ rc = 1;
+ goto multi_select_end;
+ }
+
+ /* Compound SELECTs that have an ORDER BY clause are handled separately.
+ */
+ if( p->pOrderBy ){
+ return multiSelectOrderBy(pParse, p, pDest);
+ }
+
+ /* Generate code for the left and right SELECT statements.
+ */
+ switch( p->op ){
+ case TK_ALL: {
+ int addr = 0;
+ int nLimit;
+ assert( !pPrior->pLimit );
+ pPrior->iLimit = p->iLimit;
+ pPrior->iOffset = p->iOffset;
+ pPrior->pLimit = p->pLimit;
+ pPrior->pOffset = p->pOffset;
+ explainSetInteger(iSub1, pParse->iNextSelectId);
+ rc = sqlite3Select(pParse, pPrior, &dest);
+ p->pLimit = 0;
+ p->pOffset = 0;
+ if( rc ){
+ goto multi_select_end;
+ }
+ p->pPrior = 0;
+ p->iLimit = pPrior->iLimit;
+ p->iOffset = pPrior->iOffset;
+ if( p->iLimit ){
+ addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
+ VdbeComment((v, "Jump ahead if LIMIT reached"));
+ }
+ explainSetInteger(iSub2, pParse->iNextSelectId);
+ rc = sqlite3Select(pParse, p, &dest);
+ testcase( rc!=SQLITE_OK );
+ pDelete = p->pPrior;
+ p->pPrior = pPrior;
+ p->nSelectRow += pPrior->nSelectRow;
+ if( pPrior->pLimit
+ && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
+ && p->nSelectRow > (double)nLimit
+ ){
+ p->nSelectRow = (double)nLimit;
+ }
+ if( addr ){
+ sqlite3VdbeJumpHere(v, addr);
+ }
+ break;
+ }
+ case TK_EXCEPT:
+ case TK_UNION: {
+ int unionTab; /* Cursor number of the temporary table holding result */
+ u8 op = 0; /* One of the SRT_ operations to apply to self */
+ int priorOp; /* The SRT_ operation to apply to prior selects */
+ Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
+ int addr;
+ SelectDest uniondest;
+
+ testcase( p->op==TK_EXCEPT );
+ testcase( p->op==TK_UNION );
+ priorOp = SRT_Union;
+ if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){
+ /* We can reuse a temporary table generated by a SELECT to our
+ ** right.
+ */
+ assert( p->pRightmost!=p ); /* Can only happen for leftward elements
+ ** of a 3-way or more compound */
+ assert( p->pLimit==0 ); /* Not allowed on leftward elements */
+ assert( p->pOffset==0 ); /* Not allowed on leftward elements */
+ unionTab = dest.iSDParm;
+ }else{
+ /* We will need to create our own temporary table to hold the
+ ** intermediate results.
+ */
+ unionTab = pParse->nTab++;
+ assert( p->pOrderBy==0 );
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
+ assert( p->addrOpenEphm[0] == -1 );
+ p->addrOpenEphm[0] = addr;
+ p->pRightmost->selFlags |= SF_UsesEphemeral;
+ assert( p->pEList );
+ }
+
+ /* Code the SELECT statements to our left
+ */
+ assert( !pPrior->pOrderBy );
+ sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
+ explainSetInteger(iSub1, pParse->iNextSelectId);
+ rc = sqlite3Select(pParse, pPrior, &uniondest);
+ if( rc ){
+ goto multi_select_end;
+ }
+
+ /* Code the current SELECT statement
+ */
+ if( p->op==TK_EXCEPT ){
+ op = SRT_Except;
+ }else{
+ assert( p->op==TK_UNION );
+ op = SRT_Union;
+ }
+ p->pPrior = 0;
+ pLimit = p->pLimit;
+ p->pLimit = 0;
+ pOffset = p->pOffset;
+ p->pOffset = 0;
+ uniondest.eDest = op;
+ explainSetInteger(iSub2, pParse->iNextSelectId);
+ rc = sqlite3Select(pParse, p, &uniondest);
+ testcase( rc!=SQLITE_OK );
+ /* Query flattening in sqlite3Select() might refill p->pOrderBy.
+ ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
+ sqlite3ExprListDelete(db, p->pOrderBy);
+ pDelete = p->pPrior;
+ p->pPrior = pPrior;
+ p->pOrderBy = 0;
+ if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
+ sqlite3ExprDelete(db, p->pLimit);
+ p->pLimit = pLimit;
+ p->pOffset = pOffset;
+ p->iLimit = 0;
+ p->iOffset = 0;
+
+ /* Convert the data in the temporary table into whatever form
+ ** it is that we currently need.
+ */
+ assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
+ if( dest.eDest!=priorOp ){
+ int iCont, iBreak, iStart;
+ assert( p->pEList );
+ if( dest.eDest==SRT_Output ){
+ Select *pFirst = p;
+ while( pFirst->pPrior ) pFirst = pFirst->pPrior;
+ generateColumnNames(pParse, 0, pFirst->pEList);
+ }
+ iBreak = sqlite3VdbeMakeLabel(v);
+ iCont = sqlite3VdbeMakeLabel(v);
+ computeLimitRegisters(pParse, p, iBreak);
+ sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);
+ iStart = sqlite3VdbeCurrentAddr(v);
+ selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
+ 0, 0, &dest, iCont, iBreak);
+ sqlite3VdbeResolveLabel(v, iCont);
+ sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart);
+ sqlite3VdbeResolveLabel(v, iBreak);
+ sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
+ }
+ break;
+ }
+ default: assert( p->op==TK_INTERSECT ); {
+ int tab1, tab2;
+ int iCont, iBreak, iStart;
+ Expr *pLimit, *pOffset;
+ int addr;
+ SelectDest intersectdest;
+ int r1;
+
+ /* INTERSECT is different from the others since it requires
+ ** two temporary tables. Hence it has its own case. Begin
+ ** by allocating the tables we will need.
+ */
+ tab1 = pParse->nTab++;
+ tab2 = pParse->nTab++;
+ assert( p->pOrderBy==0 );
+
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
+ assert( p->addrOpenEphm[0] == -1 );
+ p->addrOpenEphm[0] = addr;
+ p->pRightmost->selFlags |= SF_UsesEphemeral;
+ assert( p->pEList );
+
+ /* Code the SELECTs to our left into temporary table "tab1".
+ */
+ sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
+ explainSetInteger(iSub1, pParse->iNextSelectId);
+ rc = sqlite3Select(pParse, pPrior, &intersectdest);
+ if( rc ){
+ goto multi_select_end;
+ }
+
+ /* Code the current SELECT into temporary table "tab2"
+ */
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
+ assert( p->addrOpenEphm[1] == -1 );
+ p->addrOpenEphm[1] = addr;
+ p->pPrior = 0;
+ pLimit = p->pLimit;
+ p->pLimit = 0;
+ pOffset = p->pOffset;
+ p->pOffset = 0;
+ intersectdest.iSDParm = tab2;
+ explainSetInteger(iSub2, pParse->iNextSelectId);
+ rc = sqlite3Select(pParse, p, &intersectdest);
+ testcase( rc!=SQLITE_OK );
+ pDelete = p->pPrior;
+ p->pPrior = pPrior;
+ if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
+ sqlite3ExprDelete(db, p->pLimit);
+ p->pLimit = pLimit;
+ p->pOffset = pOffset;
+
+ /* Generate code to take the intersection of the two temporary
+ ** tables.
+ */
+ assert( p->pEList );
+ if( dest.eDest==SRT_Output ){
+ Select *pFirst = p;
+ while( pFirst->pPrior ) pFirst = pFirst->pPrior;
+ generateColumnNames(pParse, 0, pFirst->pEList);
+ }
+ iBreak = sqlite3VdbeMakeLabel(v);
+ iCont = sqlite3VdbeMakeLabel(v);
+ computeLimitRegisters(pParse, p, iBreak);
+ sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
+ r1 = sqlite3GetTempReg(pParse);
+ iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
+ sqlite3ReleaseTempReg(pParse, r1);
+ selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
+ 0, 0, &dest, iCont, iBreak);
+ sqlite3VdbeResolveLabel(v, iCont);
+ sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart);
+ sqlite3VdbeResolveLabel(v, iBreak);
+ sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
+ sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
+ break;
+ }
+ }
+
+ explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL);
+
+ /* Compute collating sequences used by
+ ** temporary tables needed to implement the compound select.
+ ** Attach the KeyInfo structure to all temporary tables.
+ **
+ ** This section is run by the right-most SELECT statement only.
+ ** SELECT statements to the left always skip this part. The right-most
+ ** SELECT might also skip this part if it has no ORDER BY clause and
+ ** no temp tables are required.
+ */
+ if( p->selFlags & SF_UsesEphemeral ){
+ int i; /* Loop counter */
+ KeyInfo *pKeyInfo; /* Collating sequence for the result set */
+ Select *pLoop; /* For looping through SELECT statements */
+ CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
+ int nCol; /* Number of columns in result set */
+
+ assert( p->pRightmost==p );
+ nCol = p->pEList->nExpr;
+ pKeyInfo = sqlite3DbMallocZero(db,
+ sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
+ if( !pKeyInfo ){
+ rc = SQLITE_NOMEM;
+ goto multi_select_end;
+ }
+
+ pKeyInfo->enc = ENC(db);
+ pKeyInfo->nField = (u16)nCol;
+
+ for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
+ *apColl = multiSelectCollSeq(pParse, p, i);
+ if( 0==*apColl ){
+ *apColl = db->pDfltColl;
+ }
+ }
+ pKeyInfo->aSortOrder = (u8*)apColl;
+
+ for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
+ for(i=0; i<2; i++){
+ int addr = pLoop->addrOpenEphm[i];
+ if( addr<0 ){
+ /* If [0] is unused then [1] is also unused. So we can
+ ** always safely abort as soon as the first unused slot is found */
+ assert( pLoop->addrOpenEphm[1]<0 );
+ break;
+ }
+ sqlite3VdbeChangeP2(v, addr, nCol);
+ sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO);
+ pLoop->addrOpenEphm[i] = -1;
+ }
+ }
+ sqlite3DbFree(db, pKeyInfo);
+ }
+
+multi_select_end:
+ pDest->iSdst = dest.iSdst;
+ pDest->nSdst = dest.nSdst;
+ sqlite3SelectDelete(db, pDelete);
+ return rc;
+}
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
+
+/*
+** Code an output subroutine for a coroutine implementation of a
+** SELECT statment.
+**
+** The data to be output is contained in pIn->iSdst. There are
+** pIn->nSdst columns to be output. pDest is where the output should
+** be sent.
+**
+** regReturn is the number of the register holding the subroutine
+** return address.
+**
+** If regPrev>0 then it is the first register in a vector that
+** records the previous output. mem[regPrev] is a flag that is false
+** if there has been no previous output. If regPrev>0 then code is
+** generated to suppress duplicates. pKeyInfo is used for comparing
+** keys.
+**
+** If the LIMIT found in p->iLimit is reached, jump immediately to
+** iBreak.
+*/
+static int generateOutputSubroutine(
+ Parse *pParse, /* Parsing context */
+ Select *p, /* The SELECT statement */
+ SelectDest *pIn, /* Coroutine supplying data */
+ SelectDest *pDest, /* Where to send the data */
+ int regReturn, /* The return address register */
+ int regPrev, /* Previous result register. No uniqueness if 0 */
+ KeyInfo *pKeyInfo, /* For comparing with previous entry */
+ int p4type, /* The p4 type for pKeyInfo */
+ int iBreak /* Jump here if we hit the LIMIT */
+){
+ Vdbe *v = pParse->pVdbe;
+ int iContinue;
+ int addr;
+
+ addr = sqlite3VdbeCurrentAddr(v);
+ iContinue = sqlite3VdbeMakeLabel(v);
+
+ /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
+ */
+ if( regPrev ){
+ int j1, j2;
+ j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
+ j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
+ (char*)pKeyInfo, p4type);
+ sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
+ sqlite3VdbeJumpHere(v, j1);
+ sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
+ }
+ if( pParse->db->mallocFailed ) return 0;
+
+ /* Suppress the first OFFSET entries if there is an OFFSET clause
+ */
+ codeOffset(v, p, iContinue);
+
+ switch( pDest->eDest ){
+ /* Store the result as data using a unique key.
+ */
+ case SRT_Table:
+ case SRT_EphemTab: {
+ int r1 = sqlite3GetTempReg(pParse);
+ int r2 = sqlite3GetTempReg(pParse);
+ testcase( pDest->eDest==SRT_Table );
+ testcase( pDest->eDest==SRT_EphemTab );
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
+ sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ sqlite3ReleaseTempReg(pParse, r2);
+ sqlite3ReleaseTempReg(pParse, r1);
+ break;
+ }
+
+#ifndef SQLITE_OMIT_SUBQUERY
+ /* If we are creating a set for an "expr IN (SELECT ...)" construct,
+ ** then there should be a single item on the stack. Write this
+ ** item into the set table with bogus data.
+ */
+ case SRT_Set: {
+ int r1;
+ assert( pIn->nSdst==1 );
+ pDest->affSdst =
+ sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
+ r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1);
+ sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
+ sqlite3ReleaseTempReg(pParse, r1);
+ break;
+ }
+
+#if 0 /* Never occurs on an ORDER BY query */
+ /* If any row exist in the result set, record that fact and abort.
+ */
+ case SRT_Exists: {
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
+ /* The LIMIT clause will terminate the loop for us */
+ break;
+ }
+#endif
+
+ /* If this is a scalar select that is part of an expression, then
+ ** store the results in the appropriate memory cell and break out
+ ** of the scan loop.
+ */
+ case SRT_Mem: {
+ assert( pIn->nSdst==1 );
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
+ /* The LIMIT clause will jump out of the loop for us */
+ break;
+ }
+#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
+
+ /* The results are stored in a sequence of registers
+ ** starting at pDest->iSdst. Then the co-routine yields.
+ */
+ case SRT_Coroutine: {
+ if( pDest->iSdst==0 ){
+ pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst);
+ pDest->nSdst = pIn->nSdst;
+ }
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst);
+ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
+ break;
+ }
+
+ /* If none of the above, then the result destination must be
+ ** SRT_Output. This routine is never called with any other
+ ** destination other than the ones handled above or SRT_Output.
+ **
+ ** For SRT_Output, results are stored in a sequence of registers.
+ ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
+ ** return the next row of result.
+ */
+ default: {
+ assert( pDest->eDest==SRT_Output );
+ sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
+ sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
+ break;
+ }
+ }
+
+ /* Jump to the end of the loop if the LIMIT is reached.
+ */
+ if( p->iLimit ){
+ sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
+ }
+
+ /* Generate the subroutine return
+ */
+ sqlite3VdbeResolveLabel(v, iContinue);
+ sqlite3VdbeAddOp1(v, OP_Return, regReturn);
+
+ return addr;
+}
+
+/*
+** Alternative compound select code generator for cases when there
+** is an ORDER BY clause.
+**
+** We assume a query of the following form:
+**
+** <selectA> <operator> <selectB> ORDER BY <orderbylist>
+**
+** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT. The idea
+** is to code both <selectA> and <selectB> with the ORDER BY clause as
+** co-routines. Then run the co-routines in parallel and merge the results
+** into the output. In addition to the two coroutines (called selectA and
+** selectB) there are 7 subroutines:
+**
+** outA: Move the output of the selectA coroutine into the output
+** of the compound query.
+**
+** outB: Move the output of the selectB coroutine into the output
+** of the compound query. (Only generated for UNION and
+** UNION ALL. EXCEPT and INSERTSECT never output a row that
+** appears only in B.)
+**
+** AltB: Called when there is data from both coroutines and A<B.
+**
+** AeqB: Called when there is data from both coroutines and A==B.
+**
+** AgtB: Called when there is data from both coroutines and A>B.
+**
+** EofA: Called when data is exhausted from selectA.
+**
+** EofB: Called when data is exhausted from selectB.
+**
+** The implementation of the latter five subroutines depend on which
+** <operator> is used:
+**
+**
+** UNION ALL UNION EXCEPT INTERSECT
+** ------------- ----------------- -------------- -----------------
+** AltB: outA, nextA outA, nextA outA, nextA nextA
+**
+** AeqB: outA, nextA nextA nextA outA, nextA
+**
+** AgtB: outB, nextB outB, nextB nextB nextB
+**
+** EofA: outB, nextB outB, nextB halt halt
+**
+** EofB: outA, nextA outA, nextA outA, nextA halt
+**
+** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA
+** causes an immediate jump to EofA and an EOF on B following nextB causes
+** an immediate jump to EofB. Within EofA and EofB, and EOF on entry or
+** following nextX causes a jump to the end of the select processing.
+**
+** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled
+** within the output subroutine. The regPrev register set holds the previously
+** output value. A comparison is made against this value and the output
+** is skipped if the next results would be the same as the previous.
+**
+** The implementation plan is to implement the two coroutines and seven
+** subroutines first, then put the control logic at the bottom. Like this:
+**
+** goto Init
+** coA: coroutine for left query (A)
+** coB: coroutine for right query (B)
+** outA: output one row of A
+** outB: output one row of B (UNION and UNION ALL only)
+** EofA: ...
+** EofB: ...
+** AltB: ...
+** AeqB: ...
+** AgtB: ...
+** Init: initialize coroutine registers
+** yield coA
+** if eof(A) goto EofA
+** yield coB
+** if eof(B) goto EofB
+** Cmpr: Compare A, B
+** Jump AltB, AeqB, AgtB
+** End: ...
+**
+** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
+** actually called using Gosub and they do not Return. EofA and EofB loop
+** until all data is exhausted then jump to the "end" labe. AltB, AeqB,
+** and AgtB jump to either L2 or to one of EofA or EofB.
+*/
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
+static int multiSelectOrderBy(
+ Parse *pParse, /* Parsing context */
+ Select *p, /* The right-most of SELECTs to be coded */
+ SelectDest *pDest /* What to do with query results */
+){
+ int i, j; /* Loop counters */
+ Select *pPrior; /* Another SELECT immediately to our left */
+ Vdbe *v; /* Generate code to this VDBE */
+ SelectDest destA; /* Destination for coroutine A */
+ SelectDest destB; /* Destination for coroutine B */
+ int regAddrA; /* Address register for select-A coroutine */
+ int regEofA; /* Flag to indicate when select-A is complete */
+ int regAddrB; /* Address register for select-B coroutine */
+ int regEofB; /* Flag to indicate when select-B is complete */
+ int addrSelectA; /* Address of the select-A coroutine */
+ int addrSelectB; /* Address of the select-B coroutine */
+ int regOutA; /* Address register for the output-A subroutine */
+ int regOutB; /* Address register for the output-B subroutine */
+ int addrOutA; /* Address of the output-A subroutine */
+ int addrOutB = 0; /* Address of the output-B subroutine */
+ int addrEofA; /* Address of the select-A-exhausted subroutine */
+ int addrEofB; /* Address of the select-B-exhausted subroutine */
+ int addrAltB; /* Address of the A<B subroutine */
+ int addrAeqB; /* Address of the A==B subroutine */
+ int addrAgtB; /* Address of the A>B subroutine */
+ int regLimitA; /* Limit register for select-A */
+ int regLimitB; /* Limit register for select-A */
+ int regPrev; /* A range of registers to hold previous output */
+ int savedLimit; /* Saved value of p->iLimit */
+ int savedOffset; /* Saved value of p->iOffset */
+ int labelCmpr; /* Label for the start of the merge algorithm */
+ int labelEnd; /* Label for the end of the overall SELECT stmt */
+ int j1; /* Jump instructions that get retargetted */
+ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
+ KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
+ KeyInfo *pKeyMerge; /* Comparison information for merging rows */
+ sqlite3 *db; /* Database connection */
+ ExprList *pOrderBy; /* The ORDER BY clause */
+ int nOrderBy; /* Number of terms in the ORDER BY clause */
+ int *aPermute; /* Mapping from ORDER BY terms to result set columns */
+#ifndef SQLITE_OMIT_EXPLAIN
+ int iSub1; /* EQP id of left-hand query */
+ int iSub2; /* EQP id of right-hand query */
+#endif
+
+ assert( p->pOrderBy!=0 );
+ assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */
+ db = pParse->db;
+ v = pParse->pVdbe;
+ assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */
+ labelEnd = sqlite3VdbeMakeLabel(v);
+ labelCmpr = sqlite3VdbeMakeLabel(v);
+
+
+ /* Patch up the ORDER BY clause
+ */
+ op = p->op;
+ pPrior = p->pPrior;
+ assert( pPrior->pOrderBy==0 );
+ pOrderBy = p->pOrderBy;
+ assert( pOrderBy );
+ nOrderBy = pOrderBy->nExpr;
+
+ /* For operators other than UNION ALL we have to make sure that
+ ** the ORDER BY clause covers every term of the result set. Add
+ ** terms to the ORDER BY clause as necessary.
+ */
+ if( op!=TK_ALL ){
+ for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
+ struct ExprList_item *pItem;
+ for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
+ assert( pItem->iOrderByCol>0 );
+ if( pItem->iOrderByCol==i ) break;
+ }
+ if( j==nOrderBy ){
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+ if( pNew==0 ) return SQLITE_NOMEM;
+ pNew->flags |= EP_IntValue;
+ pNew->u.iValue = i;
+ pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
+ if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
+ }
+ }
+ }
+
+ /* Compute the comparison permutation and keyinfo that is used with
+ ** the permutation used to determine if the next
+ ** row of results comes from selectA or selectB. Also add explicit
+ ** collations to the ORDER BY clause terms so that when the subqueries
+ ** to the right and the left are evaluated, they use the correct
+ ** collation.
+ */
+ aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
+ if( aPermute ){
+ struct ExprList_item *pItem;
+ for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
+ assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr );
+ aPermute[i] = pItem->iOrderByCol - 1;
+ }
+ pKeyMerge =
+ sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
+ if( pKeyMerge ){
+ pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
+ pKeyMerge->nField = (u16)nOrderBy;
+ pKeyMerge->enc = ENC(db);
+ for(i=0; i<nOrderBy; i++){
+ CollSeq *pColl;
+ Expr *pTerm = pOrderBy->a[i].pExpr;
+ if( pTerm->flags & EP_Collate ){
+ pColl = sqlite3ExprCollSeq(pParse, pTerm);
+ }else{
+ pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
+ if( pColl==0 ) pColl = db->pDfltColl;
+ pOrderBy->a[i].pExpr =
+ sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
+ }
+ pKeyMerge->aColl[i] = pColl;
+ pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
+ }
+ }
+ }else{
+ pKeyMerge = 0;
+ }
+
+ /* Reattach the ORDER BY clause to the query.
+ */
+ p->pOrderBy = pOrderBy;
+ pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
+
+ /* Allocate a range of temporary registers and the KeyInfo needed
+ ** for the logic that removes duplicate result rows when the
+ ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
+ */
+ if( op==TK_ALL ){
+ regPrev = 0;
+ }else{
+ int nExpr = p->pEList->nExpr;
+ assert( nOrderBy>=nExpr || db->mallocFailed );
+ regPrev = pParse->nMem+1;
+ pParse->nMem += nExpr+1;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
+ pKeyDup = sqlite3DbMallocZero(db,
+ sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
+ if( pKeyDup ){
+ pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr];
+ pKeyDup->nField = (u16)nExpr;
+ pKeyDup->enc = ENC(db);
+ for(i=0; i<nExpr; i++){
+ pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
+ pKeyDup->aSortOrder[i] = 0;
+ }
+ }
+ }
+
+ /* Separate the left and the right query from one another
+ */
+ p->pPrior = 0;
+ sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
+ if( pPrior->pPrior==0 ){
+ sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
+ }
+
+ /* Compute the limit registers */
+ computeLimitRegisters(pParse, p, labelEnd);
+ if( p->iLimit && op==TK_ALL ){
+ regLimitA = ++pParse->nMem;
+ regLimitB = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit,
+ regLimitA);
+ sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB);
+ }else{
+ regLimitA = regLimitB = 0;
+ }
+ sqlite3ExprDelete(db, p->pLimit);
+ p->pLimit = 0;
+ sqlite3ExprDelete(db, p->pOffset);
+ p->pOffset = 0;
+
+ regAddrA = ++pParse->nMem;
+ regEofA = ++pParse->nMem;
+ regAddrB = ++pParse->nMem;
+ regEofB = ++pParse->nMem;
+ regOutA = ++pParse->nMem;
+ regOutB = ++pParse->nMem;
+ sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
+ sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
+
+ /* Jump past the various subroutines and coroutines to the main
+ ** merge loop
+ */
+ j1 = sqlite3VdbeAddOp0(v, OP_Goto);
+ addrSelectA = sqlite3VdbeCurrentAddr(v);
+
+
+ /* Generate a coroutine to evaluate the SELECT statement to the
+ ** left of the compound operator - the "A" select.
+ */
+ VdbeNoopComment((v, "Begin coroutine for left SELECT"));
+ pPrior->iLimit = regLimitA;
+ explainSetInteger(iSub1, pParse->iNextSelectId);
+ sqlite3Select(pParse, pPrior, &destA);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
+ sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
+ VdbeNoopComment((v, "End coroutine for left SELECT"));
+
+ /* Generate a coroutine to evaluate the SELECT statement on
+ ** the right - the "B" select
+ */
+ addrSelectB = sqlite3VdbeCurrentAddr(v);
+ VdbeNoopComment((v, "Begin coroutine for right SELECT"));
+ savedLimit = p->iLimit;
+ savedOffset = p->iOffset;
+ p->iLimit = regLimitB;
+ p->iOffset = 0;
+ explainSetInteger(iSub2, pParse->iNextSelectId);
+ sqlite3Select(pParse, p, &destB);
+ p->iLimit = savedLimit;
+ p->iOffset = savedOffset;
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
+ sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
+ VdbeNoopComment((v, "End coroutine for right SELECT"));
+
+ /* Generate a subroutine that outputs the current row of the A
+ ** select as the next output row of the compound select.
+ */
+ VdbeNoopComment((v, "Output routine for A"));
+ addrOutA = generateOutputSubroutine(pParse,
+ p, &destA, pDest, regOutA,
+ regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);
+
+ /* Generate a subroutine that outputs the current row of the B
+ ** select as the next output row of the compound select.
+ */
+ if( op==TK_ALL || op==TK_UNION ){
+ VdbeNoopComment((v, "Output routine for B"));
+ addrOutB = generateOutputSubroutine(pParse,
+ p, &destB, pDest, regOutB,
+ regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd);
+ }
+
+ /* Generate a subroutine to run when the results from select A
+ ** are exhausted and only data in select B remains.
+ */
+ VdbeNoopComment((v, "eof-A subroutine"));
+ if( op==TK_EXCEPT || op==TK_INTERSECT ){
+ addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
+ }else{
+ addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
+ sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
+ p->nSelectRow += pPrior->nSelectRow;
+ }
+
+ /* Generate a subroutine to run when the results from select B
+ ** are exhausted and only data in select A remains.
+ */
+ if( op==TK_INTERSECT ){
+ addrEofB = addrEofA;
+ if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
+ }else{
+ VdbeNoopComment((v, "eof-B subroutine"));
+ addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
+ sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB);
+ }
+
+ /* Generate code to handle the case of A<B
+ */
+ VdbeNoopComment((v, "A-lt-B subroutine"));
+ addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
+ sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
+ sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
+
+ /* Generate code to handle the case of A==B
+ */
+ if( op==TK_ALL ){
+ addrAeqB = addrAltB;
+ }else if( op==TK_INTERSECT ){
+ addrAeqB = addrAltB;
+ addrAltB++;
+ }else{
+ VdbeNoopComment((v, "A-eq-B subroutine"));
+ addrAeqB =
+ sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
+ sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
+ }
+
+ /* Generate code to handle the case of A>B
+ */
+ VdbeNoopComment((v, "A-gt-B subroutine"));
+ addrAgtB = sqlite3VdbeCurrentAddr(v);
+ if( op==TK_ALL || op==TK_UNION ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
+ }
+ sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
+ sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
+
+ /* This code runs once to initialize everything.
+ */
+ sqlite3VdbeJumpHere(v, j1);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
+ sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
+ sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
+
+ /* Implement the main merge loop
+ */
+ sqlite3VdbeResolveLabel(v, labelCmpr);
+ sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
+ sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
+ (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
+ sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
+
+ /* Jump to the this point in order to terminate the query.
+ */
+ sqlite3VdbeResolveLabel(v, labelEnd);
+
+ /* Set the number of output columns
+ */
+ if( pDest->eDest==SRT_Output ){
+ Select *pFirst = pPrior;
+ while( pFirst->pPrior ) pFirst = pFirst->pPrior;
+ generateColumnNames(pParse, 0, pFirst->pEList);
+ }
+
+ /* Reassembly the compound query so that it will be freed correctly
+ ** by the calling function */
+ if( p->pPrior ){
+ sqlite3SelectDelete(db, p->pPrior);
+ }
+ p->pPrior = pPrior;
+
+ /*** TBD: Insert subroutine calls to close cursors on incomplete
+ **** subqueries ****/
+ explainComposite(pParse, p->op, iSub1, iSub2, 0);
+ return SQLITE_OK;
+}
+#endif
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/* Forward Declarations */
+static void substExprList(sqlite3*, ExprList*, int, ExprList*);
+static void substSelect(sqlite3*, Select *, int, ExprList *);
+
+/*
+** Scan through the expression pExpr. Replace every reference to
+** a column in table number iTable with a copy of the iColumn-th
+** entry in pEList. (But leave references to the ROWID column
+** unchanged.)
+**
+** This routine is part of the flattening procedure. A subquery
+** whose result set is defined by pEList appears as entry in the
+** FROM clause of a SELECT such that the VDBE cursor assigned to that
+** FORM clause entry is iTable. This routine make the necessary
+** changes to pExpr so that it refers directly to the source table
+** of the subquery rather the result set of the subquery.
+*/
+static Expr *substExpr(
+ sqlite3 *db, /* Report malloc errors to this connection */
+ Expr *pExpr, /* Expr in which substitution occurs */
+ int iTable, /* Table to be substituted */
+ ExprList *pEList /* Substitute expressions */
+){
+ if( pExpr==0 ) return 0;
+ if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
+ if( pExpr->iColumn<0 ){
+ pExpr->op = TK_NULL;
+ }else{
+ Expr *pNew;
+ assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
+ sqlite3ExprDelete(db, pExpr);
+ pExpr = pNew;
+ }
+ }else{
+ pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
+ pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ substSelect(db, pExpr->x.pSelect, iTable, pEList);
+ }else{
+ substExprList(db, pExpr->x.pList, iTable, pEList);
+ }
+ }
+ return pExpr;
+}
+static void substExprList(
+ sqlite3 *db, /* Report malloc errors here */
+ ExprList *pList, /* List to scan and in which to make substitutes */
+ int iTable, /* Table to be substituted */
+ ExprList *pEList /* Substitute values */
+){
+ int i;
+ if( pList==0 ) return;
+ for(i=0; i<pList->nExpr; i++){
+ pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList);
+ }
+}
+static void substSelect(
+ sqlite3 *db, /* Report malloc errors here */
+ Select *p, /* SELECT statement in which to make substitutions */
+ int iTable, /* Table to be replaced */
+ ExprList *pEList /* Substitute values */
+){
+ SrcList *pSrc;
+ struct SrcList_item *pItem;
+ int i;
+ if( !p ) return;
+ substExprList(db, p->pEList, iTable, pEList);
+ substExprList(db, p->pGroupBy, iTable, pEList);
+ substExprList(db, p->pOrderBy, iTable, pEList);
+ p->pHaving = substExpr(db, p->pHaving, iTable, pEList);
+ p->pWhere = substExpr(db, p->pWhere, iTable, pEList);
+ substSelect(db, p->pPrior, iTable, pEList);
+ pSrc = p->pSrc;
+ assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */
+ if( ALWAYS(pSrc) ){
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+ substSelect(db, pItem->pSelect, iTable, pEList);
+ }
+ }
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/*
+** This routine attempts to flatten subqueries as a performance optimization.
+** This routine returns 1 if it makes changes and 0 if no flattening occurs.
+**
+** To understand the concept of flattening, consider the following
+** query:
+**
+** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5
+**
+** The default way of implementing this query is to execute the
+** subquery first and store the results in a temporary table, then
+** run the outer query on that temporary table. This requires two
+** passes over the data. Furthermore, because the temporary table
+** has no indices, the WHERE clause on the outer query cannot be
+** optimized.
+**
+** This routine attempts to rewrite queries such as the above into
+** a single flat select, like this:
+**
+** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
+**
+** The code generated for this simpification gives the same result
+** but only has to scan the data once. And because indices might
+** exist on the table t1, a complete scan of the data might be
+** avoided.
+**
+** Flattening is only attempted if all of the following are true:
+**
+** (1) The subquery and the outer query do not both use aggregates.
+**
+** (2) The subquery is not an aggregate or the outer query is not a join.
+**
+** (3) The subquery is not the right operand of a left outer join
+** (Originally ticket #306. Strengthened by ticket #3300)
+**
+** (4) The subquery is not DISTINCT.
+**
+** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
+** sub-queries that were excluded from this optimization. Restriction
+** (4) has since been expanded to exclude all DISTINCT subqueries.
+**
+** (6) The subquery does not use aggregates or the outer query is not
+** DISTINCT.
+**
+** (7) The subquery has a FROM clause. TODO: For subqueries without
+** A FROM clause, consider adding a FROM close with the special
+** table sqlite_once that consists of a single row containing a
+** single NULL.
+**
+** (8) The subquery does not use LIMIT or the outer query is not a join.
+**
+** (9) The subquery does not use LIMIT or the outer query does not use
+** aggregates.
+**
+** (10) The subquery does not use aggregates or the outer query does not
+** use LIMIT.
+**
+** (11) The subquery and the outer query do not both have ORDER BY clauses.
+**
+** (**) Not implemented. Subsumed into restriction (3). Was previously
+** a separate restriction deriving from ticket #350.
+**
+** (13) The subquery and outer query do not both use LIMIT.
+**
+** (14) The subquery does not use OFFSET.
+**
+** (15) The outer query is not part of a compound select or the
+** subquery does not have a LIMIT clause.
+** (See ticket #2339 and ticket [02a8e81d44]).
+**
+** (16) The outer query is not an aggregate or the subquery does
+** not contain ORDER BY. (Ticket #2942) This used to not matter
+** until we introduced the group_concat() function.
+**
+** (17) The sub-query is not a compound select, or it is a UNION ALL
+** compound clause made up entirely of non-aggregate queries, and
+** the parent query:
+**
+** * is not itself part of a compound select,
+** * is not an aggregate or DISTINCT query, and
+** * is not a join
+**
+** The parent and sub-query may contain WHERE clauses. Subject to
+** rules (11), (13) and (14), they may also contain ORDER BY,
+** LIMIT and OFFSET clauses. The subquery cannot use any compound
+** operator other than UNION ALL because all the other compound
+** operators have an implied DISTINCT which is disallowed by
+** restriction (4).
+**
+** Also, each component of the sub-query must return the same number
+** of result columns. This is actually a requirement for any compound
+** SELECT statement, but all the code here does is make sure that no
+** such (illegal) sub-query is flattened. The caller will detect the
+** syntax error and return a detailed message.
+**
+** (18) If the sub-query is a compound select, then all terms of the
+** ORDER by clause of the parent must be simple references to
+** columns of the sub-query.
+**
+** (19) The subquery does not use LIMIT or the outer query does not
+** have a WHERE clause.
+**
+** (20) If the sub-query is a compound select, then it must not use
+** an ORDER BY clause. Ticket #3773. We could relax this constraint
+** somewhat by saying that the terms of the ORDER BY clause must
+** appear as unmodified result columns in the outer query. But we
+** have other optimizations in mind to deal with that case.
+**
+** (21) The subquery does not use LIMIT or the outer query is not
+** DISTINCT. (See ticket [752e1646fc]).
+**
+** In this routine, the "p" parameter is a pointer to the outer query.
+** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
+** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
+**
+** If flattening is not attempted, this routine is a no-op and returns 0.
+** If flattening is attempted this routine returns 1.
+**
+** All of the expression analysis must occur on both the outer query and
+** the subquery before this routine runs.
+*/
+static int flattenSubquery(
+ Parse *pParse, /* Parsing context */
+ Select *p, /* The parent or outer SELECT statement */
+ int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
+ int isAgg, /* True if outer SELECT uses aggregate functions */
+ int subqueryIsAgg /* True if the subquery uses aggregate functions */
+){
+ const char *zSavedAuthContext = pParse->zAuthContext;
+ Select *pParent;
+ Select *pSub; /* The inner query or "subquery" */
+ Select *pSub1; /* Pointer to the rightmost select in sub-query */
+ SrcList *pSrc; /* The FROM clause of the outer query */
+ SrcList *pSubSrc; /* The FROM clause of the subquery */
+ ExprList *pList; /* The result set of the outer query */
+ int iParent; /* VDBE cursor number of the pSub result set temp table */
+ int i; /* Loop counter */
+ Expr *pWhere; /* The WHERE clause */
+ struct SrcList_item *pSubitem; /* The subquery */
+ sqlite3 *db = pParse->db;
+
+ /* Check to see if flattening is permitted. Return 0 if not.
+ */
+ assert( p!=0 );
+ assert( p->pPrior==0 ); /* Unable to flatten compound queries */
+ if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
+ pSrc = p->pSrc;
+ assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
+ pSubitem = &pSrc->a[iFrom];
+ iParent = pSubitem->iCursor;
+ pSub = pSubitem->pSelect;
+ assert( pSub!=0 );
+ if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */
+ if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */
+ pSubSrc = pSub->pSrc;
+ assert( pSubSrc );
+ /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
+ ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
+ ** because they could be computed at compile-time. But when LIMIT and OFFSET
+ ** became arbitrary expressions, we were forced to add restrictions (13)
+ ** and (14). */
+ if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
+ if( pSub->pOffset ) return 0; /* Restriction (14) */
+ if( p->pRightmost && pSub->pLimit ){
+ return 0; /* Restriction (15) */
+ }
+ if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
+ if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */
+ if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
+ return 0; /* Restrictions (8)(9) */
+ }
+ if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
+ return 0; /* Restriction (6) */
+ }
+ if( p->pOrderBy && pSub->pOrderBy ){
+ return 0; /* Restriction (11) */
+ }
+ if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
+ if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
+ if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
+ return 0; /* Restriction (21) */
+ }
+
+ /* OBSOLETE COMMENT 1:
+ ** Restriction 3: If the subquery is a join, make sure the subquery is
+ ** not used as the right operand of an outer join. Examples of why this
+ ** is not allowed:
+ **
+ ** t1 LEFT OUTER JOIN (t2 JOIN t3)
+ **
+ ** If we flatten the above, we would get
+ **
+ ** (t1 LEFT OUTER JOIN t2) JOIN t3
+ **
+ ** which is not at all the same thing.
+ **
+ ** OBSOLETE COMMENT 2:
+ ** Restriction 12: If the subquery is the right operand of a left outer
+ ** join, make sure the subquery has no WHERE clause.
+ ** An examples of why this is not allowed:
+ **
+ ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
+ **
+ ** If we flatten the above, we would get
+ **
+ ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
+ **
+ ** But the t2.x>0 test will always fail on a NULL row of t2, which
+ ** effectively converts the OUTER JOIN into an INNER JOIN.
+ **
+ ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
+ ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
+ ** is fraught with danger. Best to avoid the whole thing. If the
+ ** subquery is the right term of a LEFT JOIN, then do not flatten.
+ */
+ if( (pSubitem->jointype & JT_OUTER)!=0 ){
+ return 0;
+ }
+
+ /* Restriction 17: If the sub-query is a compound SELECT, then it must
+ ** use only the UNION ALL operator. And none of the simple select queries
+ ** that make up the compound SELECT are allowed to be aggregate or distinct
+ ** queries.
+ */
+ if( pSub->pPrior ){
+ if( pSub->pOrderBy ){
+ return 0; /* Restriction 20 */
+ }
+ if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
+ return 0;
+ }
+ for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
+ testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
+ testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
+ assert( pSub->pSrc!=0 );
+ if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
+ || (pSub1->pPrior && pSub1->op!=TK_ALL)
+ || pSub1->pSrc->nSrc<1
+ || pSub->pEList->nExpr!=pSub1->pEList->nExpr
+ ){
+ return 0;
+ }
+ testcase( pSub1->pSrc->nSrc>1 );
+ }
+
+ /* Restriction 18. */
+ if( p->pOrderBy ){
+ int ii;
+ for(ii=0; ii<p->pOrderBy->nExpr; ii++){
+ if( p->pOrderBy->a[ii].iOrderByCol==0 ) return 0;
+ }
+ }
+ }
+
+ /***** If we reach this point, flattening is permitted. *****/
+
+ /* Authorize the subquery */
+ pParse->zAuthContext = pSubitem->zName;
+ TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
+ testcase( i==SQLITE_DENY );
+ pParse->zAuthContext = zSavedAuthContext;
+
+ /* If the sub-query is a compound SELECT statement, then (by restrictions
+ ** 17 and 18 above) it must be a UNION ALL and the parent query must
+ ** be of the form:
+ **
+ ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
+ **
+ ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
+ ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
+ ** OFFSET clauses and joins them to the left-hand-side of the original
+ ** using UNION ALL operators. In this case N is the number of simple
+ ** select statements in the compound sub-query.
+ **
+ ** Example:
+ **
+ ** SELECT a+1 FROM (
+ ** SELECT x FROM tab
+ ** UNION ALL
+ ** SELECT y FROM tab
+ ** UNION ALL
+ ** SELECT abs(z*2) FROM tab2
+ ** ) WHERE a!=5 ORDER BY 1
+ **
+ ** Transformed into:
+ **
+ ** SELECT x+1 FROM tab WHERE x+1!=5
+ ** UNION ALL
+ ** SELECT y+1 FROM tab WHERE y+1!=5
+ ** UNION ALL
+ ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5
+ ** ORDER BY 1
+ **
+ ** We call this the "compound-subquery flattening".
+ */
+ for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
+ Select *pNew;
+ ExprList *pOrderBy = p->pOrderBy;
+ Expr *pLimit = p->pLimit;
+ Expr *pOffset = p->pOffset;
+ Select *pPrior = p->pPrior;
+ p->pOrderBy = 0;
+ p->pSrc = 0;
+ p->pPrior = 0;
+ p->pLimit = 0;
+ p->pOffset = 0;
+ pNew = sqlite3SelectDup(db, p, 0);
+ p->pOffset = pOffset;
+ p->pLimit = pLimit;
+ p->pOrderBy = pOrderBy;
+ p->pSrc = pSrc;
+ p->op = TK_ALL;
+ p->pRightmost = 0;
+ if( pNew==0 ){
+ pNew = pPrior;
+ }else{
+ pNew->pPrior = pPrior;
+ pNew->pRightmost = 0;
+ }
+ p->pPrior = pNew;
+ if( db->mallocFailed ) return 1;
+ }
+
+ /* Begin flattening the iFrom-th entry of the FROM clause
+ ** in the outer query.
+ */
+ pSub = pSub1 = pSubitem->pSelect;
+
+ /* Delete the transient table structure associated with the
+ ** subquery
+ */
+ sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlite3DbFree(db, pSubitem->zName);
+ sqlite3DbFree(db, pSubitem->zAlias);
+ pSubitem->zDatabase = 0;
+ pSubitem->zName = 0;
+ pSubitem->zAlias = 0;
+ pSubitem->pSelect = 0;
+
+ /* Defer deleting the Table object associated with the
+ ** subquery until code generation is
+ ** complete, since there may still exist Expr.pTab entries that
+ ** refer to the subquery even after flattening. Ticket #3346.
+ **
+ ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
+ */
+ if( ALWAYS(pSubitem->pTab!=0) ){
+ Table *pTabToDel = pSubitem->pTab;
+ if( pTabToDel->nRef==1 ){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ pTabToDel->pNextZombie = pToplevel->pZombieTab;
+ pToplevel->pZombieTab = pTabToDel;
+ }else{
+ pTabToDel->nRef--;
+ }
+ pSubitem->pTab = 0;
+ }
+
+ /* The following loop runs once for each term in a compound-subquery
+ ** flattening (as described above). If we are doing a different kind
+ ** of flattening - a flattening other than a compound-subquery flattening -
+ ** then this loop only runs once.
+ **
+ ** This loop moves all of the FROM elements of the subquery into the
+ ** the FROM clause of the outer query. Before doing this, remember
+ ** the cursor number for the original outer query FROM element in
+ ** iParent. The iParent cursor will never be used. Subsequent code
+ ** will scan expressions looking for iParent references and replace
+ ** those references with expressions that resolve to the subquery FROM
+ ** elements we are now copying in.
+ */
+ for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
+ int nSubSrc;
+ u8 jointype = 0;
+ pSubSrc = pSub->pSrc; /* FROM clause of subquery */
+ nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
+ pSrc = pParent->pSrc; /* FROM clause of the outer query */
+
+ if( pSrc ){
+ assert( pParent==p ); /* First time through the loop */
+ jointype = pSubitem->jointype;
+ }else{
+ assert( pParent!=p ); /* 2nd and subsequent times through the loop */
+ pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
+ if( pSrc==0 ){
+ assert( db->mallocFailed );
+ break;
+ }
+ }
+
+ /* The subquery uses a single slot of the FROM clause of the outer
+ ** query. If the subquery has more than one element in its FROM clause,
+ ** then expand the outer query to make space for it to hold all elements
+ ** of the subquery.
+ **
+ ** Example:
+ **
+ ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
+ **
+ ** The outer query has 3 slots in its FROM clause. One slot of the
+ ** outer query (the middle slot) is used by the subquery. The next
+ ** block of code will expand the out query to 4 slots. The middle
+ ** slot is expanded to two slots in order to make space for the
+ ** two elements in the FROM clause of the subquery.
+ */
+ if( nSubSrc>1 ){
+ pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
+ if( db->mallocFailed ){
+ break;
+ }
+ }
+
+ /* Transfer the FROM clause terms from the subquery into the
+ ** outer query.
+ */
+ for(i=0; i<nSubSrc; i++){
+ sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
+ pSrc->a[i+iFrom] = pSubSrc->a[i];
+ memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
+ }
+ pSrc->a[iFrom].jointype = jointype;
+
+ /* Now begin substituting subquery result set expressions for
+ ** references to the iParent in the outer query.
+ **
+ ** Example:
+ **
+ ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
+ ** \ \_____________ subquery __________/ /
+ ** \_____________________ outer query ______________________________/
+ **
+ ** We look at every expression in the outer query and every place we see
+ ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
+ */
+ pList = pParent->pEList;
+ for(i=0; i<pList->nExpr; i++){
+ if( pList->a[i].zName==0 ){
+ char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
+ sqlite3Dequote(zName);
+ pList->a[i].zName = zName;
+ }
+ }
+ substExprList(db, pParent->pEList, iParent, pSub->pEList);
+ if( isAgg ){
+ substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
+ pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
+ }
+ if( pSub->pOrderBy ){
+ assert( pParent->pOrderBy==0 );
+ pParent->pOrderBy = pSub->pOrderBy;
+ pSub->pOrderBy = 0;
+ }else if( pParent->pOrderBy ){
+ substExprList(db, pParent->pOrderBy, iParent, pSub->pEList);
+ }
+ if( pSub->pWhere ){
+ pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
+ }else{
+ pWhere = 0;
+ }
+ if( subqueryIsAgg ){
+ assert( pParent->pHaving==0 );
+ pParent->pHaving = pParent->pWhere;
+ pParent->pWhere = pWhere;
+ pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
+ pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
+ sqlite3ExprDup(db, pSub->pHaving, 0));
+ assert( pParent->pGroupBy==0 );
+ pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
+ }else{
+ pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList);
+ pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
+ }
+
+ /* The flattened query is distinct if either the inner or the
+ ** outer query is distinct.
+ */
+ pParent->selFlags |= pSub->selFlags & SF_Distinct;
+
+ /*
+ ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
+ **
+ ** One is tempted to try to add a and b to combine the limits. But this
+ ** does not work if either limit is negative.
+ */
+ if( pSub->pLimit ){
+ pParent->pLimit = pSub->pLimit;
+ pSub->pLimit = 0;
+ }
+ }
+
+ /* Finially, delete what is left of the subquery and return
+ ** success.
+ */
+ sqlite3SelectDelete(db, pSub1);
+
+ return 1;
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+/*
+** Based on the contents of the AggInfo structure indicated by the first
+** argument, this function checks if the following are true:
+**
+** * the query contains just a single aggregate function,
+** * the aggregate function is either min() or max(), and
+** * the argument to the aggregate function is a column value.
+**
+** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
+** is returned as appropriate. Also, *ppMinMax is set to point to the
+** list of arguments passed to the aggregate before returning.
+**
+** Or, if the conditions above are not met, *ppMinMax is set to 0 and
+** WHERE_ORDERBY_NORMAL is returned.
+*/
+static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
+ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
+
+ *ppMinMax = 0;
+ if( pAggInfo->nFunc==1 ){
+ Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
+ ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */
+
+ assert( pExpr->op==TK_AGG_FUNCTION );
+ if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
+ const char *zFunc = pExpr->u.zToken;
+ if( sqlite3StrICmp(zFunc, "min")==0 ){
+ eRet = WHERE_ORDERBY_MIN;
+ *ppMinMax = pEList;
+ }else if( sqlite3StrICmp(zFunc, "max")==0 ){
+ eRet = WHERE_ORDERBY_MAX;
+ *ppMinMax = pEList;
+ }
+ }
+ }
+
+ assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
+ return eRet;
+}
+
+/*
+** The select statement passed as the first argument is an aggregate query.
+** The second argment is the associated aggregate-info object. This
+** function tests if the SELECT is of the form:
+**
+** SELECT count(*) FROM <tbl>
+**
+** where table is a database table, not a sub-select or view. If the query
+** does match this pattern, then a pointer to the Table object representing
+** <tbl> is returned. Otherwise, 0 is returned.
+*/
+static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
+ Table *pTab;
+ Expr *pExpr;
+
+ assert( !p->pGroupBy );
+
+ if( p->pWhere || p->pEList->nExpr!=1
+ || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
+ ){
+ return 0;
+ }
+ pTab = p->pSrc->a[0].pTab;
+ pExpr = p->pEList->a[0].pExpr;
+ assert( pTab && !pTab->pSelect && pExpr );
+
+ if( IsVirtual(pTab) ) return 0;
+ if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
+ if( NEVER(pAggInfo->nFunc==0) ) return 0;
+ if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
+ if( pExpr->flags&EP_Distinct ) return 0;
+
+ return pTab;
+}
+
+/*
+** If the source-list item passed as an argument was augmented with an
+** INDEXED BY clause, then try to locate the specified index. If there
+** was such a clause and the named index cannot be found, return
+** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
+** pFrom->pIndex and return SQLITE_OK.
+*/
+SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
+ if( pFrom->pTab && pFrom->zIndex ){
+ Table *pTab = pFrom->pTab;
+ char *zIndex = pFrom->zIndex;
+ Index *pIdx;
+ for(pIdx=pTab->pIndex;
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
+ pIdx=pIdx->pNext
+ );
+ if( !pIdx ){
+ sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0);
+ pParse->checkSchema = 1;
+ return SQLITE_ERROR;
+ }
+ pFrom->pIndex = pIdx;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** This routine is a Walker callback for "expanding" a SELECT statement.
+** "Expanding" means to do the following:
+**
+** (1) Make sure VDBE cursor numbers have been assigned to every
+** element of the FROM clause.
+**
+** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
+** defines FROM clause. When views appear in the FROM clause,
+** fill pTabList->a[].pSelect with a copy of the SELECT statement
+** that implements the view. A copy is made of the view's SELECT
+** statement so that we can freely modify or delete that statement
+** without worrying about messing up the presistent representation
+** of the view.
+**
+** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
+** on joins and the ON and USING clause of joins.
+**
+** (4) Scan the list of columns in the result set (pEList) looking
+** for instances of the "*" operator or the TABLE.* operator.
+** If found, expand each "*" to be every column in every table
+** and TABLE.* to be every column in TABLE.
+**
+*/
+static int selectExpander(Walker *pWalker, Select *p){
+ Parse *pParse = pWalker->pParse;
+ int i, j, k;
+ SrcList *pTabList;
+ ExprList *pEList;
+ struct SrcList_item *pFrom;
+ sqlite3 *db = pParse->db;
+ Expr *pE, *pRight, *pExpr;
+ u16 selFlags = p->selFlags;
+
+ p->selFlags |= SF_Expanded;
+ if( db->mallocFailed ){
+ return WRC_Abort;
+ }
+ if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){
+ return WRC_Prune;
+ }
+ pTabList = p->pSrc;
+ pEList = p->pEList;
+
+ /* Make sure cursor numbers have been assigned to all entries in
+ ** the FROM clause of the SELECT statement.
+ */
+ sqlite3SrcListAssignCursors(pParse, pTabList);
+
+ /* Look up every table named in the FROM clause of the select. If
+ ** an entry of the FROM clause is a subquery instead of a table or view,
+ ** then create a transient table structure to describe the subquery.
+ */
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab;
+ if( pFrom->pTab!=0 ){
+ /* This statement has already been prepared. There is no need
+ ** to go further. */
+ assert( i==0 );
+ return WRC_Prune;
+ }
+ if( pFrom->zName==0 ){
+#ifndef SQLITE_OMIT_SUBQUERY
+ Select *pSel = pFrom->pSelect;
+ /* A sub-query in the FROM clause of a SELECT */
+ assert( pSel!=0 );
+ assert( pFrom->pTab==0 );
+ sqlite3WalkSelect(pWalker, pSel);
+ pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTab==0 ) return WRC_Abort;
+ pTab->nRef = 1;
+ pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
+ while( pSel->pPrior ){ pSel = pSel->pPrior; }
+ selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
+ pTab->iPKey = -1;
+ pTab->nRowEst = 1000000;
+ pTab->tabFlags |= TF_Ephemeral;
+#endif
+ }else{
+ /* An ordinary table or view name in the FROM clause */
+ assert( pFrom->pTab==0 );
+ pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
+ if( pTab==0 ) return WRC_Abort;
+ if( pTab->nRef==0xffff ){
+ sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
+ pTab->zName);
+ pFrom->pTab = 0;
+ return WRC_Abort;
+ }
+ pTab->nRef++;
+#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+ if( pTab->pSelect || IsVirtual(pTab) ){
+ /* We reach here if the named table is a really a view */
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
+ assert( pFrom->pSelect==0 );
+ pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
+ sqlite3WalkSelect(pWalker, pFrom->pSelect);
+ }
+#endif
+ }
+
+ /* Locate the index named by the INDEXED BY clause, if any. */
+ if( sqlite3IndexedByLookup(pParse, pFrom) ){
+ return WRC_Abort;
+ }
+ }
+
+ /* Process NATURAL keywords, and ON and USING clauses of joins.
+ */
+ if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+ return WRC_Abort;
+ }
+
+ /* For every "*" that occurs in the column list, insert the names of
+ ** all columns in all tables. And for every TABLE.* insert the names
+ ** of all columns in TABLE. The parser inserted a special expression
+ ** with the TK_ALL operator for each "*" that it found in the column list.
+ ** The following code just has to locate the TK_ALL expressions and expand
+ ** each one to the list of all columns in all tables.
+ **
+ ** The first loop just checks to see if there are any "*" operators
+ ** that need expanding.
+ */
+ for(k=0; k<pEList->nExpr; k++){
+ pE = pEList->a[k].pExpr;
+ if( pE->op==TK_ALL ) break;
+ assert( pE->op!=TK_DOT || pE->pRight!=0 );
+ assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
+ if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
+ }
+ if( k<pEList->nExpr ){
+ /*
+ ** If we get here it means the result set contains one or more "*"
+ ** operators that need to be expanded. Loop through each expression
+ ** in the result set and expand them one by one.
+ */
+ struct ExprList_item *a = pEList->a;
+ ExprList *pNew = 0;
+ int flags = pParse->db->flags;
+ int longNames = (flags & SQLITE_FullColNames)!=0
+ && (flags & SQLITE_ShortColNames)==0;
+
+ /* When processing FROM-clause subqueries, it is always the case
+ ** that full_column_names=OFF and short_column_names=ON. The
+ ** sqlite3ResultSetOfSelect() routine makes it so. */
+ assert( (p->selFlags & SF_NestedFrom)==0
+ || ((flags & SQLITE_FullColNames)==0 &&
+ (flags & SQLITE_ShortColNames)!=0) );
+
+ for(k=0; k<pEList->nExpr; k++){
+ pE = a[k].pExpr;
+ pRight = pE->pRight;
+ assert( pE->op!=TK_DOT || pRight!=0 );
+ if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
+ /* This particular expression does not need to be expanded.
+ */
+ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
+ if( pNew ){
+ pNew->a[pNew->nExpr-1].zName = a[k].zName;
+ pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
+ a[k].zName = 0;
+ a[k].zSpan = 0;
+ }
+ a[k].pExpr = 0;
+ }else{
+ /* This expression is a "*" or a "TABLE.*" and needs to be
+ ** expanded. */
+ int tableSeen = 0; /* Set to 1 when TABLE matches */
+ char *zTName = 0; /* text of name of TABLE */
+ if( pE->op==TK_DOT ){
+ assert( pE->pLeft!=0 );
+ assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
+ zTName = pE->pLeft->u.zToken;
+ }
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab = pFrom->pTab;
+ Select *pSub = pFrom->pSelect;
+ char *zTabName = pFrom->zAlias;
+ const char *zSchemaName = 0;
+ int iDb;
+ if( zTabName==0 ){
+ zTabName = pTab->zName;
+ }
+ if( db->mallocFailed ) break;
+ if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
+ pSub = 0;
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+ continue;
+ }
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
+ }
+ for(j=0; j<pTab->nCol; j++){
+ char *zName = pTab->aCol[j].zName;
+ char *zColname; /* The computed column name */
+ char *zToFree; /* Malloced string that needs to be freed */
+ Token sColname; /* Computed column name as a token */
+
+ assert( zName );
+ if( zTName && pSub
+ && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
+ ){
+ continue;
+ }
+
+ /* If a column is marked as 'hidden' (currently only possible
+ ** for virtual tables), do not include it in the expanded
+ ** result-set list.
+ */
+ if( IsHiddenColumn(&pTab->aCol[j]) ){
+ assert(IsVirtual(pTab));
+ continue;
+ }
+ tableSeen = 1;
+
+ if( i>0 && zTName==0 ){
+ if( (pFrom->jointype & JT_NATURAL)!=0
+ && tableAndColumnIndex(pTabList, i, zName, 0, 0)
+ ){
+ /* In a NATURAL join, omit the join columns from the
+ ** table to the right of the join */
+ continue;
+ }
+ if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){
+ /* In a join with a USING clause, omit columns in the
+ ** using clause from the table on the right. */
+ continue;
+ }
+ }
+ pRight = sqlite3Expr(db, TK_ID, zName);
+ zColname = zName;
+ zToFree = 0;
+ if( longNames || pTabList->nSrc>1 ){
+ Expr *pLeft;
+ pLeft = sqlite3Expr(db, TK_ID, zTabName);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ if( zSchemaName ){
+ pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
+ }
+ if( longNames ){
+ zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
+ zToFree = zColname;
+ }
+ }else{
+ pExpr = pRight;
+ }
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
+ sColname.z = zColname;
+ sColname.n = sqlite3Strlen30(zColname);
+ sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
+ if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
+ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+ if( pSub ){
+ pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
+ testcase( pX->zSpan==0 );
+ }else{
+ pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
+ zSchemaName, zTabName, zColname);
+ testcase( pX->zSpan==0 );
+ }
+ pX->bSpanIsTab = 1;
+ }
+ sqlite3DbFree(db, zToFree);
+ }
+ }
+ if( !tableSeen ){
+ if( zTName ){
+ sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
+ }else{
+ sqlite3ErrorMsg(pParse, "no tables specified");
+ }
+ }
+ }
+ }
+ sqlite3ExprListDelete(db, pEList);
+ p->pEList = pNew;
+ }
+#if SQLITE_MAX_COLUMN
+ if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many columns in result set");
+ }
+#endif
+ return WRC_Continue;
+}
+
+/*
+** No-op routine for the parse-tree walker.
+**
+** When this routine is the Walker.xExprCallback then expression trees
+** are walked without any actions being taken at each node. Presumably,
+** when this routine is used for Walker.xExprCallback then
+** Walker.xSelectCallback is set to do something useful for every
+** subquery in the parser tree.
+*/
+static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ return WRC_Continue;
+}
+
+/*
+** This routine "expands" a SELECT statement and all of its subqueries.
+** For additional information on what it means to "expand" a SELECT
+** statement, see the comment on the selectExpand worker callback above.
+**
+** Expanding a SELECT statement is the first step in processing a
+** SELECT statement. The SELECT statement must be expanded before
+** name resolution is performed.
+**
+** If anything goes wrong, an error message is written into pParse.
+** The calling function can detect the problem by looking at pParse->nErr
+** and/or pParse->db->mallocFailed.
+*/
+static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
+ Walker w;
+ w.xSelectCallback = selectExpander;
+ w.xExprCallback = exprWalkNoop;
+ w.pParse = pParse;
+ sqlite3WalkSelect(&w, pSelect);
+}
+
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
+** interface.
+**
+** For each FROM-clause subquery, add Column.zType and Column.zColl
+** information to the Table structure that represents the result set
+** of that subquery.
+**
+** The Table structure that represents the result set was constructed
+** by selectExpander() but the type and collation information was omitted
+** at that point because identifiers had not yet been resolved. This
+** routine is called after identifier resolution.
+*/
+static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
+ Parse *pParse;
+ int i;
+ SrcList *pTabList;
+ struct SrcList_item *pFrom;
+
+ assert( p->selFlags & SF_Resolved );
+ if( (p->selFlags & SF_HasTypeInfo)==0 ){
+ p->selFlags |= SF_HasTypeInfo;
+ pParse = pWalker->pParse;
+ pTabList = p->pSrc;
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab = pFrom->pTab;
+ if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
+ /* A sub-query in the FROM clause of a SELECT */
+ Select *pSel = pFrom->pSelect;
+ assert( pSel );
+ while( pSel->pPrior ) pSel = pSel->pPrior;
+ selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
+ }
+ }
+ }
+ return WRC_Continue;
+}
+#endif
+
+
+/*
+** This routine adds datatype and collating sequence information to
+** the Table structures of all FROM-clause subqueries in a
+** SELECT statement.
+**
+** Use this routine after name resolution.
+*/
+static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
+#ifndef SQLITE_OMIT_SUBQUERY
+ Walker w;
+ w.xSelectCallback = selectAddSubqueryTypeInfo;
+ w.xExprCallback = exprWalkNoop;
+ w.pParse = pParse;
+ sqlite3WalkSelect(&w, pSelect);
+#endif
+}
+
+
+/*
+** This routine sets up a SELECT statement for processing. The
+** following is accomplished:
+**
+** * VDBE Cursor numbers are assigned to all FROM-clause terms.
+** * Ephemeral Table objects are created for all FROM-clause subqueries.
+** * ON and USING clauses are shifted into WHERE statements
+** * Wildcards "*" and "TABLE.*" in result sets are expanded.
+** * Identifiers in expression are matched to tables.
+**
+** This routine acts recursively on all subqueries within the SELECT.
+*/
+SQLITE_PRIVATE void sqlite3SelectPrep(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The SELECT statement being coded. */
+ NameContext *pOuterNC /* Name context for container */
+){
+ sqlite3 *db;
+ if( NEVER(p==0) ) return;
+ db = pParse->db;
+ if( db->mallocFailed ) return;
+ if( p->selFlags & SF_HasTypeInfo ) return;
+ sqlite3SelectExpand(pParse, p);
+ if( pParse->nErr || db->mallocFailed ) return;
+ sqlite3ResolveSelectNames(pParse, p, pOuterNC);
+ if( pParse->nErr || db->mallocFailed ) return;
+ sqlite3SelectAddTypeInfo(pParse, p);
+}
+
+/*
+** Reset the aggregate accumulator.
+**
+** The aggregate accumulator is a set of memory cells that hold
+** intermediate results while calculating an aggregate. This
+** routine generates code that stores NULLs in all of those memory
+** cells.
+*/
+static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ struct AggInfo_func *pFunc;
+ if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){
+ return;
+ }
+ for(i=0; i<pAggInfo->nColumn; i++){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pAggInfo->aCol[i].iMem);
+ }
+ for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc->iMem);
+ if( pFunc->iDistinct>=0 ){
+ Expr *pE = pFunc->pExpr;
+ assert( !ExprHasProperty(pE, EP_xIsSelect) );
+ if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
+ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
+ "argument");
+ pFunc->iDistinct = -1;
+ }else{
+ KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList);
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
+ (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ }
+ }
+ }
+}
+
+/*
+** Invoke the OP_AggFinalize opcode for every aggregate function
+** in the AggInfo structure.
+*/
+static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ struct AggInfo_func *pF;
+ for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
+ ExprList *pList = pF->pExpr->x.pList;
+ assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
+ sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0,
+ (void*)pF->pFunc, P4_FUNCDEF);
+ }
+}
+
+/*
+** Update the accumulator memory cells for an aggregate based on
+** the current cursor position.
+*/
+static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ int regHit = 0;
+ int addrHitTest = 0;
+ struct AggInfo_func *pF;
+ struct AggInfo_col *pC;
+
+ pAggInfo->directMode = 1;
+ sqlite3ExprCacheClear(pParse);
+ for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
+ int nArg;
+ int addrNext = 0;
+ int regAgg;
+ ExprList *pList = pF->pExpr->x.pList;
+ assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
+ if( pList ){
+ nArg = pList->nExpr;
+ regAgg = sqlite3GetTempRange(pParse, nArg);
+ sqlite3ExprCodeExprList(pParse, pList, regAgg, 1);
+ }else{
+ nArg = 0;
+ regAgg = 0;
+ }
+ if( pF->iDistinct>=0 ){
+ addrNext = sqlite3VdbeMakeLabel(v);
+ assert( nArg==1 );
+ codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
+ }
+ if( pF->pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ CollSeq *pColl = 0;
+ struct ExprList_item *pItem;
+ int j;
+ assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */
+ for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
+ pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
+ }
+ if( !pColl ){
+ pColl = pParse->db->pDfltColl;
+ }
+ if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
+ sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
+ }
+ sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
+ (void*)pF->pFunc, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, (u8)nArg);
+ sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
+ sqlite3ReleaseTempRange(pParse, regAgg, nArg);
+ if( addrNext ){
+ sqlite3VdbeResolveLabel(v, addrNext);
+ sqlite3ExprCacheClear(pParse);
+ }
+ }
+
+ /* Before populating the accumulator registers, clear the column cache.
+ ** Otherwise, if any of the required column values are already present
+ ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value
+ ** to pC->iMem. But by the time the value is used, the original register
+ ** may have been used, invalidating the underlying buffer holding the
+ ** text or blob value. See ticket [883034dcb5].
+ **
+ ** Another solution would be to change the OP_SCopy used to copy cached
+ ** values to an OP_Copy.
+ */
+ if( regHit ){
+ addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit);
+ }
+ sqlite3ExprCacheClear(pParse);
+ for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
+ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
+ }
+ pAggInfo->directMode = 0;
+ sqlite3ExprCacheClear(pParse);
+ if( addrHitTest ){
+ sqlite3VdbeJumpHere(v, addrHitTest);
+ }
+}
+
+/*
+** Add a single OP_Explain instruction to the VDBE to explain a simple
+** count(*) query ("SELECT count(*) FROM pTab").
+*/
+#ifndef SQLITE_OMIT_EXPLAIN
+static void explainSimpleCount(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Table being queried */
+ Index *pIdx /* Index used to optimize scan, or NULL */
+){
+ if( pParse->explain==2 ){
+ char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s %s%s(~%d rows)",
+ pTab->zName,
+ pIdx ? "USING COVERING INDEX " : "",
+ pIdx ? pIdx->zName : "",
+ pTab->nRowEst
+ );
+ sqlite3VdbeAddOp4(
+ pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
+ );
+ }
+}
+#else
+# define explainSimpleCount(a,b,c)
+#endif
+
+/*
+** Generate code for the SELECT statement given in the p argument.
+**
+** The results are distributed in various ways depending on the
+** contents of the SelectDest structure pointed to by argument pDest
+** as follows:
+**
+** pDest->eDest Result
+** ------------ -------------------------------------------
+** SRT_Output Generate a row of output (using the OP_ResultRow
+** opcode) for each row in the result set.
+**
+** SRT_Mem Only valid if the result is a single column.
+** Store the first column of the first result row
+** in register pDest->iSDParm then abandon the rest
+** of the query. This destination implies "LIMIT 1".
+**
+** SRT_Set The result must be a single column. Store each
+** row of result as the key in table pDest->iSDParm.
+** Apply the affinity pDest->affSdst before storing
+** results. Used to implement "IN (SELECT ...)".
+**
+** SRT_Union Store results as a key in a temporary table
+** identified by pDest->iSDParm.
+**
+** SRT_Except Remove results from the temporary table pDest->iSDParm.
+**
+** SRT_Table Store results in temporary table pDest->iSDParm.
+** This is like SRT_EphemTab except that the table
+** is assumed to already be open.
+**
+** SRT_EphemTab Create an temporary table pDest->iSDParm and store
+** the result there. The cursor is left open after
+** returning. This is like SRT_Table except that
+** this destination uses OP_OpenEphemeral to create
+** the table first.
+**
+** SRT_Coroutine Generate a co-routine that returns a new row of
+** results each time it is invoked. The entry point
+** of the co-routine is stored in register pDest->iSDParm.
+**
+** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
+** set is not empty.
+**
+** SRT_Discard Throw the results away. This is used by SELECT
+** statements within triggers whose only purpose is
+** the side-effects of functions.
+**
+** This routine returns the number of errors. If any errors are
+** encountered, then an appropriate error message is left in
+** pParse->zErrMsg.
+**
+** This routine does NOT free the Select structure passed in. The
+** calling function needs to do that.
+*/
+SQLITE_PRIVATE int sqlite3Select(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The SELECT statement being coded. */
+ SelectDest *pDest /* What to do with the query results */
+){
+ int i, j; /* Loop counters */
+ WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */
+ Vdbe *v; /* The virtual machine under construction */
+ int isAgg; /* True for select lists like "count(*)" */
+ ExprList *pEList; /* List of columns to extract. */
+ SrcList *pTabList; /* List of tables to select from */
+ Expr *pWhere; /* The WHERE clause. May be NULL */
+ ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */
+ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
+ Expr *pHaving; /* The HAVING clause. May be NULL */
+ int rc = 1; /* Value to return from this function */
+ int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
+ DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
+ AggInfo sAggInfo; /* Information used by aggregate queries */
+ int iEnd; /* Address of the end of the query */
+ sqlite3 *db; /* The database connection */
+
+#ifndef SQLITE_OMIT_EXPLAIN
+ int iRestoreSelectId = pParse->iSelectId;
+ pParse->iSelectId = pParse->iNextSelectId++;
+#endif
+
+ db = pParse->db;
+ if( p==0 || db->mallocFailed || pParse->nErr ){
+ return 1;
+ }
+ if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
+ memset(&sAggInfo, 0, sizeof(sAggInfo));
+
+ if( IgnorableOrderby(pDest) ){
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
+ pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
+ /* If ORDER BY makes no difference in the output then neither does
+ ** DISTINCT so it can be removed too. */
+ sqlite3ExprListDelete(db, p->pOrderBy);
+ p->pOrderBy = 0;
+ p->selFlags &= ~SF_Distinct;
+ }
+ sqlite3SelectPrep(pParse, p, 0);
+ pOrderBy = p->pOrderBy;
+ pTabList = p->pSrc;
+ pEList = p->pEList;
+ if( pParse->nErr || db->mallocFailed ){
+ goto select_end;
+ }
+ isAgg = (p->selFlags & SF_Aggregate)!=0;
+ assert( pEList!=0 );
+
+ /* Begin generating code.
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto select_end;
+
+ /* If writing to memory or generating a set
+ ** only a single column may be output.
+ */
+#ifndef SQLITE_OMIT_SUBQUERY
+ if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
+ goto select_end;
+ }
+#endif
+
+ /* Generate code for all sub-queries in the FROM clause
+ */
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+ for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
+ struct SrcList_item *pItem = &pTabList->a[i];
+ SelectDest dest;
+ Select *pSub = pItem->pSelect;
+ int isAggSub;
+
+ if( pSub==0 ) continue;
+
+ /* Sometimes the code for a subquery will be generated more than
+ ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
+ ** for example. In that case, do not regenerate the code to manifest
+ ** a view or the co-routine to implement a view. The first instance
+ ** is sufficient, though the subroutine to manifest the view does need
+ ** to be invoked again. */
+ if( pItem->addrFillSub ){
+ if( pItem->viaCoroutine==0 ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+ }
+ continue;
+ }
+
+ /* Increment Parse.nHeight by the height of the largest expression
+ ** tree refered to by this, the parent select. The child select
+ ** may contain expression trees of at most
+ ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
+ ** more conservative than necessary, but much easier than enforcing
+ ** an exact limit.
+ */
+ pParse->nHeight += sqlite3SelectExprHeight(p);
+
+ isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
+ if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
+ /* This subquery can be absorbed into its parent. */
+ if( isAggSub ){
+ isAgg = 1;
+ p->selFlags |= SF_Aggregate;
+ }
+ i = -1;
+ }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0
+ && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+ ){
+ /* Implement a co-routine that will return a single row of the result
+ ** set on each invocation.
+ */
+ int addrTop;
+ int addrEof;
+ pItem->regReturn = ++pParse->nMem;
+ addrEof = ++pParse->nMem;
+ /* Before coding the OP_Goto to jump to the start of the main routine,
+ ** ensure that the jump to the verify-schema routine has already
+ ** been coded. Otherwise, the verify-schema would likely be coded as
+ ** part of the co-routine. If the main routine then accessed the
+ ** database before invoking the co-routine for the first time (for
+ ** example to initialize a LIMIT register from a sub-select), it would
+ ** be doing so without having verified the schema version and obtained
+ ** the required db locks. See ticket d6b36be38. */
+ sqlite3CodeVerifySchema(pParse, -1);
+ sqlite3VdbeAddOp0(v, OP_Goto);
+ addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
+ sqlite3VdbeChangeP5(v, 1);
+ VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
+ pItem->addrFillSub = addrTop;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof);
+ sqlite3VdbeChangeP5(v, 1);
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+ explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+ sqlite3Select(pParse, pSub, &dest);
+ pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+ pItem->viaCoroutine = 1;
+ sqlite3VdbeChangeP2(v, addrTop, dest.iSdst);
+ sqlite3VdbeChangeP3(v, addrTop, dest.nSdst);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof);
+ sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn);
+ VdbeComment((v, "end %s", pItem->pTab->zName));
+ sqlite3VdbeJumpHere(v, addrTop-1);
+ sqlite3ClearTempRegCache(pParse);
+ }else{
+ /* Generate a subroutine that will fill an ephemeral table with
+ ** the content of this subquery. pItem->addrFillSub will point
+ ** to the address of the generated subroutine. pItem->regReturn
+ ** is a register allocated to hold the subroutine return address
+ */
+ int topAddr;
+ int onceAddr = 0;
+ int retAddr;
+ assert( pItem->addrFillSub==0 );
+ pItem->regReturn = ++pParse->nMem;
+ topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
+ pItem->addrFillSub = topAddr+1;
+ VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
+ if( pItem->isCorrelated==0 ){
+ /* If the subquery is no correlated and if we are not inside of
+ ** a trigger, then we only need to compute the value of the subquery
+ ** once. */
+ onceAddr = sqlite3CodeOnce(pParse);
+ }
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
+ explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+ sqlite3Select(pParse, pSub, &dest);
+ pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+ if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
+ retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
+ VdbeComment((v, "end %s", pItem->pTab->zName));
+ sqlite3VdbeChangeP1(v, topAddr, retAddr);
+ sqlite3ClearTempRegCache(pParse);
+ }
+ if( /*pParse->nErr ||*/ db->mallocFailed ){
+ goto select_end;
+ }
+ pParse->nHeight -= sqlite3SelectExprHeight(p);
+ pTabList = p->pSrc;
+ if( !IgnorableOrderby(pDest) ){
+ pOrderBy = p->pOrderBy;
+ }
+ }
+ pEList = p->pEList;
+#endif
+ pWhere = p->pWhere;
+ pGroupBy = p->pGroupBy;
+ pHaving = p->pHaving;
+ sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
+
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
+ /* If there is are a sequence of queries, do the earlier ones first.
+ */
+ if( p->pPrior ){
+ if( p->pRightmost==0 ){
+ Select *pLoop, *pRight = 0;
+ int cnt = 0;
+ int mxSelect;
+ for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
+ pLoop->pRightmost = p;
+ pLoop->pNext = pRight;
+ pRight = pLoop;
+ }
+ mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
+ if( mxSelect && cnt>mxSelect ){
+ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
+ goto select_end;
+ }
+ }
+ rc = multiSelect(pParse, p, pDest);
+ explainSetInteger(pParse->iSelectId, iRestoreSelectId);
+ return rc;
+ }
+#endif
+
+ /* If there is both a GROUP BY and an ORDER BY clause and they are
+ ** identical, then disable the ORDER BY clause since the GROUP BY
+ ** will cause elements to come out in the correct order. This is
+ ** an optimization - the correct answer should result regardless.
+ ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
+ ** to disable this optimization for testing purposes.
+ */
+ if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
+ && OptimizationEnabled(db, SQLITE_GroupByOrder) ){
+ pOrderBy = 0;
+ }
+
+ /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
+ ** if the select-list is the same as the ORDER BY list, then this query
+ ** can be rewritten as a GROUP BY. In other words, this:
+ **
+ ** SELECT DISTINCT xyz FROM ... ORDER BY xyz
+ **
+ ** is transformed to:
+ **
+ ** SELECT xyz FROM ... GROUP BY xyz
+ **
+ ** The second form is preferred as a single index (or temp-table) may be
+ ** used for both the ORDER BY and DISTINCT processing. As originally
+ ** written the query must use a temp-table for at least one of the ORDER
+ ** BY and DISTINCT, and an index or separate temp-table for the other.
+ */
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
+ && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
+ ){
+ p->selFlags &= ~SF_Distinct;
+ p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
+ pGroupBy = p->pGroupBy;
+ pOrderBy = 0;
+ /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
+ ** the sDistinct.isTnct is still set. Hence, isTnct represents the
+ ** original setting of the SF_Distinct flag, not the current setting */
+ assert( sDistinct.isTnct );
+ }
+
+ /* If there is an ORDER BY clause, then this sorting
+ ** index might end up being unused if the data can be
+ ** extracted in pre-sorted order. If that is the case, then the
+ ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
+ ** we figure out that the sorting index is not needed. The addrSortIndex
+ ** variable is used to facilitate that change.
+ */
+ if( pOrderBy ){
+ KeyInfo *pKeyInfo;
+ pKeyInfo = keyInfoFromExprList(pParse, pOrderBy);
+ pOrderBy->iECursor = pParse->nTab++;
+ p->addrOpenEphm[2] = addrSortIndex =
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ pOrderBy->iECursor, pOrderBy->nExpr+2, 0,
+ (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ }else{
+ addrSortIndex = -1;
+ }
+
+ /* If the output is destined for a temporary table, open that table.
+ */
+ if( pDest->eDest==SRT_EphemTab ){
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
+ }
+
+ /* Set the limiter.
+ */
+ iEnd = sqlite3VdbeMakeLabel(v);
+ p->nSelectRow = (double)LARGEST_INT64;
+ computeLimitRegisters(pParse, p, iEnd);
+ if( p->iLimit==0 && addrSortIndex>=0 ){
+ sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
+ p->selFlags |= SF_UseSorter;
+ }
+
+ /* Open a virtual index to use for the distinct set.
+ */
+ if( p->selFlags & SF_Distinct ){
+ sDistinct.tabTnct = pParse->nTab++;
+ sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ sDistinct.tabTnct, 0, 0,
+ (char*)keyInfoFromExprList(pParse, p->pEList),
+ P4_KEYINFO_HANDOFF);
+ sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
+ sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
+ }else{
+ sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
+ }
+
+ if( !isAgg && pGroupBy==0 ){
+ /* No aggregate functions and no GROUP BY clause */
+ ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
+
+ /* Begin the database scan. */
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
+ if( pWInfo==0 ) goto select_end;
+ if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
+ if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
+ if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
+
+ /* If sorting index that was created by a prior OP_OpenEphemeral
+ ** instruction ended up not being needed, then change the OP_OpenEphemeral
+ ** into an OP_Noop.
+ */
+ if( addrSortIndex>=0 && pOrderBy==0 ){
+ sqlite3VdbeChangeToNoop(v, addrSortIndex);
+ p->addrOpenEphm[2] = -1;
+ }
+
+ /* Use the standard inner loop. */
+ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest,
+ pWInfo->iContinue, pWInfo->iBreak);
+
+ /* End the database scan loop.
+ */
+ sqlite3WhereEnd(pWInfo);
+ }else{
+ /* This case when there exist aggregate functions or a GROUP BY clause
+ ** or both */
+ NameContext sNC; /* Name context for processing aggregate information */
+ int iAMem; /* First Mem address for storing current GROUP BY */
+ int iBMem; /* First Mem address for previous GROUP BY */
+ int iUseFlag; /* Mem address holding flag indicating that at least
+ ** one row of the input to the aggregator has been
+ ** processed */
+ int iAbortFlag; /* Mem address which causes query abort if positive */
+ int groupBySort; /* Rows come from source in GROUP BY order */
+ int addrEnd; /* End of processing for this SELECT */
+ int sortPTab = 0; /* Pseudotable used to decode sorting results */
+ int sortOut = 0; /* Output register from the sorter */
+
+ /* Remove any and all aliases between the result set and the
+ ** GROUP BY clause.
+ */
+ if( pGroupBy ){
+ int k; /* Loop counter */
+ struct ExprList_item *pItem; /* For looping over expression in a list */
+
+ for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
+ pItem->iAlias = 0;
+ }
+ for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
+ pItem->iAlias = 0;
+ }
+ if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
+ }else{
+ p->nSelectRow = (double)1;
+ }
+
+
+ /* Create a label to jump to when we want to abort the query */
+ addrEnd = sqlite3VdbeMakeLabel(v);
+
+ /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
+ ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
+ ** SELECT statement.
+ */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+ sNC.pAggInfo = &sAggInfo;
+ sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
+ sAggInfo.pGroupBy = pGroupBy;
+ sqlite3ExprAnalyzeAggList(&sNC, pEList);
+ sqlite3ExprAnalyzeAggList(&sNC, pOrderBy);
+ if( pHaving ){
+ sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
+ }
+ sAggInfo.nAccumulator = sAggInfo.nColumn;
+ for(i=0; i<sAggInfo.nFunc; i++){
+ assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
+ sNC.ncFlags |= NC_InAggFunc;
+ sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
+ sNC.ncFlags &= ~NC_InAggFunc;
+ }
+ if( db->mallocFailed ) goto select_end;
+
+ /* Processing for aggregates with GROUP BY is very different and
+ ** much more complex than aggregates without a GROUP BY.
+ */
+ if( pGroupBy ){
+ KeyInfo *pKeyInfo; /* Keying information for the group by clause */
+ int j1; /* A-vs-B comparision jump */
+ int addrOutputRow; /* Start of subroutine that outputs a result row */
+ int regOutputRow; /* Return address register for output subroutine */
+ int addrSetAbort; /* Set the abort flag and return */
+ int addrTopOfLoop; /* Top of the input loop */
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
+ int addrReset; /* Subroutine for resetting the accumulator */
+ int regReset; /* Return address register for reset subroutine */
+
+ /* If there is a GROUP BY clause we might need a sorting index to
+ ** implement it. Allocate that sorting index now. If it turns out
+ ** that we do not need it after all, the OP_SorterOpen instruction
+ ** will be converted into a Noop.
+ */
+ sAggInfo.sortingIdx = pParse->nTab++;
+ pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
+ sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
+ 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+
+ /* Initialize memory locations used by GROUP BY aggregate processing
+ */
+ iUseFlag = ++pParse->nMem;
+ iAbortFlag = ++pParse->nMem;
+ regOutputRow = ++pParse->nMem;
+ addrOutputRow = sqlite3VdbeMakeLabel(v);
+ regReset = ++pParse->nMem;
+ addrReset = sqlite3VdbeMakeLabel(v);
+ iAMem = pParse->nMem + 1;
+ pParse->nMem += pGroupBy->nExpr;
+ iBMem = pParse->nMem + 1;
+ pParse->nMem += pGroupBy->nExpr;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
+ VdbeComment((v, "clear abort flag"));
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
+ VdbeComment((v, "indicate accumulator empty"));
+ sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
+
+ /* Begin a loop that will extract all source rows in GROUP BY order.
+ ** This might involve two separate loops with an OP_Sort in between, or
+ ** it might be a single loop that uses an index to extract information
+ ** in the right order to begin with.
+ */
+ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0);
+ if( pWInfo==0 ) goto select_end;
+ if( pWInfo->nOBSat==pGroupBy->nExpr ){
+ /* The optimizer is able to deliver rows in group by order so
+ ** we do not have to sort. The OP_OpenEphemeral table will be
+ ** cancelled later because we still need to use the pKeyInfo
+ */
+ groupBySort = 0;
+ }else{
+ /* Rows are coming out in undetermined order. We have to push
+ ** each row into a sorting index, terminate the first loop,
+ ** then loop over the sorting index in order to get the output
+ ** in sorted order
+ */
+ int regBase;
+ int regRecord;
+ int nCol;
+ int nGroupBy;
+
+ explainTempTable(pParse,
+ (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
+ "DISTINCT" : "GROUP BY");
+
+ groupBySort = 1;
+ nGroupBy = pGroupBy->nExpr;
+ nCol = nGroupBy + 1;
+ j = nGroupBy+1;
+ for(i=0; i<sAggInfo.nColumn; i++){
+ if( sAggInfo.aCol[i].iSorterColumn>=j ){
+ nCol++;
+ j++;
+ }
+ }
+ regBase = sqlite3GetTempRange(pParse, nCol);
+ sqlite3ExprCacheClear(pParse);
+ sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0);
+ sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
+ j = nGroupBy+1;
+ for(i=0; i<sAggInfo.nColumn; i++){
+ struct AggInfo_col *pCol = &sAggInfo.aCol[i];
+ if( pCol->iSorterColumn>=j ){
+ int r1 = j + regBase;
+ int r2;
+
+ r2 = sqlite3ExprCodeGetColumn(pParse,
+ pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
+ if( r1!=r2 ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
+ }
+ j++;
+ }
+ }
+ regRecord = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord);
+ sqlite3ReleaseTempReg(pParse, regRecord);
+ sqlite3ReleaseTempRange(pParse, regBase, nCol);
+ sqlite3WhereEnd(pWInfo);
+ sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++;
+ sortOut = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
+ sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
+ VdbeComment((v, "GROUP BY sort"));
+ sAggInfo.useSortingIdx = 1;
+ sqlite3ExprCacheClear(pParse);
+ }
+
+ /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
+ ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
+ ** Then compare the current GROUP BY terms against the GROUP BY terms
+ ** from the previous row currently stored in a0, a1, a2...
+ */
+ addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
+ sqlite3ExprCacheClear(pParse);
+ if( groupBySort ){
+ sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut);
+ }
+ for(j=0; j<pGroupBy->nExpr; j++){
+ if( groupBySort ){
+ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
+ if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
+ }else{
+ sAggInfo.directMode = 1;
+ sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
+ }
+ }
+ sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
+ (char*)pKeyInfo, P4_KEYINFO);
+ j1 = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1);
+
+ /* Generate code that runs whenever the GROUP BY changes.
+ ** Changes in the GROUP BY are detected by the previous code
+ ** block. If there were no changes, this block is skipped.
+ **
+ ** This code copies current group by terms in b0,b1,b2,...
+ ** over to a0,a1,a2. It then calls the output subroutine
+ ** and resets the aggregate accumulator registers in preparation
+ ** for the next GROUP BY batch.
+ */
+ sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
+ VdbeComment((v, "output one row"));
+ sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd);
+ VdbeComment((v, "check abort flag"));
+ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
+ VdbeComment((v, "reset accumulator"));
+
+ /* Update the aggregate accumulators based on the content of
+ ** the current row
+ */
+ sqlite3VdbeJumpHere(v, j1);
+ updateAccumulator(pParse, &sAggInfo);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
+ VdbeComment((v, "indicate data in accumulator"));
+
+ /* End of the loop
+ */
+ if( groupBySort ){
+ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
+ }else{
+ sqlite3WhereEnd(pWInfo);
+ sqlite3VdbeChangeToNoop(v, addrSortingIdx);
+ }
+
+ /* Output the final row of result
+ */
+ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
+ VdbeComment((v, "output final row"));
+
+ /* Jump over the subroutines
+ */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd);
+
+ /* Generate a subroutine that outputs a single row of the result
+ ** set. This subroutine first looks at the iUseFlag. If iUseFlag
+ ** is less than or equal to zero, the subroutine is a no-op. If
+ ** the processing calls for the query to abort, this subroutine
+ ** increments the iAbortFlag memory location before returning in
+ ** order to signal the caller to abort.
+ */
+ addrSetAbort = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
+ VdbeComment((v, "set abort flag"));
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ sqlite3VdbeResolveLabel(v, addrOutputRow);
+ addrOutputRow = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
+ VdbeComment((v, "Groupby result generator entry point"));
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ finalizeAggFunctions(pParse, &sAggInfo);
+ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
+ &sDistinct, pDest,
+ addrOutputRow+1, addrSetAbort);
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ VdbeComment((v, "end groupby result generator"));
+
+ /* Generate a subroutine that will reset the group-by accumulator
+ */
+ sqlite3VdbeResolveLabel(v, addrReset);
+ resetAccumulator(pParse, &sAggInfo);
+ sqlite3VdbeAddOp1(v, OP_Return, regReset);
+
+ } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
+ else {
+ ExprList *pDel = 0;
+#ifndef SQLITE_OMIT_BTREECOUNT
+ Table *pTab;
+ if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
+ /* If isSimpleCount() returns a pointer to a Table structure, then
+ ** the SQL statement is of the form:
+ **
+ ** SELECT count(*) FROM <tbl>
+ **
+ ** where the Table structure returned represents table <tbl>.
+ **
+ ** This statement is so common that it is optimized specially. The
+ ** OP_Count instruction is executed either on the intkey table that
+ ** contains the data for table <tbl> or on one of its indexes. It
+ ** is better to execute the op on an index, as indexes are almost
+ ** always spread across less pages than their corresponding tables.
+ */
+ const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */
+ Index *pIdx; /* Iterator variable */
+ KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */
+ Index *pBest = 0; /* Best index found so far */
+ int iRoot = pTab->tnum; /* Root page of scanned b-tree */
+
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+
+ /* Search for the index that has the least amount of columns. If
+ ** there is such an index, and it has less columns than the table
+ ** does, then we can assume that it consumes less space on disk and
+ ** will therefore be cheaper to scan to determine the query result.
+ ** In this case set iRoot to the root page number of the index b-tree
+ ** and pKeyInfo to the KeyInfo structure required to navigate the
+ ** index.
+ **
+ ** (2011-04-15) Do not do a full scan of an unordered index.
+ **
+ ** In practice the KeyInfo structure will not be used. It is only
+ ** passed to keep OP_OpenRead happy.
+ */
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
+ pBest = pIdx;
+ }
+ }
+ if( pBest && pBest->nColumn<pTab->nCol ){
+ iRoot = pBest->tnum;
+ pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
+ }
+
+ /* Open a read-only cursor, execute the OP_Count, close the cursor. */
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb);
+ if( pKeyInfo ){
+ sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
+ }
+ sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
+ sqlite3VdbeAddOp1(v, OP_Close, iCsr);
+ explainSimpleCount(pParse, pTab, pBest);
+ }else
+#endif /* SQLITE_OMIT_BTREECOUNT */
+ {
+ /* Check if the query is of one of the following forms:
+ **
+ ** SELECT min(x) FROM ...
+ ** SELECT max(x) FROM ...
+ **
+ ** If it is, then ask the code in where.c to attempt to sort results
+ ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
+ ** If where.c is able to produce results sorted in this order, then
+ ** add vdbe code to break out of the processing loop after the
+ ** first iteration (since the first iteration of the loop is
+ ** guaranteed to operate on the row with the minimum or maximum
+ ** value of x, the only row required).
+ **
+ ** A special flag must be passed to sqlite3WhereBegin() to slightly
+ ** modify behavior as follows:
+ **
+ ** + If the query is a "SELECT min(x)", then the loop coded by
+ ** where.c should not iterate over any values with a NULL value
+ ** for x.
+ **
+ ** + The optimizer code in where.c (the thing that decides which
+ ** index or indices to use) should place a different priority on
+ ** satisfying the 'ORDER BY' clause than it does in other cases.
+ ** Refer to code and comments in where.c for details.
+ */
+ ExprList *pMinMax = 0;
+ u8 flag = WHERE_ORDERBY_NORMAL;
+
+ assert( p->pGroupBy==0 );
+ assert( flag==0 );
+ if( p->pHaving==0 ){
+ flag = minMaxQuery(&sAggInfo, &pMinMax);
+ }
+ assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
+
+ if( flag ){
+ pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
+ pDel = pMinMax;
+ if( pMinMax && !db->mallocFailed ){
+ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
+ pMinMax->a[0].pExpr->op = TK_COLUMN;
+ }
+ }
+
+ /* This case runs if the aggregate has no GROUP BY clause. The
+ ** processing is much simpler since there is only a single row
+ ** of output.
+ */
+ resetAccumulator(pParse, &sAggInfo);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
+ if( pWInfo==0 ){
+ sqlite3ExprListDelete(db, pDel);
+ goto select_end;
+ }
+ updateAccumulator(pParse, &sAggInfo);
+ assert( pMinMax==0 || pMinMax->nExpr==1 );
+ if( pWInfo->nOBSat>0 ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
+ VdbeComment((v, "%s() by index",
+ (flag==WHERE_ORDERBY_MIN?"min":"max")));
+ }
+ sqlite3WhereEnd(pWInfo);
+ finalizeAggFunctions(pParse, &sAggInfo);
+ }
+
+ pOrderBy = 0;
+ sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0,
+ pDest, addrEnd, addrEnd);
+ sqlite3ExprListDelete(db, pDel);
+ }
+ sqlite3VdbeResolveLabel(v, addrEnd);
+
+ } /* endif aggregate query */
+
+ if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
+ explainTempTable(pParse, "DISTINCT");
+ }
+
+ /* If there is an ORDER BY clause, then we need to sort the results
+ ** and send them to the callback one by one.
+ */
+ if( pOrderBy ){
+ explainTempTable(pParse, "ORDER BY");
+ generateSortTail(pParse, p, v, pEList->nExpr, pDest);
+ }
+
+ /* Jump here to skip this query
+ */
+ sqlite3VdbeResolveLabel(v, iEnd);
+
+ /* The SELECT was successfully coded. Set the return code to 0
+ ** to indicate no errors.
+ */
+ rc = 0;
+
+ /* Control jumps to here if an error is encountered above, or upon
+ ** successful coding of the SELECT.
+ */
+select_end:
+ explainSetInteger(pParse->iSelectId, iRestoreSelectId);
+
+ /* Identify column names if results of the SELECT are to be output.
+ */
+ if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
+ generateColumnNames(pParse, pTabList, pEList);
+ }
+
+ sqlite3DbFree(db, sAggInfo.aCol);
+ sqlite3DbFree(db, sAggInfo.aFunc);
+ return rc;
+}
+
+#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
+/*
+** Generate a human-readable description of a the Select object.
+*/
+static void explainOneSelect(Vdbe *pVdbe, Select *p){
+ sqlite3ExplainPrintf(pVdbe, "SELECT ");
+ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
+ if( p->selFlags & SF_Distinct ){
+ sqlite3ExplainPrintf(pVdbe, "DISTINCT ");
+ }
+ if( p->selFlags & SF_Aggregate ){
+ sqlite3ExplainPrintf(pVdbe, "agg_flag ");
+ }
+ sqlite3ExplainNL(pVdbe);
+ sqlite3ExplainPrintf(pVdbe, " ");
+ }
+ sqlite3ExplainExprList(pVdbe, p->pEList);
+ sqlite3ExplainNL(pVdbe);
+ if( p->pSrc && p->pSrc->nSrc ){
+ int i;
+ sqlite3ExplainPrintf(pVdbe, "FROM ");
+ sqlite3ExplainPush(pVdbe);
+ for(i=0; i<p->pSrc->nSrc; i++){
+ struct SrcList_item *pItem = &p->pSrc->a[i];
+ sqlite3ExplainPrintf(pVdbe, "{%d,*} = ", pItem->iCursor);
+ if( pItem->pSelect ){
+ sqlite3ExplainSelect(pVdbe, pItem->pSelect);
+ if( pItem->pTab ){
+ sqlite3ExplainPrintf(pVdbe, " (tabname=%s)", pItem->pTab->zName);
+ }
+ }else if( pItem->zName ){
+ sqlite3ExplainPrintf(pVdbe, "%s", pItem->zName);
+ }
+ if( pItem->zAlias ){
+ sqlite3ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias);
+ }
+ if( pItem->jointype & JT_LEFT ){
+ sqlite3ExplainPrintf(pVdbe, " LEFT-JOIN");
+ }
+ sqlite3ExplainNL(pVdbe);
+ }
+ sqlite3ExplainPop(pVdbe);
+ }
+ if( p->pWhere ){
+ sqlite3ExplainPrintf(pVdbe, "WHERE ");
+ sqlite3ExplainExpr(pVdbe, p->pWhere);
+ sqlite3ExplainNL(pVdbe);
+ }
+ if( p->pGroupBy ){
+ sqlite3ExplainPrintf(pVdbe, "GROUPBY ");
+ sqlite3ExplainExprList(pVdbe, p->pGroupBy);
+ sqlite3ExplainNL(pVdbe);
+ }
+ if( p->pHaving ){
+ sqlite3ExplainPrintf(pVdbe, "HAVING ");
+ sqlite3ExplainExpr(pVdbe, p->pHaving);
+ sqlite3ExplainNL(pVdbe);
+ }
+ if( p->pOrderBy ){
+ sqlite3ExplainPrintf(pVdbe, "ORDERBY ");
+ sqlite3ExplainExprList(pVdbe, p->pOrderBy);
+ sqlite3ExplainNL(pVdbe);
+ }
+ if( p->pLimit ){
+ sqlite3ExplainPrintf(pVdbe, "LIMIT ");
+ sqlite3ExplainExpr(pVdbe, p->pLimit);
+ sqlite3ExplainNL(pVdbe);
+ }
+ if( p->pOffset ){
+ sqlite3ExplainPrintf(pVdbe, "OFFSET ");
+ sqlite3ExplainExpr(pVdbe, p->pOffset);
+ sqlite3ExplainNL(pVdbe);
+ }
+}
+SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
+ if( p==0 ){
+ sqlite3ExplainPrintf(pVdbe, "(null-select)");
+ return;
+ }
+ while( p->pPrior ){
+ p->pPrior->pNext = p;
+ p = p->pPrior;
+ }
+ sqlite3ExplainPush(pVdbe);
+ while( p ){
+ explainOneSelect(pVdbe, p);
+ p = p->pNext;
+ if( p==0 ) break;
+ sqlite3ExplainNL(pVdbe);
+ sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op));
+ }
+ sqlite3ExplainPrintf(pVdbe, "END");
+ sqlite3ExplainPop(pVdbe);
+}
+
+/* End of the structure debug printing code
+*****************************************************************************/
+#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */
+
+/************** End of select.c **********************************************/
+/************** Begin file table.c *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the sqlite3_get_table() and sqlite3_free_table()
+** interface routines. These are just wrappers around the main
+** interface routine of sqlite3_exec().
+**
+** These routines are in a separate files so that they will not be linked
+** if they are not used.
+*/
+/* #include <stdlib.h> */
+/* #include <string.h> */
+
+#ifndef SQLITE_OMIT_GET_TABLE
+
+/*
+** This structure is used to pass data from sqlite3_get_table() through
+** to the callback function is uses to build the result.
+*/
+typedef struct TabResult {
+ char **azResult; /* Accumulated output */
+ char *zErrMsg; /* Error message text, if an error occurs */
+ int nAlloc; /* Slots allocated for azResult[] */
+ int nRow; /* Number of rows in the result */
+ int nColumn; /* Number of columns in the result */
+ int nData; /* Slots used in azResult[]. (nRow+1)*nColumn */
+ int rc; /* Return code from sqlite3_exec() */
+} TabResult;
+
+/*
+** This routine is called once for each row in the result table. Its job
+** is to fill in the TabResult structure appropriately, allocating new
+** memory as necessary.
+*/
+static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
+ TabResult *p = (TabResult*)pArg; /* Result accumulator */
+ int need; /* Slots needed in p->azResult[] */
+ int i; /* Loop counter */
+ char *z; /* A single column of result */
+
+ /* Make sure there is enough space in p->azResult to hold everything
+ ** we need to remember from this invocation of the callback.
+ */
+ if( p->nRow==0 && argv!=0 ){
+ need = nCol*2;
+ }else{
+ need = nCol;
+ }
+ if( p->nData + need > p->nAlloc ){
+ char **azNew;
+ p->nAlloc = p->nAlloc*2 + need;
+ azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc );
+ if( azNew==0 ) goto malloc_failed;
+ p->azResult = azNew;
+ }
+
+ /* If this is the first row, then generate an extra row containing
+ ** the names of all columns.
+ */
+ if( p->nRow==0 ){
+ p->nColumn = nCol;
+ for(i=0; i<nCol; i++){
+ z = sqlite3_mprintf("%s", colv[i]);
+ if( z==0 ) goto malloc_failed;
+ p->azResult[p->nData++] = z;
+ }
+ }else if( p->nColumn!=nCol ){
+ sqlite3_free(p->zErrMsg);
+ p->zErrMsg = sqlite3_mprintf(
+ "sqlite3_get_table() called with two or more incompatible queries"
+ );
+ p->rc = SQLITE_ERROR;
+ return 1;
+ }
+
+ /* Copy over the row data
+ */
+ if( argv!=0 ){
+ for(i=0; i<nCol; i++){
+ if( argv[i]==0 ){
+ z = 0;
+ }else{
+ int n = sqlite3Strlen30(argv[i])+1;
+ z = sqlite3_malloc( n );
+ if( z==0 ) goto malloc_failed;
+ memcpy(z, argv[i], n);
+ }
+ p->azResult[p->nData++] = z;
+ }
+ p->nRow++;
+ }
+ return 0;
+
+malloc_failed:
+ p->rc = SQLITE_NOMEM;
+ return 1;
+}
+
+/*
+** Query the database. But instead of invoking a callback for each row,
+** malloc() for space to hold the result and return the entire results
+** at the conclusion of the call.
+**
+** The result that is written to ***pazResult is held in memory obtained
+** from malloc(). But the caller cannot free this memory directly.
+** Instead, the entire table should be passed to sqlite3_free_table() when
+** the calling procedure is finished using it.
+*/
+SQLITE_API int sqlite3_get_table(
+ sqlite3 *db, /* The database on which the SQL executes */
+ const char *zSql, /* The SQL to be executed */
+ char ***pazResult, /* Write the result table here */
+ int *pnRow, /* Write the number of rows in the result here */
+ int *pnColumn, /* Write the number of columns of result here */
+ char **pzErrMsg /* Write error messages here */
+){
+ int rc;
+ TabResult res;
+
+ *pazResult = 0;
+ if( pnColumn ) *pnColumn = 0;
+ if( pnRow ) *pnRow = 0;
+ if( pzErrMsg ) *pzErrMsg = 0;
+ res.zErrMsg = 0;
+ res.nRow = 0;
+ res.nColumn = 0;
+ res.nData = 1;
+ res.nAlloc = 20;
+ res.rc = SQLITE_OK;
+ res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc );
+ if( res.azResult==0 ){
+ db->errCode = SQLITE_NOMEM;
+ return SQLITE_NOMEM;
+ }
+ res.azResult[0] = 0;
+ rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
+ assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
+ res.azResult[0] = SQLITE_INT_TO_PTR(res.nData);
+ if( (rc&0xff)==SQLITE_ABORT ){
+ sqlite3_free_table(&res.azResult[1]);
+ if( res.zErrMsg ){
+ if( pzErrMsg ){
+ sqlite3_free(*pzErrMsg);
+ *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
+ }
+ sqlite3_free(res.zErrMsg);
+ }
+ db->errCode = res.rc; /* Assume 32-bit assignment is atomic */
+ return res.rc;
+ }
+ sqlite3_free(res.zErrMsg);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free_table(&res.azResult[1]);
+ return rc;
+ }
+ if( res.nAlloc>res.nData ){
+ char **azNew;
+ azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData );
+ if( azNew==0 ){
+ sqlite3_free_table(&res.azResult[1]);
+ db->errCode = SQLITE_NOMEM;
+ return SQLITE_NOMEM;
+ }
+ res.azResult = azNew;
+ }
+ *pazResult = &res.azResult[1];
+ if( pnColumn ) *pnColumn = res.nColumn;
+ if( pnRow ) *pnRow = res.nRow;
+ return rc;
+}
+
+/*
+** This routine frees the space the sqlite3_get_table() malloced.
+*/
+SQLITE_API void sqlite3_free_table(
+ char **azResult /* Result returned from from sqlite3_get_table() */
+){
+ if( azResult ){
+ int i, n;
+ azResult--;
+ assert( azResult!=0 );
+ n = SQLITE_PTR_TO_INT(azResult[0]);
+ for(i=1; i<n; i++){ if( azResult[i] ) sqlite3_free(azResult[i]); }
+ sqlite3_free(azResult);
+ }
+}
+
+#endif /* SQLITE_OMIT_GET_TABLE */
+
+/************** End of table.c ***********************************************/
+/************** Begin file trigger.c *****************************************/
+/*
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the implementation for TRIGGERs
+*/
+
+#ifndef SQLITE_OMIT_TRIGGER
+/*
+** Delete a linked list of TriggerStep structures.
+*/
+SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
+ while( pTriggerStep ){
+ TriggerStep * pTmp = pTriggerStep;
+ pTriggerStep = pTriggerStep->pNext;
+
+ sqlite3ExprDelete(db, pTmp->pWhere);
+ sqlite3ExprListDelete(db, pTmp->pExprList);
+ sqlite3SelectDelete(db, pTmp->pSelect);
+ sqlite3IdListDelete(db, pTmp->pIdList);
+
+ sqlite3DbFree(db, pTmp);
+ }
+}
+
+/*
+** Given table pTab, return a list of all the triggers attached to
+** the table. The list is connected by Trigger.pNext pointers.
+**
+** All of the triggers on pTab that are in the same database as pTab
+** are already attached to pTab->pTrigger. But there might be additional
+** triggers on pTab in the TEMP schema. This routine prepends all
+** TEMP triggers on pTab to the beginning of the pTab->pTrigger list
+** and returns the combined list.
+**
+** To state it another way: This routine returns a list of all triggers
+** that fire off of pTab. The list will include any TEMP triggers on
+** pTab as well as the triggers lised in pTab->pTrigger.
+*/
+SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
+ Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
+ Trigger *pList = 0; /* List of triggers to return */
+
+ if( pParse->disableTriggers ){
+ return 0;
+ }
+
+ if( pTmpSchema!=pTab->pSchema ){
+ HashElem *p;
+ assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
+ for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
+ Trigger *pTrig = (Trigger *)sqliteHashData(p);
+ if( pTrig->pTabSchema==pTab->pSchema
+ && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
+ ){
+ pTrig->pNext = (pList ? pList : pTab->pTrigger);
+ pList = pTrig;
+ }
+ }
+ }
+
+ return (pList ? pList : pTab->pTrigger);
+}
+
+/*
+** This is called by the parser when it sees a CREATE TRIGGER statement
+** up to the point of the BEGIN before the trigger actions. A Trigger
+** structure is generated based on the information available and stored
+** in pParse->pNewTrigger. After the trigger actions have been parsed, the
+** sqlite3FinishTrigger() function is called to complete the trigger
+** construction process.
+*/
+SQLITE_PRIVATE void sqlite3BeginTrigger(
+ Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
+ Token *pName1, /* The name of the trigger */
+ Token *pName2, /* The name of the trigger */
+ int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
+ int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
+ IdList *pColumns, /* column list if this is an UPDATE OF trigger */
+ SrcList *pTableName,/* The name of the table/view the trigger applies to */
+ Expr *pWhen, /* WHEN clause */
+ int isTemp, /* True if the TEMPORARY keyword is present */
+ int noErr /* Suppress errors if the trigger already exists */
+){
+ Trigger *pTrigger = 0; /* The new trigger */
+ Table *pTab; /* Table that the trigger fires off of */
+ char *zName = 0; /* Name of the trigger */
+ sqlite3 *db = pParse->db; /* The database connection */
+ int iDb; /* The database to store the trigger in */
+ Token *pName; /* The unqualified db name */
+ DbFixer sFix; /* State vector for the DB fixer */
+ int iTabDb; /* Index of the database holding pTab */
+
+ assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */
+ assert( pName2!=0 );
+ assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE );
+ assert( op>0 && op<0xff );
+ if( isTemp ){
+ /* If TEMP was specified, then the trigger name may not be qualified. */
+ if( pName2->n>0 ){
+ sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
+ goto trigger_cleanup;
+ }
+ iDb = 1;
+ pName = pName1;
+ }else{
+ /* Figure out the db that the trigger will be created in */
+ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
+ if( iDb<0 ){
+ goto trigger_cleanup;
+ }
+ }
+ if( !pTableName || db->mallocFailed ){
+ goto trigger_cleanup;
+ }
+
+ /* A long-standing parser bug is that this syntax was allowed:
+ **
+ ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab ....
+ ** ^^^^^^^^
+ **
+ ** To maintain backwards compatibility, ignore the database
+ ** name on pTableName if we are reparsing our of SQLITE_MASTER.
+ */
+ if( db->init.busy && iDb!=1 ){
+ sqlite3DbFree(db, pTableName->a[0].zDatabase);
+ pTableName->a[0].zDatabase = 0;
+ }
+
+ /* If the trigger name was unqualified, and the table is a temp table,
+ ** then set iDb to 1 to create the trigger in the temporary database.
+ ** If sqlite3SrcListLookup() returns 0, indicating the table does not
+ ** exist, the error is caught by the block below.
+ */
+ pTab = sqlite3SrcListLookup(pParse, pTableName);
+ if( db->init.busy==0 && pName2->n==0 && pTab
+ && pTab->pSchema==db->aDb[1].pSchema ){
+ iDb = 1;
+ }
+
+ /* Ensure the table name matches database name and that the table exists */
+ if( db->mallocFailed ) goto trigger_cleanup;
+ assert( pTableName->nSrc==1 );
+ if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
+ sqlite3FixSrcList(&sFix, pTableName) ){
+ goto trigger_cleanup;
+ }
+ pTab = sqlite3SrcListLookup(pParse, pTableName);
+ if( !pTab ){
+ /* The table does not exist. */
+ if( db->init.iDb==1 ){
+ /* Ticket #3810.
+ ** Normally, whenever a table is dropped, all associated triggers are
+ ** dropped too. But if a TEMP trigger is created on a non-TEMP table
+ ** and the table is dropped by a different database connection, the
+ ** trigger is not visible to the database connection that does the
+ ** drop so the trigger cannot be dropped. This results in an
+ ** "orphaned trigger" - a trigger whose associated table is missing.
+ */
+ db->init.orphanTrigger = 1;
+ }
+ goto trigger_cleanup;
+ }
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
+ goto trigger_cleanup;
+ }
+
+ /* Check that the trigger name is not reserved and that no trigger of the
+ ** specified name exists */
+ zName = sqlite3NameFromToken(db, pName);
+ if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+ goto trigger_cleanup;
+ }
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),
+ zName, sqlite3Strlen30(zName)) ){
+ if( !noErr ){
+ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
+ }else{
+ assert( !db->init.busy );
+ sqlite3CodeVerifySchema(pParse, iDb);
+ }
+ goto trigger_cleanup;
+ }
+
+ /* Do not create a trigger on a system table */
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
+ sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
+ pParse->nErr++;
+ goto trigger_cleanup;
+ }
+
+ /* INSTEAD of triggers are only for views and views only support INSTEAD
+ ** of triggers.
+ */
+ if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
+ sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
+ (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
+ goto trigger_cleanup;
+ }
+ if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
+ sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
+ " trigger on table: %S", pTableName, 0);
+ goto trigger_cleanup;
+ }
+ iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ {
+ int code = SQLITE_CREATE_TRIGGER;
+ const char *zDb = db->aDb[iTabDb].zName;
+ const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
+ if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
+ if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
+ goto trigger_cleanup;
+ }
+ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
+ goto trigger_cleanup;
+ }
+ }
+#endif
+
+ /* INSTEAD OF triggers can only appear on views and BEFORE triggers
+ ** cannot appear on views. So we might as well translate every
+ ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code
+ ** elsewhere.
+ */
+ if (tr_tm == TK_INSTEAD){
+ tr_tm = TK_BEFORE;
+ }
+
+ /* Build the Trigger object */
+ pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
+ if( pTrigger==0 ) goto trigger_cleanup;
+ pTrigger->zName = zName;
+ zName = 0;
+ pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
+ pTrigger->pSchema = db->aDb[iDb].pSchema;
+ pTrigger->pTabSchema = pTab->pSchema;
+ pTrigger->op = (u8)op;
+ pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
+ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
+ pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
+ assert( pParse->pNewTrigger==0 );
+ pParse->pNewTrigger = pTrigger;
+
+trigger_cleanup:
+ sqlite3DbFree(db, zName);
+ sqlite3SrcListDelete(db, pTableName);
+ sqlite3IdListDelete(db, pColumns);
+ sqlite3ExprDelete(db, pWhen);
+ if( !pParse->pNewTrigger ){
+ sqlite3DeleteTrigger(db, pTrigger);
+ }else{
+ assert( pParse->pNewTrigger==pTrigger );
+ }
+}
+
+/*
+** This routine is called after all of the trigger actions have been parsed
+** in order to complete the process of building the trigger.
+*/
+SQLITE_PRIVATE void sqlite3FinishTrigger(
+ Parse *pParse, /* Parser context */
+ TriggerStep *pStepList, /* The triggered program */
+ Token *pAll /* Token that describes the complete CREATE TRIGGER */
+){
+ Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
+ char *zName; /* Name of trigger */
+ sqlite3 *db = pParse->db; /* The database */
+ DbFixer sFix; /* Fixer object */
+ int iDb; /* Database containing the trigger */
+ Token nameToken; /* Trigger name for error reporting */
+
+ pParse->pNewTrigger = 0;
+ if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
+ zName = pTrig->zName;
+ iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
+ pTrig->step_list = pStepList;
+ while( pStepList ){
+ pStepList->pTrig = pTrig;
+ pStepList = pStepList->pNext;
+ }
+ nameToken.z = pTrig->zName;
+ nameToken.n = sqlite3Strlen30(nameToken.z);
+ if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
+ && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
+ goto triggerfinish_cleanup;
+ }
+
+ /* if we are not initializing,
+ ** build the sqlite_master entry
+ */
+ if( !db->init.busy ){
+ Vdbe *v;
+ char *z;
+
+ /* Make an entry in the sqlite_master table */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto triggerfinish_cleanup;
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
+ sqlite3NestedParse(pParse,
+ "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
+ pTrig->table, z);
+ sqlite3DbFree(db, z);
+ sqlite3ChangeCookie(pParse, iDb);
+ sqlite3VdbeAddParseSchemaOp(v, iDb,
+ sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
+ }
+
+ if( db->init.busy ){
+ Trigger *pLink = pTrig;
+ Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig);
+ if( pTrig ){
+ db->mallocFailed = 1;
+ }else if( pLink->pSchema==pLink->pTabSchema ){
+ Table *pTab;
+ int n = sqlite3Strlen30(pLink->table);
+ pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n);
+ assert( pTab!=0 );
+ pLink->pNext = pTab->pTrigger;
+ pTab->pTrigger = pLink;
+ }
+ }
+
+triggerfinish_cleanup:
+ sqlite3DeleteTrigger(db, pTrig);
+ assert( !pParse->pNewTrigger );
+ sqlite3DeleteTriggerStep(db, pStepList);
+}
+
+/*
+** Turn a SELECT statement (that the pSelect parameter points to) into
+** a trigger step. Return a pointer to a TriggerStep structure.
+**
+** The parser calls this routine when it finds a SELECT statement in
+** body of a TRIGGER.
+*/
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
+ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
+ if( pTriggerStep==0 ) {
+ sqlite3SelectDelete(db, pSelect);
+ return 0;
+ }
+ pTriggerStep->op = TK_SELECT;
+ pTriggerStep->pSelect = pSelect;
+ pTriggerStep->orconf = OE_Default;
+ return pTriggerStep;
+}
+
+/*
+** Allocate space to hold a new trigger step. The allocated space
+** holds both the TriggerStep object and the TriggerStep.target.z string.
+**
+** If an OOM error occurs, NULL is returned and db->mallocFailed is set.
+*/
+static TriggerStep *triggerStepAllocate(
+ sqlite3 *db, /* Database connection */
+ u8 op, /* Trigger opcode */
+ Token *pName /* The target name */
+){
+ TriggerStep *pTriggerStep;
+
+ pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n);
+ if( pTriggerStep ){
+ char *z = (char*)&pTriggerStep[1];
+ memcpy(z, pName->z, pName->n);
+ pTriggerStep->target.z = z;
+ pTriggerStep->target.n = pName->n;
+ pTriggerStep->op = op;
+ }
+ return pTriggerStep;
+}
+
+/*
+** Build a trigger step out of an INSERT statement. Return a pointer
+** to the new trigger step.
+**
+** The parser calls this routine when it sees an INSERT inside the
+** body of a trigger.
+*/
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
+ sqlite3 *db, /* The database connection */
+ Token *pTableName, /* Name of the table into which we insert */
+ IdList *pColumn, /* List of columns in pTableName to insert into */
+ ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
+ Select *pSelect, /* A SELECT statement that supplies values */
+ u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
+){
+ TriggerStep *pTriggerStep;
+
+ assert(pEList == 0 || pSelect == 0);
+ assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
+
+ pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
+ if( pTriggerStep ){
+ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ pTriggerStep->pIdList = pColumn;
+ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
+ pTriggerStep->orconf = orconf;
+ }else{
+ sqlite3IdListDelete(db, pColumn);
+ }
+ sqlite3ExprListDelete(db, pEList);
+ sqlite3SelectDelete(db, pSelect);
+
+ return pTriggerStep;
+}
+
+/*
+** Construct a trigger step that implements an UPDATE statement and return
+** a pointer to that trigger step. The parser calls this routine when it
+** sees an UPDATE statement inside the body of a CREATE TRIGGER.
+*/
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
+ sqlite3 *db, /* The database connection */
+ Token *pTableName, /* Name of the table to be updated */
+ ExprList *pEList, /* The SET clause: list of column and new values */
+ Expr *pWhere, /* The WHERE clause */
+ u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
+){
+ TriggerStep *pTriggerStep;
+
+ pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName);
+ if( pTriggerStep ){
+ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
+ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
+ pTriggerStep->orconf = orconf;
+ }
+ sqlite3ExprListDelete(db, pEList);
+ sqlite3ExprDelete(db, pWhere);
+ return pTriggerStep;
+}
+
+/*
+** Construct a trigger step that implements a DELETE statement and return
+** a pointer to that trigger step. The parser calls this routine when it
+** sees a DELETE statement inside the body of a CREATE TRIGGER.
+*/
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(
+ sqlite3 *db, /* Database connection */
+ Token *pTableName, /* The table from which rows are deleted */
+ Expr *pWhere /* The WHERE clause */
+){
+ TriggerStep *pTriggerStep;
+
+ pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName);
+ if( pTriggerStep ){
+ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
+ pTriggerStep->orconf = OE_Default;
+ }
+ sqlite3ExprDelete(db, pWhere);
+ return pTriggerStep;
+}
+
+/*
+** Recursively delete a Trigger structure
+*/
+SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
+ if( pTrigger==0 ) return;
+ sqlite3DeleteTriggerStep(db, pTrigger->step_list);
+ sqlite3DbFree(db, pTrigger->zName);
+ sqlite3DbFree(db, pTrigger->table);
+ sqlite3ExprDelete(db, pTrigger->pWhen);
+ sqlite3IdListDelete(db, pTrigger->pColumns);
+ sqlite3DbFree(db, pTrigger);
+}
+
+/*
+** This function is called to drop a trigger from the database schema.
+**
+** This may be called directly from the parser and therefore identifies
+** the trigger by name. The sqlite3DropTriggerPtr() routine does the
+** same job as this routine except it takes a pointer to the trigger
+** instead of the trigger name.
+**/
+SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
+ Trigger *pTrigger = 0;
+ int i;
+ const char *zDb;
+ const char *zName;
+ int nName;
+ sqlite3 *db = pParse->db;
+
+ if( db->mallocFailed ) goto drop_trigger_cleanup;
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ goto drop_trigger_cleanup;
+ }
+
+ assert( pName->nSrc==1 );
+ zDb = pName->a[0].zDatabase;
+ zName = pName->a[0].zName;
+ nName = sqlite3Strlen30(zName);
+ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
+ for(i=OMIT_TEMPDB; i<db->nDb; i++){
+ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
+ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
+ assert( sqlite3SchemaMutexHeld(db, j, 0) );
+ pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
+ if( pTrigger ) break;
+ }
+ if( !pTrigger ){
+ if( !noErr ){
+ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+ }else{
+ sqlite3CodeVerifyNamedSchema(pParse, zDb);
+ }
+ pParse->checkSchema = 1;
+ goto drop_trigger_cleanup;
+ }
+ sqlite3DropTriggerPtr(pParse, pTrigger);
+
+drop_trigger_cleanup:
+ sqlite3SrcListDelete(db, pName);
+}
+
+/*
+** Return a pointer to the Table structure for the table that a trigger
+** is set on.
+*/
+static Table *tableOfTrigger(Trigger *pTrigger){
+ int n = sqlite3Strlen30(pTrigger->table);
+ return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
+}
+
+
+/*
+** Drop a trigger given a pointer to that trigger.
+*/
+SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
+ Table *pTable;
+ Vdbe *v;
+ sqlite3 *db = pParse->db;
+ int iDb;
+
+ iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
+ assert( iDb>=0 && iDb<db->nDb );
+ pTable = tableOfTrigger(pTrigger);
+ assert( pTable );
+ assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ {
+ int code = SQLITE_DROP_TRIGGER;
+ const char *zDb = db->aDb[iDb].zName;
+ const char *zTab = SCHEMA_TABLE(iDb);
+ if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
+ if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) ||
+ sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
+ return;
+ }
+ }
+#endif
+
+ /* Generate code to destroy the database record of the trigger.
+ */
+ assert( pTable!=0 );
+ if( (v = sqlite3GetVdbe(pParse))!=0 ){
+ int base;
+ static const VdbeOpList dropTrigger[] = {
+ { OP_Rewind, 0, ADDR(9), 0},
+ { OP_String8, 0, 1, 0}, /* 1 */
+ { OP_Column, 0, 1, 2},
+ { OP_Ne, 2, ADDR(8), 1},
+ { OP_String8, 0, 1, 0}, /* 4: "trigger" */
+ { OP_Column, 0, 0, 2},
+ { OP_Ne, 2, ADDR(8), 1},
+ { OP_Delete, 0, 0, 0},
+ { OP_Next, 0, ADDR(1), 0}, /* 8 */
+ };
+
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3OpenMasterTable(pParse, iDb);
+ base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
+ sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT);
+ sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
+ sqlite3ChangeCookie(pParse, iDb);
+ sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
+ sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
+ if( pParse->nMem<3 ){
+ pParse->nMem = 3;
+ }
+ }
+}
+
+/*
+** Remove a trigger from the hash tables of the sqlite* pointer.
+*/
+SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
+ Trigger *pTrigger;
+ Hash *pHash;
+
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ pHash = &(db->aDb[iDb].pSchema->trigHash);
+ pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0);
+ if( ALWAYS(pTrigger) ){
+ if( pTrigger->pSchema==pTrigger->pTabSchema ){
+ Table *pTab = tableOfTrigger(pTrigger);
+ Trigger **pp;
+ for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
+ *pp = (*pp)->pNext;
+ }
+ sqlite3DeleteTrigger(db, pTrigger);
+ db->flags |= SQLITE_InternChanges;
+ }
+}
+
+/*
+** pEList is the SET clause of an UPDATE statement. Each entry
+** in pEList is of the format <id>=<expr>. If any of the entries
+** in pEList have an <id> which matches an identifier in pIdList,
+** then return TRUE. If pIdList==NULL, then it is considered a
+** wildcard that matches anything. Likewise if pEList==NULL then
+** it matches anything so always return true. Return false only
+** if there is no match.
+*/
+static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
+ int e;
+ if( pIdList==0 || NEVER(pEList==0) ) return 1;
+ for(e=0; e<pEList->nExpr; e++){
+ if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Return a list of all triggers on table pTab if there exists at least
+** one trigger that must be fired when an operation of type 'op' is
+** performed on the table, and, if that operation is an UPDATE, if at
+** least one of the columns in pChanges is being modified.
+*/
+SQLITE_PRIVATE Trigger *sqlite3TriggersExist(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* The table the contains the triggers */
+ int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
+ ExprList *pChanges, /* Columns that change in an UPDATE statement */
+ int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
+){
+ int mask = 0;
+ Trigger *pList = 0;
+ Trigger *p;
+
+ if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){
+ pList = sqlite3TriggerList(pParse, pTab);
+ }
+ assert( pList==0 || IsVirtual(pTab)==0 );
+ for(p=pList; p; p=p->pNext){
+ if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
+ mask |= p->tr_tm;
+ }
+ }
+ if( pMask ){
+ *pMask = mask;
+ }
+ return (mask ? pList : 0);
+}
+
+/*
+** Convert the pStep->target token into a SrcList and return a pointer
+** to that SrcList.
+**
+** This routine adds a specific database name, if needed, to the target when
+** forming the SrcList. This prevents a trigger in one database from
+** referring to a target in another database. An exception is when the
+** trigger is in TEMP in which case it can refer to any other database it
+** wants.
+*/
+static SrcList *targetSrcList(
+ Parse *pParse, /* The parsing context */
+ TriggerStep *pStep /* The trigger containing the target token */
+){
+ int iDb; /* Index of the database to use */
+ SrcList *pSrc; /* SrcList to be returned */
+
+ pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
+ if( pSrc ){
+ assert( pSrc->nSrc>0 );
+ assert( pSrc->a!=0 );
+ iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
+ if( iDb==0 || iDb>=2 ){
+ sqlite3 *db = pParse->db;
+ assert( iDb<pParse->db->nDb );
+ pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
+ }
+ }
+ return pSrc;
+}
+
+/*
+** Generate VDBE code for the statements inside the body of a single
+** trigger.
+*/
+static int codeTriggerProgram(
+ Parse *pParse, /* The parser context */
+ TriggerStep *pStepList, /* List of statements inside the trigger body */
+ int orconf /* Conflict algorithm. (OE_Abort, etc) */
+){
+ TriggerStep *pStep;
+ Vdbe *v = pParse->pVdbe;
+ sqlite3 *db = pParse->db;
+
+ assert( pParse->pTriggerTab && pParse->pToplevel );
+ assert( pStepList );
+ assert( v!=0 );
+ for(pStep=pStepList; pStep; pStep=pStep->pNext){
+ /* Figure out the ON CONFLICT policy that will be used for this step
+ ** of the trigger program. If the statement that caused this trigger
+ ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use
+ ** the ON CONFLICT policy that was specified as part of the trigger
+ ** step statement. Example:
+ **
+ ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN;
+ ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
+ ** END;
+ **
+ ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy
+ ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
+ */
+ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
+
+ /* Clear the cookieGoto flag. When coding triggers, the cookieGoto
+ ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
+ ** that it is not safe to refactor constants (this happens after the
+ ** start of the first loop in the SQL statement is coded - at that
+ ** point code may be conditionally executed, so it is no longer safe to
+ ** initialize constant register values). */
+ assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
+ pParse->cookieGoto = 0;
+
+ switch( pStep->op ){
+ case TK_UPDATE: {
+ sqlite3Update(pParse,
+ targetSrcList(pParse, pStep),
+ sqlite3ExprListDup(db, pStep->pExprList, 0),
+ sqlite3ExprDup(db, pStep->pWhere, 0),
+ pParse->eOrconf
+ );
+ break;
+ }
+ case TK_INSERT: {
+ sqlite3Insert(pParse,
+ targetSrcList(pParse, pStep),
+ sqlite3ExprListDup(db, pStep->pExprList, 0),
+ sqlite3SelectDup(db, pStep->pSelect, 0),
+ sqlite3IdListDup(db, pStep->pIdList),
+ pParse->eOrconf
+ );
+ break;
+ }
+ case TK_DELETE: {
+ sqlite3DeleteFrom(pParse,
+ targetSrcList(pParse, pStep),
+ sqlite3ExprDup(db, pStep->pWhere, 0)
+ );
+ break;
+ }
+ default: assert( pStep->op==TK_SELECT ); {
+ SelectDest sDest;
+ Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0);
+ sqlite3SelectDestInit(&sDest, SRT_Discard, 0);
+ sqlite3Select(pParse, pSelect, &sDest);
+ sqlite3SelectDelete(db, pSelect);
+ break;
+ }
+ }
+ if( pStep->op!=TK_SELECT ){
+ sqlite3VdbeAddOp0(v, OP_ResetCount);
+ }
+ }
+
+ return 0;
+}
+
+#ifdef SQLITE_DEBUG
+/*
+** This function is used to add VdbeComment() annotations to a VDBE
+** program. It is not used in production code, only for debugging.
+*/
+static const char *onErrorText(int onError){
+ switch( onError ){
+ case OE_Abort: return "abort";
+ case OE_Rollback: return "rollback";
+ case OE_Fail: return "fail";
+ case OE_Replace: return "replace";
+ case OE_Ignore: return "ignore";
+ case OE_Default: return "default";
+ }
+ return "n/a";
+}
+#endif
+
+/*
+** Parse context structure pFrom has just been used to create a sub-vdbe
+** (trigger program). If an error has occurred, transfer error information
+** from pFrom to pTo.
+*/
+static void transferParseError(Parse *pTo, Parse *pFrom){
+ assert( pFrom->zErrMsg==0 || pFrom->nErr );
+ assert( pTo->zErrMsg==0 || pTo->nErr );
+ if( pTo->nErr==0 ){
+ pTo->zErrMsg = pFrom->zErrMsg;
+ pTo->nErr = pFrom->nErr;
+ }else{
+ sqlite3DbFree(pFrom->db, pFrom->zErrMsg);
+ }
+}
+
+/*
+** Create and populate a new TriggerPrg object with a sub-program
+** implementing trigger pTrigger with ON CONFLICT policy orconf.
+*/
+static TriggerPrg *codeRowTrigger(
+ Parse *pParse, /* Current parse context */
+ Trigger *pTrigger, /* Trigger to code */
+ Table *pTab, /* The table pTrigger is attached to */
+ int orconf /* ON CONFLICT policy to code trigger program with */
+){
+ Parse *pTop = sqlite3ParseToplevel(pParse);
+ sqlite3 *db = pParse->db; /* Database handle */
+ TriggerPrg *pPrg; /* Value to return */
+ Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */
+ Vdbe *v; /* Temporary VM */
+ NameContext sNC; /* Name context for sub-vdbe */
+ SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
+ Parse *pSubParse; /* Parse context for sub-vdbe */
+ int iEndTrigger = 0; /* Label to jump to if WHEN is false */
+
+ assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
+ assert( pTop->pVdbe );
+
+ /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
+ ** are freed if an error occurs, link them into the Parse.pTriggerPrg
+ ** list of the top-level Parse object sooner rather than later. */
+ pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
+ if( !pPrg ) return 0;
+ pPrg->pNext = pTop->pTriggerPrg;
+ pTop->pTriggerPrg = pPrg;
+ pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram));
+ if( !pProgram ) return 0;
+ sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram);
+ pPrg->pTrigger = pTrigger;
+ pPrg->orconf = orconf;
+ pPrg->aColmask[0] = 0xffffffff;
+ pPrg->aColmask[1] = 0xffffffff;
+
+ /* Allocate and populate a new Parse context to use for coding the
+ ** trigger sub-program. */
+ pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
+ if( !pSubParse ) return 0;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pSubParse;
+ pSubParse->db = db;
+ pSubParse->pTriggerTab = pTab;
+ pSubParse->pToplevel = pTop;
+ pSubParse->zAuthContext = pTrigger->zName;
+ pSubParse->eTriggerOp = pTrigger->op;
+ pSubParse->nQueryLoop = pParse->nQueryLoop;
+
+ v = sqlite3GetVdbe(pSubParse);
+ if( v ){
+ VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
+ pTrigger->zName, onErrorText(orconf),
+ (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
+ (pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
+ (pTrigger->op==TK_INSERT ? "INSERT" : ""),
+ (pTrigger->op==TK_DELETE ? "DELETE" : ""),
+ pTab->zName
+ ));
+#ifndef SQLITE_OMIT_TRACE
+ sqlite3VdbeChangeP4(v, -1,
+ sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
+ );
+#endif
+
+ /* If one was specified, code the WHEN clause. If it evaluates to false
+ ** (or NULL) the sub-vdbe is immediately halted by jumping to the
+ ** OP_Halt inserted at the end of the program. */
+ if( pTrigger->pWhen ){
+ pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
+ if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
+ && db->mallocFailed==0
+ ){
+ iEndTrigger = sqlite3VdbeMakeLabel(v);
+ sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
+ }
+ sqlite3ExprDelete(db, pWhen);
+ }
+
+ /* Code the trigger program into the sub-vdbe. */
+ codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);
+
+ /* Insert an OP_Halt at the end of the sub-program. */
+ if( iEndTrigger ){
+ sqlite3VdbeResolveLabel(v, iEndTrigger);
+ }
+ sqlite3VdbeAddOp0(v, OP_Halt);
+ VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));
+
+ transferParseError(pParse, pSubParse);
+ if( db->mallocFailed==0 ){
+ pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
+ }
+ pProgram->nMem = pSubParse->nMem;
+ pProgram->nCsr = pSubParse->nTab;
+ pProgram->nOnce = pSubParse->nOnce;
+ pProgram->token = (void *)pTrigger;
+ pPrg->aColmask[0] = pSubParse->oldmask;
+ pPrg->aColmask[1] = pSubParse->newmask;
+ sqlite3VdbeDelete(v);
+ }
+
+ assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
+ assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
+ sqlite3StackFree(db, pSubParse);
+
+ return pPrg;
+}
+
+/*
+** Return a pointer to a TriggerPrg object containing the sub-program for
+** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such
+** TriggerPrg object exists, a new object is allocated and populated before
+** being returned.
+*/
+static TriggerPrg *getRowTrigger(
+ Parse *pParse, /* Current parse context */
+ Trigger *pTrigger, /* Trigger to code */
+ Table *pTab, /* The table trigger pTrigger is attached to */
+ int orconf /* ON CONFLICT algorithm. */
+){
+ Parse *pRoot = sqlite3ParseToplevel(pParse);
+ TriggerPrg *pPrg;
+
+ assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
+
+ /* It may be that this trigger has already been coded (or is in the
+ ** process of being coded). If this is the case, then an entry with
+ ** a matching TriggerPrg.pTrigger field will be present somewhere
+ ** in the Parse.pTriggerPrg list. Search for such an entry. */
+ for(pPrg=pRoot->pTriggerPrg;
+ pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf);
+ pPrg=pPrg->pNext
+ );
+
+ /* If an existing TriggerPrg could not be located, create a new one. */
+ if( !pPrg ){
+ pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
+ }
+
+ return pPrg;
+}
+
+/*
+** Generate code for the trigger program associated with trigger p on
+** table pTab. The reg, orconf and ignoreJump parameters passed to this
+** function are the same as those described in the header function for
+** sqlite3CodeRowTrigger()
+*/
+SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
+ Parse *pParse, /* Parse context */
+ Trigger *p, /* Trigger to code */
+ Table *pTab, /* The table to code triggers from */
+ int reg, /* Reg array containing OLD.* and NEW.* values */
+ int orconf, /* ON CONFLICT policy */
+ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
+){
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
+ TriggerPrg *pPrg;
+ pPrg = getRowTrigger(pParse, p, pTab, orconf);
+ assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
+
+ /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
+ ** is a pointer to the sub-vdbe containing the trigger program. */
+ if( pPrg ){
+ int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers));
+
+ sqlite3VdbeAddOp3(v, OP_Program, reg, ignoreJump, ++pParse->nMem);
+ sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM);
+ VdbeComment(
+ (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf)));
+
+ /* Set the P5 operand of the OP_Program instruction to non-zero if
+ ** recursive invocation of this trigger program is disallowed. Recursive
+ ** invocation is disallowed if (a) the sub-program is really a trigger,
+ ** not a foreign key action, and (b) the flag to enable recursive triggers
+ ** is clear. */
+ sqlite3VdbeChangeP5(v, (u8)bRecursive);
+ }
+}
+
+/*
+** This is called to code the required FOR EACH ROW triggers for an operation
+** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
+** is given by the op paramater. The tr_tm parameter determines whether the
+** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
+** parameter pChanges is passed the list of columns being modified.
+**
+** If there are no triggers that fire at the specified time for the specified
+** operation on pTab, this function is a no-op.
+**
+** The reg argument is the address of the first in an array of registers
+** that contain the values substituted for the new.* and old.* references
+** in the trigger program. If N is the number of columns in table pTab
+** (a copy of pTab->nCol), then registers are populated as follows:
+**
+** Register Contains
+** ------------------------------------------------------
+** reg+0 OLD.rowid
+** reg+1 OLD.* value of left-most column of pTab
+** ... ...
+** reg+N OLD.* value of right-most column of pTab
+** reg+N+1 NEW.rowid
+** reg+N+2 OLD.* value of left-most column of pTab
+** ... ...
+** reg+N+N+1 NEW.* value of right-most column of pTab
+**
+** For ON DELETE triggers, the registers containing the NEW.* values will
+** never be accessed by the trigger program, so they are not allocated or
+** populated by the caller (there is no data to populate them with anyway).
+** Similarly, for ON INSERT triggers the values stored in the OLD.* registers
+** are never accessed, and so are not allocated by the caller. So, for an
+** ON INSERT trigger, the value passed to this function as parameter reg
+** is not a readable register, although registers (reg+N) through
+** (reg+N+N+1) are.
+**
+** Parameter orconf is the default conflict resolution algorithm for the
+** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump
+** is the instruction that control should jump to if a trigger program
+** raises an IGNORE exception.
+*/
+SQLITE_PRIVATE void sqlite3CodeRowTrigger(
+ Parse *pParse, /* Parse context */
+ Trigger *pTrigger, /* List of triggers on table pTab */
+ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
+ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
+ int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
+ Table *pTab, /* The table to code triggers from */
+ int reg, /* The first in an array of registers (see above) */
+ int orconf, /* ON CONFLICT policy */
+ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
+){
+ Trigger *p; /* Used to iterate through pTrigger list */
+
+ assert( op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE );
+ assert( tr_tm==TRIGGER_BEFORE || tr_tm==TRIGGER_AFTER );
+ assert( (op==TK_UPDATE)==(pChanges!=0) );
+
+ for(p=pTrigger; p; p=p->pNext){
+
+ /* Sanity checking: The schema for the trigger and for the table are
+ ** always defined. The trigger must be in the same schema as the table
+ ** or else it must be a TEMP trigger. */
+ assert( p->pSchema!=0 );
+ assert( p->pTabSchema!=0 );
+ assert( p->pSchema==p->pTabSchema
+ || p->pSchema==pParse->db->aDb[1].pSchema );
+
+ /* Determine whether we should code this trigger */
+ if( p->op==op
+ && p->tr_tm==tr_tm
+ && checkColumnOverlap(p->pColumns, pChanges)
+ ){
+ sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+ }
+ }
+}
+
+/*
+** Triggers may access values stored in the old.* or new.* pseudo-table.
+** This function returns a 32-bit bitmask indicating which columns of the
+** old.* or new.* tables actually are used by triggers. This information
+** may be used by the caller, for example, to avoid having to load the entire
+** old.* record into memory when executing an UPDATE or DELETE command.
+**
+** Bit 0 of the returned mask is set if the left-most column of the
+** table may be accessed using an [old|new].<col> reference. Bit 1 is set if
+** the second leftmost column value is required, and so on. If there
+** are more than 32 columns in the table, and at least one of the columns
+** with an index greater than 32 may be accessed, 0xffffffff is returned.
+**
+** It is not possible to determine if the old.rowid or new.rowid column is
+** accessed by triggers. The caller must always assume that it is.
+**
+** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned
+** applies to the old.* table. If 1, the new.* table.
+**
+** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE
+** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only
+** included in the returned mask if the TRIGGER_BEFORE bit is set in the
+** tr_tm parameter. Similarly, values accessed by AFTER triggers are only
+** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm.
+*/
+SQLITE_PRIVATE u32 sqlite3TriggerColmask(
+ Parse *pParse, /* Parse context */
+ Trigger *pTrigger, /* List of triggers on table pTab */
+ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
+ int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */
+ int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
+ Table *pTab, /* The table to code triggers from */
+ int orconf /* Default ON CONFLICT policy for trigger steps */
+){
+ const int op = pChanges ? TK_UPDATE : TK_DELETE;
+ u32 mask = 0;
+ Trigger *p;
+
+ assert( isNew==1 || isNew==0 );
+ for(p=pTrigger; p; p=p->pNext){
+ if( p->op==op && (tr_tm&p->tr_tm)
+ && checkColumnOverlap(p->pColumns,pChanges)
+ ){
+ TriggerPrg *pPrg;
+ pPrg = getRowTrigger(pParse, p, pTab, orconf);
+ if( pPrg ){
+ mask |= pPrg->aColmask[isNew];
+ }
+ }
+ }
+
+ return mask;
+}
+
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+
+/************** End of trigger.c *********************************************/
+/************** Begin file update.c ******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that are called by the parser
+** to handle UPDATE statements.
+*/
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Forward declaration */
+static void updateVirtualTable(
+ Parse *pParse, /* The parsing context */
+ SrcList *pSrc, /* The virtual table to be modified */
+ Table *pTab, /* The virtual table */
+ ExprList *pChanges, /* The columns to change in the UPDATE statement */
+ Expr *pRowidExpr, /* Expression used to recompute the rowid */
+ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
+ Expr *pWhere, /* WHERE clause of the UPDATE statement */
+ int onError /* ON CONFLICT strategy */
+);
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/*
+** The most recently coded instruction was an OP_Column to retrieve the
+** i-th column of table pTab. This routine sets the P4 parameter of the
+** OP_Column to the default value, if any.
+**
+** The default value of a column is specified by a DEFAULT clause in the
+** column definition. This was either supplied by the user when the table
+** was created, or added later to the table definition by an ALTER TABLE
+** command. If the latter, then the row-records in the table btree on disk
+** may not contain a value for the column and the default value, taken
+** from the P4 parameter of the OP_Column instruction, is returned instead.
+** If the former, then all row-records are guaranteed to include a value
+** for the column and the P4 value is not required.
+**
+** Column definitions created by an ALTER TABLE command may only have
+** literal default values specified: a number, null or a string. (If a more
+** complicated default expression value was provided, it is evaluated
+** when the ALTER TABLE is executed and one of the literal values written
+** into the sqlite_master table.)
+**
+** Therefore, the P4 parameter is only required if the default value for
+** the column is a literal number, string or null. The sqlite3ValueFromExpr()
+** function is capable of transforming these types of expressions into
+** sqlite3_value objects.
+**
+** If parameter iReg is not negative, code an OP_RealAffinity instruction
+** on register iReg. This is used when an equivalent integer value is
+** stored in place of an 8-byte floating point value in order to save
+** space.
+*/
+SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
+ assert( pTab!=0 );
+ if( !pTab->pSelect ){
+ sqlite3_value *pValue;
+ u8 enc = ENC(sqlite3VdbeDb(v));
+ Column *pCol = &pTab->aCol[i];
+ VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
+ assert( i<pTab->nCol );
+ sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
+ pCol->affinity, &pValue);
+ if( pValue ){
+ sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
+ }
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
+ }
+#endif
+ }
+}
+
+/*
+** Process an UPDATE statement.
+**
+** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
+** \_______/ \________/ \______/ \________________/
+* onError pTabList pChanges pWhere
+*/
+SQLITE_PRIVATE void sqlite3Update(
+ Parse *pParse, /* The parser context */
+ SrcList *pTabList, /* The table in which we should change things */
+ ExprList *pChanges, /* Things to be changed */
+ Expr *pWhere, /* The WHERE clause. May be null */
+ int onError /* How to handle constraint errors */
+){
+ int i, j; /* Loop counters */
+ Table *pTab; /* The table to be updated */
+ int addr = 0; /* VDBE instruction address of the start of the loop */
+ WhereInfo *pWInfo; /* Information about the WHERE clause */
+ Vdbe *v; /* The virtual database engine */
+ Index *pIdx; /* For looping over indices */
+ int nIdx; /* Number of indices that need updating */
+ int iCur; /* VDBE Cursor number of pTab */
+ sqlite3 *db; /* The database structure */
+ int *aRegIdx = 0; /* One register assigned to each index to be updated */
+ int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
+ ** an expression for the i-th column of the table.
+ ** aXRef[i]==-1 if the i-th column is not changed. */
+ int chngRowid; /* True if the record number is being changed */
+ Expr *pRowidExpr = 0; /* Expression defining the new record number */
+ int openAll = 0; /* True if all indices need to be opened */
+ AuthContext sContext; /* The authorization context */
+ NameContext sNC; /* The name-context to resolve expressions in */
+ int iDb; /* Database containing the table being updated */
+ int okOnePass; /* True for one-pass algorithm without the FIFO */
+ int hasFK; /* True if foreign key processing is required */
+
+#ifndef SQLITE_OMIT_TRIGGER
+ int isView; /* True when updating a view (INSTEAD OF trigger) */
+ Trigger *pTrigger; /* List of triggers on pTab, if required */
+ int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
+#endif
+ int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */
+
+ /* Register Allocations */
+ int regRowCount = 0; /* A count of rows changed */
+ int regOldRowid; /* The old rowid */
+ int regNewRowid; /* The new rowid */
+ int regNew; /* Content of the NEW.* table in triggers */
+ int regOld = 0; /* Content of OLD.* table in triggers */
+ int regRowSet = 0; /* Rowset of rows to be updated */
+
+ memset(&sContext, 0, sizeof(sContext));
+ db = pParse->db;
+ if( pParse->nErr || db->mallocFailed ){
+ goto update_cleanup;
+ }
+ assert( pTabList->nSrc==1 );
+
+ /* Locate the table which we want to update.
+ */
+ pTab = sqlite3SrcListLookup(pParse, pTabList);
+ if( pTab==0 ) goto update_cleanup;
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+
+ /* Figure out if we have any triggers and if the table being
+ ** updated is a view.
+ */
+#ifndef SQLITE_OMIT_TRIGGER
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
+ isView = pTab->pSelect!=0;
+ assert( pTrigger || tmask==0 );
+#else
+# define pTrigger 0
+# define isView 0
+# define tmask 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+ goto update_cleanup;
+ }
+ if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
+ goto update_cleanup;
+ }
+ aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol );
+ if( aXRef==0 ) goto update_cleanup;
+ for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
+
+ /* Allocate a cursors for the main database table and for all indices.
+ ** The index cursors might not be used, but if they are used they
+ ** need to occur right after the database cursor. So go ahead and
+ ** allocate enough space, just in case.
+ */
+ pTabList->a[0].iCursor = iCur = pParse->nTab++;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ pParse->nTab++;
+ }
+
+ /* Initialize the name-context */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+
+ /* Resolve the column names in all the expressions of the
+ ** of the UPDATE statement. Also find the column index
+ ** for each column to be updated in the pChanges array. For each
+ ** column to be updated, make sure we have authorization to change
+ ** that column.
+ */
+ chngRowid = 0;
+ for(i=0; i<pChanges->nExpr; i++){
+ if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
+ goto update_cleanup;
+ }
+ for(j=0; j<pTab->nCol; j++){
+ if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
+ if( j==pTab->iPKey ){
+ chngRowid = 1;
+ pRowidExpr = pChanges->a[i].pExpr;
+ }
+ aXRef[j] = i;
+ break;
+ }
+ }
+ if( j>=pTab->nCol ){
+ if( sqlite3IsRowid(pChanges->a[i].zName) ){
+ chngRowid = 1;
+ pRowidExpr = pChanges->a[i].pExpr;
+ }else{
+ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
+ pParse->checkSchema = 1;
+ goto update_cleanup;
+ }
+ }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ {
+ int rc;
+ rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
+ pTab->aCol[j].zName, db->aDb[iDb].zName);
+ if( rc==SQLITE_DENY ){
+ goto update_cleanup;
+ }else if( rc==SQLITE_IGNORE ){
+ aXRef[j] = -1;
+ }
+ }
+#endif
+ }
+
+ hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngRowid);
+
+ /* Allocate memory for the array aRegIdx[]. There is one entry in the
+ ** array for each index associated with table being updated. Fill in
+ ** the value with a register number for indices that are to be used
+ ** and with zero for unused indices.
+ */
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
+ if( nIdx>0 ){
+ aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
+ if( aRegIdx==0 ) goto update_cleanup;
+ }
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ int reg;
+ if( hasFK || chngRowid ){
+ reg = ++pParse->nMem;
+ }else{
+ reg = 0;
+ for(i=0; i<pIdx->nColumn; i++){
+ if( aXRef[pIdx->aiColumn[i]]>=0 ){
+ reg = ++pParse->nMem;
+ break;
+ }
+ }
+ }
+ aRegIdx[j] = reg;
+ }
+
+ /* Begin generating code. */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto update_cleanup;
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Virtual tables must be handled separately */
+ if( IsVirtual(pTab) ){
+ updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
+ pWhere, onError);
+ pWhere = 0;
+ pTabList = 0;
+ goto update_cleanup;
+ }
+#endif
+
+ /* Allocate required registers. */
+ regRowSet = ++pParse->nMem;
+ regOldRowid = regNewRowid = ++pParse->nMem;
+ if( pTrigger || hasFK ){
+ regOld = pParse->nMem + 1;
+ pParse->nMem += pTab->nCol;
+ }
+ if( chngRowid || pTrigger || hasFK ){
+ regNewRowid = ++pParse->nMem;
+ }
+ regNew = pParse->nMem + 1;
+ pParse->nMem += pTab->nCol;
+
+ /* Start the view context. */
+ if( isView ){
+ sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
+ }
+
+ /* If we are trying to update a view, realize that view into
+ ** a ephemeral table.
+ */
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
+ if( isView ){
+ sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ }
+#endif
+
+ /* Resolve the column names in all the expressions in the
+ ** WHERE clause.
+ */
+ if( sqlite3ResolveExprNames(&sNC, pWhere) ){
+ goto update_cleanup;
+ }
+
+ /* Begin the database scan
+ */
+ sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
+ pWInfo = sqlite3WhereBegin(
+ pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
+ );
+ if( pWInfo==0 ) goto update_cleanup;
+ okOnePass = pWInfo->okOnePass;
+
+ /* Remember the rowid of every item to be updated.
+ */
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
+ if( !okOnePass ){
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ }
+
+ /* End the database scan loop.
+ */
+ sqlite3WhereEnd(pWInfo);
+
+ /* Initialize the count of updated rows
+ */
+ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
+ regRowCount = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
+ }
+
+ if( !isView ){
+ /*
+ ** Open every index that needs updating. Note that if any
+ ** index could potentially invoke a REPLACE conflict resolution
+ ** action, then we need to open all indices because we might need
+ ** to be deleting some records.
+ */
+ if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ if( onError==OE_Replace ){
+ openAll = 1;
+ }else{
+ openAll = 0;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->onError==OE_Replace ){
+ openAll = 1;
+ break;
+ }
+ }
+ }
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ assert( aRegIdx );
+ if( openAll || aRegIdx[i]>0 ){
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+ sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
+ (char*)pKey, P4_KEYINFO_HANDOFF);
+ assert( pParse->nTab>iCur+i+1 );
+ }
+ }
+ }
+
+ /* Top of the update loop */
+ if( okOnePass ){
+ int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
+ addr = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, a1);
+ }else{
+ addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid);
+ }
+
+ /* Make cursor iCur point to the record that is being updated. If
+ ** this record does not exist for some reason (deleted by a trigger,
+ ** for example, then jump to the next iteration of the RowSet loop. */
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
+
+ /* If the record number will change, set register regNewRowid to
+ ** contain the new value. If the record number is not being modified,
+ ** then regNewRowid is the same register as regOldRowid, which is
+ ** already populated. */
+ assert( chngRowid || pTrigger || hasFK || regOldRowid==regNewRowid );
+ if( chngRowid ){
+ sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
+ }
+
+ /* If there are triggers on this table, populate an array of registers
+ ** with the required old.* column data. */
+ if( hasFK || pTrigger ){
+ u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
+ oldmask |= sqlite3TriggerColmask(pParse,
+ pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
+ );
+ for(i=0; i<pTab->nCol; i++){
+ if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
+ }
+ }
+ if( chngRowid==0 ){
+ sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
+ }
+ }
+
+ /* Populate the array of registers beginning at regNew with the new
+ ** row data. This array is used to check constaints, create the new
+ ** table and index records, and as the values for any new.* references
+ ** made by triggers.
+ **
+ ** If there are one or more BEFORE triggers, then do not populate the
+ ** registers associated with columns that are (a) not modified by
+ ** this UPDATE statement and (b) not accessed by new.* references. The
+ ** values for registers not modified by the UPDATE must be reloaded from
+ ** the database after the BEFORE triggers are fired anyway (as the trigger
+ ** may have modified them). So not loading those that are not going to
+ ** be used eliminates some redundant opcodes.
+ */
+ newmask = sqlite3TriggerColmask(
+ pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
+ );
+ sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);
+ for(i=0; i<pTab->nCol; i++){
+ if( i==pTab->iPKey ){
+ /*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/
+ }else{
+ j = aXRef[i];
+ if( j>=0 ){
+ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
+ }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
+ /* This branch loads the value of a column that will not be changed
+ ** into a register. This is done if there are no BEFORE triggers, or
+ ** if there are one or more BEFORE triggers that use this value via
+ ** a new.* reference in a trigger program.
+ */
+ testcase( i==31 );
+ testcase( i==32 );
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
+ sqlite3ColumnDefault(v, pTab, i, regNew+i);
+ }
+ }
+ }
+
+ /* Fire any BEFORE UPDATE triggers. This happens before constraints are
+ ** verified. One could argue that this is wrong.
+ */
+ if( tmask&TRIGGER_BEFORE ){
+ sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
+ sqlite3TableAffinityStr(v, pTab);
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ TRIGGER_BEFORE, pTab, regOldRowid, onError, addr);
+
+ /* The row-trigger may have deleted the row being updated. In this
+ ** case, jump to the next row. No updates or AFTER triggers are
+ ** required. This behavior - what happens when the row being updated
+ ** is deleted or renamed by a BEFORE trigger - is left undefined in the
+ ** documentation.
+ */
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
+
+ /* If it did not delete it, the row-trigger may still have modified
+ ** some of the columns of the row being updated. Load the values for
+ ** all columns not modified by the update statement into their
+ ** registers in case this has happened.
+ */
+ for(i=0; i<pTab->nCol; i++){
+ if( aXRef[i]<0 && i!=pTab->iPKey ){
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
+ sqlite3ColumnDefault(v, pTab, i, regNew+i);
+ }
+ }
+ }
+
+ if( !isView ){
+ int j1; /* Address of jump instruction */
+
+ /* Do constraint checks. */
+ sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid,
+ aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0);
+
+ /* Do FK constraint checks. */
+ if( hasFK ){
+ sqlite3FkCheck(pParse, pTab, regOldRowid, 0);
+ }
+
+ /* Delete the index entries associated with the current record. */
+ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
+
+ /* If changing the record number, delete the old record. */
+ if( hasFK || chngRowid ){
+ sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
+ }
+ sqlite3VdbeJumpHere(v, j1);
+
+ if( hasFK ){
+ sqlite3FkCheck(pParse, pTab, 0, regNewRowid);
+ }
+
+ /* Insert the new index entries and the new record. */
+ sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0);
+
+ /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
+ ** handle rows (possibly in other tables) that refer via a foreign key
+ ** to the row just updated. */
+ if( hasFK ){
+ sqlite3FkActions(pParse, pTab, pChanges, regOldRowid);
+ }
+ }
+
+ /* Increment the row counter
+ */
+ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){
+ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
+ }
+
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ TRIGGER_AFTER, pTab, regOldRowid, onError, addr);
+
+ /* Repeat the above with the next record to be updated, until
+ ** all record selected by the WHERE clause have been updated.
+ */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
+ sqlite3VdbeJumpHere(v, addr);
+
+ /* Close all tables */
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ assert( aRegIdx );
+ if( openAll || aRegIdx[i]>0 ){
+ sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
+ }
+ }
+ sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
+
+ /* Update the sqlite_sequence table by storing the content of the
+ ** maximum rowid counter values recorded while inserting into
+ ** autoincrement tables.
+ */
+ if( pParse->nested==0 && pParse->pTriggerTab==0 ){
+ sqlite3AutoincrementEnd(pParse);
+ }
+
+ /*
+ ** Return the number of rows that were changed. If this routine is
+ ** generating code because of a call to sqlite3NestedParse(), do not
+ ** invoke the callback function.
+ */
+ if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
+ }
+
+update_cleanup:
+ sqlite3AuthContextPop(&sContext);
+ sqlite3DbFree(db, aRegIdx);
+ sqlite3DbFree(db, aXRef);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprListDelete(db, pChanges);
+ sqlite3ExprDelete(db, pWhere);
+ return;
+}
+/* Make sure "isView" and other macros defined above are undefined. Otherwise
+** thely may interfere with compilation of other functions in this file
+** (or in another file, if this file becomes part of the amalgamation). */
+#ifdef isView
+ #undef isView
+#endif
+#ifdef pTrigger
+ #undef pTrigger
+#endif
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Generate code for an UPDATE of a virtual table.
+**
+** The strategy is that we create an ephemerial table that contains
+** for each row to be changed:
+**
+** (A) The original rowid of that row.
+** (B) The revised rowid for the row. (note1)
+** (C) The content of every column in the row.
+**
+** Then we loop over this ephemeral table and for each row in
+** the ephermeral table call VUpdate.
+**
+** When finished, drop the ephemeral table.
+**
+** (note1) Actually, if we know in advance that (A) is always the same
+** as (B) we only store (A), then duplicate (A) when pulling
+** it out of the ephemeral table before calling VUpdate.
+*/
+static void updateVirtualTable(
+ Parse *pParse, /* The parsing context */
+ SrcList *pSrc, /* The virtual table to be modified */
+ Table *pTab, /* The virtual table */
+ ExprList *pChanges, /* The columns to change in the UPDATE statement */
+ Expr *pRowid, /* Expression used to recompute the rowid */
+ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
+ Expr *pWhere, /* WHERE clause of the UPDATE statement */
+ int onError /* ON CONFLICT strategy */
+){
+ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
+ ExprList *pEList = 0; /* The result set of the SELECT statement */
+ Select *pSelect = 0; /* The SELECT statement */
+ Expr *pExpr; /* Temporary expression */
+ int ephemTab; /* Table holding the result of the SELECT */
+ int i; /* Loop counter */
+ int addr; /* Address of top of loop */
+ int iReg; /* First register in set passed to OP_VUpdate */
+ sqlite3 *db = pParse->db; /* Database connection */
+ const char *pVTab = (const char*)sqlite3GetVTable(db, pTab);
+ SelectDest dest;
+
+ /* Construct the SELECT statement that will find the new values for
+ ** all updated rows.
+ */
+ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_"));
+ if( pRowid ){
+ pEList = sqlite3ExprListAppend(pParse, pEList,
+ sqlite3ExprDup(db, pRowid, 0));
+ }
+ assert( pTab->iPKey<0 );
+ for(i=0; i<pTab->nCol; i++){
+ if( aXRef[i]>=0 ){
+ pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0);
+ }else{
+ pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName);
+ }
+ pEList = sqlite3ExprListAppend(pParse, pEList, pExpr);
+ }
+ pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
+
+ /* Create the ephemeral table into which the update results will
+ ** be stored.
+ */
+ assert( v );
+ ephemTab = pParse->nTab++;
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
+ sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
+
+ /* fill the ephemeral table
+ */
+ sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
+ sqlite3Select(pParse, pSelect, &dest);
+
+ /* Generate code to scan the ephemeral table and call VUpdate. */
+ iReg = ++pParse->nMem;
+ pParse->nMem += pTab->nCol+1;
+ addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0);
+ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg);
+ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1);
+ for(i=0; i<pTab->nCol; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
+ }
+ sqlite3VtabMakeWritable(pParse, pTab);
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
+ sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
+ sqlite3MayAbort(pParse);
+ sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
+ sqlite3VdbeJumpHere(v, addr);
+ sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
+
+ /* Cleanup */
+ sqlite3SelectDelete(db, pSelect);
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/************** End of update.c **********************************************/
+/************** Begin file vacuum.c ******************************************/
+/*
+** 2003 April 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used to implement the VACUUM command.
+**
+** Most of the code in this file may be omitted by defining the
+** SQLITE_OMIT_VACUUM macro.
+*/
+
+#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
+/*
+** Finalize a prepared statement. If there was an error, store the
+** text of the error message in *pzErrMsg. Return the result code.
+*/
+static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
+ int rc;
+ rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
+ if( rc ){
+ sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
+ }
+ return rc;
+}
+
+/*
+** Execute zSql on database db. Return an error code.
+*/
+static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
+ sqlite3_stmt *pStmt;
+ VVA_ONLY( int rc; )
+ if( !zSql ){
+ return SQLITE_NOMEM;
+ }
+ if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
+ sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
+ return sqlite3_errcode(db);
+ }
+ VVA_ONLY( rc = ) sqlite3_step(pStmt);
+ assert( rc!=SQLITE_ROW || (db->flags&SQLITE_CountRows) );
+ return vacuumFinalize(db, pStmt, pzErrMsg);
+}
+
+/*
+** Execute zSql on database db. The statement returns exactly
+** one column. Execute this as SQL on the same database.
+*/
+static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
+ sqlite3_stmt *pStmt;
+ int rc;
+
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ) return rc;
+
+ while( SQLITE_ROW==sqlite3_step(pStmt) ){
+ rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
+ if( rc!=SQLITE_OK ){
+ vacuumFinalize(db, pStmt, pzErrMsg);
+ return rc;
+ }
+ }
+
+ return vacuumFinalize(db, pStmt, pzErrMsg);
+}
+
+/*
+** The non-standard VACUUM command is used to clean up the database,
+** collapse free space, etc. It is modelled after the VACUUM command
+** in PostgreSQL.
+**
+** In version 1.0.x of SQLite, the VACUUM command would call
+** gdbm_reorganize() on all the database tables. But beginning
+** with 2.0.0, SQLite no longer uses GDBM so this command has
+** become a no-op.
+*/
+SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
+ sqlite3VdbeUsesBtree(v, 0);
+ }
+ return;
+}
+
+/*
+** This routine implements the OP_Vacuum opcode of the VDBE.
+*/
+SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
+ int rc = SQLITE_OK; /* Return code from service routines */
+ Btree *pMain; /* The database being vacuumed */
+ Btree *pTemp; /* The temporary database we vacuum into */
+ char *zSql = 0; /* SQL statements */
+ int saved_flags; /* Saved value of the db->flags */
+ int saved_nChange; /* Saved value of db->nChange */
+ int saved_nTotalChange; /* Saved value of db->nTotalChange */
+ void (*saved_xTrace)(void*,const char*); /* Saved db->xTrace */
+ Db *pDb = 0; /* Database to detach at end of vacuum */
+ int isMemDb; /* True if vacuuming a :memory: database */
+ int nRes; /* Bytes of reserved space at the end of each page */
+ int nDb; /* Number of attached databases */
+
+ if( !db->autoCommit ){
+ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
+ return SQLITE_ERROR;
+ }
+ if( db->activeVdbeCnt>1 ){
+ sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
+ return SQLITE_ERROR;
+ }
+
+ /* Save the current value of the database flags so that it can be
+ ** restored before returning. Then set the writable-schema flag, and
+ ** disable CHECK and foreign key constraints. */
+ saved_flags = db->flags;
+ saved_nChange = db->nChange;
+ saved_nTotalChange = db->nTotalChange;
+ saved_xTrace = db->xTrace;
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
+ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
+ db->xTrace = 0;
+
+ pMain = db->aDb[0].pBt;
+ isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
+
+ /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
+ ** can be set to 'off' for this file, as it is not recovered if a crash
+ ** occurs anyway. The integrity of the database is maintained by a
+ ** (possibly synchronous) transaction opened on the main database before
+ ** sqlite3BtreeCopyFile() is called.
+ **
+ ** An optimisation would be to use a non-journaled pager.
+ ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
+ ** that actually made the VACUUM run slower. Very little journalling
+ ** actually occurs when doing a vacuum since the vacuum_db is initially
+ ** empty. Only the journal header is written. Apparently it takes more
+ ** time to parse and run the PRAGMA to turn journalling off than it does
+ ** to write the journal header file.
+ */
+ nDb = db->nDb;
+ if( sqlite3TempInMemory(db) ){
+ zSql = "ATTACH ':memory:' AS vacuum_db;";
+ }else{
+ zSql = "ATTACH '' AS vacuum_db;";
+ }
+ rc = execSql(db, pzErrMsg, zSql);
+ if( db->nDb>nDb ){
+ pDb = &db->aDb[db->nDb-1];
+ assert( strcmp(pDb->zName,"vacuum_db")==0 );
+ }
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ pTemp = db->aDb[db->nDb-1].pBt;
+
+ /* The call to execSql() to attach the temp database has left the file
+ ** locked (as there was more than one active statement when the transaction
+ ** to read the schema was concluded. Unlock it here so that this doesn't
+ ** cause problems for the call to BtreeSetPageSize() below. */
+ sqlite3BtreeCommit(pTemp);
+
+ nRes = sqlite3BtreeGetReserve(pMain);
+
+ /* A VACUUM cannot change the pagesize of an encrypted database. */
+#ifdef SQLITE_HAS_CODEC
+ if( db->nextPagesize ){
+ extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
+ int nKey;
+ char *zKey;
+ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
+ if( nKey ) db->nextPagesize = 0;
+ }
+#endif
+
+ rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+ /* Begin a transaction and take an exclusive lock on the main database
+ ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
+ ** to ensure that we do not try to change the page-size on a WAL database.
+ */
+ rc = execSql(db, pzErrMsg, "BEGIN;");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = sqlite3BtreeBeginTrans(pMain, 2);
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+ /* Do not attempt to change the page size for a WAL database */
+ if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
+ ==PAGER_JOURNALMODE_WAL ){
+ db->nextPagesize = 0;
+ }
+
+ if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
+ || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
+ || NEVER(db->mallocFailed)
+ ){
+ rc = SQLITE_NOMEM;
+ goto end_of_vacuum;
+ }
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac :
+ sqlite3BtreeGetAutoVacuum(pMain));
+#endif
+
+ /* Query the schema of the main database. Create a mirror schema
+ ** in the temporary database.
+ */
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
+ " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
+ " AND rootpage>0"
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
+ " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
+ " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+ /* Loop through the tables in the main database. For each, do
+ ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
+ ** the contents to the temporary database.
+ */
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
+ "|| ' SELECT * FROM main.' || quote(name) || ';'"
+ "FROM main.sqlite_master "
+ "WHERE type = 'table' AND name!='sqlite_sequence' "
+ " AND rootpage>0"
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+ /* Copy over the sequence table
+ */
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
+ "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
+ "|| ' SELECT * FROM main.' || quote(name) || ';' "
+ "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+
+ /* Copy the triggers, views, and virtual tables from the main database
+ ** over to the temporary database. None of these objects has any
+ ** associated storage, so all we have to do is copy their entries
+ ** from the SQLITE_MASTER table.
+ */
+ rc = execSql(db, pzErrMsg,
+ "INSERT INTO vacuum_db.sqlite_master "
+ " SELECT type, name, tbl_name, rootpage, sql"
+ " FROM main.sqlite_master"
+ " WHERE type='view' OR type='trigger'"
+ " OR (type='table' AND rootpage=0)"
+ );
+ if( rc ) goto end_of_vacuum;
+
+ /* At this point, there is a write transaction open on both the
+ ** vacuum database and the main database. Assuming no error occurs,
+ ** both transactions are closed by this block - the main database
+ ** transaction by sqlite3BtreeCopyFile() and the other by an explicit
+ ** call to sqlite3BtreeCommit().
+ */
+ {
+ u32 meta;
+ int i;
+
+ /* This array determines which meta meta values are preserved in the
+ ** vacuum. Even entries are the meta value number and odd entries
+ ** are an increment to apply to the meta value after the vacuum.
+ ** The increment is used to increase the schema cookie so that other
+ ** connections to the same database will know to reread the schema.
+ */
+ static const unsigned char aCopy[] = {
+ BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */
+ BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */
+ BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */
+ BTREE_USER_VERSION, 0, /* Preserve the user version */
+ };
+
+ assert( 1==sqlite3BtreeIsInTrans(pTemp) );
+ assert( 1==sqlite3BtreeIsInTrans(pMain) );
+
+ /* Copy Btree meta values */
+ for(i=0; i<ArraySize(aCopy); i+=2){
+ /* GetMeta() and UpdateMeta() cannot fail in this context because
+ ** we already have page 1 loaded into cache and marked dirty. */
+ sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
+ rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
+ if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum;
+ }
+
+ rc = sqlite3BtreeCopyFile(pMain, pTemp);
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = sqlite3BtreeCommit(pTemp);
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+#endif
+ }
+
+ assert( rc==SQLITE_OK );
+ rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
+
+end_of_vacuum:
+ /* Restore the original value of db->flags */
+ db->flags = saved_flags;
+ db->nChange = saved_nChange;
+ db->nTotalChange = saved_nTotalChange;
+ db->xTrace = saved_xTrace;
+ sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
+
+ /* Currently there is an SQL level transaction open on the vacuum
+ ** database. No locks are held on any other files (since the main file
+ ** was committed at the btree level). So it safe to end the transaction
+ ** by manually setting the autoCommit flag to true and detaching the
+ ** vacuum database. The vacuum_db journal file is deleted when the pager
+ ** is closed by the DETACH.
+ */
+ db->autoCommit = 1;
+
+ if( pDb ){
+ sqlite3BtreeClose(pDb->pBt);
+ pDb->pBt = 0;
+ pDb->pSchema = 0;
+ }
+
+ /* This both clears the schemas and reduces the size of the db->aDb[]
+ ** array. */
+ sqlite3ResetAllSchemasOfConnection(db);
+
+ return rc;
+}
+
+#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */
+
+/************** End of vacuum.c **********************************************/
+/************** Begin file vtab.c ********************************************/
+/*
+** 2006 June 10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used to help implement virtual tables.
+*/
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+/*
+** Before a virtual table xCreate() or xConnect() method is invoked, the
+** sqlite3.pVtabCtx member variable is set to point to an instance of
+** this struct allocated on the stack. It is used by the implementation of
+** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
+** are invoked only from within xCreate and xConnect methods.
+*/
+struct VtabCtx {
+ VTable *pVTable; /* The virtual table being constructed */
+ Table *pTab; /* The Table object to which the virtual table belongs */
+};
+
+/*
+** The actual function that does the work of creating a new module.
+** This function implements the sqlite3_create_module() and
+** sqlite3_create_module_v2() interfaces.
+*/
+static int createModule(
+ sqlite3 *db, /* Database in which module is registered */
+ const char *zName, /* Name assigned to this module */
+ const sqlite3_module *pModule, /* The definition of the module */
+ void *pAux, /* Context pointer for xCreate/xConnect */
+ void (*xDestroy)(void *) /* Module destructor function */
+){
+ int rc = SQLITE_OK;
+ int nName;
+
+ sqlite3_mutex_enter(db->mutex);
+ nName = sqlite3Strlen30(zName);
+ if( sqlite3HashFind(&db->aModule, zName, nName) ){
+ rc = SQLITE_MISUSE_BKPT;
+ }else{
+ Module *pMod;
+ pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
+ if( pMod ){
+ Module *pDel;
+ char *zCopy = (char *)(&pMod[1]);
+ memcpy(zCopy, zName, nName+1);
+ pMod->zName = zCopy;
+ pMod->pModule = pModule;
+ pMod->pAux = pAux;
+ pMod->xDestroy = xDestroy;
+ pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod);
+ assert( pDel==0 || pDel==pMod );
+ if( pDel ){
+ db->mallocFailed = 1;
+ sqlite3DbFree(db, pDel);
+ }
+ }
+ }
+ rc = sqlite3ApiExit(db, rc);
+ if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
+
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+
+/*
+** External API function used to create a new virtual-table module.
+*/
+SQLITE_API int sqlite3_create_module(
+ sqlite3 *db, /* Database in which module is registered */
+ const char *zName, /* Name assigned to this module */
+ const sqlite3_module *pModule, /* The definition of the module */
+ void *pAux /* Context pointer for xCreate/xConnect */
+){
+ return createModule(db, zName, pModule, pAux, 0);
+}
+
+/*
+** External API function used to create a new virtual-table module.
+*/
+SQLITE_API int sqlite3_create_module_v2(
+ sqlite3 *db, /* Database in which module is registered */
+ const char *zName, /* Name assigned to this module */
+ const sqlite3_module *pModule, /* The definition of the module */
+ void *pAux, /* Context pointer for xCreate/xConnect */
+ void (*xDestroy)(void *) /* Module destructor function */
+){
+ return createModule(db, zName, pModule, pAux, xDestroy);
+}
+
+/*
+** Lock the virtual table so that it cannot be disconnected.
+** Locks nest. Every lock should have a corresponding unlock.
+** If an unlock is omitted, resources leaks will occur.
+**
+** If a disconnect is attempted while a virtual table is locked,
+** the disconnect is deferred until all locks have been removed.
+*/
+SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){
+ pVTab->nRef++;
+}
+
+
+/*
+** pTab is a pointer to a Table structure representing a virtual-table.
+** Return a pointer to the VTable object used by connection db to access
+** this virtual-table, if one has been created, or NULL otherwise.
+*/
+SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
+ VTable *pVtab;
+ assert( IsVirtual(pTab) );
+ for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
+ return pVtab;
+}
+
+/*
+** Decrement the ref-count on a virtual table object. When the ref-count
+** reaches zero, call the xDisconnect() method to delete the object.
+*/
+SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){
+ sqlite3 *db = pVTab->db;
+
+ assert( db );
+ assert( pVTab->nRef>0 );
+ assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE );
+
+ pVTab->nRef--;
+ if( pVTab->nRef==0 ){
+ sqlite3_vtab *p = pVTab->pVtab;
+ if( p ){
+ p->pModule->xDisconnect(p);
+ }
+ sqlite3DbFree(db, pVTab);
+ }
+}
+
+/*
+** Table p is a virtual table. This function moves all elements in the
+** p->pVTable list to the sqlite3.pDisconnect lists of their associated
+** database connections to be disconnected at the next opportunity.
+** Except, if argument db is not NULL, then the entry associated with
+** connection db is left in the p->pVTable list.
+*/
+static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
+ VTable *pRet = 0;
+ VTable *pVTable = p->pVTable;
+ p->pVTable = 0;
+
+ /* Assert that the mutex (if any) associated with the BtShared database
+ ** that contains table p is held by the caller. See header comments
+ ** above function sqlite3VtabUnlockList() for an explanation of why
+ ** this makes it safe to access the sqlite3.pDisconnect list of any
+ ** database connection that may have an entry in the p->pVTable list.
+ */
+ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
+
+ while( pVTable ){
+ sqlite3 *db2 = pVTable->db;
+ VTable *pNext = pVTable->pNext;
+ assert( db2 );
+ if( db2==db ){
+ pRet = pVTable;
+ p->pVTable = pRet;
+ pRet->pNext = 0;
+ }else{
+ pVTable->pNext = db2->pDisconnect;
+ db2->pDisconnect = pVTable;
+ }
+ pVTable = pNext;
+ }
+
+ assert( !db || pRet );
+ return pRet;
+}
+
+/*
+** Table *p is a virtual table. This function removes the VTable object
+** for table *p associated with database connection db from the linked
+** list in p->pVTab. It also decrements the VTable ref count. This is
+** used when closing database connection db to free all of its VTable
+** objects without disturbing the rest of the Schema object (which may
+** be being used by other shared-cache connections).
+*/
+SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
+ VTable **ppVTab;
+
+ assert( IsVirtual(p) );
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ assert( sqlite3_mutex_held(db->mutex) );
+
+ for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
+ if( (*ppVTab)->db==db ){
+ VTable *pVTab = *ppVTab;
+ *ppVTab = pVTab->pNext;
+ sqlite3VtabUnlock(pVTab);
+ break;
+ }
+ }
+}
+
+
+/*
+** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
+**
+** This function may only be called when the mutexes associated with all
+** shared b-tree databases opened using connection db are held by the
+** caller. This is done to protect the sqlite3.pDisconnect list. The
+** sqlite3.pDisconnect list is accessed only as follows:
+**
+** 1) By this function. In this case, all BtShared mutexes and the mutex
+** associated with the database handle itself must be held.
+**
+** 2) By function vtabDisconnectAll(), when it adds a VTable entry to
+** the sqlite3.pDisconnect list. In this case either the BtShared mutex
+** associated with the database the virtual table is stored in is held
+** or, if the virtual table is stored in a non-sharable database, then
+** the database handle mutex is held.
+**
+** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously
+** by multiple threads. It is thread-safe.
+*/
+SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
+ VTable *p = db->pDisconnect;
+ db->pDisconnect = 0;
+
+ assert( sqlite3BtreeHoldsAllMutexes(db) );
+ assert( sqlite3_mutex_held(db->mutex) );
+
+ if( p ){
+ sqlite3ExpirePreparedStatements(db);
+ do {
+ VTable *pNext = p->pNext;
+ sqlite3VtabUnlock(p);
+ p = pNext;
+ }while( p );
+ }
+}
+
+/*
+** Clear any and all virtual-table information from the Table record.
+** This routine is called, for example, just before deleting the Table
+** record.
+**
+** Since it is a virtual-table, the Table structure contains a pointer
+** to the head of a linked list of VTable structures. Each VTable
+** structure is associated with a single sqlite3* user of the schema.
+** The reference count of the VTable structure associated with database
+** connection db is decremented immediately (which may lead to the
+** structure being xDisconnected and free). Any other VTable structures
+** in the list are moved to the sqlite3.pDisconnect list of the associated
+** database connection.
+*/
+SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
+ if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
+ if( p->azModuleArg ){
+ int i;
+ for(i=0; i<p->nModuleArg; i++){
+ if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
+ }
+ sqlite3DbFree(db, p->azModuleArg);
+ }
+}
+
+/*
+** Add a new module argument to pTable->azModuleArg[].
+** The string is not copied - the pointer is stored. The
+** string will be freed automatically when the table is
+** deleted.
+*/
+static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){
+ int i = pTable->nModuleArg++;
+ int nBytes = sizeof(char *)*(1+pTable->nModuleArg);
+ char **azModuleArg;
+ azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
+ if( azModuleArg==0 ){
+ int j;
+ for(j=0; j<i; j++){
+ sqlite3DbFree(db, pTable->azModuleArg[j]);
+ }
+ sqlite3DbFree(db, zArg);
+ sqlite3DbFree(db, pTable->azModuleArg);
+ pTable->nModuleArg = 0;
+ }else{
+ azModuleArg[i] = zArg;
+ azModuleArg[i+1] = 0;
+ }
+ pTable->azModuleArg = azModuleArg;
+}
+
+/*
+** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
+** statement. The module name has been parsed, but the optional list
+** of parameters that follow the module name are still pending.
+*/
+SQLITE_PRIVATE void sqlite3VtabBeginParse(
+ Parse *pParse, /* Parsing context */
+ Token *pName1, /* Name of new table, or database name */
+ Token *pName2, /* Name of new table or NULL */
+ Token *pModuleName, /* Name of the module for the virtual table */
+ int ifNotExists /* No error if the table already exists */
+){
+ int iDb; /* The database the table is being created in */
+ Table *pTable; /* The new virtual table */
+ sqlite3 *db; /* Database connection */
+
+ sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists);
+ pTable = pParse->pNewTable;
+ if( pTable==0 ) return;
+ assert( 0==pTable->pIndex );
+
+ db = pParse->db;
+ iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
+ assert( iDb>=0 );
+
+ pTable->tabFlags |= TF_Virtual;
+ pTable->nModuleArg = 0;
+ addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
+ addModuleArgument(db, pTable, 0);
+ addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
+ pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Creating a virtual table invokes the authorization callback twice.
+ ** The first invocation, to obtain permission to INSERT a row into the
+ ** sqlite_master table, has already been made by sqlite3StartTable().
+ ** The second call, to obtain permission to create the table, is made now.
+ */
+ if( pTable->azModuleArg ){
+ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
+ pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
+ }
+#endif
+}
+
+/*
+** This routine takes the module argument that has been accumulating
+** in pParse->zArg[] and appends it to the list of arguments on the
+** virtual table currently under construction in pParse->pTable.
+*/
+static void addArgumentToVtab(Parse *pParse){
+ if( pParse->sArg.z && pParse->pNewTable ){
+ const char *z = (const char*)pParse->sArg.z;
+ int n = pParse->sArg.n;
+ sqlite3 *db = pParse->db;
+ addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
+ }
+}
+
+/*
+** The parser calls this routine after the CREATE VIRTUAL TABLE statement
+** has been completely parsed.
+*/
+SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
+ Table *pTab = pParse->pNewTable; /* The table being constructed */
+ sqlite3 *db = pParse->db; /* The database connection */
+
+ if( pTab==0 ) return;
+ addArgumentToVtab(pParse);
+ pParse->sArg.z = 0;
+ if( pTab->nModuleArg<1 ) return;
+
+ /* If the CREATE VIRTUAL TABLE statement is being entered for the
+ ** first time (in other words if the virtual table is actually being
+ ** created now instead of just being read out of sqlite_master) then
+ ** do additional initialization work and store the statement text
+ ** in the sqlite_master table.
+ */
+ if( !db->init.busy ){
+ char *zStmt;
+ char *zWhere;
+ int iDb;
+ Vdbe *v;
+
+ /* Compute the complete text of the CREATE VIRTUAL TABLE statement */
+ if( pEnd ){
+ pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n;
+ }
+ zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
+
+ /* A slot for the record has already been allocated in the
+ ** SQLITE_MASTER table. We just need to update that slot with all
+ ** the information we've collected.
+ **
+ ** The VM register number pParse->regRowid holds the rowid of an
+ ** entry in the sqlite_master table tht was created for this vtab
+ ** by sqlite3StartTable().
+ */
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s "
+ "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
+ "WHERE rowid=#%d",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ pTab->zName,
+ pTab->zName,
+ zStmt,
+ pParse->regRowid
+ );
+ sqlite3DbFree(db, zStmt);
+ v = sqlite3GetVdbe(pParse);
+ sqlite3ChangeCookie(pParse, iDb);
+
+ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
+ zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
+ sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+ sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
+ pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
+ }
+
+ /* If we are rereading the sqlite_master table create the in-memory
+ ** record of the table. The xConnect() method is not called until
+ ** the first time the virtual table is used in an SQL statement. This
+ ** allows a schema that contains virtual tables to be loaded before
+ ** the required virtual table implementations are registered. */
+ else {
+ Table *pOld;
+ Schema *pSchema = pTab->pSchema;
+ const char *zName = pTab->zName;
+ int nName = sqlite3Strlen30(zName);
+ assert( sqlite3SchemaMutexHeld(db, 0, pSchema) );
+ pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
+ if( pOld ){
+ db->mallocFailed = 1;
+ assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
+ return;
+ }
+ pParse->pNewTable = 0;
+ }
+}
+
+/*
+** The parser calls this routine when it sees the first token
+** of an argument to the module name in a CREATE VIRTUAL TABLE statement.
+*/
+SQLITE_PRIVATE void sqlite3VtabArgInit(Parse *pParse){
+ addArgumentToVtab(pParse);
+ pParse->sArg.z = 0;
+ pParse->sArg.n = 0;
+}
+
+/*
+** The parser calls this routine for each token after the first token
+** in an argument to the module name in a CREATE VIRTUAL TABLE statement.
+*/
+SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse *pParse, Token *p){
+ Token *pArg = &pParse->sArg;
+ if( pArg->z==0 ){
+ pArg->z = p->z;
+ pArg->n = p->n;
+ }else{
+ assert(pArg->z < p->z);
+ pArg->n = (int)(&p->z[p->n] - pArg->z);
+ }
+}
+
+/*
+** Invoke a virtual table constructor (either xCreate or xConnect). The
+** pointer to the function to invoke is passed as the fourth parameter
+** to this procedure.
+*/
+static int vtabCallConstructor(
+ sqlite3 *db,
+ Table *pTab,
+ Module *pMod,
+ int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
+ char **pzErr
+){
+ VtabCtx sCtx, *pPriorCtx;
+ VTable *pVTable;
+ int rc;
+ const char *const*azArg = (const char *const*)pTab->azModuleArg;
+ int nArg = pTab->nModuleArg;
+ char *zErr = 0;
+ char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+ int iDb;
+
+ if( !zModuleName ){
+ return SQLITE_NOMEM;
+ }
+
+ pVTable = sqlite3DbMallocZero(db, sizeof(VTable));
+ if( !pVTable ){
+ sqlite3DbFree(db, zModuleName);
+ return SQLITE_NOMEM;
+ }
+ pVTable->db = db;
+ pVTable->pMod = pMod;
+
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pTab->azModuleArg[1] = db->aDb[iDb].zName;
+
+ /* Invoke the virtual table constructor */
+ assert( &db->pVtabCtx );
+ assert( xConstruct );
+ sCtx.pTab = pTab;
+ sCtx.pVTable = pVTable;
+ pPriorCtx = db->pVtabCtx;
+ db->pVtabCtx = &sCtx;
+ rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
+ db->pVtabCtx = pPriorCtx;
+ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+
+ if( SQLITE_OK!=rc ){
+ if( zErr==0 ){
+ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
+ }else {
+ *pzErr = sqlite3MPrintf(db, "%s", zErr);
+ sqlite3_free(zErr);
+ }
+ sqlite3DbFree(db, pVTable);
+ }else if( ALWAYS(pVTable->pVtab) ){
+ /* Justification of ALWAYS(): A correct vtab constructor must allocate
+ ** the sqlite3_vtab object if successful. */
+ pVTable->pVtab->pModule = pMod->pModule;
+ pVTable->nRef = 1;
+ if( sCtx.pTab ){
+ const char *zFormat = "vtable constructor did not declare schema: %s";
+ *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
+ sqlite3VtabUnlock(pVTable);
+ rc = SQLITE_ERROR;
+ }else{
+ int iCol;
+ /* If everything went according to plan, link the new VTable structure
+ ** into the linked list headed by pTab->pVTable. Then loop through the
+ ** columns of the table to see if any of them contain the token "hidden".
+ ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
+ ** the type string. */
+ pVTable->pNext = pTab->pVTable;
+ pTab->pVTable = pVTable;
+
+ for(iCol=0; iCol<pTab->nCol; iCol++){
+ char *zType = pTab->aCol[iCol].zType;
+ int nType;
+ int i = 0;
+ if( !zType ) continue;
+ nType = sqlite3Strlen30(zType);
+ if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){
+ for(i=0; i<nType; i++){
+ if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7))
+ && (zType[i+7]=='\0' || zType[i+7]==' ')
+ ){
+ i++;
+ break;
+ }
+ }
+ }
+ if( i<nType ){
+ int j;
+ int nDel = 6 + (zType[i+6] ? 1 : 0);
+ for(j=i; (j+nDel)<=nType; j++){
+ zType[j] = zType[j+nDel];
+ }
+ if( zType[i]=='\0' && i>0 ){
+ assert(zType[i-1]==' ');
+ zType[i-1] = '\0';
+ }
+ pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
+ }
+ }
+ }
+ }
+
+ sqlite3DbFree(db, zModuleName);
+ return rc;
+}
+
+/*
+** This function is invoked by the parser to call the xConnect() method
+** of the virtual table pTab. If an error occurs, an error code is returned
+** and an error left in pParse.
+**
+** This call is a no-op if table pTab is not a virtual table.
+*/
+SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
+ sqlite3 *db = pParse->db;
+ const char *zMod;
+ Module *pMod;
+ int rc;
+
+ assert( pTab );
+ if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){
+ return SQLITE_OK;
+ }
+
+ /* Locate the required virtual table module */
+ zMod = pTab->azModuleArg[0];
+ pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod));
+
+ if( !pMod ){
+ const char *zModule = pTab->azModuleArg[0];
+ sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
+ rc = SQLITE_ERROR;
+ }else{
+ char *zErr = 0;
+ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
+ if( rc!=SQLITE_OK ){
+ sqlite3ErrorMsg(pParse, "%s", zErr);
+ }
+ sqlite3DbFree(db, zErr);
+ }
+
+ return rc;
+}
+/*
+** Grow the db->aVTrans[] array so that there is room for at least one
+** more v-table. Return SQLITE_NOMEM if a malloc fails, or SQLITE_OK otherwise.
+*/
+static int growVTrans(sqlite3 *db){
+ const int ARRAY_INCR = 5;
+
+ /* Grow the sqlite3.aVTrans array if required */
+ if( (db->nVTrans%ARRAY_INCR)==0 ){
+ VTable **aVTrans;
+ int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
+ aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes);
+ if( !aVTrans ){
+ return SQLITE_NOMEM;
+ }
+ memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR);
+ db->aVTrans = aVTrans;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Add the virtual table pVTab to the array sqlite3.aVTrans[]. Space should
+** have already been reserved using growVTrans().
+*/
+static void addToVTrans(sqlite3 *db, VTable *pVTab){
+ /* Add pVtab to the end of sqlite3.aVTrans */
+ db->aVTrans[db->nVTrans++] = pVTab;
+ sqlite3VtabLock(pVTab);
+}
+
+/*
+** This function is invoked by the vdbe to call the xCreate method
+** of the virtual table named zTab in database iDb.
+**
+** If an error occurs, *pzErr is set to point an an English language
+** description of the error and an SQLITE_XXX error code is returned.
+** In this case the caller must call sqlite3DbFree(db, ) on *pzErr.
+*/
+SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
+ int rc = SQLITE_OK;
+ Table *pTab;
+ Module *pMod;
+ const char *zMod;
+
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
+ assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable );
+
+ /* Locate the required virtual table module */
+ zMod = pTab->azModuleArg[0];
+ pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod));
+
+ /* If the module has been registered and includes a Create method,
+ ** invoke it now. If the module has not been registered, return an
+ ** error. Otherwise, do nothing.
+ */
+ if( !pMod ){
+ *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod);
+ rc = SQLITE_ERROR;
+ }else{
+ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
+ }
+
+ /* Justification of ALWAYS(): The xConstructor method is required to
+ ** create a valid sqlite3_vtab if it returns SQLITE_OK. */
+ if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){
+ rc = growVTrans(db);
+ if( rc==SQLITE_OK ){
+ addToVTrans(db, sqlite3GetVTable(db, pTab));
+ }
+ }
+
+ return rc;
+}
+
+/*
+** This function is used to set the schema of a virtual table. It is only
+** valid to call this function from within the xCreate() or xConnect() of a
+** virtual table module.
+*/
+SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
+ Parse *pParse;
+
+ int rc = SQLITE_OK;
+ Table *pTab;
+ char *zErr = 0;
+
+ sqlite3_mutex_enter(db->mutex);
+ if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
+ sqlite3Error(db, SQLITE_MISUSE, 0);
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_MISUSE_BKPT;
+ }
+ assert( (pTab->tabFlags & TF_Virtual)!=0 );
+
+ pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
+ if( pParse==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pParse->declareVtab = 1;
+ pParse->db = db;
+ pParse->nQueryLoop = 1;
+
+ if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
+ && pParse->pNewTable
+ && !db->mallocFailed
+ && !pParse->pNewTable->pSelect
+ && (pParse->pNewTable->tabFlags & TF_Virtual)==0
+ ){
+ if( !pTab->aCol ){
+ pTab->aCol = pParse->pNewTable->aCol;
+ pTab->nCol = pParse->pNewTable->nCol;
+ pParse->pNewTable->nCol = 0;
+ pParse->pNewTable->aCol = 0;
+ }
+ db->pVtabCtx->pTab = 0;
+ }else{
+ sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
+ sqlite3DbFree(db, zErr);
+ rc = SQLITE_ERROR;
+ }
+ pParse->declareVtab = 0;
+
+ if( pParse->pVdbe ){
+ sqlite3VdbeFinalize(pParse->pVdbe);
+ }
+ sqlite3DeleteTable(db, pParse->pNewTable);
+ sqlite3StackFree(db, pParse);
+ }
+
+ assert( (rc&0xff)==rc );
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** This function is invoked by the vdbe to call the xDestroy method
+** of the virtual table named zTab in database iDb. This occurs
+** when a DROP TABLE is mentioned.
+**
+** This call is a no-op if zTab is not a virtual table.
+*/
+SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
+ int rc = SQLITE_OK;
+ Table *pTab;
+
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
+ if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
+ VTable *p = vtabDisconnectAll(db, pTab);
+
+ assert( rc==SQLITE_OK );
+ rc = p->pMod->pModule->xDestroy(p->pVtab);
+
+ /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
+ if( rc==SQLITE_OK ){
+ assert( pTab->pVTable==p && p->pNext==0 );
+ p->pVtab = 0;
+ pTab->pVTable = 0;
+ sqlite3VtabUnlock(p);
+ }
+ }
+
+ return rc;
+}
+
+/*
+** This function invokes either the xRollback or xCommit method
+** of each of the virtual tables in the sqlite3.aVTrans array. The method
+** called is identified by the second argument, "offset", which is
+** the offset of the method to call in the sqlite3_module structure.
+**
+** The array is cleared after invoking the callbacks.
+*/
+static void callFinaliser(sqlite3 *db, int offset){
+ int i;
+ if( db->aVTrans ){
+ for(i=0; i<db->nVTrans; i++){
+ VTable *pVTab = db->aVTrans[i];
+ sqlite3_vtab *p = pVTab->pVtab;
+ if( p ){
+ int (*x)(sqlite3_vtab *);
+ x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset);
+ if( x ) x(p);
+ }
+ pVTab->iSavepoint = 0;
+ sqlite3VtabUnlock(pVTab);
+ }
+ sqlite3DbFree(db, db->aVTrans);
+ db->nVTrans = 0;
+ db->aVTrans = 0;
+ }
+}
+
+/*
+** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
+** array. Return the error code for the first error that occurs, or
+** SQLITE_OK if all xSync operations are successful.
+**
+** Set *pzErrmsg to point to a buffer that should be released using
+** sqlite3DbFree() containing an error message, if one is available.
+*/
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
+ int i;
+ int rc = SQLITE_OK;
+ VTable **aVTrans = db->aVTrans;
+
+ db->aVTrans = 0;
+ for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
+ int (*x)(sqlite3_vtab *);
+ sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
+ if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
+ rc = x(pVtab);
+ sqlite3DbFree(db, *pzErrmsg);
+ *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
+ sqlite3_free(pVtab->zErrMsg);
+ }
+ }
+ db->aVTrans = aVTrans;
+ return rc;
+}
+
+/*
+** Invoke the xRollback method of all virtual tables in the
+** sqlite3.aVTrans array. Then clear the array itself.
+*/
+SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){
+ callFinaliser(db, offsetof(sqlite3_module,xRollback));
+ return SQLITE_OK;
+}
+
+/*
+** Invoke the xCommit method of all virtual tables in the
+** sqlite3.aVTrans array. Then clear the array itself.
+*/
+SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){
+ callFinaliser(db, offsetof(sqlite3_module,xCommit));
+ return SQLITE_OK;
+}
+
+/*
+** If the virtual table pVtab supports the transaction interface
+** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is
+** not currently open, invoke the xBegin method now.
+**
+** If the xBegin call is successful, place the sqlite3_vtab pointer
+** in the sqlite3.aVTrans array.
+*/
+SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
+ int rc = SQLITE_OK;
+ const sqlite3_module *pModule;
+
+ /* Special case: If db->aVTrans is NULL and db->nVTrans is greater
+ ** than zero, then this function is being called from within a
+ ** virtual module xSync() callback. It is illegal to write to
+ ** virtual module tables in this case, so return SQLITE_LOCKED.
+ */
+ if( sqlite3VtabInSync(db) ){
+ return SQLITE_LOCKED;
+ }
+ if( !pVTab ){
+ return SQLITE_OK;
+ }
+ pModule = pVTab->pVtab->pModule;
+
+ if( pModule->xBegin ){
+ int i;
+
+ /* If pVtab is already in the aVTrans array, return early */
+ for(i=0; i<db->nVTrans; i++){
+ if( db->aVTrans[i]==pVTab ){
+ return SQLITE_OK;
+ }
+ }
+
+ /* Invoke the xBegin method. If successful, add the vtab to the
+ ** sqlite3.aVTrans[] array. */
+ rc = growVTrans(db);
+ if( rc==SQLITE_OK ){
+ rc = pModule->xBegin(pVTab->pVtab);
+ if( rc==SQLITE_OK ){
+ addToVTrans(db, pVTab);
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Invoke either the xSavepoint, xRollbackTo or xRelease method of all
+** virtual tables that currently have an open transaction. Pass iSavepoint
+** as the second argument to the virtual table method invoked.
+**
+** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is
+** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is
+** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with
+** an open transaction is invoked.
+**
+** If any virtual table method returns an error code other than SQLITE_OK,
+** processing is abandoned and the error returned to the caller of this
+** function immediately. If all calls to virtual table methods are successful,
+** SQLITE_OK is returned.
+*/
+SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
+ int rc = SQLITE_OK;
+
+ assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
+ assert( iSavepoint>=0 );
+ if( db->aVTrans ){
+ int i;
+ for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
+ VTable *pVTab = db->aVTrans[i];
+ const sqlite3_module *pMod = pVTab->pMod->pModule;
+ if( pVTab->pVtab && pMod->iVersion>=2 ){
+ int (*xMethod)(sqlite3_vtab *, int);
+ switch( op ){
+ case SAVEPOINT_BEGIN:
+ xMethod = pMod->xSavepoint;
+ pVTab->iSavepoint = iSavepoint+1;
+ break;
+ case SAVEPOINT_ROLLBACK:
+ xMethod = pMod->xRollbackTo;
+ break;
+ default:
+ xMethod = pMod->xRelease;
+ break;
+ }
+ if( xMethod && pVTab->iSavepoint>iSavepoint ){
+ rc = xMethod(pVTab->pVtab, iSavepoint);
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** The first parameter (pDef) is a function implementation. The
+** second parameter (pExpr) is the first argument to this function.
+** If pExpr is a column in a virtual table, then let the virtual
+** table implementation have an opportunity to overload the function.
+**
+** This routine is used to allow virtual table implementations to
+** overload MATCH, LIKE, GLOB, and REGEXP operators.
+**
+** Return either the pDef argument (indicating no change) or a
+** new FuncDef structure that is marked as ephemeral using the
+** SQLITE_FUNC_EPHEM flag.
+*/
+SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
+ sqlite3 *db, /* Database connection for reporting malloc problems */
+ FuncDef *pDef, /* Function to possibly overload */
+ int nArg, /* Number of arguments to the function */
+ Expr *pExpr /* First argument to the function */
+){
+ Table *pTab;
+ sqlite3_vtab *pVtab;
+ sqlite3_module *pMod;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**) = 0;
+ void *pArg = 0;
+ FuncDef *pNew;
+ int rc = 0;
+ char *zLowerName;
+ unsigned char *z;
+
+
+ /* Check to see the left operand is a column in a virtual table */
+ if( NEVER(pExpr==0) ) return pDef;
+ if( pExpr->op!=TK_COLUMN ) return pDef;
+ pTab = pExpr->pTab;
+ if( NEVER(pTab==0) ) return pDef;
+ if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
+ pVtab = sqlite3GetVTable(db, pTab)->pVtab;
+ assert( pVtab!=0 );
+ assert( pVtab->pModule!=0 );
+ pMod = (sqlite3_module *)pVtab->pModule;
+ if( pMod->xFindFunction==0 ) return pDef;
+
+ /* Call the xFindFunction method on the virtual table implementation
+ ** to see if the implementation wants to overload this function
+ */
+ zLowerName = sqlite3DbStrDup(db, pDef->zName);
+ if( zLowerName ){
+ for(z=(unsigned char*)zLowerName; *z; z++){
+ *z = sqlite3UpperToLower[*z];
+ }
+ rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
+ sqlite3DbFree(db, zLowerName);
+ }
+ if( rc==0 ){
+ return pDef;
+ }
+
+ /* Create a new ephemeral function definition for the overloaded
+ ** function */
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew)
+ + sqlite3Strlen30(pDef->zName) + 1);
+ if( pNew==0 ){
+ return pDef;
+ }
+ *pNew = *pDef;
+ pNew->zName = (char *)&pNew[1];
+ memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1);
+ pNew->xFunc = xFunc;
+ pNew->pUserData = pArg;
+ pNew->flags |= SQLITE_FUNC_EPHEM;
+ return pNew;
+}
+
+/*
+** Make sure virtual table pTab is contained in the pParse->apVirtualLock[]
+** array so that an OP_VBegin will get generated for it. Add pTab to the
+** array if it is missing. If pTab is already in the array, this routine
+** is a no-op.
+*/
+SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ int i, n;
+ Table **apVtabLock;
+
+ assert( IsVirtual(pTab) );
+ for(i=0; i<pToplevel->nVtabLock; i++){
+ if( pTab==pToplevel->apVtabLock[i] ) return;
+ }
+ n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
+ apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n);
+ if( apVtabLock ){
+ pToplevel->apVtabLock = apVtabLock;
+ pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
+ }else{
+ pToplevel->db->mallocFailed = 1;
+ }
+}
+
+/*
+** Return the ON CONFLICT resolution mode in effect for the virtual
+** table update operation currently in progress.
+**
+** The results of this routine are undefined unless it is called from
+** within an xUpdate method.
+*/
+SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
+ static const unsigned char aMap[] = {
+ SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
+ };
+ assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
+ assert( OE_Ignore==4 && OE_Replace==5 );
+ assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
+ return (int)aMap[db->vtabOnConflict-1];
+}
+
+/*
+** Call from within the xCreate() or xConnect() methods to provide
+** the SQLite core with additional information about the behavior
+** of the virtual table being implemented.
+*/
+SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
+ va_list ap;
+ int rc = SQLITE_OK;
+
+ sqlite3_mutex_enter(db->mutex);
+
+ va_start(ap, op);
+ switch( op ){
+ case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
+ VtabCtx *p = db->pVtabCtx;
+ if( !p ){
+ rc = SQLITE_MISUSE_BKPT;
+ }else{
+ assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
+ p->pVTable->bConstraint = (u8)va_arg(ap, int);
+ }
+ break;
+ }
+ default:
+ rc = SQLITE_MISUSE_BKPT;
+ break;
+ }
+ va_end(ap);
+
+ if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/************** End of vtab.c ************************************************/
+/************** Begin file where.c *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This module contains C code that generates VDBE code used to process
+** the WHERE clause of SQL statements. This module is responsible for
+** generating the code that loops through a table looking for applicable
+** rows. Indices are selected and used to speed the search when doing
+** so is applicable. Because this module is responsible for selecting
+** indices, you might also think of this module as the "query optimizer".
+*/
+
+
+/*
+** Trace output macros
+*/
+#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
+/***/ int sqlite3WhereTrace = 0;
+#endif
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
+# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X
+#else
+# define WHERETRACE(X)
+#endif
+
+/* Forward reference
+*/
+typedef struct WhereClause WhereClause;
+typedef struct WhereMaskSet WhereMaskSet;
+typedef struct WhereOrInfo WhereOrInfo;
+typedef struct WhereAndInfo WhereAndInfo;
+typedef struct WhereCost WhereCost;
+
+/*
+** The query generator uses an array of instances of this structure to
+** help it analyze the subexpressions of the WHERE clause. Each WHERE
+** clause subexpression is separated from the others by AND operators,
+** usually, or sometimes subexpressions separated by OR.
+**
+** All WhereTerms are collected into a single WhereClause structure.
+** The following identity holds:
+**
+** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
+**
+** When a term is of the form:
+**
+** X <op> <expr>
+**
+** where X is a column name and <op> is one of certain operators,
+** then WhereTerm.leftCursor and WhereTerm.u.leftColumn record the
+** cursor number and column number for X. WhereTerm.eOperator records
+** the <op> using a bitmask encoding defined by WO_xxx below. The
+** use of a bitmask encoding for the operator allows us to search
+** quickly for terms that match any of several different operators.
+**
+** A WhereTerm might also be two or more subterms connected by OR:
+**
+** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
+**
+** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
+** and the WhereTerm.u.pOrInfo field points to auxiliary information that
+** is collected about the
+**
+** If a term in the WHERE clause does not match either of the two previous
+** categories, then eOperator==0. The WhereTerm.pExpr field is still set
+** to the original subexpression content and wtFlags is set up appropriately
+** but no other fields in the WhereTerm object are meaningful.
+**
+** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers,
+** but they do so indirectly. A single WhereMaskSet structure translates
+** cursor number into bits and the translated bit is stored in the prereq
+** fields. The translation is used in order to maximize the number of
+** bits that will fit in a Bitmask. The VDBE cursor numbers might be
+** spread out over the non-negative integers. For example, the cursor
+** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The WhereMaskSet
+** translates these sparse cursor numbers into consecutive integers
+** beginning with 0 in order to make the best possible use of the available
+** bits in the Bitmask. So, in the example above, the cursor numbers
+** would be mapped into integers 0 through 7.
+**
+** The number of terms in a join is limited by the number of bits
+** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
+** is only able to process joins with 64 or fewer tables.
+*/
+typedef struct WhereTerm WhereTerm;
+struct WhereTerm {
+ Expr *pExpr; /* Pointer to the subexpression that is this term */
+ int iParent; /* Disable pWC->a[iParent] when this term disabled */
+ int leftCursor; /* Cursor number of X in "X <op> <expr>" */
+ union {
+ int leftColumn; /* Column number of X in "X <op> <expr>" */
+ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
+ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
+ } u;
+ u16 eOperator; /* A WO_xx value describing <op> */
+ u8 wtFlags; /* TERM_xxx bit flags. See below */
+ u8 nChild; /* Number of children that must disable us */
+ WhereClause *pWC; /* The clause this term is part of */
+ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
+ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
+};
+
+/*
+** Allowed values of WhereTerm.wtFlags
+*/
+#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */
+#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
+#define TERM_CODED 0x04 /* This term is already coded */
+#define TERM_COPIED 0x08 /* Has a child */
+#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
+#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
+#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
+#ifdef SQLITE_ENABLE_STAT3
+# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
+#else
+# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
+#endif
+
+/*
+** An instance of the following structure holds all information about a
+** WHERE clause. Mostly this is a container for one or more WhereTerms.
+**
+** Explanation of pOuter: For a WHERE clause of the form
+**
+** a AND ((b AND c) OR (d AND e)) AND f
+**
+** There are separate WhereClause objects for the whole clause and for
+** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the
+** subclauses points to the WhereClause object for the whole clause.
+*/
+struct WhereClause {
+ Parse *pParse; /* The parser context */
+ WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */
+ WhereClause *pOuter; /* Outer conjunction */
+ u8 op; /* Split operator. TK_AND or TK_OR */
+ u16 wctrlFlags; /* Might include WHERE_AND_ONLY */
+ int nTerm; /* Number of terms */
+ int nSlot; /* Number of entries in a[] */
+ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
+#if defined(SQLITE_SMALL_STACK)
+ WhereTerm aStatic[1]; /* Initial static space for a[] */
+#else
+ WhereTerm aStatic[8]; /* Initial static space for a[] */
+#endif
+};
+
+/*
+** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to
+** a dynamically allocated instance of the following structure.
+*/
+struct WhereOrInfo {
+ WhereClause wc; /* Decomposition into subterms */
+ Bitmask indexable; /* Bitmask of all indexable tables in the clause */
+};
+
+/*
+** A WhereTerm with eOperator==WO_AND has its u.pAndInfo pointer set to
+** a dynamically allocated instance of the following structure.
+*/
+struct WhereAndInfo {
+ WhereClause wc; /* The subexpression broken out */
+};
+
+/*
+** An instance of the following structure keeps track of a mapping
+** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
+**
+** The VDBE cursor numbers are small integers contained in
+** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
+** clause, the cursor numbers might not begin with 0 and they might
+** contain gaps in the numbering sequence. But we want to make maximum
+** use of the bits in our bitmasks. This structure provides a mapping
+** from the sparse cursor numbers into consecutive integers beginning
+** with 0.
+**
+** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
+** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<<A.
+**
+** For example, if the WHERE clause expression used these VDBE
+** cursors: 4, 5, 8, 29, 57, 73. Then the WhereMaskSet structure
+** would map those cursor numbers into bits 0 through 5.
+**
+** Note that the mapping is not necessarily ordered. In the example
+** above, the mapping might go like this: 4->3, 5->1, 8->2, 29->0,
+** 57->5, 73->4. Or one of 719 other combinations might be used. It
+** does not really matter. What is important is that sparse cursor
+** numbers all get mapped into bit numbers that begin with 0 and contain
+** no gaps.
+*/
+struct WhereMaskSet {
+ int n; /* Number of assigned cursor values */
+ int ix[BMS]; /* Cursor assigned to each bit */
+};
+
+/*
+** A WhereCost object records a lookup strategy and the estimated
+** cost of pursuing that strategy.
+*/
+struct WhereCost {
+ WherePlan plan; /* The lookup strategy */
+ double rCost; /* Overall cost of pursuing this search strategy */
+ Bitmask used; /* Bitmask of cursors used by this plan */
+};
+
+/*
+** Bitmasks for the operators that indices are able to exploit. An
+** OR-ed combination of these values can be used when searching for
+** terms in the where clause.
+*/
+#define WO_IN 0x001
+#define WO_EQ 0x002
+#define WO_LT (WO_EQ<<(TK_LT-TK_EQ))
+#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
+#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
+#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
+#define WO_MATCH 0x040
+#define WO_ISNULL 0x080
+#define WO_OR 0x100 /* Two or more OR-connected terms */
+#define WO_AND 0x200 /* Two or more AND-connected terms */
+#define WO_EQUIV 0x400 /* Of the form A==B, both columns */
+#define WO_NOOP 0x800 /* This term does not restrict search space */
+
+#define WO_ALL 0xfff /* Mask of all possible WO_* values */
+#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
+
+/*
+** Value for wsFlags returned by bestIndex() and stored in
+** WhereLevel.wsFlags. These flags determine which search
+** strategies are appropriate.
+**
+** The least significant 12 bits is reserved as a mask for WO_ values above.
+** The WhereLevel.wsFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
+** But if the table is the right table of a left join, WhereLevel.wsFlags
+** is set to WO_IN|WO_EQ. The WhereLevel.wsFlags field can then be used as
+** the "op" parameter to findTerm when we are resolving equality constraints.
+** ISNULL constraints will then not be used on the right table of a left
+** join. Tickets #2177 and #2189.
+*/
+#define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */
+#define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */
+#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */
+#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
+#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
+#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
+#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
+#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
+#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */
+#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
+#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
+#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
+#define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */
+#define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */
+#define WHERE_REVERSE 0x01000000 /* Scan in reverse order */
+#define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */
+#define WHERE_ALL_UNIQUE 0x04000000 /* This and all prior have one row */
+#define WHERE_OB_UNIQUE 0x00004000 /* Values in ORDER BY columns are
+ ** different for every output row */
+#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
+#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
+#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
+#define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
+#define WHERE_COVER_SCAN 0x80000000 /* Full scan of a covering index */
+
+/*
+** This module contains many separate subroutines that work together to
+** find the best indices to use for accessing a particular table in a query.
+** An instance of the following structure holds context information about the
+** index search so that it can be more easily passed between the various
+** routines.
+*/
+typedef struct WhereBestIdx WhereBestIdx;
+struct WhereBestIdx {
+ Parse *pParse; /* Parser context */
+ WhereClause *pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc; /* The FROM clause term to search */
+ Bitmask notReady; /* Mask of cursors not available */
+ Bitmask notValid; /* Cursors not available for any purpose */
+ ExprList *pOrderBy; /* The ORDER BY clause */
+ ExprList *pDistinct; /* The select-list if query is DISTINCT */
+ sqlite3_index_info **ppIdxInfo; /* Index information passed to xBestIndex */
+ int i, n; /* Which loop is being coded; # of loops */
+ WhereLevel *aLevel; /* Info about outer loops */
+ WhereCost cost; /* Lowest cost query plan */
+};
+
+/*
+** Return TRUE if the probe cost is less than the baseline cost
+*/
+static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
+ if( pProbe->rCost<pBaseline->rCost ) return 1;
+ if( pProbe->rCost>pBaseline->rCost ) return 0;
+ if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1;
+ if( pProbe->plan.nRow<pBaseline->plan.nRow ) return 1;
+ return 0;
+}
+
+/*
+** Initialize a preallocated WhereClause structure.
+*/
+static void whereClauseInit(
+ WhereClause *pWC, /* The WhereClause to be initialized */
+ Parse *pParse, /* The parsing context */
+ WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmasks */
+ u16 wctrlFlags /* Might include WHERE_AND_ONLY */
+){
+ pWC->pParse = pParse;
+ pWC->pMaskSet = pMaskSet;
+ pWC->pOuter = 0;
+ pWC->nTerm = 0;
+ pWC->nSlot = ArraySize(pWC->aStatic);
+ pWC->a = pWC->aStatic;
+ pWC->wctrlFlags = wctrlFlags;
+}
+
+/* Forward reference */
+static void whereClauseClear(WhereClause*);
+
+/*
+** Deallocate all memory associated with a WhereOrInfo object.
+*/
+static void whereOrInfoDelete(sqlite3 *db, WhereOrInfo *p){
+ whereClauseClear(&p->wc);
+ sqlite3DbFree(db, p);
+}
+
+/*
+** Deallocate all memory associated with a WhereAndInfo object.
+*/
+static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){
+ whereClauseClear(&p->wc);
+ sqlite3DbFree(db, p);
+}
+
+/*
+** Deallocate a WhereClause structure. The WhereClause structure
+** itself is not freed. This routine is the inverse of whereClauseInit().
+*/
+static void whereClauseClear(WhereClause *pWC){
+ int i;
+ WhereTerm *a;
+ sqlite3 *db = pWC->pParse->db;
+ for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
+ if( a->wtFlags & TERM_DYNAMIC ){
+ sqlite3ExprDelete(db, a->pExpr);
+ }
+ if( a->wtFlags & TERM_ORINFO ){
+ whereOrInfoDelete(db, a->u.pOrInfo);
+ }else if( a->wtFlags & TERM_ANDINFO ){
+ whereAndInfoDelete(db, a->u.pAndInfo);
+ }
+ }
+ if( pWC->a!=pWC->aStatic ){
+ sqlite3DbFree(db, pWC->a);
+ }
+}
+
+/*
+** Add a single new WhereTerm entry to the WhereClause object pWC.
+** The new WhereTerm object is constructed from Expr p and with wtFlags.
+** The index in pWC->a[] of the new WhereTerm is returned on success.
+** 0 is returned if the new WhereTerm could not be added due to a memory
+** allocation error. The memory allocation failure will be recorded in
+** the db->mallocFailed flag so that higher-level functions can detect it.
+**
+** This routine will increase the size of the pWC->a[] array as necessary.
+**
+** If the wtFlags argument includes TERM_DYNAMIC, then responsibility
+** for freeing the expression p is assumed by the WhereClause object pWC.
+** This is true even if this routine fails to allocate a new WhereTerm.
+**
+** WARNING: This routine might reallocate the space used to store
+** WhereTerms. All pointers to WhereTerms should be invalidated after
+** calling this routine. Such pointers may be reinitialized by referencing
+** the pWC->a[] array.
+*/
+static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
+ WhereTerm *pTerm;
+ int idx;
+ testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */
+ if( pWC->nTerm>=pWC->nSlot ){
+ WhereTerm *pOld = pWC->a;
+ sqlite3 *db = pWC->pParse->db;
+ pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
+ if( pWC->a==0 ){
+ if( wtFlags & TERM_DYNAMIC ){
+ sqlite3ExprDelete(db, p);
+ }
+ pWC->a = pOld;
+ return 0;
+ }
+ memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
+ if( pOld!=pWC->aStatic ){
+ sqlite3DbFree(db, pOld);
+ }
+ pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
+ }
+ pTerm = &pWC->a[idx = pWC->nTerm++];
+ pTerm->pExpr = sqlite3ExprSkipCollate(p);
+ pTerm->wtFlags = wtFlags;
+ pTerm->pWC = pWC;
+ pTerm->iParent = -1;
+ return idx;
+}
+
+/*
+** This routine identifies subexpressions in the WHERE clause where
+** each subexpression is separated by the AND operator or some other
+** operator specified in the op parameter. The WhereClause structure
+** is filled with pointers to subexpressions. For example:
+**
+** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22)
+** \________/ \_______________/ \________________/
+** slot[0] slot[1] slot[2]
+**
+** The original WHERE clause in pExpr is unaltered. All this routine
+** does is make slot[] entries point to substructure within pExpr.
+**
+** In the previous sentence and in the diagram, "slot[]" refers to
+** the WhereClause.a[] array. The slot[] array grows as needed to contain
+** all terms of the WHERE clause.
+*/
+static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
+ pWC->op = (u8)op;
+ if( pExpr==0 ) return;
+ if( pExpr->op!=op ){
+ whereClauseInsert(pWC, pExpr, 0);
+ }else{
+ whereSplit(pWC, pExpr->pLeft, op);
+ whereSplit(pWC, pExpr->pRight, op);
+ }
+}
+
+/*
+** Initialize an expression mask set (a WhereMaskSet object)
+*/
+#define initMaskSet(P) memset(P, 0, sizeof(*P))
+
+/*
+** Return the bitmask for the given cursor number. Return 0 if
+** iCursor is not in the set.
+*/
+static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){
+ int i;
+ assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
+ for(i=0; i<pMaskSet->n; i++){
+ if( pMaskSet->ix[i]==iCursor ){
+ return ((Bitmask)1)<<i;
+ }
+ }
+ return 0;
+}
+
+/*
+** Create a new mask for cursor iCursor.
+**
+** There is one cursor per table in the FROM clause. The number of
+** tables in the FROM clause is limited by a test early in the
+** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[]
+** array will never overflow.
+*/
+static void createMask(WhereMaskSet *pMaskSet, int iCursor){
+ assert( pMaskSet->n < ArraySize(pMaskSet->ix) );
+ pMaskSet->ix[pMaskSet->n++] = iCursor;
+}
+
+/*
+** This routine walks (recursively) an expression tree and generates
+** a bitmask indicating which tables are used in that expression
+** tree.
+**
+** In order for this routine to work, the calling function must have
+** previously invoked sqlite3ResolveExprNames() on the expression. See
+** the header comment on that routine for additional information.
+** The sqlite3ResolveExprNames() routines looks for column names and
+** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
+** the VDBE cursor number of the table. This routine just has to
+** translate the cursor numbers into bitmask values and OR all
+** the bitmasks together.
+*/
+static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*);
+static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*);
+static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){
+ Bitmask mask = 0;
+ if( p==0 ) return 0;
+ if( p->op==TK_COLUMN ){
+ mask = getMask(pMaskSet, p->iTable);
+ return mask;
+ }
+ mask = exprTableUsage(pMaskSet, p->pRight);
+ mask |= exprTableUsage(pMaskSet, p->pLeft);
+ if( ExprHasProperty(p, EP_xIsSelect) ){
+ mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect);
+ }else{
+ mask |= exprListTableUsage(pMaskSet, p->x.pList);
+ }
+ return mask;
+}
+static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
+ int i;
+ Bitmask mask = 0;
+ if( pList ){
+ for(i=0; i<pList->nExpr; i++){
+ mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr);
+ }
+ }
+ return mask;
+}
+static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
+ Bitmask mask = 0;
+ while( pS ){
+ SrcList *pSrc = pS->pSrc;
+ mask |= exprListTableUsage(pMaskSet, pS->pEList);
+ mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
+ mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
+ mask |= exprTableUsage(pMaskSet, pS->pWhere);
+ mask |= exprTableUsage(pMaskSet, pS->pHaving);
+ if( ALWAYS(pSrc!=0) ){
+ int i;
+ for(i=0; i<pSrc->nSrc; i++){
+ mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
+ mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
+ }
+ }
+ pS = pS->pPrior;
+ }
+ return mask;
+}
+
+/*
+** Return TRUE if the given operator is one of the operators that is
+** allowed for an indexable WHERE clause term. The allowed operators are
+** "=", "<", ">", "<=", ">=", and "IN".
+**
+** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
+** of one of the following forms: column = expression column > expression
+** column >= expression column < expression column <= expression
+** expression = column expression > column expression >= column
+** expression < column expression <= column column IN
+** (expression-list) column IN (subquery) column IS NULL
+*/
+static int allowedOp(int op){
+ assert( TK_GT>TK_EQ && TK_GT<TK_GE );
+ assert( TK_LT>TK_EQ && TK_LT<TK_GE );
+ assert( TK_LE>TK_EQ && TK_LE<TK_GE );
+ assert( TK_GE==TK_EQ+4 );
+ return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
+}
+
+/*
+** Swap two objects of type TYPE.
+*/
+#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
+
+/*
+** Commute a comparison operator. Expressions of the form "X op Y"
+** are converted into "Y op X".
+**
+** If left/right precedence rules come into play when determining the
+** collating
+** side of the comparison, it remains associated with the same side after
+** the commutation. So "Y collate NOCASE op X" becomes
+** "X op Y". This is because any collation sequence on
+** the left hand side of a comparison overrides any collation sequence
+** attached to the right. For the same reason the EP_Collate flag
+** is not commuted.
+*/
+static void exprCommute(Parse *pParse, Expr *pExpr){
+ u16 expRight = (pExpr->pRight->flags & EP_Collate);
+ u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
+ assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
+ if( expRight==expLeft ){
+ /* Either X and Y both have COLLATE operator or neither do */
+ if( expRight ){
+ /* Both X and Y have COLLATE operators. Make sure X is always
+ ** used by clearing the EP_Collate flag from Y. */
+ pExpr->pRight->flags &= ~EP_Collate;
+ }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
+ /* Neither X nor Y have COLLATE operators, but X has a non-default
+ ** collating sequence. So add the EP_Collate marker on X to cause
+ ** it to be searched first. */
+ pExpr->pLeft->flags |= EP_Collate;
+ }
+ }
+ SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
+ if( pExpr->op>=TK_GT ){
+ assert( TK_LT==TK_GT+2 );
+ assert( TK_GE==TK_LE+2 );
+ assert( TK_GT>TK_EQ );
+ assert( TK_GT<TK_LE );
+ assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
+ pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
+ }
+}
+
+/*
+** Translate from TK_xx operator to WO_xx bitmask.
+*/
+static u16 operatorMask(int op){
+ u16 c;
+ assert( allowedOp(op) );
+ if( op==TK_IN ){
+ c = WO_IN;
+ }else if( op==TK_ISNULL ){
+ c = WO_ISNULL;
+ }else{
+ assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
+ c = (u16)(WO_EQ<<(op-TK_EQ));
+ }
+ assert( op!=TK_ISNULL || c==WO_ISNULL );
+ assert( op!=TK_IN || c==WO_IN );
+ assert( op!=TK_EQ || c==WO_EQ );
+ assert( op!=TK_LT || c==WO_LT );
+ assert( op!=TK_LE || c==WO_LE );
+ assert( op!=TK_GT || c==WO_GT );
+ assert( op!=TK_GE || c==WO_GE );
+ return c;
+}
+
+/*
+** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
+** where X is a reference to the iColumn of table iCur and <op> is one of
+** the WO_xx operator codes specified by the op parameter.
+** Return a pointer to the term. Return 0 if not found.
+**
+** The term returned might by Y=<expr> if there is another constraint in
+** the WHERE clause that specifies that X=Y. Any such constraints will be
+** identified by the WO_EQUIV bit in the pTerm->eOperator field. The
+** aEquiv[] array holds X and all its equivalents, with each SQL variable
+** taking up two slots in aEquiv[]. The first slot is for the cursor number
+** and the second is for the column number. There are 22 slots in aEquiv[]
+** so that means we can look for X plus up to 10 other equivalent values.
+** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
+** and ... and A9=A10 and A10=<expr>.
+**
+** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
+** then try for the one with no dependencies on <expr> - in other words where
+** <expr> is a constant expression of some kind. Only return entries of
+** the form "X <op> Y" where Y is a column in another table if no terms of
+** the form "X <op> <const-expr>" exist. If no terms with a constant RHS
+** exist, try to return a term that does not use WO_EQUIV.
+*/
+static WhereTerm *findTerm(
+ WhereClause *pWC, /* The WHERE clause to be searched */
+ int iCur, /* Cursor number of LHS */
+ int iColumn, /* Column number of LHS */
+ Bitmask notReady, /* RHS must not overlap with this mask */
+ u32 op, /* Mask of WO_xx values describing operator */
+ Index *pIdx /* Must be compatible with this index, if not NULL */
+){
+ WhereTerm *pTerm; /* Term being examined as possible result */
+ WhereTerm *pResult = 0; /* The answer to return */
+ WhereClause *pWCOrig = pWC; /* Original pWC value */
+ int j, k; /* Loop counters */
+ Expr *pX; /* Pointer to an expression */
+ Parse *pParse; /* Parsing context */
+ int iOrigCol = iColumn; /* Original value of iColumn */
+ int nEquiv = 2; /* Number of entires in aEquiv[] */
+ int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */
+ int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */
+
+ assert( iCur>=0 );
+ aEquiv[0] = iCur;
+ aEquiv[1] = iColumn;
+ for(;;){
+ for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
+ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+ if( pTerm->leftCursor==iCur
+ && pTerm->u.leftColumn==iColumn
+ ){
+ if( (pTerm->prereqRight & notReady)==0
+ && (pTerm->eOperator & op & WO_ALL)!=0
+ ){
+ if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
+ CollSeq *pColl;
+ char idxaff;
+
+ pX = pTerm->pExpr;
+ pParse = pWC->pParse;
+ idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
+ if( !sqlite3IndexAffinityOk(pX, idxaff) ){
+ continue;
+ }
+
+ /* Figure out the collation sequence required from an index for
+ ** it to be useful for optimising expression pX. Store this
+ ** value in variable pColl.
+ */
+ assert(pX->pLeft);
+ pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
+ if( pColl==0 ) pColl = pParse->db->pDfltColl;
+
+ for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
+ if( NEVER(j>=pIdx->nColumn) ) return 0;
+ }
+ if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
+ continue;
+ }
+ }
+ if( pTerm->prereqRight==0 ){
+ pResult = pTerm;
+ goto findTerm_success;
+ }else if( pResult==0 ){
+ pResult = pTerm;
+ }
+ }
+ if( (pTerm->eOperator & WO_EQUIV)!=0
+ && nEquiv<ArraySize(aEquiv)
+ ){
+ pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
+ assert( pX->op==TK_COLUMN );
+ for(j=0; j<nEquiv; j+=2){
+ if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
+ }
+ if( j==nEquiv ){
+ aEquiv[j] = pX->iTable;
+ aEquiv[j+1] = pX->iColumn;
+ nEquiv += 2;
+ }
+ }
+ }
+ }
+ }
+ if( iEquiv>=nEquiv ) break;
+ iCur = aEquiv[iEquiv++];
+ iColumn = aEquiv[iEquiv++];
+ }
+findTerm_success:
+ return pResult;
+}
+
+/* Forward reference */
+static void exprAnalyze(SrcList*, WhereClause*, int);
+
+/*
+** Call exprAnalyze on all terms in a WHERE clause.
+**
+**
+*/
+static void exprAnalyzeAll(
+ SrcList *pTabList, /* the FROM clause */
+ WhereClause *pWC /* the WHERE clause to be analyzed */
+){
+ int i;
+ for(i=pWC->nTerm-1; i>=0; i--){
+ exprAnalyze(pTabList, pWC, i);
+ }
+}
+
+#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
+/*
+** Check to see if the given expression is a LIKE or GLOB operator that
+** can be optimized using inequality constraints. Return TRUE if it is
+** so and false if not.
+**
+** In order for the operator to be optimizible, the RHS must be a string
+** literal that does not begin with a wildcard.
+*/
+static int isLikeOrGlob(
+ Parse *pParse, /* Parsing and code generating context */
+ Expr *pExpr, /* Test this expression */
+ Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */
+ int *pisComplete, /* True if the only wildcard is % in the last character */
+ int *pnoCase /* True if uppercase is equivalent to lowercase */
+){
+ const char *z = 0; /* String on RHS of LIKE operator */
+ Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
+ ExprList *pList; /* List of operands to the LIKE operator */
+ int c; /* One character in z[] */
+ int cnt; /* Number of non-wildcard prefix characters */
+ char wc[3]; /* Wildcard characters */
+ sqlite3 *db = pParse->db; /* Database connection */
+ sqlite3_value *pVal = 0;
+ int op; /* Opcode of pRight */
+
+ if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
+ return 0;
+ }
+#ifdef SQLITE_EBCDIC
+ if( *pnoCase ) return 0;
+#endif
+ pList = pExpr->x.pList;
+ pLeft = pList->a[1].pExpr;
+ if( pLeft->op!=TK_COLUMN
+ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
+ || IsVirtual(pLeft->pTab)
+ ){
+ /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
+ ** be the name of an indexed column with TEXT affinity. */
+ return 0;
+ }
+ assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
+
+ pRight = pList->a[0].pExpr;
+ op = pRight->op;
+ if( op==TK_REGISTER ){
+ op = pRight->op2;
+ }
+ if( op==TK_VARIABLE ){
+ Vdbe *pReprepare = pParse->pReprepare;
+ int iCol = pRight->iColumn;
+ pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE);
+ if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
+ z = (char *)sqlite3_value_text(pVal);
+ }
+ sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
+ assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
+ }else if( op==TK_STRING ){
+ z = pRight->u.zToken;
+ }
+ if( z ){
+ cnt = 0;
+ while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
+ cnt++;
+ }
+ if( cnt!=0 && 255!=(u8)z[cnt-1] ){
+ Expr *pPrefix;
+ *pisComplete = c==wc[0] && z[cnt+1]==0;
+ pPrefix = sqlite3Expr(db, TK_STRING, z);
+ if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
+ *ppPrefix = pPrefix;
+ if( op==TK_VARIABLE ){
+ Vdbe *v = pParse->pVdbe;
+ sqlite3VdbeSetVarmask(v, pRight->iColumn);
+ if( *pisComplete && pRight->u.zToken[1] ){
+ /* If the rhs of the LIKE expression is a variable, and the current
+ ** value of the variable means there is no need to invoke the LIKE
+ ** function, then no OP_Variable will be added to the program.
+ ** This causes problems for the sqlite3_bind_parameter_name()
+ ** API. To workaround them, add a dummy OP_Variable here.
+ */
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3ExprCodeTarget(pParse, pRight, r1);
+ sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0);
+ sqlite3ReleaseTempReg(pParse, r1);
+ }
+ }
+ }else{
+ z = 0;
+ }
+ }
+
+ sqlite3ValueFree(pVal);
+ return (z!=0);
+}
+#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Check to see if the given expression is of the form
+**
+** column MATCH expr
+**
+** If it is then return TRUE. If not, return FALSE.
+*/
+static int isMatchOfColumn(
+ Expr *pExpr /* Test this expression */
+){
+ ExprList *pList;
+
+ if( pExpr->op!=TK_FUNCTION ){
+ return 0;
+ }
+ if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){
+ return 0;
+ }
+ pList = pExpr->x.pList;
+ if( pList->nExpr!=2 ){
+ return 0;
+ }
+ if( pList->a[1].pExpr->op != TK_COLUMN ){
+ return 0;
+ }
+ return 1;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/*
+** If the pBase expression originated in the ON or USING clause of
+** a join, then transfer the appropriate markings over to derived.
+*/
+static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
+ pDerived->flags |= pBase->flags & EP_FromJoin;
+ pDerived->iRightJoinTable = pBase->iRightJoinTable;
+}
+
+#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
+/*
+** Analyze a term that consists of two or more OR-connected
+** subterms. So in:
+**
+** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)
+** ^^^^^^^^^^^^^^^^^^^^
+**
+** This routine analyzes terms such as the middle term in the above example.
+** A WhereOrTerm object is computed and attached to the term under
+** analysis, regardless of the outcome of the analysis. Hence:
+**
+** WhereTerm.wtFlags |= TERM_ORINFO
+** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object
+**
+** The term being analyzed must have two or more of OR-connected subterms.
+** A single subterm might be a set of AND-connected sub-subterms.
+** Examples of terms under analysis:
+**
+** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5
+** (B) x=expr1 OR expr2=x OR x=expr3
+** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
+** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
+** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
+**
+** CASE 1:
+**
+** If all subterms are of the form T.C=expr for some single column of C and
+** a single table T (as shown in example B above) then create a new virtual
+** term that is an equivalent IN expression. In other words, if the term
+** being analyzed is:
+**
+** x = expr1 OR expr2 = x OR x = expr3
+**
+** then create a new virtual term like this:
+**
+** x IN (expr1,expr2,expr3)
+**
+** CASE 2:
+**
+** If all subterms are indexable by a single table T, then set
+**
+** WhereTerm.eOperator = WO_OR
+** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T
+**
+** A subterm is "indexable" if it is of the form
+** "T.C <op> <expr>" where C is any column of table T and
+** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
+** A subterm is also indexable if it is an AND of two or more
+** subsubterms at least one of which is indexable. Indexable AND
+** subterms have their eOperator set to WO_AND and they have
+** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
+**
+** From another point of view, "indexable" means that the subterm could
+** potentially be used with an index if an appropriate index exists.
+** This analysis does not consider whether or not the index exists; that
+** is something the bestIndex() routine will determine. This analysis
+** only looks at whether subterms appropriate for indexing exist.
+**
+** All examples A through E above all satisfy case 2. But if a term
+** also statisfies case 1 (such as B) we know that the optimizer will
+** always prefer case 1, so in that case we pretend that case 2 is not
+** satisfied.
+**
+** It might be the case that multiple tables are indexable. For example,
+** (E) above is indexable on tables P, Q, and R.
+**
+** Terms that satisfy case 2 are candidates for lookup by using
+** separate indices to find rowids for each subterm and composing
+** the union of all rowids using a RowSet object. This is similar
+** to "bitmap indices" in other database engines.
+**
+** OTHERWISE:
+**
+** If neither case 1 nor case 2 apply, then leave the eOperator set to
+** zero. This term is not useful for search.
+*/
+static void exprAnalyzeOrTerm(
+ SrcList *pSrc, /* the FROM clause */
+ WhereClause *pWC, /* the complete WHERE clause */
+ int idxTerm /* Index of the OR-term to be analyzed */
+){
+ Parse *pParse = pWC->pParse; /* Parser context */
+ sqlite3 *db = pParse->db; /* Database connection */
+ WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */
+ Expr *pExpr = pTerm->pExpr; /* The expression of the term */
+ WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */
+ int i; /* Loop counters */
+ WhereClause *pOrWc; /* Breakup of pTerm into subterms */
+ WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */
+ WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */
+ Bitmask chngToIN; /* Tables that might satisfy case 1 */
+ Bitmask indexable; /* Tables that are indexable, satisfying case 2 */
+
+ /*
+ ** Break the OR clause into its separate subterms. The subterms are
+ ** stored in a WhereClause structure containing within the WhereOrInfo
+ ** object that is attached to the original OR clause term.
+ */
+ assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 );
+ assert( pExpr->op==TK_OR );
+ pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo));
+ if( pOrInfo==0 ) return;
+ pTerm->wtFlags |= TERM_ORINFO;
+ pOrWc = &pOrInfo->wc;
+ whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereSplit(pOrWc, pExpr, TK_OR);
+ exprAnalyzeAll(pSrc, pOrWc);
+ if( db->mallocFailed ) return;
+ assert( pOrWc->nTerm>=2 );
+
+ /*
+ ** Compute the set of tables that might satisfy cases 1 or 2.
+ */
+ indexable = ~(Bitmask)0;
+ chngToIN = ~(Bitmask)0;
+ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
+ if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
+ WhereAndInfo *pAndInfo;
+ assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
+ chngToIN = 0;
+ pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
+ if( pAndInfo ){
+ WhereClause *pAndWC;
+ WhereTerm *pAndTerm;
+ int j;
+ Bitmask b = 0;
+ pOrTerm->u.pAndInfo = pAndInfo;
+ pOrTerm->wtFlags |= TERM_ANDINFO;
+ pOrTerm->eOperator = WO_AND;
+ pAndWC = &pAndInfo->wc;
+ whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
+ exprAnalyzeAll(pSrc, pAndWC);
+ pAndWC->pOuter = pWC;
+ testcase( db->mallocFailed );
+ if( !db->mallocFailed ){
+ for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
+ assert( pAndTerm->pExpr );
+ if( allowedOp(pAndTerm->pExpr->op) ){
+ b |= getMask(pMaskSet, pAndTerm->leftCursor);
+ }
+ }
+ }
+ indexable &= b;
+ }
+ }else if( pOrTerm->wtFlags & TERM_COPIED ){
+ /* Skip this term for now. We revisit it when we process the
+ ** corresponding TERM_VIRTUAL term */
+ }else{
+ Bitmask b;
+ b = getMask(pMaskSet, pOrTerm->leftCursor);
+ if( pOrTerm->wtFlags & TERM_VIRTUAL ){
+ WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
+ b |= getMask(pMaskSet, pOther->leftCursor);
+ }
+ indexable &= b;
+ if( (pOrTerm->eOperator & WO_EQ)==0 ){
+ chngToIN = 0;
+ }else{
+ chngToIN &= b;
+ }
+ }
+ }
+
+ /*
+ ** Record the set of tables that satisfy case 2. The set might be
+ ** empty.
+ */
+ pOrInfo->indexable = indexable;
+ pTerm->eOperator = indexable==0 ? 0 : WO_OR;
+
+ /*
+ ** chngToIN holds a set of tables that *might* satisfy case 1. But
+ ** we have to do some additional checking to see if case 1 really
+ ** is satisfied.
+ **
+ ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
+ ** that there is no possibility of transforming the OR clause into an
+ ** IN operator because one or more terms in the OR clause contain
+ ** something other than == on a column in the single table. The 1-bit
+ ** case means that every term of the OR clause is of the form
+ ** "table.column=expr" for some single table. The one bit that is set
+ ** will correspond to the common table. We still need to check to make
+ ** sure the same column is used on all terms. The 2-bit case is when
+ ** the all terms are of the form "table1.column=table2.column". It
+ ** might be possible to form an IN operator with either table1.column
+ ** or table2.column as the LHS if either is common to every term of
+ ** the OR clause.
+ **
+ ** Note that terms of the form "table.column1=table.column2" (the
+ ** same table on both sizes of the ==) cannot be optimized.
+ */
+ if( chngToIN ){
+ int okToChngToIN = 0; /* True if the conversion to IN is valid */
+ int iColumn = -1; /* Column index on lhs of IN operator */
+ int iCursor = -1; /* Table cursor common to all terms */
+ int j = 0; /* Loop counter */
+
+ /* Search for a table and column that appears on one side or the
+ ** other of the == operator in every subterm. That table and column
+ ** will be recorded in iCursor and iColumn. There might not be any
+ ** such table and column. Set okToChngToIN if an appropriate table
+ ** and column is found but leave okToChngToIN false if not found.
+ */
+ for(j=0; j<2 && !okToChngToIN; j++){
+ pOrTerm = pOrWc->a;
+ for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
+ assert( pOrTerm->eOperator & WO_EQ );
+ pOrTerm->wtFlags &= ~TERM_OR_OK;
+ if( pOrTerm->leftCursor==iCursor ){
+ /* This is the 2-bit case and we are on the second iteration and
+ ** current term is from the first iteration. So skip this term. */
+ assert( j==1 );
+ continue;
+ }
+ if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
+ /* This term must be of the form t1.a==t2.b where t2 is in the
+ ** chngToIN set but t1 is not. This term will be either preceeded
+ ** or follwed by an inverted copy (t2.b==t1.a). Skip this term
+ ** and use its inversion. */
+ testcase( pOrTerm->wtFlags & TERM_COPIED );
+ testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
+ assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
+ continue;
+ }
+ iColumn = pOrTerm->u.leftColumn;
+ iCursor = pOrTerm->leftCursor;
+ break;
+ }
+ if( i<0 ){
+ /* No candidate table+column was found. This can only occur
+ ** on the second iteration */
+ assert( j==1 );
+ assert( IsPowerOfTwo(chngToIN) );
+ assert( chngToIN==getMask(pMaskSet, iCursor) );
+ break;
+ }
+ testcase( j==1 );
+
+ /* We have found a candidate table and column. Check to see if that
+ ** table and column is common to every term in the OR clause */
+ okToChngToIN = 1;
+ for(; i>=0 && okToChngToIN; i--, pOrTerm++){
+ assert( pOrTerm->eOperator & WO_EQ );
+ if( pOrTerm->leftCursor!=iCursor ){
+ pOrTerm->wtFlags &= ~TERM_OR_OK;
+ }else if( pOrTerm->u.leftColumn!=iColumn ){
+ okToChngToIN = 0;
+ }else{
+ int affLeft, affRight;
+ /* If the right-hand side is also a column, then the affinities
+ ** of both right and left sides must be such that no type
+ ** conversions are required on the right. (Ticket #2249)
+ */
+ affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
+ affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
+ if( affRight!=0 && affRight!=affLeft ){
+ okToChngToIN = 0;
+ }else{
+ pOrTerm->wtFlags |= TERM_OR_OK;
+ }
+ }
+ }
+ }
+
+ /* At this point, okToChngToIN is true if original pTerm satisfies
+ ** case 1. In that case, construct a new virtual term that is
+ ** pTerm converted into an IN operator.
+ **
+ ** EV: R-00211-15100
+ */
+ if( okToChngToIN ){
+ Expr *pDup; /* A transient duplicate expression */
+ ExprList *pList = 0; /* The RHS of the IN operator */
+ Expr *pLeft = 0; /* The LHS of the IN operator */
+ Expr *pNew; /* The complete IN operator */
+
+ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
+ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
+ assert( pOrTerm->eOperator & WO_EQ );
+ assert( pOrTerm->leftCursor==iCursor );
+ assert( pOrTerm->u.leftColumn==iColumn );
+ pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
+ pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
+ pLeft = pOrTerm->pExpr->pLeft;
+ }
+ assert( pLeft!=0 );
+ pDup = sqlite3ExprDup(db, pLeft, 0);
+ pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0);
+ if( pNew ){
+ int idxNew;
+ transferJoinMarkings(pNew, pExpr);
+ assert( !ExprHasProperty(pNew, EP_xIsSelect) );
+ pNew->x.pList = pList;
+ idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
+ exprAnalyze(pSrc, pWC, idxNew);
+ pTerm = &pWC->a[idxTerm];
+ pWC->a[idxNew].iParent = idxTerm;
+ pTerm->nChild = 1;
+ }else{
+ sqlite3ExprListDelete(db, pList);
+ }
+ pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */
+ }
+ }
+}
+#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
+
+/*
+** The input to this routine is an WhereTerm structure with only the
+** "pExpr" field filled in. The job of this routine is to analyze the
+** subexpression and populate all the other fields of the WhereTerm
+** structure.
+**
+** If the expression is of the form "<expr> <op> X" it gets commuted
+** to the standard form of "X <op> <expr>".
+**
+** If the expression is of the form "X <op> Y" where both X and Y are
+** columns, then the original expression is unchanged and a new virtual
+** term of the form "Y <op> X" is added to the WHERE clause and
+** analyzed separately. The original term is marked with TERM_COPIED
+** and the new term is marked with TERM_DYNAMIC (because it's pExpr
+** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it
+** is a commuted copy of a prior term.) The original term has nChild=1
+** and the copy has idxParent set to the index of the original term.
+*/
+static void exprAnalyze(
+ SrcList *pSrc, /* the FROM clause */
+ WhereClause *pWC, /* the WHERE clause */
+ int idxTerm /* Index of the term to be analyzed */
+){
+ WhereTerm *pTerm; /* The term to be analyzed */
+ WhereMaskSet *pMaskSet; /* Set of table index masks */
+ Expr *pExpr; /* The expression to be analyzed */
+ Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
+ Bitmask prereqAll; /* Prerequesites of pExpr */
+ Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
+ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
+ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
+ int noCase = 0; /* LIKE/GLOB distinguishes case */
+ int op; /* Top-level operator. pExpr->op */
+ Parse *pParse = pWC->pParse; /* Parsing context */
+ sqlite3 *db = pParse->db; /* Database connection */
+
+ if( db->mallocFailed ){
+ return;
+ }
+ pTerm = &pWC->a[idxTerm];
+ pMaskSet = pWC->pMaskSet;
+ pExpr = pTerm->pExpr;
+ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
+ prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
+ op = pExpr->op;
+ if( op==TK_IN ){
+ assert( pExpr->pRight==0 );
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect);
+ }else{
+ pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList);
+ }
+ }else if( op==TK_ISNULL ){
+ pTerm->prereqRight = 0;
+ }else{
+ pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
+ }
+ prereqAll = exprTableUsage(pMaskSet, pExpr);
+ if( ExprHasProperty(pExpr, EP_FromJoin) ){
+ Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable);
+ prereqAll |= x;
+ extraRight = x-1; /* ON clause terms may not be used with an index
+ ** on left table of a LEFT JOIN. Ticket #3015 */
+ }
+ pTerm->prereqAll = prereqAll;
+ pTerm->leftCursor = -1;
+ pTerm->iParent = -1;
+ pTerm->eOperator = 0;
+ if( allowedOp(op) ){
+ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
+ Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
+ u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
+ if( pLeft->op==TK_COLUMN ){
+ pTerm->leftCursor = pLeft->iTable;
+ pTerm->u.leftColumn = pLeft->iColumn;
+ pTerm->eOperator = operatorMask(op) & opMask;
+ }
+ if( pRight && pRight->op==TK_COLUMN ){
+ WhereTerm *pNew;
+ Expr *pDup;
+ u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
+ if( pTerm->leftCursor>=0 ){
+ int idxNew;
+ pDup = sqlite3ExprDup(db, pExpr, 0);
+ if( db->mallocFailed ){
+ sqlite3ExprDelete(db, pDup);
+ return;
+ }
+ idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
+ if( idxNew==0 ) return;
+ pNew = &pWC->a[idxNew];
+ pNew->iParent = idxTerm;
+ pTerm = &pWC->a[idxTerm];
+ pTerm->nChild = 1;
+ pTerm->wtFlags |= TERM_COPIED;
+ if( pExpr->op==TK_EQ
+ && !ExprHasProperty(pExpr, EP_FromJoin)
+ && OptimizationEnabled(db, SQLITE_Transitive)
+ ){
+ pTerm->eOperator |= WO_EQUIV;
+ eExtraOp = WO_EQUIV;
+ }
+ }else{
+ pDup = pExpr;
+ pNew = pTerm;
+ }
+ exprCommute(pParse, pDup);
+ pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
+ pNew->leftCursor = pLeft->iTable;
+ pNew->u.leftColumn = pLeft->iColumn;
+ testcase( (prereqLeft | extraRight) != prereqLeft );
+ pNew->prereqRight = prereqLeft | extraRight;
+ pNew->prereqAll = prereqAll;
+ pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
+ }
+ }
+
+#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
+ /* If a term is the BETWEEN operator, create two new virtual terms
+ ** that define the range that the BETWEEN implements. For example:
+ **
+ ** a BETWEEN b AND c
+ **
+ ** is converted into:
+ **
+ ** (a BETWEEN b AND c) AND (a>=b) AND (a<=c)
+ **
+ ** The two new terms are added onto the end of the WhereClause object.
+ ** The new terms are "dynamic" and are children of the original BETWEEN
+ ** term. That means that if the BETWEEN term is coded, the children are
+ ** skipped. Or, if the children are satisfied by an index, the original
+ ** BETWEEN term is skipped.
+ */
+ else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
+ ExprList *pList = pExpr->x.pList;
+ int i;
+ static const u8 ops[] = {TK_GE, TK_LE};
+ assert( pList!=0 );
+ assert( pList->nExpr==2 );
+ for(i=0; i<2; i++){
+ Expr *pNewExpr;
+ int idxNew;
+ pNewExpr = sqlite3PExpr(pParse, ops[i],
+ sqlite3ExprDup(db, pExpr->pLeft, 0),
+ sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
+ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
+ exprAnalyze(pSrc, pWC, idxNew);
+ pTerm = &pWC->a[idxTerm];
+ pWC->a[idxNew].iParent = idxTerm;
+ }
+ pTerm->nChild = 2;
+ }
+#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */
+
+#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
+ /* Analyze a term that is composed of two or more subterms connected by
+ ** an OR operator.
+ */
+ else if( pExpr->op==TK_OR ){
+ assert( pWC->op==TK_AND );
+ exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ }
+#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+
+#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
+ /* Add constraints to reduce the search space on a LIKE or GLOB
+ ** operator.
+ **
+ ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
+ **
+ ** x>='abc' AND x<'abd' AND x LIKE 'abc%'
+ **
+ ** The last character of the prefix "abc" is incremented to form the
+ ** termination condition "abd".
+ */
+ if( pWC->op==TK_AND
+ && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
+ ){
+ Expr *pLeft; /* LHS of LIKE/GLOB operator */
+ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */
+ Expr *pNewExpr1;
+ Expr *pNewExpr2;
+ int idxNew1;
+ int idxNew2;
+ Token sCollSeqName; /* Name of collating sequence */
+
+ pLeft = pExpr->x.pList->a[1].pExpr;
+ pStr2 = sqlite3ExprDup(db, pStr1, 0);
+ if( !db->mallocFailed ){
+ u8 c, *pC; /* Last character before the first wildcard */
+ pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
+ c = *pC;
+ if( noCase ){
+ /* The point is to increment the last character before the first
+ ** wildcard. But if we increment '@', that will push it into the
+ ** alphabetic range where case conversions will mess up the
+ ** inequality. To avoid this, make sure to also run the full
+ ** LIKE on all candidate expressions by clearing the isComplete flag
+ */
+ if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */
+
+
+ c = sqlite3UpperToLower[c];
+ }
+ *pC = c + 1;
+ }
+ sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
+ sCollSeqName.n = 6;
+ pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
+ pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
+ sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
+ pStr1, 0);
+ idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew1==0 );
+ exprAnalyze(pSrc, pWC, idxNew1);
+ pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
+ pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
+ sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
+ pStr2, 0);
+ idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew2==0 );
+ exprAnalyze(pSrc, pWC, idxNew2);
+ pTerm = &pWC->a[idxTerm];
+ if( isComplete ){
+ pWC->a[idxNew1].iParent = idxTerm;
+ pWC->a[idxNew2].iParent = idxTerm;
+ pTerm->nChild = 2;
+ }
+ }
+#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Add a WO_MATCH auxiliary term to the constraint set if the
+ ** current expression is of the form: column MATCH expr.
+ ** This information is used by the xBestIndex methods of
+ ** virtual tables. The native query optimizer does not attempt
+ ** to do anything with MATCH functions.
+ */
+ if( isMatchOfColumn(pExpr) ){
+ int idxNew;
+ Expr *pRight, *pLeft;
+ WhereTerm *pNewTerm;
+ Bitmask prereqColumn, prereqExpr;
+
+ pRight = pExpr->x.pList->a[0].pExpr;
+ pLeft = pExpr->x.pList->a[1].pExpr;
+ prereqExpr = exprTableUsage(pMaskSet, pRight);
+ prereqColumn = exprTableUsage(pMaskSet, pLeft);
+ if( (prereqExpr & prereqColumn)==0 ){
+ Expr *pNewExpr;
+ pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
+ 0, sqlite3ExprDup(db, pRight, 0), 0);
+ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_MATCH;
+ pNewTerm->iParent = idxTerm;
+ pTerm = &pWC->a[idxTerm];
+ pTerm->nChild = 1;
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ }
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifdef SQLITE_ENABLE_STAT3
+ /* When sqlite_stat3 histogram data is available an operator of the
+ ** form "x IS NOT NULL" can sometimes be evaluated more efficiently
+ ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
+ ** virtual term of that form.
+ **
+ ** Note that the virtual term must be tagged with TERM_VNULL. This
+ ** TERM_VNULL tag will suppress the not-null check at the beginning
+ ** of the loop. Without the TERM_VNULL flag, the not-null check at
+ ** the start of the loop will prevent any results from being returned.
+ */
+ if( pExpr->op==TK_NOTNULL
+ && pExpr->pLeft->op==TK_COLUMN
+ && pExpr->pLeft->iColumn>=0
+ ){
+ Expr *pNewExpr;
+ Expr *pLeft = pExpr->pLeft;
+ int idxNew;
+ WhereTerm *pNewTerm;
+
+ pNewExpr = sqlite3PExpr(pParse, TK_GT,
+ sqlite3ExprDup(db, pLeft, 0),
+ sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0);
+
+ idxNew = whereClauseInsert(pWC, pNewExpr,
+ TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
+ if( idxNew ){
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = 0;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_GT;
+ pNewTerm->iParent = idxTerm;
+ pTerm = &pWC->a[idxTerm];
+ pTerm->nChild = 1;
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ }
+#endif /* SQLITE_ENABLE_STAT */
+
+ /* Prevent ON clause terms of a LEFT JOIN from being used to drive
+ ** an index for tables to the left of the join.
+ */
+ pTerm->prereqRight |= extraRight;
+}
+
+/*
+** This function searches the expression list passed as the second argument
+** for an expression of type TK_COLUMN that refers to the same column and
+** uses the same collation sequence as the iCol'th column of index pIdx.
+** Argument iBase is the cursor number used for the table that pIdx refers
+** to.
+**
+** If such an expression is found, its index in pList->a[] is returned. If
+** no expression is found, -1 is returned.
+*/
+static int findIndexCol(
+ Parse *pParse, /* Parse context */
+ ExprList *pList, /* Expression list to search */
+ int iBase, /* Cursor for table associated with pIdx */
+ Index *pIdx, /* Index to match column of */
+ int iCol /* Column of index to match */
+){
+ int i;
+ const char *zColl = pIdx->azColl[iCol];
+
+ for(i=0; i<pList->nExpr; i++){
+ Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
+ if( p->op==TK_COLUMN
+ && p->iColumn==pIdx->aiColumn[iCol]
+ && p->iTable==iBase
+ ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
+ if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/*
+** This routine determines if pIdx can be used to assist in processing a
+** DISTINCT qualifier. In other words, it tests whether or not using this
+** index for the outer loop guarantees that rows with equal values for
+** all expressions in the pDistinct list are delivered grouped together.
+**
+** For example, the query
+**
+** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
+**
+** can benefit from any index on columns "b" and "c".
+*/
+static int isDistinctIndex(
+ Parse *pParse, /* Parsing context */
+ WhereClause *pWC, /* The WHERE clause */
+ Index *pIdx, /* The index being considered */
+ int base, /* Cursor number for the table pIdx is on */
+ ExprList *pDistinct, /* The DISTINCT expressions */
+ int nEqCol /* Number of index columns with == */
+){
+ Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
+ int i; /* Iterator variable */
+
+ assert( pDistinct!=0 );
+ if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0;
+ testcase( pDistinct->nExpr==BMS-1 );
+
+ /* Loop through all the expressions in the distinct list. If any of them
+ ** are not simple column references, return early. Otherwise, test if the
+ ** WHERE clause contains a "col=X" clause. If it does, the expression
+ ** can be ignored. If it does not, and the column does not belong to the
+ ** same table as index pIdx, return early. Finally, if there is no
+ ** matching "col=X" expression and the column is on the same table as pIdx,
+ ** set the corresponding bit in variable mask.
+ */
+ for(i=0; i<pDistinct->nExpr; i++){
+ WhereTerm *pTerm;
+ Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
+ if( p->op!=TK_COLUMN ) return 0;
+ pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
+ if( pTerm ){
+ Expr *pX = pTerm->pExpr;
+ CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+ CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
+ if( p1==p2 ) continue;
+ }
+ if( p->iTable!=base ) return 0;
+ mask |= (((Bitmask)1) << i);
+ }
+
+ for(i=nEqCol; mask && i<pIdx->nColumn; i++){
+ int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
+ if( iExpr<0 ) break;
+ mask &= ~(((Bitmask)1) << iExpr);
+ }
+
+ return (mask==0);
+}
+
+
+/*
+** Return true if the DISTINCT expression-list passed as the third argument
+** is redundant. A DISTINCT list is redundant if the database contains a
+** UNIQUE index that guarantees that the result of the query will be distinct
+** anyway.
+*/
+static int isDistinctRedundant(
+ Parse *pParse,
+ SrcList *pTabList,
+ WhereClause *pWC,
+ ExprList *pDistinct
+){
+ Table *pTab;
+ Index *pIdx;
+ int i;
+ int iBase;
+
+ /* If there is more than one table or sub-select in the FROM clause of
+ ** this query, then it will not be possible to show that the DISTINCT
+ ** clause is redundant. */
+ if( pTabList->nSrc!=1 ) return 0;
+ iBase = pTabList->a[0].iCursor;
+ pTab = pTabList->a[0].pTab;
+
+ /* If any of the expressions is an IPK column on table iBase, then return
+ ** true. Note: The (p->iTable==iBase) part of this test may be false if the
+ ** current SELECT is a correlated sub-query.
+ */
+ for(i=0; i<pDistinct->nExpr; i++){
+ Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
+ if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
+ }
+
+ /* Loop through all indices on the table, checking each to see if it makes
+ ** the DISTINCT qualifier redundant. It does so if:
+ **
+ ** 1. The index is itself UNIQUE, and
+ **
+ ** 2. All of the columns in the index are either part of the pDistinct
+ ** list, or else the WHERE clause contains a term of the form "col=X",
+ ** where X is a constant value. The collation sequences of the
+ ** comparison and select-list expressions must match those of the index.
+ **
+ ** 3. All of those index columns for which the WHERE clause does not
+ ** contain a "col=X" term are subject to a NOT NULL constraint.
+ */
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->onError==OE_None ) continue;
+ for(i=0; i<pIdx->nColumn; i++){
+ int iCol = pIdx->aiColumn[i];
+ if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){
+ int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
+ if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){
+ break;
+ }
+ }
+ }
+ if( i==pIdx->nColumn ){
+ /* This index implies that the DISTINCT qualifier is redundant. */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+** Prepare a crude estimate of the logarithm of the input value.
+** The results need not be exact. This is only used for estimating
+** the total cost of performing operations with O(logN) or O(NlogN)
+** complexity. Because N is just a guess, it is no great tragedy if
+** logN is a little off.
+*/
+static double estLog(double N){
+ double logN = 1;
+ double x = 10;
+ while( N>x ){
+ logN += 1;
+ x *= 10;
+ }
+ return logN;
+}
+
+/*
+** Two routines for printing the content of an sqlite3_index_info
+** structure. Used for testing and debugging only. If neither
+** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
+** are no-ops.
+*/
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG)
+static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
+ int i;
+ if( !sqlite3WhereTrace ) return;
+ for(i=0; i<p->nConstraint; i++){
+ sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
+ i,
+ p->aConstraint[i].iColumn,
+ p->aConstraint[i].iTermOffset,
+ p->aConstraint[i].op,
+ p->aConstraint[i].usable);
+ }
+ for(i=0; i<p->nOrderBy; i++){
+ sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n",
+ i,
+ p->aOrderBy[i].iColumn,
+ p->aOrderBy[i].desc);
+ }
+}
+static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
+ int i;
+ if( !sqlite3WhereTrace ) return;
+ for(i=0; i<p->nConstraint; i++){
+ sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n",
+ i,
+ p->aConstraintUsage[i].argvIndex,
+ p->aConstraintUsage[i].omit);
+ }
+ sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum);
+ sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr);
+ sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed);
+ sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost);
+}
+#else
+#define TRACE_IDX_INPUTS(A)
+#define TRACE_IDX_OUTPUTS(A)
+#endif
+
+/*
+** Required because bestIndex() is called by bestOrClauseIndex()
+*/
+static void bestIndex(WhereBestIdx*);
+
+/*
+** This routine attempts to find an scanning strategy that can be used
+** to optimize an 'OR' expression that is part of a WHERE clause.
+**
+** The table associated with FROM clause term pSrc may be either a
+** regular B-Tree table or a virtual table.
+*/
+static void bestOrClauseIndex(WhereBestIdx *p){
+#ifndef SQLITE_OMIT_OR_OPTIMIZATION
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+ const int iCur = pSrc->iCursor; /* The cursor of the table */
+ const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */
+ WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
+
+ /* The OR-clause optimization is disallowed if the INDEXED BY or
+ ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
+ if( pSrc->notIndexed || pSrc->pIndex!=0 ){
+ return;
+ }
+ if( pWC->wctrlFlags & WHERE_AND_ONLY ){
+ return;
+ }
+
+ /* Search the WHERE clause terms for a usable WO_OR term. */
+ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
+ if( (pTerm->eOperator & WO_OR)!=0
+ && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
+ && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
+ ){
+ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
+ WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
+ WhereTerm *pOrTerm;
+ int flags = WHERE_MULTI_OR;
+ double rTotal = 0;
+ double nRow = 0;
+ Bitmask used = 0;
+ WhereBestIdx sBOI;
+
+ sBOI = *p;
+ sBOI.pOrderBy = 0;
+ sBOI.pDistinct = 0;
+ sBOI.ppIdxInfo = 0;
+ for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
+ WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
+ (pOrTerm - pOrWC->a), (pTerm - pWC->a)
+ ));
+ if( (pOrTerm->eOperator& WO_AND)!=0 ){
+ sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
+ bestIndex(&sBOI);
+ }else if( pOrTerm->leftCursor==iCur ){
+ WhereClause tempWC;
+ tempWC.pParse = pWC->pParse;
+ tempWC.pMaskSet = pWC->pMaskSet;
+ tempWC.pOuter = pWC;
+ tempWC.op = TK_AND;
+ tempWC.a = pOrTerm;
+ tempWC.wctrlFlags = 0;
+ tempWC.nTerm = 1;
+ sBOI.pWC = &tempWC;
+ bestIndex(&sBOI);
+ }else{
+ continue;
+ }
+ rTotal += sBOI.cost.rCost;
+ nRow += sBOI.cost.plan.nRow;
+ used |= sBOI.cost.used;
+ if( rTotal>=p->cost.rCost ) break;
+ }
+
+ /* If there is an ORDER BY clause, increase the scan cost to account
+ ** for the cost of the sort. */
+ if( p->pOrderBy!=0 ){
+ WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
+ rTotal, rTotal+nRow*estLog(nRow)));
+ rTotal += nRow*estLog(nRow);
+ }
+
+ /* If the cost of scanning using this OR term for optimization is
+ ** less than the current cost stored in pCost, replace the contents
+ ** of pCost. */
+ WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
+ if( rTotal<p->cost.rCost ){
+ p->cost.rCost = rTotal;
+ p->cost.used = used;
+ p->cost.plan.nRow = nRow;
+ p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
+ p->cost.plan.wsFlags = flags;
+ p->cost.plan.u.pTerm = pTerm;
+ }
+ }
+ }
+#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+}
+
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+/*
+** Return TRUE if the WHERE clause term pTerm is of a form where it
+** could be used with an index to access pSrc, assuming an appropriate
+** index existed.
+*/
+static int termCanDriveIndex(
+ WhereTerm *pTerm, /* WHERE clause term to check */
+ struct SrcList_item *pSrc, /* Table we are trying to access */
+ Bitmask notReady /* Tables in outer loops of the join */
+){
+ char aff;
+ if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
+ if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
+ if( (pTerm->prereqRight & notReady)!=0 ) return 0;
+ aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
+ if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
+ return 1;
+}
+#endif
+
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+/*
+** If the query plan for pSrc specified in pCost is a full table scan
+** and indexing is allows (if there is no NOT INDEXED clause) and it
+** possible to construct a transient index that would perform better
+** than a full table scan even when the cost of constructing the index
+** is taken into account, then alter the query plan to use the
+** transient index.
+*/
+static void bestAutomaticIndex(WhereBestIdx *p){
+ Parse *pParse = p->pParse; /* The parsing context */
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+ double nTableRow; /* Rows in the input table */
+ double logN; /* log(nTableRow) */
+ double costTempIdx; /* per-query cost of the transient index */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
+ WhereTerm *pWCEnd; /* End of pWC->a[] */
+ Table *pTable; /* Table tht might be indexed */
+
+ if( pParse->nQueryLoop<=(double)1 ){
+ /* There is no point in building an automatic index for a single scan */
+ return;
+ }
+ if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
+ /* Automatic indices are disabled at run-time */
+ return;
+ }
+ if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
+ && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
+ ){
+ /* We already have some kind of index in use for this query. */
+ return;
+ }
+ if( pSrc->viaCoroutine ){
+ /* Cannot index a co-routine */
+ return;
+ }
+ if( pSrc->notIndexed ){
+ /* The NOT INDEXED clause appears in the SQL. */
+ return;
+ }
+ if( pSrc->isCorrelated ){
+ /* The source is a correlated sub-query. No point in indexing it. */
+ return;
+ }
+
+ assert( pParse->nQueryLoop >= (double)1 );
+ pTable = pSrc->pTab;
+ nTableRow = pTable->nRowEst;
+ logN = estLog(nTableRow);
+ costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
+ if( costTempIdx>=p->cost.rCost ){
+ /* The cost of creating the transient table would be greater than
+ ** doing the full table scan */
+ return;
+ }
+
+ /* Search for any equality comparison term */
+ pWCEnd = &pWC->a[pWC->nTerm];
+ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
+ if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){
+ WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
+ p->cost.rCost, costTempIdx));
+ p->cost.rCost = costTempIdx;
+ p->cost.plan.nRow = logN + 1;
+ p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
+ p->cost.used = pTerm->prereqRight;
+ break;
+ }
+ }
+}
+#else
+# define bestAutomaticIndex(A) /* no-op */
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+
+
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+/*
+** Generate code to construct the Index object for an automatic index
+** and to set up the WhereLevel object pLevel so that the code generator
+** makes use of the automatic index.
+*/
+static void constructAutomaticIndex(
+ Parse *pParse, /* The parsing context */
+ WhereClause *pWC, /* The WHERE clause */
+ struct SrcList_item *pSrc, /* The FROM clause term to get the next index */
+ Bitmask notReady, /* Mask of cursors that are not available */
+ WhereLevel *pLevel /* Write new index here */
+){
+ int nColumn; /* Number of columns in the constructed index */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
+ WhereTerm *pWCEnd; /* End of pWC->a[] */
+ int nByte; /* Byte of memory needed for pIdx */
+ Index *pIdx; /* Object describing the transient index */
+ Vdbe *v; /* Prepared statement under construction */
+ int addrInit; /* Address of the initialization bypass jump */
+ Table *pTable; /* The table being indexed */
+ KeyInfo *pKeyinfo; /* Key information for the index */
+ int addrTop; /* Top of the index fill loop */
+ int regRecord; /* Register holding an index record */
+ int n; /* Column counter */
+ int i; /* Loop counter */
+ int mxBitCol; /* Maximum column in pSrc->colUsed */
+ CollSeq *pColl; /* Collating sequence to on a column */
+ Bitmask idxCols; /* Bitmap of columns used for indexing */
+ Bitmask extraCols; /* Bitmap of additional columns */
+
+ /* Generate code to skip over the creation and initialization of the
+ ** transient index on 2nd and subsequent iterations of the loop. */
+ v = pParse->pVdbe;
+ assert( v!=0 );
+ addrInit = sqlite3CodeOnce(pParse);
+
+ /* Count the number of columns that will be added to the index
+ ** and used to match WHERE clause constraints */
+ nColumn = 0;
+ pTable = pSrc->pTab;
+ pWCEnd = &pWC->a[pWC->nTerm];
+ idxCols = 0;
+ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
+ if( termCanDriveIndex(pTerm, pSrc, notReady) ){
+ int iCol = pTerm->u.leftColumn;
+ Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+ testcase( iCol==BMS );
+ testcase( iCol==BMS-1 );
+ if( (idxCols & cMask)==0 ){
+ nColumn++;
+ idxCols |= cMask;
+ }
+ }
+ }
+ assert( nColumn>0 );
+ pLevel->plan.nEq = nColumn;
+
+ /* Count the number of additional columns needed to create a
+ ** covering index. A "covering index" is an index that contains all
+ ** columns that are needed by the query. With a covering index, the
+ ** original table never needs to be accessed. Automatic indices must
+ ** be a covering index because the index will not be updated if the
+ ** original table changes and the index and table cannot both be used
+ ** if they go out of sync.
+ */
+ extraCols = pSrc->colUsed & (~idxCols | (((Bitmask)1)<<(BMS-1)));
+ mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
+ testcase( pTable->nCol==BMS-1 );
+ testcase( pTable->nCol==BMS-2 );
+ for(i=0; i<mxBitCol; i++){
+ if( extraCols & (((Bitmask)1)<<i) ) nColumn++;
+ }
+ if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
+ nColumn += pTable->nCol - BMS + 1;
+ }
+ pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ;
+
+ /* Construct the Index object to describe this index */
+ nByte = sizeof(Index);
+ nByte += nColumn*sizeof(int); /* Index.aiColumn */
+ nByte += nColumn*sizeof(char*); /* Index.azColl */
+ nByte += nColumn; /* Index.aSortOrder */
+ pIdx = sqlite3DbMallocZero(pParse->db, nByte);
+ if( pIdx==0 ) return;
+ pLevel->plan.u.pIdx = pIdx;
+ pIdx->azColl = (char**)&pIdx[1];
+ pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
+ pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
+ pIdx->zName = "auto-index";
+ pIdx->nColumn = nColumn;
+ pIdx->pTable = pTable;
+ n = 0;
+ idxCols = 0;
+ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
+ if( termCanDriveIndex(pTerm, pSrc, notReady) ){
+ int iCol = pTerm->u.leftColumn;
+ Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+ if( (idxCols & cMask)==0 ){
+ Expr *pX = pTerm->pExpr;
+ idxCols |= cMask;
+ pIdx->aiColumn[n] = pTerm->u.leftColumn;
+ pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+ pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY";
+ n++;
+ }
+ }
+ }
+ assert( (u32)n==pLevel->plan.nEq );
+
+ /* Add additional columns needed to make the automatic index into
+ ** a covering index */
+ for(i=0; i<mxBitCol; i++){
+ if( extraCols & (((Bitmask)1)<<i) ){
+ pIdx->aiColumn[n] = i;
+ pIdx->azColl[n] = "BINARY";
+ n++;
+ }
+ }
+ if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
+ for(i=BMS-1; i<pTable->nCol; i++){
+ pIdx->aiColumn[n] = i;
+ pIdx->azColl[n] = "BINARY";
+ n++;
+ }
+ }
+ assert( n==nColumn );
+
+ /* Create the automatic index */
+ pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx);
+ assert( pLevel->iIdxCur>=0 );
+ sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
+ (char*)pKeyinfo, P4_KEYINFO_HANDOFF);
+ VdbeComment((v, "for %s", pTable->zName));
+
+ /* Fill the automatic index with content */
+ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
+ regRecord = sqlite3GetTempReg(pParse);
+ sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
+ sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
+ sqlite3VdbeJumpHere(v, addrTop);
+ sqlite3ReleaseTempReg(pParse, regRecord);
+
+ /* Jump here when skipping the initialization */
+ sqlite3VdbeJumpHere(v, addrInit);
+}
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Allocate and populate an sqlite3_index_info structure. It is the
+** responsibility of the caller to eventually release the structure
+** by passing the pointer returned by this function to sqlite3_free().
+*/
+static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
+ Parse *pParse = p->pParse;
+ WhereClause *pWC = p->pWC;
+ struct SrcList_item *pSrc = p->pSrc;
+ ExprList *pOrderBy = p->pOrderBy;
+ int i, j;
+ int nTerm;
+ struct sqlite3_index_constraint *pIdxCons;
+ struct sqlite3_index_orderby *pIdxOrderBy;
+ struct sqlite3_index_constraint_usage *pUsage;
+ WhereTerm *pTerm;
+ int nOrderBy;
+ sqlite3_index_info *pIdxInfo;
+
+ WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));
+
+ /* Count the number of possible WHERE clause constraints referring
+ ** to this virtual table */
+ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+ testcase( pTerm->eOperator & WO_IN );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ if( pTerm->eOperator & (WO_ISNULL) ) continue;
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
+ nTerm++;
+ }
+
+ /* If the ORDER BY clause contains only columns in the current
+ ** virtual table then allocate space for the aOrderBy part of
+ ** the sqlite3_index_info structure.
+ */
+ nOrderBy = 0;
+ if( pOrderBy ){
+ int n = pOrderBy->nExpr;
+ for(i=0; i<n; i++){
+ Expr *pExpr = pOrderBy->a[i].pExpr;
+ if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
+ }
+ if( i==n){
+ nOrderBy = n;
+ }
+ }
+
+ /* Allocate the sqlite3_index_info structure
+ */
+ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
+ + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
+ + sizeof(*pIdxOrderBy)*nOrderBy );
+ if( pIdxInfo==0 ){
+ sqlite3ErrorMsg(pParse, "out of memory");
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ return 0;
+ }
+
+ /* Initialize the structure. The sqlite3_index_info structure contains
+ ** many fields that are declared "const" to prevent xBestIndex from
+ ** changing them. We have to do some funky casting in order to
+ ** initialize those fields.
+ */
+ pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1];
+ pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
+ pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
+ *(int*)&pIdxInfo->nConstraint = nTerm;
+ *(int*)&pIdxInfo->nOrderBy = nOrderBy;
+ *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
+ *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
+ *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
+ pUsage;
+
+ for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+ u8 op;
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+ testcase( pTerm->eOperator & WO_IN );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ if( pTerm->eOperator & (WO_ISNULL) ) continue;
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
+ pIdxCons[j].iColumn = pTerm->u.leftColumn;
+ pIdxCons[j].iTermOffset = i;
+ op = (u8)pTerm->eOperator & WO_ALL;
+ if( op==WO_IN ) op = WO_EQ;
+ pIdxCons[j].op = op;
+ /* The direct assignment in the previous line is possible only because
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
+ ** following asserts verify this fact. */
+ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
+ assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
+ assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
+ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
+ assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
+ assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+ j++;
+ }
+ for(i=0; i<nOrderBy; i++){
+ Expr *pExpr = pOrderBy->a[i].pExpr;
+ pIdxOrderBy[i].iColumn = pExpr->iColumn;
+ pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
+ }
+
+ return pIdxInfo;
+}
+
+/*
+** The table object reference passed as the second argument to this function
+** must represent a virtual table. This function invokes the xBestIndex()
+** method of the virtual table with the sqlite3_index_info pointer passed
+** as the argument.
+**
+** If an error occurs, pParse is populated with an error message and a
+** non-zero value is returned. Otherwise, 0 is returned and the output
+** part of the sqlite3_index_info structure is left populated.
+**
+** Whether or not an error is returned, it is the responsibility of the
+** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
+** that this is required.
+*/
+static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
+ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
+ int i;
+ int rc;
+
+ WHERETRACE(("xBestIndex for %s\n", pTab->zName));
+ TRACE_IDX_INPUTS(p);
+ rc = pVtab->pModule->xBestIndex(pVtab, p);
+ TRACE_IDX_OUTPUTS(p);
+
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ){
+ pParse->db->mallocFailed = 1;
+ }else if( !pVtab->zErrMsg ){
+ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
+ }else{
+ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
+ }
+ }
+ sqlite3_free(pVtab->zErrMsg);
+ pVtab->zErrMsg = 0;
+
+ for(i=0; i<p->nConstraint; i++){
+ if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
+ sqlite3ErrorMsg(pParse,
+ "table %s: xBestIndex returned an invalid plan", pTab->zName);
+ }
+ }
+
+ return pParse->nErr;
+}
+
+
+/*
+** Compute the best index for a virtual table.
+**
+** The best index is computed by the xBestIndex method of the virtual
+** table module. This routine is really just a wrapper that sets up
+** the sqlite3_index_info structure that is used to communicate with
+** xBestIndex.
+**
+** In a join, this routine might be called multiple times for the
+** same virtual table. The sqlite3_index_info structure is created
+** and initialized on the first invocation and reused on all subsequent
+** invocations. The sqlite3_index_info structure is also used when
+** code is generated to access the virtual table. The whereInfoDelete()
+** routine takes care of freeing the sqlite3_index_info structure after
+** everybody has finished with it.
+*/
+static void bestVirtualIndex(WhereBestIdx *p){
+ Parse *pParse = p->pParse; /* The parsing context */
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+ Table *pTab = pSrc->pTab;
+ sqlite3_index_info *pIdxInfo;
+ struct sqlite3_index_constraint *pIdxCons;
+ struct sqlite3_index_constraint_usage *pUsage;
+ WhereTerm *pTerm;
+ int i, j, k;
+ int nOrderBy;
+ int sortOrder; /* Sort order for IN clauses */
+ int bAllowIN; /* Allow IN optimizations */
+ double rCost;
+
+ /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
+ ** malloc in allocateIndexInfo() fails and this function returns leaving
+ ** wsFlags in an uninitialized state, the caller may behave unpredictably.
+ */
+ memset(&p->cost, 0, sizeof(p->cost));
+ p->cost.plan.wsFlags = WHERE_VIRTUALTABLE;
+
+ /* If the sqlite3_index_info structure has not been previously
+ ** allocated and initialized, then allocate and initialize it now.
+ */
+ pIdxInfo = *p->ppIdxInfo;
+ if( pIdxInfo==0 ){
+ *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p);
+ }
+ if( pIdxInfo==0 ){
+ return;
+ }
+
+ /* At this point, the sqlite3_index_info structure that pIdxInfo points
+ ** to will have been initialized, either during the current invocation or
+ ** during some prior invocation. Now we just have to customize the
+ ** details of pIdxInfo for the current invocation and pass it to
+ ** xBestIndex.
+ */
+
+ /* The module name must be defined. Also, by this point there must
+ ** be a pointer to an sqlite3_vtab structure. Otherwise
+ ** sqlite3ViewGetColumnNames() would have picked up the error.
+ */
+ assert( pTab->azModuleArg && pTab->azModuleArg[0] );
+ assert( sqlite3GetVTable(pParse->db, pTab) );
+
+ /* Try once or twice. On the first attempt, allow IN optimizations.
+ ** If an IN optimization is accepted by the virtual table xBestIndex
+ ** method, but the pInfo->aConstrainUsage.omit flag is not set, then
+ ** the query will not work because it might allow duplicate rows in
+ ** output. In that case, run the xBestIndex method a second time
+ ** without the IN constraints. Usually this loop only runs once.
+ ** The loop will exit using a "break" statement.
+ */
+ for(bAllowIN=1; 1; bAllowIN--){
+ assert( bAllowIN==0 || bAllowIN==1 );
+
+ /* Set the aConstraint[].usable fields and initialize all
+ ** output variables to zero.
+ **
+ ** aConstraint[].usable is true for constraints where the right-hand
+ ** side contains only references to tables to the left of the current
+ ** table. In other words, if the constraint is of the form:
+ **
+ ** column = expr
+ **
+ ** and we are evaluating a join, then the constraint on column is
+ ** only valid if all tables referenced in expr occur to the left
+ ** of the table containing column.
+ **
+ ** The aConstraints[] array contains entries for all constraints
+ ** on the current table. That way we only have to compute it once
+ ** even though we might try to pick the best index multiple times.
+ ** For each attempt at picking an index, the order of tables in the
+ ** join might be different so we have to recompute the usable flag
+ ** each time.
+ */
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ pUsage = pIdxInfo->aConstraintUsage;
+ for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ if( (pTerm->prereqRight&p->notReady)==0
+ && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
+ ){
+ pIdxCons->usable = 1;
+ }else{
+ pIdxCons->usable = 0;
+ }
+ }
+ memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+ if( pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
+ }
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->idxNum = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pIdxInfo->orderByConsumed = 0;
+ /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
+ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
+ nOrderBy = pIdxInfo->nOrderBy;
+ if( !p->pOrderBy ){
+ pIdxInfo->nOrderBy = 0;
+ }
+
+ if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
+ return;
+ }
+
+ sortOrder = SQLITE_SO_ASC;
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+ if( pUsage[i].argvIndex>0 ){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ p->cost.used |= pTerm->prereqRight;
+ if( (pTerm->eOperator & WO_IN)!=0 ){
+ if( pUsage[i].omit==0 ){
+ /* Do not attempt to use an IN constraint if the virtual table
+ ** says that the equivalent EQ constraint cannot be safely omitted.
+ ** If we do attempt to use such a constraint, some rows might be
+ ** repeated in the output. */
+ break;
+ }
+ for(k=0; k<pIdxInfo->nOrderBy; k++){
+ if( pIdxInfo->aOrderBy[k].iColumn==pIdxCons->iColumn ){
+ sortOrder = pIdxInfo->aOrderBy[k].desc;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if( i>=pIdxInfo->nConstraint ) break;
+ }
+
+ /* If there is an ORDER BY clause, and the selected virtual table index
+ ** does not satisfy it, increase the cost of the scan accordingly. This
+ ** matches the processing for non-virtual tables in bestBtreeIndex().
+ */
+ rCost = pIdxInfo->estimatedCost;
+ if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
+ rCost += estLog(rCost)*rCost;
+ }
+
+ /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
+ ** inital value of lowestCost in this loop. If it is, then the
+ ** (cost<lowestCost) test below will never be true.
+ **
+ ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
+ ** is defined.
+ */
+ if( (SQLITE_BIG_DBL/((double)2))<rCost ){
+ p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
+ }else{
+ p->cost.rCost = rCost;
+ }
+ p->cost.plan.u.pVtabIdx = pIdxInfo;
+ if( pIdxInfo->orderByConsumed ){
+ assert( sortOrder==0 || sortOrder==1 );
+ p->cost.plan.wsFlags |= WHERE_ORDERED + sortOrder*WHERE_REVERSE;
+ p->cost.plan.nOBSat = nOrderBy;
+ }else{
+ p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
+ }
+ p->cost.plan.nEq = 0;
+ pIdxInfo->nOrderBy = nOrderBy;
+
+ /* Try to find a more efficient access pattern by using multiple indexes
+ ** to optimize an OR expression within the WHERE clause.
+ */
+ bestOrClauseIndex(p);
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifdef SQLITE_ENABLE_STAT3
+/*
+** Estimate the location of a particular key among all keys in an
+** index. Store the results in aStat as follows:
+**
+** aStat[0] Est. number of rows less than pVal
+** aStat[1] Est. number of rows equal to pVal
+**
+** Return SQLITE_OK on success.
+*/
+static int whereKeyStats(
+ Parse *pParse, /* Database connection */
+ Index *pIdx, /* Index to consider domain of */
+ sqlite3_value *pVal, /* Value to consider */
+ int roundUp, /* Round up if true. Round down if false */
+ tRowcnt *aStat /* OUT: stats written here */
+){
+ tRowcnt n;
+ IndexSample *aSample;
+ int i, eType;
+ int isEq = 0;
+ i64 v;
+ double r, rS;
+
+ assert( roundUp==0 || roundUp==1 );
+ assert( pIdx->nSample>0 );
+ if( pVal==0 ) return SQLITE_ERROR;
+ n = pIdx->aiRowEst[0];
+ aSample = pIdx->aSample;
+ eType = sqlite3_value_type(pVal);
+
+ if( eType==SQLITE_INTEGER ){
+ v = sqlite3_value_int64(pVal);
+ r = (i64)v;
+ for(i=0; i<pIdx->nSample; i++){
+ if( aSample[i].eType==SQLITE_NULL ) continue;
+ if( aSample[i].eType>=SQLITE_TEXT ) break;
+ if( aSample[i].eType==SQLITE_INTEGER ){
+ if( aSample[i].u.i>=v ){
+ isEq = aSample[i].u.i==v;
+ break;
+ }
+ }else{
+ assert( aSample[i].eType==SQLITE_FLOAT );
+ if( aSample[i].u.r>=r ){
+ isEq = aSample[i].u.r==r;
+ break;
+ }
+ }
+ }
+ }else if( eType==SQLITE_FLOAT ){
+ r = sqlite3_value_double(pVal);
+ for(i=0; i<pIdx->nSample; i++){
+ if( aSample[i].eType==SQLITE_NULL ) continue;
+ if( aSample[i].eType>=SQLITE_TEXT ) break;
+ if( aSample[i].eType==SQLITE_FLOAT ){
+ rS = aSample[i].u.r;
+ }else{
+ rS = aSample[i].u.i;
+ }
+ if( rS>=r ){
+ isEq = rS==r;
+ break;
+ }
+ }
+ }else if( eType==SQLITE_NULL ){
+ i = 0;
+ if( aSample[0].eType==SQLITE_NULL ) isEq = 1;
+ }else{
+ assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
+ for(i=0; i<pIdx->nSample; i++){
+ if( aSample[i].eType==SQLITE_TEXT || aSample[i].eType==SQLITE_BLOB ){
+ break;
+ }
+ }
+ if( i<pIdx->nSample ){
+ sqlite3 *db = pParse->db;
+ CollSeq *pColl;
+ const u8 *z;
+ if( eType==SQLITE_BLOB ){
+ z = (const u8 *)sqlite3_value_blob(pVal);
+ pColl = db->pDfltColl;
+ assert( pColl->enc==SQLITE_UTF8 );
+ }else{
+ pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
+ if( pColl==0 ){
+ return SQLITE_ERROR;
+ }
+ z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
+ if( !z ){
+ return SQLITE_NOMEM;
+ }
+ assert( z && pColl && pColl->xCmp );
+ }
+ n = sqlite3ValueBytes(pVal, pColl->enc);
+
+ for(; i<pIdx->nSample; i++){
+ int c;
+ int eSampletype = aSample[i].eType;
+ if( eSampletype<eType ) continue;
+ if( eSampletype!=eType ) break;
+#ifndef SQLITE_OMIT_UTF16
+ if( pColl->enc!=SQLITE_UTF8 ){
+ int nSample;
+ char *zSample = sqlite3Utf8to16(
+ db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample
+ );
+ if( !zSample ){
+ assert( db->mallocFailed );
+ return SQLITE_NOMEM;
+ }
+ c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z);
+ sqlite3DbFree(db, zSample);
+ }else
+#endif
+ {
+ c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
+ }
+ if( c>=0 ){
+ if( c==0 ) isEq = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* At this point, aSample[i] is the first sample that is greater than
+ ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less
+ ** than pVal. If aSample[i]==pVal, then isEq==1.
+ */
+ if( isEq ){
+ assert( i<pIdx->nSample );
+ aStat[0] = aSample[i].nLt;
+ aStat[1] = aSample[i].nEq;
+ }else{
+ tRowcnt iLower, iUpper, iGap;
+ if( i==0 ){
+ iLower = 0;
+ iUpper = aSample[0].nLt;
+ }else{
+ iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
+ iLower = aSample[i-1].nEq + aSample[i-1].nLt;
+ }
+ aStat[1] = pIdx->avgEq;
+ if( iLower>=iUpper ){
+ iGap = 0;
+ }else{
+ iGap = iUpper - iLower;
+ }
+ if( roundUp ){
+ iGap = (iGap*2)/3;
+ }else{
+ iGap = iGap/3;
+ }
+ aStat[0] = iLower + iGap;
+ }
+ return SQLITE_OK;
+}
+#endif /* SQLITE_ENABLE_STAT3 */
+
+/*
+** If expression pExpr represents a literal value, set *pp to point to
+** an sqlite3_value structure containing the same value, with affinity
+** aff applied to it, before returning. It is the responsibility of the
+** caller to eventually release this structure by passing it to
+** sqlite3ValueFree().
+**
+** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
+** is an SQL variable that currently has a non-NULL value bound to it,
+** create an sqlite3_value structure containing this value, again with
+** affinity aff applied to it, instead.
+**
+** If neither of the above apply, set *pp to NULL.
+**
+** If an error occurs, return an error code. Otherwise, SQLITE_OK.
+*/
+#ifdef SQLITE_ENABLE_STAT3
+static int valueFromExpr(
+ Parse *pParse,
+ Expr *pExpr,
+ u8 aff,
+ sqlite3_value **pp
+){
+ if( pExpr->op==TK_VARIABLE
+ || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
+ ){
+ int iVar = pExpr->iColumn;
+ sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
+ *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
+ return SQLITE_OK;
+ }
+ return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
+}
+#endif
+
+/*
+** This function is used to estimate the number of rows that will be visited
+** by scanning an index for a range of values. The range may have an upper
+** bound, a lower bound, or both. The WHERE clause terms that set the upper
+** and lower bounds are represented by pLower and pUpper respectively. For
+** example, assuming that index p is on t1(a):
+**
+** ... FROM t1 WHERE a > ? AND a < ? ...
+** |_____| |_____|
+** | |
+** pLower pUpper
+**
+** If either of the upper or lower bound is not present, then NULL is passed in
+** place of the corresponding WhereTerm.
+**
+** The nEq parameter is passed the index of the index column subject to the
+** range constraint. Or, equivalently, the number of equality constraints
+** optimized by the proposed index scan. For example, assuming index p is
+** on t1(a, b), and the SQL query is:
+**
+** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ...
+**
+** then nEq should be passed the value 1 (as the range restricted column,
+** b, is the second left-most column of the index). Or, if the query is:
+**
+** ... FROM t1 WHERE a > ? AND a < ? ...
+**
+** then nEq should be passed 0.
+**
+** The returned value is an integer divisor to reduce the estimated
+** search space. A return value of 1 means that range constraints are
+** no help at all. A return value of 2 means range constraints are
+** expected to reduce the search space by half. And so forth...
+**
+** In the absence of sqlite_stat3 ANALYZE data, each range inequality
+** reduces the search space by a factor of 4. Hence a single constraint (x>?)
+** results in a return of 4 and a range constraint (x>? AND x<?) results
+** in a return of 16.
+*/
+static int whereRangeScanEst(
+ Parse *pParse, /* Parsing & code generating context */
+ Index *p, /* The index containing the range-compared column; "x" */
+ int nEq, /* index into p->aCol[] of the range-compared column */
+ WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
+ WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
+ double *pRangeDiv /* OUT: Reduce search space by this divisor */
+){
+ int rc = SQLITE_OK;
+
+#ifdef SQLITE_ENABLE_STAT3
+
+ if( nEq==0 && p->nSample ){
+ sqlite3_value *pRangeVal;
+ tRowcnt iLower = 0;
+ tRowcnt iUpper = p->aiRowEst[0];
+ tRowcnt a[2];
+ u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
+
+ if( pLower ){
+ Expr *pExpr = pLower->pExpr->pRight;
+ rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
+ assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
+ if( rc==SQLITE_OK
+ && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
+ ){
+ iLower = a[0];
+ if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
+ }
+ sqlite3ValueFree(pRangeVal);
+ }
+ if( rc==SQLITE_OK && pUpper ){
+ Expr *pExpr = pUpper->pExpr->pRight;
+ rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
+ assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
+ if( rc==SQLITE_OK
+ && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
+ ){
+ iUpper = a[0];
+ if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
+ }
+ sqlite3ValueFree(pRangeVal);
+ }
+ if( rc==SQLITE_OK ){
+ if( iUpper<=iLower ){
+ *pRangeDiv = (double)p->aiRowEst[0];
+ }else{
+ *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
+ }
+ WHERETRACE(("range scan regions: %u..%u div=%g\n",
+ (u32)iLower, (u32)iUpper, *pRangeDiv));
+ return SQLITE_OK;
+ }
+ }
+#else
+ UNUSED_PARAMETER(pParse);
+ UNUSED_PARAMETER(p);
+ UNUSED_PARAMETER(nEq);
+#endif
+ assert( pLower || pUpper );
+ *pRangeDiv = (double)1;
+ if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4;
+ if( pUpper ) *pRangeDiv *= (double)4;
+ return rc;
+}
+
+#ifdef SQLITE_ENABLE_STAT3
+/*
+** Estimate the number of rows that will be returned based on
+** an equality constraint x=VALUE and where that VALUE occurs in
+** the histogram data. This only works when x is the left-most
+** column of an index and sqlite_stat3 histogram data is available
+** for that index. When pExpr==NULL that means the constraint is
+** "x IS NULL" instead of "x=VALUE".
+**
+** Write the estimated row count into *pnRow and return SQLITE_OK.
+** If unable to make an estimate, leave *pnRow unchanged and return
+** non-zero.
+**
+** This routine can fail if it is unable to load a collating sequence
+** required for string comparison, or if unable to allocate memory
+** for a UTF conversion required for comparison. The error is stored
+** in the pParse structure.
+*/
+static int whereEqualScanEst(
+ Parse *pParse, /* Parsing & code generating context */
+ Index *p, /* The index whose left-most column is pTerm */
+ Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */
+ double *pnRow /* Write the revised row estimate here */
+){
+ sqlite3_value *pRhs = 0; /* VALUE on right-hand side of pTerm */
+ u8 aff; /* Column affinity */
+ int rc; /* Subfunction return code */
+ tRowcnt a[2]; /* Statistics */
+
+ assert( p->aSample!=0 );
+ assert( p->nSample>0 );
+ aff = p->pTable->aCol[p->aiColumn[0]].affinity;
+ if( pExpr ){
+ rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
+ if( rc ) goto whereEqualScanEst_cancel;
+ }else{
+ pRhs = sqlite3ValueNew(pParse->db);
+ }
+ if( pRhs==0 ) return SQLITE_NOTFOUND;
+ rc = whereKeyStats(pParse, p, pRhs, 0, a);
+ if( rc==SQLITE_OK ){
+ WHERETRACE(("equality scan regions: %d\n", (int)a[1]));
+ *pnRow = a[1];
+ }
+whereEqualScanEst_cancel:
+ sqlite3ValueFree(pRhs);
+ return rc;
+}
+#endif /* defined(SQLITE_ENABLE_STAT3) */
+
+#ifdef SQLITE_ENABLE_STAT3
+/*
+** Estimate the number of rows that will be returned based on
+** an IN constraint where the right-hand side of the IN operator
+** is a list of values. Example:
+**
+** WHERE x IN (1,2,3,4)
+**
+** Write the estimated row count into *pnRow and return SQLITE_OK.
+** If unable to make an estimate, leave *pnRow unchanged and return
+** non-zero.
+**
+** This routine can fail if it is unable to load a collating sequence
+** required for string comparison, or if unable to allocate memory
+** for a UTF conversion required for comparison. The error is stored
+** in the pParse structure.
+*/
+static int whereInScanEst(
+ Parse *pParse, /* Parsing & code generating context */
+ Index *p, /* The index whose left-most column is pTerm */
+ ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
+ double *pnRow /* Write the revised row estimate here */
+){
+ int rc = SQLITE_OK; /* Subfunction return code */
+ double nEst; /* Number of rows for a single term */
+ double nRowEst = (double)0; /* New estimate of the number of rows */
+ int i; /* Loop counter */
+
+ assert( p->aSample!=0 );
+ for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
+ nEst = p->aiRowEst[0];
+ rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst);
+ nRowEst += nEst;
+ }
+ if( rc==SQLITE_OK ){
+ if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
+ *pnRow = nRowEst;
+ WHERETRACE(("IN row estimate: est=%g\n", nRowEst));
+ }
+ return rc;
+}
+#endif /* defined(SQLITE_ENABLE_STAT3) */
+
+/*
+** Check to see if column iCol of the table with cursor iTab will appear
+** in sorted order according to the current query plan.
+**
+** Return values:
+**
+** 0 iCol is not ordered
+** 1 iCol has only a single value
+** 2 iCol is in ASC order
+** 3 iCol is in DESC order
+*/
+static int isOrderedColumn(
+ WhereBestIdx *p,
+ int iTab,
+ int iCol
+){
+ int i, j;
+ WhereLevel *pLevel = &p->aLevel[p->i-1];
+ Index *pIdx;
+ u8 sortOrder;
+ for(i=p->i-1; i>=0; i--, pLevel--){
+ if( pLevel->iTabCur!=iTab ) continue;
+ if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+ return 1;
+ }
+ assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
+ if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
+ if( iCol<0 ){
+ sortOrder = 0;
+ testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+ }else{
+ int n = pIdx->nColumn;
+ for(j=0; j<n; j++){
+ if( iCol==pIdx->aiColumn[j] ) break;
+ }
+ if( j>=n ) return 0;
+ sortOrder = pIdx->aSortOrder[j];
+ testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+ }
+ }else{
+ if( iCol!=(-1) ) return 0;
+ sortOrder = 0;
+ testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+ }
+ if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
+ assert( sortOrder==0 || sortOrder==1 );
+ testcase( sortOrder==1 );
+ sortOrder = 1 - sortOrder;
+ }
+ return sortOrder+2;
+ }
+ return 0;
+}
+
+/*
+** This routine decides if pIdx can be used to satisfy the ORDER BY
+** clause, either in whole or in part. The return value is the
+** cumulative number of terms in the ORDER BY clause that are satisfied
+** by the index pIdx and other indices in outer loops.
+**
+** The table being queried has a cursor number of "base". pIdx is the
+** index that is postulated for use to access the table.
+**
+** The *pbRev value is set to 0 order 1 depending on whether or not
+** pIdx should be run in the forward order or in reverse order.
+*/
+static int isSortingIndex(
+ WhereBestIdx *p, /* Best index search context */
+ Index *pIdx, /* The index we are testing */
+ int base, /* Cursor number for the table to be sorted */
+ int *pbRev, /* Set to 1 for reverse-order scan of pIdx */
+ int *pbObUnique /* ORDER BY column values will different in every row */
+){
+ int i; /* Number of pIdx terms used */
+ int j; /* Number of ORDER BY terms satisfied */
+ int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */
+ int nTerm; /* Number of ORDER BY terms */
+ struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
+ Table *pTab = pIdx->pTable; /* Table that owns index pIdx */
+ ExprList *pOrderBy; /* The ORDER BY clause */
+ Parse *pParse = p->pParse; /* Parser context */
+ sqlite3 *db = pParse->db; /* Database connection */
+ int nPriorSat; /* ORDER BY terms satisfied by outer loops */
+ int seenRowid = 0; /* True if an ORDER BY rowid term is seen */
+ int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */
+ int outerObUnique; /* Outer loops generate different values in
+ ** every row for the ORDER BY columns */
+
+ if( p->i==0 ){
+ nPriorSat = 0;
+ outerObUnique = 1;
+ }else{
+ u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
+ nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+ if( (wsFlags & WHERE_ORDERED)==0 ){
+ /* This loop cannot be ordered unless the next outer loop is
+ ** also ordered */
+ return nPriorSat;
+ }
+ if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
+ /* Only look at the outer-most loop if the OrderByIdxJoin
+ ** optimization is disabled */
+ return nPriorSat;
+ }
+ testcase( wsFlags & WHERE_OB_UNIQUE );
+ testcase( wsFlags & WHERE_ALL_UNIQUE );
+ outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
+ }
+ pOrderBy = p->pOrderBy;
+ assert( pOrderBy!=0 );
+ if( pIdx->bUnordered ){
+ /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
+ ** be used for sorting */
+ return nPriorSat;
+ }
+ nTerm = pOrderBy->nExpr;
+ uniqueNotNull = pIdx->onError!=OE_None;
+ assert( nTerm>0 );
+
+ /* Argument pIdx must either point to a 'real' named index structure,
+ ** or an index structure allocated on the stack by bestBtreeIndex() to
+ ** represent the rowid index that is part of every table. */
+ assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
+
+ /* Match terms of the ORDER BY clause against columns of
+ ** the index.
+ **
+ ** Note that indices have pIdx->nColumn regular columns plus
+ ** one additional column containing the rowid. The rowid column
+ ** of the index is also allowed to match against the ORDER BY
+ ** clause.
+ */
+ j = nPriorSat;
+ for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
+ Expr *pOBExpr; /* The expression of the ORDER BY pOBItem */
+ CollSeq *pColl; /* The collating sequence of pOBExpr */
+ int termSortOrder; /* Sort order for this term */
+ int iColumn; /* The i-th column of the index. -1 for rowid */
+ int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
+ int isEq; /* Subject to an == or IS NULL constraint */
+ int isMatch; /* ORDER BY term matches the index term */
+ const char *zColl; /* Name of collating sequence for i-th index term */
+ WhereTerm *pConstraint; /* A constraint in the WHERE clause */
+
+ /* If the next term of the ORDER BY clause refers to anything other than
+ ** a column in the "base" table, then this index will not be of any
+ ** further use in handling the ORDER BY. */
+ pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
+ if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
+ break;
+ }
+
+ /* Find column number and collating sequence for the next entry
+ ** in the index */
+ if( pIdx->zName && i<pIdx->nColumn ){
+ iColumn = pIdx->aiColumn[i];
+ if( iColumn==pIdx->pTable->iPKey ){
+ iColumn = -1;
+ }
+ iSortOrder = pIdx->aSortOrder[i];
+ zColl = pIdx->azColl[i];
+ assert( zColl!=0 );
+ }else{
+ iColumn = -1;
+ iSortOrder = 0;
+ zColl = 0;
+ }
+
+ /* Check to see if the column number and collating sequence of the
+ ** index match the column number and collating sequence of the ORDER BY
+ ** clause entry. Set isMatch to 1 if they both match. */
+ if( pOBExpr->iColumn==iColumn ){
+ if( zColl ){
+ pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
+ }else{
+ isMatch = 1;
+ }
+ }else{
+ isMatch = 0;
+ }
+
+ /* termSortOrder is 0 or 1 for whether or not the access loop should
+ ** run forward or backwards (respectively) in order to satisfy this
+ ** term of the ORDER BY clause. */
+ assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
+ assert( iSortOrder==0 || iSortOrder==1 );
+ termSortOrder = iSortOrder ^ pOBItem->sortOrder;
+
+ /* If X is the column in the index and ORDER BY clause, check to see
+ ** if there are any X= or X IS NULL constraints in the WHERE clause. */
+ pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
+ WO_EQ|WO_ISNULL|WO_IN, pIdx);
+ if( pConstraint==0 ){
+ isEq = 0;
+ }else if( (pConstraint->eOperator & WO_IN)!=0 ){
+ isEq = 0;
+ }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
+ uniqueNotNull = 0;
+ isEq = 1; /* "X IS NULL" means X has only a single value */
+ }else if( pConstraint->prereqRight==0 ){
+ isEq = 1; /* Constraint "X=constant" means X has only a single value */
+ }else{
+ Expr *pRight = pConstraint->pExpr->pRight;
+ if( pRight->op==TK_COLUMN ){
+ WHERETRACE((" .. isOrderedColumn(tab=%d,col=%d)",
+ pRight->iTable, pRight->iColumn));
+ isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
+ WHERETRACE((" -> isEq=%d\n", isEq));
+
+ /* If the constraint is of the form X=Y where Y is an ordered value
+ ** in an outer loop, then make sure the sort order of Y matches the
+ ** sort order required for X. */
+ if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
+ testcase( isEq==2 );
+ testcase( isEq==3 );
+ break;
+ }
+ }else{
+ isEq = 0; /* "X=expr" places no ordering constraints on X */
+ }
+ }
+ if( !isMatch ){
+ if( isEq==0 ){
+ break;
+ }else{
+ continue;
+ }
+ }else if( isEq!=1 ){
+ if( sortOrder==2 ){
+ sortOrder = termSortOrder;
+ }else if( termSortOrder!=sortOrder ){
+ break;
+ }
+ }
+ j++;
+ pOBItem++;
+ if( iColumn<0 ){
+ seenRowid = 1;
+ break;
+ }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
+ testcase( isEq==0 );
+ testcase( isEq==2 );
+ testcase( isEq==3 );
+ uniqueNotNull = 0;
+ }
+ }
+ if( seenRowid ){
+ uniqueNotNull = 1;
+ }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
+ uniqueNotNull = 0;
+ }
+
+ /* If we have not found at least one ORDER BY term that matches the
+ ** index, then show no progress. */
+ if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
+
+ /* Either the outer queries must generate rows where there are no two
+ ** rows with the same values in all ORDER BY columns, or else this
+ ** loop must generate just a single row of output. Example: Suppose
+ ** the outer loops generate A=1 and A=1, and this loop generates B=3
+ ** and B=4. Then without the following test, ORDER BY A,B would
+ ** generate the wrong order output: 1,3 1,4 1,3 1,4
+ */
+ if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
+ *pbObUnique = uniqueNotNull;
+
+ /* Return the necessary scan order back to the caller */
+ *pbRev = sortOrder & 1;
+
+ /* If there was an "ORDER BY rowid" term that matched, or it is only
+ ** possible for a single row from this table to match, then skip over
+ ** any additional ORDER BY terms dealing with this table.
+ */
+ if( uniqueNotNull ){
+ /* Advance j over additional ORDER BY terms associated with base */
+ WhereMaskSet *pMS = p->pWC->pMaskSet;
+ Bitmask m = ~getMask(pMS, base);
+ while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
+ j++;
+ }
+ }
+ return j;
+}
+
+/*
+** Find the best query plan for accessing a particular table. Write the
+** best query plan and its cost into the p->cost.
+**
+** The lowest cost plan wins. The cost is an estimate of the amount of
+** CPU and disk I/O needed to process the requested result.
+** Factors that influence cost include:
+**
+** * The estimated number of rows that will be retrieved. (The
+** fewer the better.)
+**
+** * Whether or not sorting must occur.
+**
+** * Whether or not there must be separate lookups in the
+** index and in the main table.
+**
+** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in
+** the SQL statement, then this function only considers plans using the
+** named index. If no such plan is found, then the returned cost is
+** SQLITE_BIG_DBL. If a plan is found that uses the named index,
+** then the cost is calculated in the usual way.
+**
+** If a NOT INDEXED clause was attached to the table
+** in the SELECT statement, then no indexes are considered. However, the
+** selected plan may still take advantage of the built-in rowid primary key
+** index.
+*/
+static void bestBtreeIndex(WhereBestIdx *p){
+ Parse *pParse = p->pParse; /* The parsing context */
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+ int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
+ Index *pProbe; /* An index we are evaluating */
+ Index *pIdx; /* Copy of pProbe, or zero for IPK index */
+ int eqTermMask; /* Current mask of valid equality operators */
+ int idxEqTermMask; /* Index mask of valid equality operators */
+ Index sPk; /* A fake index object for the primary key */
+ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
+ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
+ int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */
+ int nPriorSat; /* ORDER BY terms satisfied by outer loops */
+ int nOrderBy; /* Number of ORDER BY terms */
+ char bSortInit; /* Initializer for bSort in inner loop */
+ char bDistInit; /* Initializer for bDist in inner loop */
+
+
+ /* Initialize the cost to a worst-case value */
+ memset(&p->cost, 0, sizeof(p->cost));
+ p->cost.rCost = SQLITE_BIG_DBL;
+
+ /* If the pSrc table is the right table of a LEFT JOIN then we may not
+ ** use an index to satisfy IS NULL constraints on that table. This is
+ ** because columns might end up being NULL if the table does not match -
+ ** a circumstance which the index cannot help us discover. Ticket #2177.
+ */
+ if( pSrc->jointype & JT_LEFT ){
+ idxEqTermMask = WO_EQ|WO_IN;
+ }else{
+ idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL;
+ }
+
+ if( pSrc->pIndex ){
+ /* An INDEXED BY clause specifies a particular index to use */
+ pIdx = pProbe = pSrc->pIndex;
+ wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
+ eqTermMask = idxEqTermMask;
+ }else{
+ /* There is no INDEXED BY clause. Create a fake Index object in local
+ ** variable sPk to represent the rowid primary key index. Make this
+ ** fake index the first in a chain of Index objects with all of the real
+ ** indices to follow */
+ Index *pFirst; /* First of real indices on the table */
+ memset(&sPk, 0, sizeof(Index));
+ sPk.nColumn = 1;
+ sPk.aiColumn = &aiColumnPk;
+ sPk.aiRowEst = aiRowEstPk;
+ sPk.onError = OE_Replace;
+ sPk.pTable = pSrc->pTab;
+ aiRowEstPk[0] = pSrc->pTab->nRowEst;
+ aiRowEstPk[1] = 1;
+ pFirst = pSrc->pTab->pIndex;
+ if( pSrc->notIndexed==0 ){
+ /* The real indices of the table are only considered if the
+ ** NOT INDEXED qualifier is omitted from the FROM clause */
+ sPk.pNext = pFirst;
+ }
+ pProbe = &sPk;
+ wsFlagMask = ~(
+ WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
+ );
+ eqTermMask = WO_EQ|WO_IN;
+ pIdx = 0;
+ }
+
+ nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
+ if( p->i ){
+ nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+ bSortInit = nPriorSat<nOrderBy;
+ bDistInit = 0;
+ }else{
+ nPriorSat = 0;
+ bSortInit = nOrderBy>0;
+ bDistInit = p->pDistinct!=0;
+ }
+
+ /* Loop over all indices looking for the best one to use
+ */
+ for(; pProbe; pIdx=pProbe=pProbe->pNext){
+ const tRowcnt * const aiRowEst = pProbe->aiRowEst;
+ WhereCost pc; /* Cost of using pProbe */
+ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */
+
+ /* The following variables are populated based on the properties of
+ ** index being evaluated. They are then used to determine the expected
+ ** cost and number of rows returned.
+ **
+ ** pc.plan.nEq:
+ ** Number of equality terms that can be implemented using the index.
+ ** In other words, the number of initial fields in the index that
+ ** are used in == or IN or NOT NULL constraints of the WHERE clause.
+ **
+ ** nInMul:
+ ** The "in-multiplier". This is an estimate of how many seek operations
+ ** SQLite must perform on the index in question. For example, if the
+ ** WHERE clause is:
+ **
+ ** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6)
+ **
+ ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is
+ ** set to 9. Given the same schema and either of the following WHERE
+ ** clauses:
+ **
+ ** WHERE a = 1
+ ** WHERE a >= 2
+ **
+ ** nInMul is set to 1.
+ **
+ ** If there exists a WHERE term of the form "x IN (SELECT ...)", then
+ ** the sub-select is assumed to return 25 rows for the purposes of
+ ** determining nInMul.
+ **
+ ** bInEst:
+ ** Set to true if there was at least one "x IN (SELECT ...)" term used
+ ** in determining the value of nInMul. Note that the RHS of the
+ ** IN operator must be a SELECT, not a value list, for this variable
+ ** to be true.
+ **
+ ** rangeDiv:
+ ** An estimate of a divisor by which to reduce the search space due
+ ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE
+ ** data, a single inequality reduces the search space to 1/4rd its
+ ** original size (rangeDiv==4). Two inequalities reduce the search
+ ** space to 1/16th of its original size (rangeDiv==16).
+ **
+ ** bSort:
+ ** Boolean. True if there is an ORDER BY clause that will require an
+ ** external sort (i.e. scanning the index being evaluated will not
+ ** correctly order records).
+ **
+ ** bDist:
+ ** Boolean. True if there is a DISTINCT clause that will require an
+ ** external btree.
+ **
+ ** bLookup:
+ ** Boolean. True if a table lookup is required for each index entry
+ ** visited. In other words, true if this is not a covering index.
+ ** This is always false for the rowid primary key index of a table.
+ ** For other indexes, it is true unless all the columns of the table
+ ** used by the SELECT statement are present in the index (such an
+ ** index is sometimes described as a covering index).
+ ** For example, given the index on (a, b), the second of the following
+ ** two queries requires table b-tree lookups in order to find the value
+ ** of column c, but the first does not because columns a and b are
+ ** both available in the index.
+ **
+ ** SELECT a, b FROM tbl WHERE a = 1;
+ ** SELECT a, b, c FROM tbl WHERE a = 1;
+ */
+ int bInEst = 0; /* True if "x IN (SELECT...)" seen */
+ int nInMul = 1; /* Number of distinct equalities to lookup */
+ double rangeDiv = (double)1; /* Estimated reduction in search space */
+ int nBound = 0; /* Number of range constraints seen */
+ char bSort = bSortInit; /* True if external sort required */
+ char bDist = bDistInit; /* True if index cannot help with DISTINCT */
+ char bLookup = 0; /* True if not a covering index */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
+#ifdef SQLITE_ENABLE_STAT3
+ WhereTerm *pFirstTerm = 0; /* First term matching the index */
+#endif
+
+ WHERETRACE((
+ " %s(%s):\n",
+ pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
+ ));
+ memset(&pc, 0, sizeof(pc));
+ pc.plan.nOBSat = nPriorSat;
+
+ /* Determine the values of pc.plan.nEq and nInMul */
+ for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
+ int j = pProbe->aiColumn[pc.plan.nEq];
+ pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
+ if( pTerm==0 ) break;
+ pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
+ testcase( pTerm->pWC!=pWC );
+ if( pTerm->eOperator & WO_IN ){
+ Expr *pExpr = pTerm->pExpr;
+ pc.plan.wsFlags |= WHERE_COLUMN_IN;
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */
+ nInMul *= 25;
+ bInEst = 1;
+ }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
+ /* "x IN (value, value, ...)" */
+ nInMul *= pExpr->x.pList->nExpr;
+ }
+ }else if( pTerm->eOperator & WO_ISNULL ){
+ pc.plan.wsFlags |= WHERE_COLUMN_NULL;
+ }
+#ifdef SQLITE_ENABLE_STAT3
+ if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
+#endif
+ pc.used |= pTerm->prereqRight;
+ }
+
+ /* If the index being considered is UNIQUE, and there is an equality
+ ** constraint for all columns in the index, then this search will find
+ ** at most a single row. In this case set the WHERE_UNIQUE flag to
+ ** indicate this to the caller.
+ **
+ ** Otherwise, if the search may find more than one row, test to see if
+ ** there is a range constraint on indexed column (pc.plan.nEq+1) that
+ ** can be optimized using the index.
+ */
+ if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
+ testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
+ testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
+ if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
+ pc.plan.wsFlags |= WHERE_UNIQUE;
+ if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+ pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
+ }
+ }
+ }else if( pProbe->bUnordered==0 ){
+ int j;
+ j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
+ if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
+ WhereTerm *pTop, *pBtm;
+ pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
+ pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
+ whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
+ if( pTop ){
+ nBound = 1;
+ pc.plan.wsFlags |= WHERE_TOP_LIMIT;
+ pc.used |= pTop->prereqRight;
+ testcase( pTop->pWC!=pWC );
+ }
+ if( pBtm ){
+ nBound++;
+ pc.plan.wsFlags |= WHERE_BTM_LIMIT;
+ pc.used |= pBtm->prereqRight;
+ testcase( pBtm->pWC!=pWC );
+ }
+ pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
+ }
+ }
+
+ /* If there is an ORDER BY clause and the index being considered will
+ ** naturally scan rows in the required order, set the appropriate flags
+ ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
+ ** the index will scan rows in a different order, set the bSort
+ ** variable. */
+ if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
+ int bRev = 2;
+ int bObUnique = 0;
+ WHERETRACE((" --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
+ pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
+ WHERETRACE((" --> after isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
+ bRev, bObUnique, pc.plan.nOBSat));
+ if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+ pc.plan.wsFlags |= WHERE_ORDERED;
+ if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
+ }
+ if( nOrderBy==pc.plan.nOBSat ){
+ bSort = 0;
+ pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
+ }
+ if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
+ }
+
+ /* If there is a DISTINCT qualifier and this index will scan rows in
+ ** order of the DISTINCT expressions, clear bDist and set the appropriate
+ ** flags in pc.plan.wsFlags. */
+ if( bDist
+ && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, pc.plan.nEq)
+ && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
+ ){
+ bDist = 0;
+ pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
+ }
+
+ /* If currently calculating the cost of using an index (not the IPK
+ ** index), determine if all required column data may be obtained without
+ ** using the main table (i.e. if the index is a covering
+ ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
+ ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true. */
+ if( pIdx ){
+ Bitmask m = pSrc->colUsed;
+ int j;
+ for(j=0; j<pIdx->nColumn; j++){
+ int x = pIdx->aiColumn[j];
+ if( x<BMS-1 ){
+ m &= ~(((Bitmask)1)<<x);
+ }
+ }
+ if( m==0 ){
+ pc.plan.wsFlags |= WHERE_IDX_ONLY;
+ }else{
+ bLookup = 1;
+ }
+ }
+
+ /*
+ ** Estimate the number of rows of output. For an "x IN (SELECT...)"
+ ** constraint, do not let the estimate exceed half the rows in the table.
+ */
+ pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
+ if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
+ pc.plan.nRow = aiRowEst[0]/2;
+ nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
+ }
+
+#ifdef SQLITE_ENABLE_STAT3
+ /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
+ ** and we do not think that values of x are unique and if histogram
+ ** data is available for column x, then it might be possible
+ ** to get a better estimate on the number of rows based on
+ ** VALUE and how common that value is according to the histogram.
+ */
+ if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
+ && pFirstTerm!=0 && aiRowEst[1]>1 ){
+ assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
+ if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
+ testcase( pFirstTerm->eOperator & WO_EQ );
+ testcase( pFirstTerm->eOperator & WO_EQUIV );
+ testcase( pFirstTerm->eOperator & WO_ISNULL );
+ whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
+ &pc.plan.nRow);
+ }else if( bInEst==0 ){
+ assert( pFirstTerm->eOperator & WO_IN );
+ whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
+ &pc.plan.nRow);
+ }
+ }
+#endif /* SQLITE_ENABLE_STAT3 */
+
+ /* Adjust the number of output rows and downward to reflect rows
+ ** that are excluded by range constraints.
+ */
+ pc.plan.nRow = pc.plan.nRow/rangeDiv;
+ if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
+
+ /* Experiments run on real SQLite databases show that the time needed
+ ** to do a binary search to locate a row in a table or index is roughly
+ ** log10(N) times the time to move from one row to the next row within
+ ** a table or index. The actual times can vary, with the size of
+ ** records being an important factor. Both moves and searches are
+ ** slower with larger records, presumably because fewer records fit
+ ** on one page and hence more pages have to be fetched.
+ **
+ ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do
+ ** not give us data on the relative sizes of table and index records.
+ ** So this computation assumes table records are about twice as big
+ ** as index records
+ */
+ if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
+ ==WHERE_IDX_ONLY
+ && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+ && sqlite3GlobalConfig.bUseCis
+ && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
+ ){
+ /* This index is not useful for indexing, but it is a covering index.
+ ** A full-scan of the index might be a little faster than a full-scan
+ ** of the table, so give this case a cost slightly less than a table
+ ** scan. */
+ pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
+ pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
+ }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+ /* The cost of a full table scan is a number of move operations equal
+ ** to the number of rows in the table.
+ **
+ ** We add an additional 4x penalty to full table scans. This causes
+ ** the cost function to err on the side of choosing an index over
+ ** choosing a full scan. This 4x full-scan penalty is an arguable
+ ** decision and one which we expect to revisit in the future. But
+ ** it seems to be working well enough at the moment.
+ */
+ pc.rCost = aiRowEst[0]*4;
+ pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
+ if( pIdx ){
+ pc.plan.wsFlags &= ~WHERE_ORDERED;
+ pc.plan.nOBSat = nPriorSat;
+ }
+ }else{
+ log10N = estLog(aiRowEst[0]);
+ pc.rCost = pc.plan.nRow;
+ if( pIdx ){
+ if( bLookup ){
+ /* For an index lookup followed by a table lookup:
+ ** nInMul index searches to find the start of each index range
+ ** + nRow steps through the index
+ ** + nRow table searches to lookup the table entry using the rowid
+ */
+ pc.rCost += (nInMul + pc.plan.nRow)*log10N;
+ }else{
+ /* For a covering index:
+ ** nInMul index searches to find the initial entry
+ ** + nRow steps through the index
+ */
+ pc.rCost += nInMul*log10N;
+ }
+ }else{
+ /* For a rowid primary key lookup:
+ ** nInMult table searches to find the initial entry for each range
+ ** + nRow steps through the table
+ */
+ pc.rCost += nInMul*log10N;
+ }
+ }
+
+ /* Add in the estimated cost of sorting the result. Actual experimental
+ ** measurements of sorting performance in SQLite show that sorting time
+ ** adds C*N*log10(N) to the cost, where N is the number of rows to be
+ ** sorted and C is a factor between 1.95 and 4.3. We will split the
+ ** difference and select C of 3.0.
+ */
+ if( bSort ){
+ double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
+ m *= (double)(pc.plan.nOBSat ? 2 : 3);
+ pc.rCost += pc.plan.nRow*m;
+ }
+ if( bDist ){
+ pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
+ }
+
+ /**** Cost of using this index has now been computed ****/
+
+ /* If there are additional constraints on this table that cannot
+ ** be used with the current index, but which might lower the number
+ ** of output rows, adjust the nRow value accordingly. This only
+ ** matters if the current index is the least costly, so do not bother
+ ** with this step if we already know this index will not be chosen.
+ ** Also, never reduce the output row count below 2 using this step.
+ **
+ ** It is critical that the notValid mask be used here instead of
+ ** the notReady mask. When computing an "optimal" index, the notReady
+ ** mask will only have one bit set - the bit for the current table.
+ ** The notValid mask, on the other hand, always has all bits set for
+ ** tables that are not in outer loops. If notReady is used here instead
+ ** of notValid, then a optimal index that depends on inner joins loops
+ ** might be selected even when there exists an optimal index that has
+ ** no such dependency.
+ */
+ if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
+ int k; /* Loop counter */
+ int nSkipEq = pc.plan.nEq; /* Number of == constraints to skip */
+ int nSkipRange = nBound; /* Number of < constraints to skip */
+ Bitmask thisTab; /* Bitmap for pSrc */
+
+ thisTab = getMask(pWC->pMaskSet, iCur);
+ for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
+ if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
+ if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
+ if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
+ if( nSkipEq ){
+ /* Ignore the first pc.plan.nEq equality matches since the index
+ ** has already accounted for these */
+ nSkipEq--;
+ }else{
+ /* Assume each additional equality match reduces the result
+ ** set size by a factor of 10 */
+ pc.plan.nRow /= 10;
+ }
+ }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
+ if( nSkipRange ){
+ /* Ignore the first nSkipRange range constraints since the index
+ ** has already accounted for these */
+ nSkipRange--;
+ }else{
+ /* Assume each additional range constraint reduces the result
+ ** set size by a factor of 3. Indexed range constraints reduce
+ ** the search space by a larger factor: 4. We make indexed range
+ ** more selective intentionally because of the subjective
+ ** observation that indexed range constraints really are more
+ ** selective in practice, on average. */
+ pc.plan.nRow /= 3;
+ }
+ }else if( (pTerm->eOperator & WO_NOOP)==0 ){
+ /* Any other expression lowers the output row count by half */
+ pc.plan.nRow /= 2;
+ }
+ }
+ if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
+ }
+
+
+ WHERETRACE((
+ " nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
+ " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
+ " used=0x%llx nOBSat=%d\n",
+ pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
+ p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
+ pc.plan.nOBSat
+ ));
+
+ /* If this index is the best we have seen so far, then record this
+ ** index and its cost in the p->cost structure.
+ */
+ if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
+ p->cost = pc;
+ p->cost.plan.wsFlags &= wsFlagMask;
+ p->cost.plan.u.pIdx = pIdx;
+ }
+
+ /* If there was an INDEXED BY clause, then only that one index is
+ ** considered. */
+ if( pSrc->pIndex ) break;
+
+ /* Reset masks for the next index in the loop */
+ wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
+ eqTermMask = idxEqTermMask;
+ }
+
+ /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
+ ** is set, then reverse the order that the index will be scanned
+ ** in. This is used for application testing, to help find cases
+ ** where application behavior depends on the (undefined) order that
+ ** SQLite outputs rows in in the absence of an ORDER BY clause. */
+ if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
+ p->cost.plan.wsFlags |= WHERE_REVERSE;
+ }
+
+ assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
+ assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
+ assert( pSrc->pIndex==0
+ || p->cost.plan.u.pIdx==0
+ || p->cost.plan.u.pIdx==pSrc->pIndex
+ );
+
+ WHERETRACE((" best index is %s cost=%.1f\n",
+ p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
+ p->cost.rCost));
+
+ bestOrClauseIndex(p);
+ bestAutomaticIndex(p);
+ p->cost.plan.wsFlags |= eqTermMask;
+}
+
+/*
+** Find the query plan for accessing table pSrc->pTab. Write the
+** best query plan and its cost into the WhereCost object supplied
+** as the last parameter. This function may calculate the cost of
+** both real and virtual table scans.
+**
+** This function does not take ORDER BY or DISTINCT into account. Nor
+** does it remember the virtual table query plan. All it does is compute
+** the cost while determining if an OR optimization is applicable. The
+** details will be reconsidered later if the optimization is found to be
+** applicable.
+*/
+static void bestIndex(WhereBestIdx *p){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(p->pSrc->pTab) ){
+ sqlite3_index_info *pIdxInfo = 0;
+ p->ppIdxInfo = &pIdxInfo;
+ bestVirtualIndex(p);
+ assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
+ if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
+ }
+ sqlite3DbFree(p->pParse->db, pIdxInfo);
+ }else
+#endif
+ {
+ bestBtreeIndex(p);
+ }
+}
+
+/*
+** Disable a term in the WHERE clause. Except, do not disable the term
+** if it controls a LEFT OUTER JOIN and it did not originate in the ON
+** or USING clause of that join.
+**
+** Consider the term t2.z='ok' in the following queries:
+**
+** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
+** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
+** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
+**
+** The t2.z='ok' is disabled in the in (2) because it originates
+** in the ON clause. The term is disabled in (3) because it is not part
+** of a LEFT OUTER JOIN. In (1), the term is not disabled.
+**
+** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
+** completely satisfied by indices.
+**
+** Disabling a term causes that term to not be tested in the inner loop
+** of the join. Disabling is an optimization. When terms are satisfied
+** by indices, we disable them to prevent redundant tests in the inner
+** loop. We would get the correct results if nothing were ever disabled,
+** but joins might run a little slower. The trick is to disable as much
+** as we can without disabling too much. If we disabled in (1), we'd get
+** the wrong answer. See ticket #813.
+*/
+static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
+ if( pTerm
+ && (pTerm->wtFlags & TERM_CODED)==0
+ && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+ ){
+ pTerm->wtFlags |= TERM_CODED;
+ if( pTerm->iParent>=0 ){
+ WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
+ if( (--pOther->nChild)==0 ){
+ disableTerm(pLevel, pOther);
+ }
+ }
+ }
+}
+
+/*
+** Code an OP_Affinity opcode to apply the column affinity string zAff
+** to the n registers starting at base.
+**
+** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
+** beginning and end of zAff are ignored. If all entries in zAff are
+** SQLITE_AFF_NONE, then no code gets generated.
+**
+** This routine makes its own copy of zAff so that the caller is free
+** to modify zAff after this routine returns.
+*/
+static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
+ Vdbe *v = pParse->pVdbe;
+ if( zAff==0 ){
+ assert( pParse->db->mallocFailed );
+ return;
+ }
+ assert( v!=0 );
+
+ /* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning
+ ** and end of the affinity string.
+ */
+ while( n>0 && zAff[0]==SQLITE_AFF_NONE ){
+ n--;
+ base++;
+ zAff++;
+ }
+ while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){
+ n--;
+ }
+
+ /* Code the OP_Affinity opcode if there is anything left to do. */
+ if( n>0 ){
+ sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
+ sqlite3VdbeChangeP4(v, -1, zAff, n);
+ sqlite3ExprCacheAffinityChange(pParse, base, n);
+ }
+}
+
+
+/*
+** Generate code for a single equality term of the WHERE clause. An equality
+** term can be either X=expr or X IN (...). pTerm is the term to be
+** coded.
+**
+** The current value for the constraint is left in register iReg.
+**
+** For a constraint of the form X=expr, the expression is evaluated and its
+** result is left on the stack. For constraints of the form X IN (...)
+** this routine sets up a loop that will iterate over all values of X.
+*/
+static int codeEqualityTerm(
+ Parse *pParse, /* The parsing context */
+ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
+ WhereLevel *pLevel, /* The level of the FROM clause we are working on */
+ int iEq, /* Index of the equality term within this level */
+ int iTarget /* Attempt to leave results in this register */
+){
+ Expr *pX = pTerm->pExpr;
+ Vdbe *v = pParse->pVdbe;
+ int iReg; /* Register holding results */
+
+ assert( iTarget>0 );
+ if( pX->op==TK_EQ ){
+ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
+ }else if( pX->op==TK_ISNULL ){
+ iReg = iTarget;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
+#ifndef SQLITE_OMIT_SUBQUERY
+ }else{
+ int eType;
+ int iTab;
+ struct InLoop *pIn;
+ u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
+
+ if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0
+ && pLevel->plan.u.pIdx->aSortOrder[iEq]
+ ){
+ testcase( iEq==0 );
+ testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
+ testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn );
+ testcase( bRev );
+ bRev = !bRev;
+ }
+ assert( pX->op==TK_IN );
+ iReg = iTarget;
+ eType = sqlite3FindInIndex(pParse, pX, 0);
+ if( eType==IN_INDEX_INDEX_DESC ){
+ testcase( bRev );
+ bRev = !bRev;
+ }
+ iTab = pX->iTable;
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
+ assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
+ if( pLevel->u.in.nIn==0 ){
+ pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
+ }
+ pLevel->u.in.nIn++;
+ pLevel->u.in.aInLoop =
+ sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
+ sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
+ pIn = pLevel->u.in.aInLoop;
+ if( pIn ){
+ pIn += pLevel->u.in.nIn - 1;
+ pIn->iCur = iTab;
+ if( eType==IN_INDEX_ROWID ){
+ pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
+ }else{
+ pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
+ }
+ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
+ sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
+ }else{
+ pLevel->u.in.nIn = 0;
+ }
+#endif
+ }
+ disableTerm(pLevel, pTerm);
+ return iReg;
+}
+
+/*
+** Generate code that will evaluate all == and IN constraints for an
+** index.
+**
+** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
+** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
+** The index has as many as three equality constraints, but in this
+** example, the third "c" value is an inequality. So only two
+** constraints are coded. This routine will generate code to evaluate
+** a==5 and b IN (1,2,3). The current values for a and b will be stored
+** in consecutive registers and the index of the first register is returned.
+**
+** In the example above nEq==2. But this subroutine works for any value
+** of nEq including 0. If nEq==0, this routine is nearly a no-op.
+** The only thing it does is allocate the pLevel->iMem memory cell and
+** compute the affinity string.
+**
+** This routine always allocates at least one memory cell and returns
+** the index of that memory cell. The code that
+** calls this routine will use that memory cell to store the termination
+** key value of the loop. If one or more IN operators appear, then
+** this routine allocates an additional nEq memory cells for internal
+** use.
+**
+** Before returning, *pzAff is set to point to a buffer containing a
+** copy of the column affinity string of the index allocated using
+** sqlite3DbMalloc(). Except, entries in the copy of the string associated
+** with equality constraints that use NONE affinity are set to
+** SQLITE_AFF_NONE. This is to deal with SQL such as the following:
+**
+** CREATE TABLE t1(a TEXT PRIMARY KEY, b);
+** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b;
+**
+** In the example above, the index on t1(a) has TEXT affinity. But since
+** the right hand side of the equality constraint (t2.b) has NONE affinity,
+** no conversion should be attempted before using a t2.b value as part of
+** a key to search the index. Hence the first byte in the returned affinity
+** string in this example would be set to SQLITE_AFF_NONE.
+*/
+static int codeAllEqualityTerms(
+ Parse *pParse, /* Parsing context */
+ WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
+ WhereClause *pWC, /* The WHERE clause */
+ Bitmask notReady, /* Which parts of FROM have not yet been coded */
+ int nExtraReg, /* Number of extra registers to allocate */
+ char **pzAff /* OUT: Set to point to affinity string */
+){
+ int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */
+ Vdbe *v = pParse->pVdbe; /* The vm under construction */
+ Index *pIdx; /* The index being used for this loop */
+ int iCur = pLevel->iTabCur; /* The cursor of the table */
+ WhereTerm *pTerm; /* A single constraint term */
+ int j; /* Loop counter */
+ int regBase; /* Base register */
+ int nReg; /* Number of registers to allocate */
+ char *zAff; /* Affinity string to return */
+
+ /* This module is only called on query plans that use an index. */
+ assert( pLevel->plan.wsFlags & WHERE_INDEXED );
+ pIdx = pLevel->plan.u.pIdx;
+
+ /* Figure out how many memory cells we will need then allocate them.
+ */
+ regBase = pParse->nMem + 1;
+ nReg = pLevel->plan.nEq + nExtraReg;
+ pParse->nMem += nReg;
+
+ zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx));
+ if( !zAff ){
+ pParse->db->mallocFailed = 1;
+ }
+
+ /* Evaluate the equality constraints
+ */
+ assert( pIdx->nColumn>=nEq );
+ for(j=0; j<nEq; j++){
+ int r1;
+ int k = pIdx->aiColumn[j];
+ pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
+ if( pTerm==0 ) break;
+ /* The following true for indices with redundant columns.
+ ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
+ testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
+ testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j);
+ if( r1!=regBase+j ){
+ if( nReg==1 ){
+ sqlite3ReleaseTempReg(pParse, regBase);
+ regBase = r1;
+ }else{
+ sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
+ }
+ }
+ testcase( pTerm->eOperator & WO_ISNULL );
+ testcase( pTerm->eOperator & WO_IN );
+ if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
+ Expr *pRight = pTerm->pExpr->pRight;
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk);
+ if( zAff ){
+ if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
+ zAff[j] = SQLITE_AFF_NONE;
+ }
+ if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
+ zAff[j] = SQLITE_AFF_NONE;
+ }
+ }
+ }
+ }
+ *pzAff = zAff;
+ return regBase;
+}
+
+#ifndef SQLITE_OMIT_EXPLAIN
+/*
+** This routine is a helper for explainIndexRange() below
+**
+** pStr holds the text of an expression that we are building up one term
+** at a time. This routine adds a new term to the end of the expression.
+** Terms are separated by AND so add the "AND" text for second and subsequent
+** terms only.
+*/
+static void explainAppendTerm(
+ StrAccum *pStr, /* The text expression being built */
+ int iTerm, /* Index of this term. First is zero */
+ const char *zColumn, /* Name of the column */
+ const char *zOp /* Name of the operator */
+){
+ if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5);
+ sqlite3StrAccumAppend(pStr, zColumn, -1);
+ sqlite3StrAccumAppend(pStr, zOp, 1);
+ sqlite3StrAccumAppend(pStr, "?", 1);
+}
+
+/*
+** Argument pLevel describes a strategy for scanning table pTab. This
+** function returns a pointer to a string buffer containing a description
+** of the subset of table rows scanned by the strategy in the form of an
+** SQL expression. Or, if all rows are scanned, NULL is returned.
+**
+** For example, if the query:
+**
+** SELECT * FROM t1 WHERE a=1 AND b>2;
+**
+** is run and there is an index on (a, b), then this function returns a
+** string similar to:
+**
+** "a=? AND b>?"
+**
+** The returned pointer points to memory obtained from sqlite3DbMalloc().
+** It is the responsibility of the caller to free the buffer when it is
+** no longer required.
+*/
+static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
+ WherePlan *pPlan = &pLevel->plan;
+ Index *pIndex = pPlan->u.pIdx;
+ int nEq = pPlan->nEq;
+ int i, j;
+ Column *aCol = pTab->aCol;
+ int *aiColumn = pIndex->aiColumn;
+ StrAccum txt;
+
+ if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
+ return 0;
+ }
+ sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
+ txt.db = db;
+ sqlite3StrAccumAppend(&txt, " (", 2);
+ for(i=0; i<nEq; i++){
+ explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "=");
+ }
+
+ j = i;
+ if( pPlan->wsFlags&WHERE_BTM_LIMIT ){
+ char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
+ explainAppendTerm(&txt, i++, z, ">");
+ }
+ if( pPlan->wsFlags&WHERE_TOP_LIMIT ){
+ char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
+ explainAppendTerm(&txt, i, z, "<");
+ }
+ sqlite3StrAccumAppend(&txt, ")", 1);
+ return sqlite3StrAccumFinish(&txt);
+}
+
+/*
+** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
+** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single
+** record is added to the output to describe the table scan strategy in
+** pLevel.
+*/
+static void explainOneScan(
+ Parse *pParse, /* Parse context */
+ SrcList *pTabList, /* Table list this loop refers to */
+ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
+ int iLevel, /* Value for "level" column of output */
+ int iFrom, /* Value for "from" column of output */
+ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
+){
+ if( pParse->explain==2 ){
+ u32 flags = pLevel->plan.wsFlags;
+ struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
+ Vdbe *v = pParse->pVdbe; /* VM being constructed */
+ sqlite3 *db = pParse->db; /* Database handle */
+ char *zMsg; /* Text to add to EQP output */
+ sqlite3_int64 nRow; /* Expected number of rows visited by scan */
+ int iId = pParse->iSelectId; /* Select id (left-most output column) */
+ int isSearch; /* True for a SEARCH. False for SCAN. */
+
+ if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
+
+ isSearch = (pLevel->plan.nEq>0)
+ || (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
+ || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
+
+ zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
+ if( pItem->pSelect ){
+ zMsg = sqlite3MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId);
+ }else{
+ zMsg = sqlite3MAppendf(db, zMsg, "%s TABLE %s", zMsg, pItem->zName);
+ }
+
+ if( pItem->zAlias ){
+ zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
+ }
+ if( (flags & WHERE_INDEXED)!=0 ){
+ char *zWhere = explainIndexRange(db, pLevel, pItem->pTab);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
+ ((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
+ ((flags & WHERE_IDX_ONLY)?"COVERING ":""),
+ ((flags & WHERE_TEMP_INDEX)?"":" "),
+ ((flags & WHERE_TEMP_INDEX)?"": pLevel->plan.u.pIdx->zName),
+ zWhere
+ );
+ sqlite3DbFree(db, zWhere);
+ }else if( flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+ zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
+
+ if( flags&WHERE_ROWID_EQ ){
+ zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
+ }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
+ zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
+ }else if( flags&WHERE_BTM_LIMIT ){
+ zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>?)", zMsg);
+ }else if( flags&WHERE_TOP_LIMIT ){
+ zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid<?)", zMsg);
+ }
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
+ sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
+ zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
+ pVtabIdx->idxNum, pVtabIdx->idxStr);
+ }
+#endif
+ if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
+ testcase( wctrlFlags & WHERE_ORDERBY_MIN );
+ nRow = 1;
+ }else{
+ nRow = (sqlite3_int64)pLevel->plan.nRow;
+ }
+ zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
+ sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
+ }
+}
+#else
+# define explainOneScan(u,v,w,x,y,z)
+#endif /* SQLITE_OMIT_EXPLAIN */
+
+
+/*
+** Generate code for the start of the iLevel-th loop in the WHERE clause
+** implementation described by pWInfo.
+*/
+static Bitmask codeOneLoopStart(
+ WhereInfo *pWInfo, /* Complete information about the WHERE clause */
+ int iLevel, /* Which level of pWInfo->a[] should be coded */
+ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
+ Bitmask notReady /* Which tables are currently available */
+){
+ int j, k; /* Loop counters */
+ int iCur; /* The VDBE cursor for the table */
+ int addrNxt; /* Where to jump to continue with the next IN case */
+ int omitTable; /* True if we use the index only */
+ int bRev; /* True if we need to scan in reverse order */
+ WhereLevel *pLevel; /* The where level to be coded */
+ WhereClause *pWC; /* Decomposition of the entire WHERE clause */
+ WhereTerm *pTerm; /* A WHERE clause term */
+ Parse *pParse; /* Parsing context */
+ Vdbe *v; /* The prepared stmt under constructions */
+ struct SrcList_item *pTabItem; /* FROM clause term being coded */
+ int addrBrk; /* Jump here to break out of the loop */
+ int addrCont; /* Jump here to continue with next cycle */
+ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
+ int iReleaseReg = 0; /* Temp register to free before returning */
+
+ pParse = pWInfo->pParse;
+ v = pParse->pVdbe;
+ pWC = pWInfo->pWC;
+ pLevel = &pWInfo->a[iLevel];
+ pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
+ iCur = pTabItem->iCursor;
+ bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
+ omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
+ && (wctrlFlags & WHERE_FORCE_TABLE)==0;
+
+ /* Create labels for the "break" and "continue" instructions
+ ** for the current loop. Jump to addrBrk to break out of a loop.
+ ** Jump to cont to go immediately to the next iteration of the
+ ** loop.
+ **
+ ** When there is an IN operator, we also have a "addrNxt" label that
+ ** means to continue with the next IN value combination. When
+ ** there are no IN operators in the constraints, the "addrNxt" label
+ ** is the same as "addrBrk".
+ */
+ addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
+ addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v);
+
+ /* If this is the right table of a LEFT OUTER JOIN, allocate and
+ ** initialize a memory cell that records if this table matches any
+ ** row of the left table of the join.
+ */
+ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){
+ pLevel->iLeftJoin = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
+ VdbeComment((v, "init LEFT JOIN no-match flag"));
+ }
+
+ /* Special case of a FROM clause subquery implemented as a co-routine */
+ if( pTabItem->viaCoroutine ){
+ int regYield = pTabItem->regReturn;
+ sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
+ pLevel->p2 = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
+ VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
+ sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
+ pLevel->op = OP_Goto;
+ }else
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+ /* Case 0: The table is a virtual-table. Use the VFilter and VNext
+ ** to access the data.
+ */
+ int iReg; /* P3 Value for OP_VFilter */
+ int addrNotFound;
+ sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
+ int nConstraint = pVtabIdx->nConstraint;
+ struct sqlite3_index_constraint_usage *aUsage =
+ pVtabIdx->aConstraintUsage;
+ const struct sqlite3_index_constraint *aConstraint =
+ pVtabIdx->aConstraint;
+
+ sqlite3ExprCachePush(pParse);
+ iReg = sqlite3GetTempRange(pParse, nConstraint+2);
+ addrNotFound = pLevel->addrBrk;
+ for(j=1; j<=nConstraint; j++){
+ for(k=0; k<nConstraint; k++){
+ if( aUsage[k].argvIndex==j ){
+ int iTarget = iReg+j+1;
+ pTerm = &pWC->a[aConstraint[k].iTermOffset];
+ if( pTerm->eOperator & WO_IN ){
+ codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget);
+ addrNotFound = pLevel->addrNxt;
+ }else{
+ sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
+ }
+ break;
+ }
+ }
+ if( k==nConstraint ) break;
+ }
+ sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
+ sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
+ sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
+ pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
+ pVtabIdx->needToFreeIdxStr = 0;
+ for(j=0; j<nConstraint; j++){
+ if( aUsage[j].omit ){
+ int iTerm = aConstraint[j].iTermOffset;
+ disableTerm(pLevel, &pWC->a[iTerm]);
+ }
+ }
+ pLevel->op = OP_VNext;
+ pLevel->p1 = iCur;
+ pLevel->p2 = sqlite3VdbeCurrentAddr(v);
+ sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
+ sqlite3ExprCachePop(pParse, 1);
+ }else
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+ if( pLevel->plan.wsFlags & WHERE_ROWID_EQ ){
+ /* Case 1: We can directly reference a single row using an
+ ** equality comparison against the ROWID field. Or
+ ** we reference multiple rows using a "rowid IN (...)"
+ ** construct.
+ */
+ iReleaseReg = sqlite3GetTempReg(pParse);
+ pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+ assert( pTerm!=0 );
+ assert( pTerm->pExpr!=0 );
+ assert( omitTable==0 );
+ testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg);
+ addrNxt = pLevel->addrNxt;
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
+ sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
+ VdbeComment((v, "pk"));
+ pLevel->op = OP_Noop;
+ }else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){
+ /* Case 2: We have an inequality comparison against the ROWID field.
+ */
+ int testOp = OP_Noop;
+ int start;
+ int memEndValue = 0;
+ WhereTerm *pStart, *pEnd;
+
+ assert( omitTable==0 );
+ pStart = findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0);
+ pEnd = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0);
+ if( bRev ){
+ pTerm = pStart;
+ pStart = pEnd;
+ pEnd = pTerm;
+ }
+ if( pStart ){
+ Expr *pX; /* The expression that defines the start bound */
+ int r1, rTemp; /* Registers for holding the start boundary */
+
+ /* The following constant maps TK_xx codes into corresponding
+ ** seek opcodes. It depends on a particular ordering of TK_xx
+ */
+ const u8 aMoveOp[] = {
+ /* TK_GT */ OP_SeekGt,
+ /* TK_LE */ OP_SeekLe,
+ /* TK_LT */ OP_SeekLt,
+ /* TK_GE */ OP_SeekGe
+ };
+ assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */
+ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */
+ assert( TK_GE==TK_GT+3 ); /* ... is correcct. */
+
+ testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ pX = pStart->pExpr;
+ assert( pX!=0 );
+ assert( pStart->leftCursor==iCur );
+ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
+ sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
+ VdbeComment((v, "pk"));
+ sqlite3ExprCacheAffinityChange(pParse, r1, 1);
+ sqlite3ReleaseTempReg(pParse, rTemp);
+ disableTerm(pLevel, pStart);
+ }else{
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
+ }
+ if( pEnd ){
+ Expr *pX;
+ pX = pEnd->pExpr;
+ assert( pX!=0 );
+ assert( pEnd->leftCursor==iCur );
+ testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ memEndValue = ++pParse->nMem;
+ sqlite3ExprCode(pParse, pX->pRight, memEndValue);
+ if( pX->op==TK_LT || pX->op==TK_GT ){
+ testOp = bRev ? OP_Le : OP_Ge;
+ }else{
+ testOp = bRev ? OP_Lt : OP_Gt;
+ }
+ disableTerm(pLevel, pEnd);
+ }
+ start = sqlite3VdbeCurrentAddr(v);
+ pLevel->op = bRev ? OP_Prev : OP_Next;
+ pLevel->p1 = iCur;
+ pLevel->p2 = start;
+ if( pStart==0 && pEnd==0 ){
+ pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+ }else{
+ assert( pLevel->p5==0 );
+ }
+ if( testOp!=OP_Noop ){
+ iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
+ sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
+ sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
+ }
+ }else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
+ /* Case 3: A scan using an index.
+ **
+ ** The WHERE clause may contain zero or more equality
+ ** terms ("==" or "IN" operators) that refer to the N
+ ** left-most columns of the index. It may also contain
+ ** inequality constraints (>, <, >= or <=) on the indexed
+ ** column that immediately follows the N equalities. Only
+ ** the right-most column can be an inequality - the rest must
+ ** use the "==" and "IN" operators. For example, if the
+ ** index is on (x,y,z), then the following clauses are all
+ ** optimized:
+ **
+ ** x=5
+ ** x=5 AND y=10
+ ** x=5 AND y<10
+ ** x=5 AND y>5 AND y<10
+ ** x=5 AND y=5 AND z<=10
+ **
+ ** The z<10 term of the following cannot be used, only
+ ** the x=5 term:
+ **
+ ** x=5 AND z<10
+ **
+ ** N may be zero if there are inequality constraints.
+ ** If there are no inequality constraints, then N is at
+ ** least one.
+ **
+ ** This case is also used when there are no WHERE clause
+ ** constraints but an index is selected anyway, in order
+ ** to force the output order to conform to an ORDER BY.
+ */
+ static const u8 aStartOp[] = {
+ 0,
+ 0,
+ OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
+ OP_Last, /* 3: (!start_constraints && startEq && bRev) */
+ OP_SeekGt, /* 4: (start_constraints && !startEq && !bRev) */
+ OP_SeekLt, /* 5: (start_constraints && !startEq && bRev) */
+ OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */
+ OP_SeekLe /* 7: (start_constraints && startEq && bRev) */
+ };
+ static const u8 aEndOp[] = {
+ OP_Noop, /* 0: (!end_constraints) */
+ OP_IdxGE, /* 1: (end_constraints && !bRev) */
+ OP_IdxLT /* 2: (end_constraints && bRev) */
+ };
+ int nEq = pLevel->plan.nEq; /* Number of == or IN terms */
+ int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
+ int regBase; /* Base register holding constraint values */
+ int r1; /* Temp register */
+ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */
+ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */
+ int startEq; /* True if range start uses ==, >= or <= */
+ int endEq; /* True if range end uses ==, >= or <= */
+ int start_constraints; /* Start of range is constrained */
+ int nConstraint; /* Number of constraint terms */
+ Index *pIdx; /* The index we will be using */
+ int iIdxCur; /* The VDBE cursor for the index */
+ int nExtraReg = 0; /* Number of extra registers needed */
+ int op; /* Instruction opcode */
+ char *zStartAff; /* Affinity for start of range constraint */
+ char *zEndAff; /* Affinity for end of range constraint */
+
+ pIdx = pLevel->plan.u.pIdx;
+ iIdxCur = pLevel->iIdxCur;
+ k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]);
+
+ /* If this loop satisfies a sort order (pOrderBy) request that
+ ** was passed to this function to implement a "SELECT min(x) ..."
+ ** query, then the caller will only allow the loop to run for
+ ** a single iteration. This means that the first row returned
+ ** should not have a NULL value stored in 'x'. If column 'x' is
+ ** the first one after the nEq equality constraints in the index,
+ ** this requires some special handling.
+ */
+ if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
+ && (pLevel->plan.wsFlags&WHERE_ORDERED)
+ && (pIdx->nColumn>nEq)
+ ){
+ /* assert( pOrderBy->nExpr==1 ); */
+ /* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */
+ isMinQuery = 1;
+ nExtraReg = 1;
+ }
+
+ /* Find any inequality constraint terms for the start and end
+ ** of the range.
+ */
+ if( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ){
+ pRangeEnd = findTerm(pWC, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
+ nExtraReg = 1;
+ }
+ if( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ){
+ pRangeStart = findTerm(pWC, iCur, k, notReady, (WO_GT|WO_GE), pIdx);
+ nExtraReg = 1;
+ }
+
+ /* Generate code to evaluate all constraint terms using == or IN
+ ** and store the values of those terms in an array of registers
+ ** starting at regBase.
+ */
+ regBase = codeAllEqualityTerms(
+ pParse, pLevel, pWC, notReady, nExtraReg, &zStartAff
+ );
+ zEndAff = sqlite3DbStrDup(pParse->db, zStartAff);
+ addrNxt = pLevel->addrNxt;
+
+ /* If we are doing a reverse order scan on an ascending index, or
+ ** a forward order scan on a descending index, interchange the
+ ** start and end terms (pRangeStart and pRangeEnd).
+ */
+ if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
+ || (bRev && pIdx->nColumn==nEq)
+ ){
+ SWAP(WhereTerm *, pRangeEnd, pRangeStart);
+ }
+
+ testcase( pRangeStart && pRangeStart->eOperator & WO_LE );
+ testcase( pRangeStart && pRangeStart->eOperator & WO_GE );
+ testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE );
+ testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE );
+ startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
+ endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
+ start_constraints = pRangeStart || nEq>0;
+
+ /* Seek the index cursor to the start of the range. */
+ nConstraint = nEq;
+ if( pRangeStart ){
+ Expr *pRight = pRangeStart->pExpr->pRight;
+ sqlite3ExprCode(pParse, pRight, regBase+nEq);
+ if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
+ }
+ if( zStartAff ){
+ if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
+ /* Since the comparison is to be performed with no conversions
+ ** applied to the operands, set the affinity to apply to pRight to
+ ** SQLITE_AFF_NONE. */
+ zStartAff[nEq] = SQLITE_AFF_NONE;
+ }
+ if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){
+ zStartAff[nEq] = SQLITE_AFF_NONE;
+ }
+ }
+ nConstraint++;
+ testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ }else if( isMinQuery ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
+ nConstraint++;
+ startEq = 0;
+ start_constraints = 1;
+ }
+ codeApplyAffinity(pParse, regBase, nConstraint, zStartAff);
+ op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
+ assert( op!=0 );
+ testcase( op==OP_Rewind );
+ testcase( op==OP_Last );
+ testcase( op==OP_SeekGt );
+ testcase( op==OP_SeekGe );
+ testcase( op==OP_SeekLe );
+ testcase( op==OP_SeekLt );
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
+
+ /* Load the value for the inequality constraint at the end of the
+ ** range (if any).
+ */
+ nConstraint = nEq;
+ if( pRangeEnd ){
+ Expr *pRight = pRangeEnd->pExpr->pRight;
+ sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
+ sqlite3ExprCode(pParse, pRight, regBase+nEq);
+ if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
+ }
+ if( zEndAff ){
+ if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){
+ /* Since the comparison is to be performed with no conversions
+ ** applied to the operands, set the affinity to apply to pRight to
+ ** SQLITE_AFF_NONE. */
+ zEndAff[nEq] = SQLITE_AFF_NONE;
+ }
+ if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
+ zEndAff[nEq] = SQLITE_AFF_NONE;
+ }
+ }
+ codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
+ nConstraint++;
+ testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ }
+ sqlite3DbFree(pParse->db, zStartAff);
+ sqlite3DbFree(pParse->db, zEndAff);
+
+ /* Top of the loop body */
+ pLevel->p2 = sqlite3VdbeCurrentAddr(v);
+
+ /* Check if the index cursor is past the end of the range. */
+ op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)];
+ testcase( op==OP_Noop );
+ testcase( op==OP_IdxGE );
+ testcase( op==OP_IdxLT );
+ if( op!=OP_Noop ){
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
+ sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0);
+ }
+
+ /* If there are inequality constraints, check that the value
+ ** of the table column that the inequality contrains is not NULL.
+ ** If it is, jump to the next iteration of the loop.
+ */
+ r1 = sqlite3GetTempReg(pParse);
+ testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT );
+ testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT );
+ if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
+ }
+ sqlite3ReleaseTempReg(pParse, r1);
+
+ /* Seek the table cursor, if required */
+ disableTerm(pLevel, pRangeStart);
+ disableTerm(pLevel, pRangeEnd);
+ if( !omitTable ){
+ iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
+ sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
+ }
+
+ /* Record the instruction used to terminate the loop. Disable
+ ** WHERE clause terms made redundant by the index range scan.
+ */
+ if( pLevel->plan.wsFlags & WHERE_UNIQUE ){
+ pLevel->op = OP_Noop;
+ }else if( bRev ){
+ pLevel->op = OP_Prev;
+ }else{
+ pLevel->op = OP_Next;
+ }
+ pLevel->p1 = iIdxCur;
+ if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){
+ pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+ }else{
+ assert( pLevel->p5==0 );
+ }
+ }else
+
+#ifndef SQLITE_OMIT_OR_OPTIMIZATION
+ if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
+ /* Case 4: Two or more separately indexed terms connected by OR
+ **
+ ** Example:
+ **
+ ** CREATE TABLE t1(a,b,c,d);
+ ** CREATE INDEX i1 ON t1(a);
+ ** CREATE INDEX i2 ON t1(b);
+ ** CREATE INDEX i3 ON t1(c);
+ **
+ ** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
+ **
+ ** In the example, there are three indexed terms connected by OR.
+ ** The top of the loop looks like this:
+ **
+ ** Null 1 # Zero the rowset in reg 1
+ **
+ ** Then, for each indexed term, the following. The arguments to
+ ** RowSetTest are such that the rowid of the current row is inserted
+ ** into the RowSet. If it is already present, control skips the
+ ** Gosub opcode and jumps straight to the code generated by WhereEnd().
+ **
+ ** sqlite3WhereBegin(<term>)
+ ** RowSetTest # Insert rowid into rowset
+ ** Gosub 2 A
+ ** sqlite3WhereEnd()
+ **
+ ** Following the above, code to terminate the loop. Label A, the target
+ ** of the Gosub above, jumps to the instruction right after the Goto.
+ **
+ ** Null 1 # Zero the rowset in reg 1
+ ** Goto B # The loop is finished.
+ **
+ ** A: <loop body> # Return data, whatever.
+ **
+ ** Return 2 # Jump back to the Gosub
+ **
+ ** B: <after the loop>
+ **
+ */
+ WhereClause *pOrWc; /* The OR-clause broken out into subterms */
+ SrcList *pOrTab; /* Shortened table list or OR-clause generation */
+ Index *pCov = 0; /* Potential covering index (or NULL) */
+ int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */
+
+ int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
+ int regRowset = 0; /* Register for RowSet object */
+ int regRowid = 0; /* Register holding rowid */
+ int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
+ int iRetInit; /* Address of regReturn init */
+ int untestedTerms = 0; /* Some terms not completely tested */
+ int ii; /* Loop counter */
+ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
+
+ pTerm = pLevel->plan.u.pTerm;
+ assert( pTerm!=0 );
+ assert( pTerm->eOperator & WO_OR );
+ assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
+ pOrWc = &pTerm->u.pOrInfo->wc;
+ pLevel->op = OP_Return;
+ pLevel->p1 = regReturn;
+
+ /* Set up a new SrcList in pOrTab containing the table being scanned
+ ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
+ ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
+ */
+ if( pWInfo->nLevel>1 ){
+ int nNotReady; /* The number of notReady tables */
+ struct SrcList_item *origSrc; /* Original list of tables */
+ nNotReady = pWInfo->nLevel - iLevel - 1;
+ pOrTab = sqlite3StackAllocRaw(pParse->db,
+ sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
+ if( pOrTab==0 ) return notReady;
+ pOrTab->nAlloc = (i16)(nNotReady + 1);
+ pOrTab->nSrc = pOrTab->nAlloc;
+ memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
+ origSrc = pWInfo->pTabList->a;
+ for(k=1; k<=nNotReady; k++){
+ memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
+ }
+ }else{
+ pOrTab = pWInfo->pTabList;
+ }
+
+ /* Initialize the rowset register to contain NULL. An SQL NULL is
+ ** equivalent to an empty rowset.
+ **
+ ** Also initialize regReturn to contain the address of the instruction
+ ** immediately following the OP_Return at the bottom of the loop. This
+ ** is required in a few obscure LEFT JOIN cases where control jumps
+ ** over the top of the loop into the body of it. In this case the
+ ** correct response for the end-of-loop code (the OP_Return) is to
+ ** fall through to the next instruction, just as an OP_Next does if
+ ** called on an uninitialized cursor.
+ */
+ if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ regRowset = ++pParse->nMem;
+ regRowid = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
+ }
+ iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
+
+ /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
+ ** Then for every term xN, evaluate as the subexpression: xN AND z
+ ** That way, terms in y that are factored into the disjunction will
+ ** be picked up by the recursive calls to sqlite3WhereBegin() below.
+ **
+ ** Actually, each subexpression is converted to "xN AND w" where w is
+ ** the "interesting" terms of z - terms that did not originate in the
+ ** ON or USING clause of a LEFT JOIN, and terms that are usable as
+ ** indices.
+ */
+ if( pWC->nTerm>1 ){
+ int iTerm;
+ for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
+ Expr *pExpr = pWC->a[iTerm].pExpr;
+ if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
+ if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
+ if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
+ pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
+ pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
+ }
+ if( pAndExpr ){
+ pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
+ }
+ }
+
+ for(ii=0; ii<pOrWc->nTerm; ii++){
+ WhereTerm *pOrTerm = &pOrWc->a[ii];
+ if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
+ WhereInfo *pSubWInfo; /* Info for single OR-term scan */
+ Expr *pOrExpr = pOrTerm->pExpr;
+ if( pAndExpr ){
+ pAndExpr->pLeft = pOrExpr;
+ pOrExpr = pAndExpr;
+ }
+ /* Loop through table entries that match term pOrTerm. */
+ pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
+ WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
+ WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
+ assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
+ if( pSubWInfo ){
+ WhereLevel *pLvl;
+ explainOneScan(
+ pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
+ );
+ if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
+ int r;
+ r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
+ regRowid, 0);
+ sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
+ sqlite3VdbeCurrentAddr(v)+2, r, iSet);
+ }
+ sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
+
+ /* The pSubWInfo->untestedTerms flag means that this OR term
+ ** contained one or more AND term from a notReady table. The
+ ** terms from the notReady table could not be tested and will
+ ** need to be tested later.
+ */
+ if( pSubWInfo->untestedTerms ) untestedTerms = 1;
+
+ /* If all of the OR-connected terms are optimized using the same
+ ** index, and the index is opened using the same cursor number
+ ** by each call to sqlite3WhereBegin() made by this loop, it may
+ ** be possible to use that index as a covering index.
+ **
+ ** If the call to sqlite3WhereBegin() above resulted in a scan that
+ ** uses an index, and this is either the first OR-connected term
+ ** processed or the index is the same as that used by all previous
+ ** terms, set pCov to the candidate covering index. Otherwise, set
+ ** pCov to NULL to indicate that no candidate covering index will
+ ** be available.
+ */
+ pLvl = &pSubWInfo->a[0];
+ if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0
+ && (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0
+ && (ii==0 || pLvl->plan.u.pIdx==pCov)
+ ){
+ assert( pLvl->iIdxCur==iCovCur );
+ pCov = pLvl->plan.u.pIdx;
+ }else{
+ pCov = 0;
+ }
+
+ /* Finish the loop through table entries that match term pOrTerm. */
+ sqlite3WhereEnd(pSubWInfo);
+ }
+ }
+ }
+ pLevel->u.pCovidx = pCov;
+ if( pCov ) pLevel->iIdxCur = iCovCur;
+ if( pAndExpr ){
+ pAndExpr->pLeft = 0;
+ sqlite3ExprDelete(pParse->db, pAndExpr);
+ }
+ sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
+ sqlite3VdbeResolveLabel(v, iLoopBody);
+
+ if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
+ if( !untestedTerms ) disableTerm(pLevel, pTerm);
+ }else
+#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+
+ {
+ /* Case 5: There is no usable index. We must do a complete
+ ** scan of the entire table.
+ */
+ static const u8 aStep[] = { OP_Next, OP_Prev };
+ static const u8 aStart[] = { OP_Rewind, OP_Last };
+ assert( bRev==0 || bRev==1 );
+ assert( omitTable==0 );
+ pLevel->op = aStep[bRev];
+ pLevel->p1 = iCur;
+ pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
+ pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+ }
+ notReady &= ~getMask(pWC->pMaskSet, iCur);
+
+ /* Insert code to test every subexpression that can be completely
+ ** computed using the current set of tables.
+ **
+ ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
+ ** the use of indices become tests that are evaluated against each row of
+ ** the relevant input tables.
+ */
+ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
+ Expr *pE;
+ testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
+ testcase( pTerm->wtFlags & TERM_CODED );
+ if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+ if( (pTerm->prereqAll & notReady)!=0 ){
+ testcase( pWInfo->untestedTerms==0
+ && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
+ pWInfo->untestedTerms = 1;
+ continue;
+ }
+ pE = pTerm->pExpr;
+ assert( pE!=0 );
+ if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
+ continue;
+ }
+ sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
+ pTerm->wtFlags |= TERM_CODED;
+ }
+
+ /* For a LEFT OUTER JOIN, generate code that will record the fact that
+ ** at least one row of the right table has matched the left table.
+ */
+ if( pLevel->iLeftJoin ){
+ pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
+ VdbeComment((v, "record LEFT JOIN hit"));
+ sqlite3ExprCacheClear(pParse);
+ for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
+ testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
+ testcase( pTerm->wtFlags & TERM_CODED );
+ if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+ if( (pTerm->prereqAll & notReady)!=0 ){
+ assert( pWInfo->untestedTerms );
+ continue;
+ }
+ assert( pTerm->pExpr );
+ sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
+ pTerm->wtFlags |= TERM_CODED;
+ }
+ }
+ sqlite3ReleaseTempReg(pParse, iReleaseReg);
+
+ return notReady;
+}
+
+#if defined(SQLITE_TEST)
+/*
+** The following variable holds a text description of query plan generated
+** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin
+** overwrites the previous. This information is used for testing and
+** analysis only.
+*/
+SQLITE_API char sqlite3_query_plan[BMS*2*40]; /* Text of the join */
+static int nQPlan = 0; /* Next free slow in _query_plan[] */
+
+#endif /* SQLITE_TEST */
+
+
+/*
+** Free a WhereInfo structure
+*/
+static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
+ if( ALWAYS(pWInfo) ){
+ int i;
+ for(i=0; i<pWInfo->nLevel; i++){
+ sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
+ if( pInfo ){
+ /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */
+ if( pInfo->needToFreeIdxStr ){
+ sqlite3_free(pInfo->idxStr);
+ }
+ sqlite3DbFree(db, pInfo);
+ }
+ if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){
+ Index *pIdx = pWInfo->a[i].plan.u.pIdx;
+ if( pIdx ){
+ sqlite3DbFree(db, pIdx->zColAff);
+ sqlite3DbFree(db, pIdx);
+ }
+ }
+ }
+ whereClauseClear(pWInfo->pWC);
+ sqlite3DbFree(db, pWInfo);
+ }
+}
+
+
+/*
+** Generate the beginning of the loop used for WHERE clause processing.
+** The return value is a pointer to an opaque structure that contains
+** information needed to terminate the loop. Later, the calling routine
+** should invoke sqlite3WhereEnd() with the return value of this function
+** in order to complete the WHERE clause processing.
+**
+** If an error occurs, this routine returns NULL.
+**
+** The basic idea is to do a nested loop, one loop for each table in
+** the FROM clause of a select. (INSERT and UPDATE statements are the
+** same as a SELECT with only a single table in the FROM clause.) For
+** example, if the SQL is this:
+**
+** SELECT * FROM t1, t2, t3 WHERE ...;
+**
+** Then the code generated is conceptually like the following:
+**
+** foreach row1 in t1 do \ Code generated
+** foreach row2 in t2 do |-- by sqlite3WhereBegin()
+** foreach row3 in t3 do /
+** ...
+** end \ Code generated
+** end |-- by sqlite3WhereEnd()
+** end /
+**
+** Note that the loops might not be nested in the order in which they
+** appear in the FROM clause if a different order is better able to make
+** use of indices. Note also that when the IN operator appears in
+** the WHERE clause, it might result in additional nested loops for
+** scanning through all values on the right-hand side of the IN.
+**
+** There are Btree cursors associated with each table. t1 uses cursor
+** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor.
+** And so forth. This routine generates code to open those VDBE cursors
+** and sqlite3WhereEnd() generates the code to close them.
+**
+** The code that sqlite3WhereBegin() generates leaves the cursors named
+** in pTabList pointing at their appropriate entries. The [...] code
+** can use OP_Column and OP_Rowid opcodes on these cursors to extract
+** data from the various tables of the loop.
+**
+** If the WHERE clause is empty, the foreach loops must each scan their
+** entire tables. Thus a three-way join is an O(N^3) operation. But if
+** the tables have indices and there are terms in the WHERE clause that
+** refer to those indices, a complete table scan can be avoided and the
+** code will run much faster. Most of the work of this routine is checking
+** to see if there are indices that can be used to speed up the loop.
+**
+** Terms of the WHERE clause are also used to limit which rows actually
+** make it to the "..." in the middle of the loop. After each "foreach",
+** terms of the WHERE clause that use only terms in that loop and outer
+** loops are evaluated and if false a jump is made around all subsequent
+** inner loops (or around the "..." if the test occurs within the inner-
+** most loop)
+**
+** OUTER JOINS
+**
+** An outer join of tables t1 and t2 is conceptally coded as follows:
+**
+** foreach row1 in t1 do
+** flag = 0
+** foreach row2 in t2 do
+** start:
+** ...
+** flag = 1
+** end
+** if flag==0 then
+** move the row2 cursor to a null row
+** goto start
+** fi
+** end
+**
+** ORDER BY CLAUSE PROCESSING
+**
+** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
+** if there is one. If there is no ORDER BY clause or if this routine
+** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
+**
+** If an index can be used so that the natural output order of the table
+** scan is correct for the ORDER BY clause, then that index is used and
+** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr. This
+** is an optimization that prevents an unnecessary sort of the result set
+** if an index appropriate for the ORDER BY clause already exists.
+**
+** If the where clause loops cannot be arranged to provide the correct
+** output order, then WhereInfo.nOBSat is 0.
+*/
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
+ Parse *pParse, /* The parser context */
+ SrcList *pTabList, /* A list of all tables to be scanned */
+ Expr *pWhere, /* The WHERE clause */
+ ExprList *pOrderBy, /* An ORDER BY clause, or NULL */
+ ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
+ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
+ int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */
+){
+ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
+ int nTabList; /* Number of elements in pTabList */
+ WhereInfo *pWInfo; /* Will become the return value of this function */
+ Vdbe *v = pParse->pVdbe; /* The virtual database engine */
+ Bitmask notReady; /* Cursors that are not yet positioned */
+ WhereBestIdx sWBI; /* Best index search context */
+ WhereMaskSet *pMaskSet; /* The expression mask set */
+ WhereLevel *pLevel; /* A single level in pWInfo->a[] */
+ int iFrom; /* First unused FROM clause element */
+ int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */
+ int ii; /* Loop counter */
+ sqlite3 *db; /* Database connection */
+
+
+ /* Variable initialization */
+ memset(&sWBI, 0, sizeof(sWBI));
+ sWBI.pParse = pParse;
+
+ /* The number of tables in the FROM clause is limited by the number of
+ ** bits in a Bitmask
+ */
+ testcase( pTabList->nSrc==BMS );
+ if( pTabList->nSrc>BMS ){
+ sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
+ return 0;
+ }
+
+ /* This function normally generates a nested loop for all tables in
+ ** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should
+ ** only generate code for the first table in pTabList and assume that
+ ** any cursors associated with subsequent tables are uninitialized.
+ */
+ nTabList = (wctrlFlags & WHERE_ONETABLE_ONLY) ? 1 : pTabList->nSrc;
+
+ /* Allocate and initialize the WhereInfo structure that will become the
+ ** return value. A single allocation is used to store the WhereInfo
+ ** struct, the contents of WhereInfo.a[], the WhereClause structure
+ ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
+ ** field (type Bitmask) it must be aligned on an 8-byte boundary on
+ ** some architectures. Hence the ROUND8() below.
+ */
+ db = pParse->db;
+ nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
+ pWInfo = sqlite3DbMallocZero(db,
+ nByteWInfo +
+ sizeof(WhereClause) +
+ sizeof(WhereMaskSet)
+ );
+ if( db->mallocFailed ){
+ sqlite3DbFree(db, pWInfo);
+ pWInfo = 0;
+ goto whereBeginError;
+ }
+ pWInfo->nLevel = nTabList;
+ pWInfo->pParse = pParse;
+ pWInfo->pTabList = pTabList;
+ pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
+ pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
+ pWInfo->wctrlFlags = wctrlFlags;
+ pWInfo->savedNQueryLoop = pParse->nQueryLoop;
+ pMaskSet = (WhereMaskSet*)&sWBI.pWC[1];
+ sWBI.aLevel = pWInfo->a;
+
+ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+ ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
+
+ /* Split the WHERE clause into separate subexpressions where each
+ ** subexpression is separated by an AND operator.
+ */
+ initMaskSet(pMaskSet);
+ whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
+ sqlite3ExprCodeConstants(pParse, pWhere);
+ whereSplit(sWBI.pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
+
+ /* Special case: a WHERE clause that is constant. Evaluate the
+ ** expression and either jump over all of the code or fall thru.
+ */
+ if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
+ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL);
+ pWhere = 0;
+ }
+
+ /* Assign a bit from the bitmask to every term in the FROM clause.
+ **
+ ** When assigning bitmask values to FROM clause cursors, it must be
+ ** the case that if X is the bitmask for the N-th FROM clause term then
+ ** the bitmask for all FROM clause terms to the left of the N-th term
+ ** is (X-1). An expression from the ON clause of a LEFT JOIN can use
+ ** its Expr.iRightJoinTable value to find the bitmask of the right table
+ ** of the join. Subtracting one from the right table bitmask gives a
+ ** bitmask for all tables to the left of the join. Knowing the bitmask
+ ** for all tables to the left of a left join is important. Ticket #3015.
+ **
+ ** Note that bitmasks are created for all pTabList->nSrc tables in
+ ** pTabList, not just the first nTabList tables. nTabList is normally
+ ** equal to pTabList->nSrc but might be shortened to 1 if the
+ ** WHERE_ONETABLE_ONLY flag is set.
+ */
+ for(ii=0; ii<pTabList->nSrc; ii++){
+ createMask(pMaskSet, pTabList->a[ii].iCursor);
+ }
+#ifndef NDEBUG
+ {
+ Bitmask toTheLeft = 0;
+ for(ii=0; ii<pTabList->nSrc; ii++){
+ Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor);
+ assert( (m-1)==toTheLeft );
+ toTheLeft |= m;
+ }
+ }
+#endif
+
+ /* Analyze all of the subexpressions. Note that exprAnalyze() might
+ ** add new virtual terms onto the end of the WHERE clause. We do not
+ ** want to analyze these virtual terms, so start analyzing at the end
+ ** and work forward so that the added virtual terms are never processed.
+ */
+ exprAnalyzeAll(pTabList, sWBI.pWC);
+ if( db->mallocFailed ){
+ goto whereBeginError;
+ }
+
+ /* Check if the DISTINCT qualifier, if there is one, is redundant.
+ ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
+ ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
+ */
+ if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){
+ pDistinct = 0;
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }
+
+ /* Chose the best index to use for each table in the FROM clause.
+ **
+ ** This loop fills in the following fields:
+ **
+ ** pWInfo->a[].pIdx The index to use for this level of the loop.
+ ** pWInfo->a[].wsFlags WHERE_xxx flags associated with pIdx
+ ** pWInfo->a[].nEq The number of == and IN constraints
+ ** pWInfo->a[].iFrom Which term of the FROM clause is being coded
+ ** pWInfo->a[].iTabCur The VDBE cursor for the database table
+ ** pWInfo->a[].iIdxCur The VDBE cursor for the index
+ ** pWInfo->a[].pTerm When wsFlags==WO_OR, the OR-clause term
+ **
+ ** This loop also figures out the nesting order of tables in the FROM
+ ** clause.
+ */
+ sWBI.notValid = ~(Bitmask)0;
+ sWBI.pOrderBy = pOrderBy;
+ sWBI.n = nTabList;
+ sWBI.pDistinct = pDistinct;
+ andFlags = ~0;
+ WHERETRACE(("*** Optimizer Start ***\n"));
+ for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
+ WhereCost bestPlan; /* Most efficient plan seen so far */
+ Index *pIdx; /* Index for FROM table at pTabItem */
+ int j; /* For looping over FROM tables */
+ int bestJ = -1; /* The value of j */
+ Bitmask m; /* Bitmask value for j or bestJ */
+ int isOptimal; /* Iterator for optimal/non-optimal search */
+ int ckOptimal; /* Do the optimal scan check */
+ int nUnconstrained; /* Number tables without INDEXED BY */
+ Bitmask notIndexed; /* Mask of tables that cannot use an index */
+
+ memset(&bestPlan, 0, sizeof(bestPlan));
+ bestPlan.rCost = SQLITE_BIG_DBL;
+ WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));
+
+ /* Loop through the remaining entries in the FROM clause to find the
+ ** next nested loop. The loop tests all FROM clause entries
+ ** either once or twice.
+ **
+ ** The first test is always performed if there are two or more entries
+ ** remaining and never performed if there is only one FROM clause entry
+ ** to choose from. The first test looks for an "optimal" scan. In
+ ** this context an optimal scan is one that uses the same strategy
+ ** for the given FROM clause entry as would be selected if the entry
+ ** were used as the innermost nested loop. In other words, a table
+ ** is chosen such that the cost of running that table cannot be reduced
+ ** by waiting for other tables to run first. This "optimal" test works
+ ** by first assuming that the FROM clause is on the inner loop and finding
+ ** its query plan, then checking to see if that query plan uses any
+ ** other FROM clause terms that are sWBI.notValid. If no notValid terms
+ ** are used then the "optimal" query plan works.
+ **
+ ** Note that the WhereCost.nRow parameter for an optimal scan might
+ ** not be as small as it would be if the table really were the innermost
+ ** join. The nRow value can be reduced by WHERE clause constraints
+ ** that do not use indices. But this nRow reduction only happens if the
+ ** table really is the innermost join.
+ **
+ ** The second loop iteration is only performed if no optimal scan
+ ** strategies were found by the first iteration. This second iteration
+ ** is used to search for the lowest cost scan overall.
+ **
+ ** Without the optimal scan step (the first iteration) a suboptimal
+ ** plan might be chosen for queries like this:
+ **
+ ** CREATE TABLE t1(a, b);
+ ** CREATE TABLE t2(c, d);
+ ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
+ **
+ ** The best strategy is to iterate through table t1 first. However it
+ ** is not possible to determine this with a simple greedy algorithm.
+ ** Since the cost of a linear scan through table t2 is the same
+ ** as the cost of a linear scan through table t1, a simple greedy
+ ** algorithm may choose to use t2 for the outer loop, which is a much
+ ** costlier approach.
+ */
+ nUnconstrained = 0;
+ notIndexed = 0;
+
+ /* The optimal scan check only occurs if there are two or more tables
+ ** available to be reordered */
+ if( iFrom==nTabList-1 ){
+ ckOptimal = 0; /* Common case of just one table in the FROM clause */
+ }else{
+ ckOptimal = -1;
+ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
+ m = getMask(pMaskSet, sWBI.pSrc->iCursor);
+ if( (m & sWBI.notValid)==0 ){
+ if( j==iFrom ) iFrom++;
+ continue;
+ }
+ if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
+ if( ++ckOptimal ) break;
+ if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
+ }
+ }
+ assert( ckOptimal==0 || ckOptimal==1 );
+
+ for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
+ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
+ if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
+ /* This break and one like it in the ckOptimal computation loop
+ ** above prevent table reordering across LEFT and CROSS JOINs.
+ ** The LEFT JOIN case is necessary for correctness. The prohibition
+ ** against reordering across a CROSS JOIN is an SQLite feature that
+ ** allows the developer to control table reordering */
+ break;
+ }
+ m = getMask(pMaskSet, sWBI.pSrc->iCursor);
+ if( (m & sWBI.notValid)==0 ){
+ assert( j>iFrom );
+ continue;
+ }
+ sWBI.notReady = (isOptimal ? m : sWBI.notValid);
+ if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
+
+ WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
+ j, sWBI.pSrc->pTab->zName, isOptimal));
+ assert( sWBI.pSrc->pTab );
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(sWBI.pSrc->pTab) ){
+ sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
+ bestVirtualIndex(&sWBI);
+ }else
+#endif
+ {
+ bestBtreeIndex(&sWBI);
+ }
+ assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 );
+
+ /* If an INDEXED BY clause is present, then the plan must use that
+ ** index if it uses any index at all */
+ assert( sWBI.pSrc->pIndex==0
+ || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
+ || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
+
+ if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+ notIndexed |= m;
+ }
+ if( isOptimal ){
+ pWInfo->a[j].rOptCost = sWBI.cost.rCost;
+ }else if( ckOptimal ){
+ /* If two or more tables have nearly the same outer loop cost, but
+ ** very different inner loop (optimal) cost, we want to choose
+ ** for the outer loop that table which benefits the least from
+ ** being in the inner loop. The following code scales the
+ ** outer loop cost estimate to accomplish that. */
+ WHERETRACE((" scaling cost from %.1f to %.1f\n",
+ sWBI.cost.rCost,
+ sWBI.cost.rCost/pWInfo->a[j].rOptCost));
+ sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
+ }
+
+ /* Conditions under which this table becomes the best so far:
+ **
+ ** (1) The table must not depend on other tables that have not
+ ** yet run. (In other words, it must not depend on tables
+ ** in inner loops.)
+ **
+ ** (2) (This rule was removed on 2012-11-09. The scaling of the
+ ** cost using the optimal scan cost made this rule obsolete.)
+ **
+ ** (3) All tables have an INDEXED BY clause or this table lacks an
+ ** INDEXED BY clause or this table uses the specific
+ ** index specified by its INDEXED BY clause. This rule ensures
+ ** that a best-so-far is always selected even if an impossible
+ ** combination of INDEXED BY clauses are given. The error
+ ** will be detected and relayed back to the application later.
+ ** The NEVER() comes about because rule (2) above prevents
+ ** An indexable full-table-scan from reaching rule (3).
+ **
+ ** (4) The plan cost must be lower than prior plans, where "cost"
+ ** is defined by the compareCost() function above.
+ */
+ if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */
+ && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
+ || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
+ && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
+ ){
+ WHERETRACE((" === table %d (%s) is best so far\n"
+ " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
+ j, sWBI.pSrc->pTab->zName,
+ sWBI.cost.rCost, sWBI.cost.plan.nRow,
+ sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
+ bestPlan = sWBI.cost;
+ bestJ = j;
+ }
+
+ /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that
+ ** table y (and not table z) is always the next inner loop inside
+ ** of table x. */
+ if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
+ }
+ }
+ assert( bestJ>=0 );
+ assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
+ assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
+ testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
+ testcase( bestJ>iFrom && bestJ<nTabList-1
+ && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
+ WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
+ " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
+ bestJ, pTabList->a[bestJ].pTab->zName,
+ pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
+ bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
+ if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
+ assert( pWInfo->eDistinct==0 );
+ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+ }
+ andFlags &= bestPlan.plan.wsFlags;
+ pLevel->plan = bestPlan.plan;
+ pLevel->iTabCur = pTabList->a[bestJ].iCursor;
+ testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
+ testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
+ if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
+ if( (wctrlFlags & WHERE_ONETABLE_ONLY)
+ && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0
+ ){
+ pLevel->iIdxCur = iIdxCur;
+ }else{
+ pLevel->iIdxCur = pParse->nTab++;
+ }
+ }else{
+ pLevel->iIdxCur = -1;
+ }
+ sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
+ pLevel->iFrom = (u8)bestJ;
+ if( bestPlan.plan.nRow>=(double)1 ){
+ pParse->nQueryLoop *= bestPlan.plan.nRow;
+ }
+
+ /* Check that if the table scanned by this loop iteration had an
+ ** INDEXED BY clause attached to it, that the named index is being
+ ** used for the scan. If not, then query compilation has failed.
+ ** Return an error.
+ */
+ pIdx = pTabList->a[bestJ].pIndex;
+ if( pIdx ){
+ if( (bestPlan.plan.wsFlags & WHERE_INDEXED)==0 ){
+ sqlite3ErrorMsg(pParse, "cannot use index: %s", pIdx->zName);
+ goto whereBeginError;
+ }else{
+ /* If an INDEXED BY clause is used, the bestIndex() function is
+ ** guaranteed to find the index specified in the INDEXED BY clause
+ ** if it find an index at all. */
+ assert( bestPlan.plan.u.pIdx==pIdx );
+ }
+ }
+ }
+ WHERETRACE(("*** Optimizer Finished ***\n"));
+ if( pParse->nErr || db->mallocFailed ){
+ goto whereBeginError;
+ }
+ if( nTabList ){
+ pLevel--;
+ pWInfo->nOBSat = pLevel->plan.nOBSat;
+ }else{
+ pWInfo->nOBSat = 0;
+ }
+
+ /* If the total query only selects a single row, then the ORDER BY
+ ** clause is irrelevant.
+ */
+ if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){
+ assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 );
+ pWInfo->nOBSat = pOrderBy->nExpr;
+ }
+
+ /* If the caller is an UPDATE or DELETE statement that is requesting
+ ** to use a one-pass algorithm, determine if this is appropriate.
+ ** The one-pass algorithm only works if the WHERE clause constraints
+ ** the statement to update a single row.
+ */
+ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
+ if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
+ pWInfo->okOnePass = 1;
+ pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY;
+ }
+
+ /* Open all tables in the pTabList and any indices selected for
+ ** searching those tables.
+ */
+ sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
+ notReady = ~(Bitmask)0;
+ pWInfo->nRowOut = (double)1;
+ for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
+ Table *pTab; /* Table to open */
+ int iDb; /* Index of database containing table/index */
+ struct SrcList_item *pTabItem;
+
+ pTabItem = &pTabList->a[pLevel->iFrom];
+ pTab = pTabItem->pTab;
+ pWInfo->nRowOut *= pLevel->plan.nRow;
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
+ /* Do nothing */
+ }else
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
+ int iCur = pTabItem->iCursor;
+ sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
+ }else if( IsVirtual(pTab) ){
+ /* noop */
+ }else
+#endif
+ if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
+ && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
+ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
+ sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
+ testcase( pTab->nCol==BMS-1 );
+ testcase( pTab->nCol==BMS );
+ if( !pWInfo->okOnePass && pTab->nCol<BMS ){
+ Bitmask b = pTabItem->colUsed;
+ int n = 0;
+ for(; b; b=b>>1, n++){}
+ sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
+ SQLITE_INT_TO_PTR(n), P4_INT32);
+ assert( n<=pTab->nCol );
+ }
+ }else{
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+ }
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+ if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
+ constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel);
+ }else
+#endif
+ if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
+ Index *pIx = pLevel->plan.u.pIdx;
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
+ int iIndexCur = pLevel->iIdxCur;
+ assert( pIx->pSchema==pTab->pSchema );
+ assert( iIndexCur>=0 );
+ sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb,
+ (char*)pKey, P4_KEYINFO_HANDOFF);
+ VdbeComment((v, "%s", pIx->zName));
+ }
+ sqlite3CodeVerifySchema(pParse, iDb);
+ notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor);
+ }
+ pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
+ if( db->mallocFailed ) goto whereBeginError;
+
+ /* Generate the code to do the search. Each iteration of the for
+ ** loop below generates code for a single nested loop of the VM
+ ** program.
+ */
+ notReady = ~(Bitmask)0;
+ for(ii=0; ii<nTabList; ii++){
+ pLevel = &pWInfo->a[ii];
+ explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
+ notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
+ pWInfo->iContinue = pLevel->addrCont;
+ }
+
+#ifdef SQLITE_TEST /* For testing and debugging use only */
+ /* Record in the query plan information about the current table
+ ** and the index used to access it (if any). If the table itself
+ ** is not used, its name is just '{}'. If no index is used
+ ** the index is listed as "{}". If the primary key is used the
+ ** index name is '*'.
+ */
+ for(ii=0; ii<nTabList; ii++){
+ char *z;
+ int n;
+ int w;
+ struct SrcList_item *pTabItem;
+
+ pLevel = &pWInfo->a[ii];
+ w = pLevel->plan.wsFlags;
+ pTabItem = &pTabList->a[pLevel->iFrom];
+ z = pTabItem->zAlias;
+ if( z==0 ) z = pTabItem->pTab->zName;
+ n = sqlite3Strlen30(z);
+ if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
+ if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
+ memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
+ nQPlan += 2;
+ }else{
+ memcpy(&sqlite3_query_plan[nQPlan], z, n);
+ nQPlan += n;
+ }
+ sqlite3_query_plan[nQPlan++] = ' ';
+ }
+ testcase( w & WHERE_ROWID_EQ );
+ testcase( w & WHERE_ROWID_RANGE );
+ if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+ memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
+ nQPlan += 2;
+ }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
+ n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
+ if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
+ memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
+ nQPlan += n;
+ sqlite3_query_plan[nQPlan++] = ' ';
+ }
+ }else{
+ memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
+ nQPlan += 3;
+ }
+ }
+ while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
+ sqlite3_query_plan[--nQPlan] = 0;
+ }
+ sqlite3_query_plan[nQPlan] = 0;
+ nQPlan = 0;
+#endif /* SQLITE_TEST // Testing and debugging use only */
+
+ /* Record the continuation address in the WhereInfo structure. Then
+ ** clean up and return.
+ */
+ return pWInfo;
+
+ /* Jump here if malloc fails */
+whereBeginError:
+ if( pWInfo ){
+ pParse->nQueryLoop = pWInfo->savedNQueryLoop;
+ whereInfoFree(db, pWInfo);
+ }
+ return 0;
+}
+
+/*
+** Generate the end of the WHERE loop. See comments on
+** sqlite3WhereBegin() for additional information.
+*/
+SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
+ Parse *pParse = pWInfo->pParse;
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ WhereLevel *pLevel;
+ SrcList *pTabList = pWInfo->pTabList;
+ sqlite3 *db = pParse->db;
+
+ /* Generate loop termination code.
+ */
+ sqlite3ExprCacheClear(pParse);
+ for(i=pWInfo->nLevel-1; i>=0; i--){
+ pLevel = &pWInfo->a[i];
+ sqlite3VdbeResolveLabel(v, pLevel->addrCont);
+ if( pLevel->op!=OP_Noop ){
+ sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
+ sqlite3VdbeChangeP5(v, pLevel->p5);
+ }
+ if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
+ struct InLoop *pIn;
+ int j;
+ sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
+ for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
+ sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
+ sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
+ sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
+ }
+ sqlite3DbFree(db, pLevel->u.in.aInLoop);
+ }
+ sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
+ if( pLevel->iLeftJoin ){
+ int addr;
+ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
+ assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
+ || (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 );
+ if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){
+ sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
+ }
+ if( pLevel->iIdxCur>=0 ){
+ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
+ }
+ if( pLevel->op==OP_Return ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
+ }
+ sqlite3VdbeJumpHere(v, addr);
+ }
+ }
+
+ /* The "break" point is here, just past the end of the outer loop.
+ ** Set it.
+ */
+ sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
+
+ /* Close all of the cursors that were opened by sqlite3WhereBegin.
+ */
+ assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
+ for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
+ Index *pIdx = 0;
+ struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
+ Table *pTab = pTabItem->pTab;
+ assert( pTab!=0 );
+ if( (pTab->tabFlags & TF_Ephemeral)==0
+ && pTab->pSelect==0
+ && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
+ ){
+ int ws = pLevel->plan.wsFlags;
+ if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
+ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
+ }
+ if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){
+ sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
+ }
+ }
+
+ /* If this scan uses an index, make code substitutions to read data
+ ** from the index in preference to the table. Sometimes, this means
+ ** the table need never be read from. This is a performance boost,
+ ** as the vdbe level waits until the table is read before actually
+ ** seeking the table cursor to the record corresponding to the current
+ ** position in the index.
+ **
+ ** Calls to the code generator in between sqlite3WhereBegin and
+ ** sqlite3WhereEnd will have created code that references the table
+ ** directly. This loop scans all that code looking for opcodes
+ ** that reference the table and converts them into opcodes that
+ ** reference the index.
+ */
+ if( pLevel->plan.wsFlags & WHERE_INDEXED ){
+ pIdx = pLevel->plan.u.pIdx;
+ }else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
+ pIdx = pLevel->u.pCovidx;
+ }
+ if( pIdx && !db->mallocFailed){
+ int k, j, last;
+ VdbeOp *pOp;
+
+ pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
+ last = sqlite3VdbeCurrentAddr(v);
+ for(k=pWInfo->iTop; k<last; k++, pOp++){
+ if( pOp->p1!=pLevel->iTabCur ) continue;
+ if( pOp->opcode==OP_Column ){
+ for(j=0; j<pIdx->nColumn; j++){
+ if( pOp->p2==pIdx->aiColumn[j] ){
+ pOp->p2 = j;
+ pOp->p1 = pLevel->iIdxCur;
+ break;
+ }
+ }
+ assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
+ || j<pIdx->nColumn );
+ }else if( pOp->opcode==OP_Rowid ){
+ pOp->p1 = pLevel->iIdxCur;
+ pOp->opcode = OP_IdxRowid;
+ }
+ }
+ }
+ }
+
+ /* Final cleanup
+ */
+ pParse->nQueryLoop = pWInfo->savedNQueryLoop;
+ whereInfoFree(db, pWInfo);
+ return;
+}
+
+/************** End of where.c ***********************************************/
+/************** Begin file parse.c *******************************************/
+/* Driver template for the LEMON parser generator.
+** The author disclaims copyright to this source code.
+**
+** This version of "lempar.c" is modified, slightly, for use by SQLite.
+** The only modifications are the addition of a couple of NEVER()
+** macros to disable tests that are needed in the case of a general
+** LALR(1) grammar but which are always false in the
+** specific grammar used by SQLite.
+*/
+/* First off, code is included that follows the "include" declaration
+** in the input grammar file. */
+/* #include <stdio.h> */
+
+
+/*
+** Disable all error recovery processing in the parser push-down
+** automaton.
+*/
+#define YYNOERRORRECOVERY 1
+
+/*
+** Make yytestcase() the same as testcase()
+*/
+#define yytestcase(X) testcase(X)
+
+/*
+** An instance of this structure holds information about the
+** LIMIT clause of a SELECT statement.
+*/
+struct LimitVal {
+ Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */
+ Expr *pOffset; /* The OFFSET expression. NULL if there is none */
+};
+
+/*
+** An instance of this structure is used to store the LIKE,
+** GLOB, NOT LIKE, and NOT GLOB operators.
+*/
+struct LikeOp {
+ Token eOperator; /* "like" or "glob" or "regexp" */
+ int bNot; /* True if the NOT keyword is present */
+};
+
+/*
+** An instance of the following structure describes the event of a
+** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
+** TK_DELETE, or TK_INSTEAD. If the event is of the form
+**
+** UPDATE ON (a,b,c)
+**
+** Then the "b" IdList records the list "a,b,c".
+*/
+struct TrigEvent { int a; IdList * b; };
+
+/*
+** An instance of this structure holds the ATTACH key and the key type.
+*/
+struct AttachKey { int type; Token key; };
+
+/*
+** One or more VALUES claues
+*/
+struct ValueList {
+ ExprList *pList;
+ Select *pSelect;
+};
+
+
+ /* This is a utility routine used to set the ExprSpan.zStart and
+ ** ExprSpan.zEnd values of pOut so that the span covers the complete
+ ** range of text beginning with pStart and going to the end of pEnd.
+ */
+ static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){
+ pOut->zStart = pStart->z;
+ pOut->zEnd = &pEnd->z[pEnd->n];
+ }
+
+ /* Construct a new Expr object from a single identifier. Use the
+ ** new Expr to populate pOut. Set the span of pOut to be the identifier
+ ** that created the expression.
+ */
+ static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){
+ pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, pValue);
+ pOut->zStart = pValue->z;
+ pOut->zEnd = &pValue->z[pValue->n];
+ }
+
+ /* This routine constructs a binary expression node out of two ExprSpan
+ ** objects and uses the result to populate a new ExprSpan object.
+ */
+ static void spanBinaryExpr(
+ ExprSpan *pOut, /* Write the result here */
+ Parse *pParse, /* The parsing context. Errors accumulate here */
+ int op, /* The binary operation */
+ ExprSpan *pLeft, /* The left operand */
+ ExprSpan *pRight /* The right operand */
+ ){
+ pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0);
+ pOut->zStart = pLeft->zStart;
+ pOut->zEnd = pRight->zEnd;
+ }
+
+ /* Construct an expression node for a unary postfix operator
+ */
+ static void spanUnaryPostfix(
+ ExprSpan *pOut, /* Write the new expression node here */
+ Parse *pParse, /* Parsing context to record errors */
+ int op, /* The operator */
+ ExprSpan *pOperand, /* The operand */
+ Token *pPostOp /* The operand token for setting the span */
+ ){
+ pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
+ pOut->zStart = pOperand->zStart;
+ pOut->zEnd = &pPostOp->z[pPostOp->n];
+ }
+
+ /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
+ ** unary TK_ISNULL or TK_NOTNULL expression. */
+ static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
+ sqlite3 *db = pParse->db;
+ if( db->mallocFailed==0 && pY->op==TK_NULL ){
+ pA->op = (u8)op;
+ sqlite3ExprDelete(db, pA->pRight);
+ pA->pRight = 0;
+ }
+ }
+
+ /* Construct an expression node for a unary prefix operator
+ */
+ static void spanUnaryPrefix(
+ ExprSpan *pOut, /* Write the new expression node here */
+ Parse *pParse, /* Parsing context to record errors */
+ int op, /* The operator */
+ ExprSpan *pOperand, /* The operand */
+ Token *pPreOp /* The operand token for setting the span */
+ ){
+ pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
+ pOut->zStart = pPreOp->z;
+ pOut->zEnd = pOperand->zEnd;
+ }
+/* Next is all token values, in a form suitable for use by makeheaders.
+** This section will be null unless lemon is run with the -m switch.
+*/
+/*
+** These constants (all generated automatically by the parser generator)
+** specify the various kinds of tokens (terminals) that the parser
+** understands.
+**
+** Each symbol here is a terminal symbol in the grammar.
+*/
+/* Make sure the INTERFACE macro is defined.
+*/
+#ifndef INTERFACE
+# define INTERFACE 1
+#endif
+/* The next thing included is series of defines which control
+** various aspects of the generated parser.
+** YYCODETYPE is the data type used for storing terminal
+** and nonterminal numbers. "unsigned char" is
+** used if there are fewer than 250 terminals
+** and nonterminals. "int" is used otherwise.
+** YYNOCODE is a number of type YYCODETYPE which corresponds
+** to no legal terminal or nonterminal number. This
+** number is used to fill in empty slots of the hash
+** table.
+** YYFALLBACK If defined, this indicates that one or more tokens
+** have fall-back values which should be used if the
+** original value of the token will not parse.
+** YYACTIONTYPE is the data type used for storing terminal
+** and nonterminal numbers. "unsigned char" is
+** used if there are fewer than 250 rules and
+** states combined. "int" is used otherwise.
+** sqlite3ParserTOKENTYPE is the data type used for minor tokens given
+** directly to the parser from the tokenizer.
+** YYMINORTYPE is the data type used for all minor tokens.
+** This is typically a union of many types, one of
+** which is sqlite3ParserTOKENTYPE. The entry in the union
+** for base tokens is called "yy0".
+** YYSTACKDEPTH is the maximum depth of the parser's stack. If
+** zero the stack is dynamically sized using realloc()
+** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument
+** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument
+** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser
+** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser
+** YYNSTATE the combined number of states.
+** YYNRULE the number of rules in the grammar
+** YYERRORSYMBOL is the code number of the error symbol. If not
+** defined, then do no error processing.
+*/
+#define YYCODETYPE unsigned char
+#define YYNOCODE 251
+#define YYACTIONTYPE unsigned short int
+#define YYWILDCARD 67
+#define sqlite3ParserTOKENTYPE Token
+typedef union {
+ int yyinit;
+ sqlite3ParserTOKENTYPE yy0;
+ struct LimitVal yy64;
+ Expr* yy122;
+ Select* yy159;
+ IdList* yy180;
+ struct {int value; int mask;} yy207;
+ u8 yy258;
+ u16 yy305;
+ struct LikeOp yy318;
+ TriggerStep* yy327;
+ ExprSpan yy342;
+ SrcList* yy347;
+ int yy392;
+ struct TrigEvent yy410;
+ ExprList* yy442;
+ struct ValueList yy487;
+} YYMINORTYPE;
+#ifndef YYSTACKDEPTH
+#define YYSTACKDEPTH 100
+#endif
+#define sqlite3ParserARG_SDECL Parse *pParse;
+#define sqlite3ParserARG_PDECL ,Parse *pParse
+#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
+#define sqlite3ParserARG_STORE yypParser->pParse = pParse
+#define YYNSTATE 627
+#define YYNRULE 327
+#define YYFALLBACK 1
+#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
+#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
+#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
+
+/* The yyzerominor constant is used to initialize instances of
+** YYMINORTYPE objects to zero. */
+static const YYMINORTYPE yyzerominor = { 0 };
+
+/* Define the yytestcase() macro to be a no-op if is not already defined
+** otherwise.
+**
+** Applications can choose to define yytestcase() in the %include section
+** to a macro that can assist in verifying code coverage. For production
+** code the yytestcase() macro should be turned off. But it is useful
+** for testing.
+*/
+#ifndef yytestcase
+# define yytestcase(X)
+#endif
+
+
+/* Next are the tables used to determine what action to take based on the
+** current state and lookahead token. These tables are used to implement
+** functions that take a state number and lookahead value and return an
+** action integer.
+**
+** Suppose the action integer is N. Then the action is determined as
+** follows
+**
+** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
+** token onto the stack and goto state N.
+**
+** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
+**
+** N == YYNSTATE+YYNRULE A syntax error has occurred.
+**
+** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
+**
+** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
+** slots in the yy_action[] table.
+**
+** The action table is constructed as a single large table named yy_action[].
+** Given state S and lookahead X, the action is computed as
+**
+** yy_action[ yy_shift_ofst[S] + X ]
+**
+** If the index value yy_shift_ofst[S]+X is out of range or if the value
+** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+** and that yy_default[S] should be used instead.
+**
+** The formula above is for computing the action when the lookahead is
+** a terminal symbol. If the lookahead is a non-terminal (as occurs after
+** a reduce action) then the yy_reduce_ofst[] array is used in place of
+** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
+** YY_SHIFT_USE_DFLT.
+**
+** The following are the tables generated in this section:
+**
+** yy_action[] A single table containing all actions.
+** yy_lookahead[] A table containing the lookahead for each entry in
+** yy_action. Used to detect hash collisions.
+** yy_shift_ofst[] For each state, the offset into yy_action for
+** shifting terminals.
+** yy_reduce_ofst[] For each state, the offset into yy_action for
+** shifting non-terminals after a reduce.
+** yy_default[] Default action for each state.
+*/
+#define YY_ACTTAB_COUNT (1564)
+static const YYACTIONTYPE yy_action[] = {
+ /* 0 */ 309, 955, 184, 417, 2, 171, 624, 594, 56, 56,
+ /* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52,
+ /* 20 */ 52, 52, 51, 233, 620, 619, 298, 620, 619, 234,
+ /* 30 */ 587, 581, 56, 56, 56, 56, 19, 54, 54, 54,
+ /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 605, 57,
+ /* 50 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
+ /* 60 */ 56, 56, 541, 54, 54, 54, 54, 53, 53, 52,
+ /* 70 */ 52, 52, 51, 233, 309, 594, 325, 196, 195, 194,
+ /* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52,
+ /* 90 */ 51, 233, 617, 616, 165, 617, 616, 380, 377, 376,
+ /* 100 */ 407, 532, 576, 576, 587, 581, 303, 422, 375, 59,
+ /* 110 */ 53, 53, 52, 52, 52, 51, 233, 50, 47, 146,
+ /* 120 */ 574, 545, 65, 57, 58, 48, 579, 578, 580, 580,
+ /* 130 */ 55, 55, 56, 56, 56, 56, 213, 54, 54, 54,
+ /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 223,
+ /* 150 */ 539, 420, 170, 176, 138, 280, 383, 275, 382, 168,
+ /* 160 */ 489, 551, 409, 668, 620, 619, 271, 438, 409, 438,
+ /* 170 */ 550, 604, 67, 482, 507, 618, 599, 412, 587, 581,
+ /* 180 */ 600, 483, 618, 412, 618, 598, 91, 439, 440, 439,
+ /* 190 */ 335, 598, 73, 669, 222, 266, 480, 57, 58, 48,
+ /* 200 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
+ /* 210 */ 670, 54, 54, 54, 54, 53, 53, 52, 52, 52,
+ /* 220 */ 51, 233, 309, 279, 232, 231, 1, 132, 200, 385,
+ /* 230 */ 620, 619, 617, 616, 278, 435, 289, 563, 175, 262,
+ /* 240 */ 409, 264, 437, 497, 436, 166, 441, 568, 336, 568,
+ /* 250 */ 201, 537, 587, 581, 599, 412, 165, 594, 600, 380,
+ /* 260 */ 377, 376, 597, 598, 92, 523, 618, 569, 569, 592,
+ /* 270 */ 375, 57, 58, 48, 579, 578, 580, 580, 55, 55,
+ /* 280 */ 56, 56, 56, 56, 597, 54, 54, 54, 54, 53,
+ /* 290 */ 53, 52, 52, 52, 51, 233, 309, 463, 617, 616,
+ /* 300 */ 590, 590, 590, 174, 272, 396, 409, 272, 409, 548,
+ /* 310 */ 397, 620, 619, 68, 326, 620, 619, 620, 619, 618,
+ /* 320 */ 546, 412, 618, 412, 471, 594, 587, 581, 472, 598,
+ /* 330 */ 92, 598, 92, 52, 52, 52, 51, 233, 513, 512,
+ /* 340 */ 206, 322, 363, 464, 221, 57, 58, 48, 579, 578,
+ /* 350 */ 580, 580, 55, 55, 56, 56, 56, 56, 529, 54,
+ /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
+ /* 370 */ 309, 396, 409, 396, 597, 372, 386, 530, 347, 617,
+ /* 380 */ 616, 575, 202, 617, 616, 617, 616, 412, 620, 619,
+ /* 390 */ 145, 255, 346, 254, 577, 598, 74, 351, 45, 489,
+ /* 400 */ 587, 581, 235, 189, 464, 544, 167, 296, 187, 469,
+ /* 410 */ 479, 67, 62, 39, 618, 546, 597, 345, 573, 57,
+ /* 420 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
+ /* 430 */ 56, 56, 6, 54, 54, 54, 54, 53, 53, 52,
+ /* 440 */ 52, 52, 51, 233, 309, 562, 558, 407, 528, 576,
+ /* 450 */ 576, 344, 255, 346, 254, 182, 617, 616, 503, 504,
+ /* 460 */ 314, 409, 557, 235, 166, 271, 409, 352, 564, 181,
+ /* 470 */ 407, 546, 576, 576, 587, 581, 412, 537, 556, 561,
+ /* 480 */ 517, 412, 618, 249, 598, 16, 7, 36, 467, 598,
+ /* 490 */ 92, 516, 618, 57, 58, 48, 579, 578, 580, 580,
+ /* 500 */ 55, 55, 56, 56, 56, 56, 541, 54, 54, 54,
+ /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 327,
+ /* 520 */ 572, 571, 525, 558, 560, 394, 871, 246, 409, 248,
+ /* 530 */ 171, 392, 594, 219, 407, 409, 576, 576, 502, 557,
+ /* 540 */ 364, 145, 510, 412, 407, 229, 576, 576, 587, 581,
+ /* 550 */ 412, 598, 92, 381, 269, 556, 166, 400, 598, 69,
+ /* 560 */ 501, 419, 945, 199, 945, 198, 546, 57, 58, 48,
+ /* 570 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
+ /* 580 */ 568, 54, 54, 54, 54, 53, 53, 52, 52, 52,
+ /* 590 */ 51, 233, 309, 317, 419, 944, 508, 944, 308, 597,
+ /* 600 */ 594, 565, 490, 212, 173, 247, 423, 615, 614, 613,
+ /* 610 */ 323, 197, 143, 405, 572, 571, 489, 66, 50, 47,
+ /* 620 */ 146, 594, 587, 581, 232, 231, 559, 427, 67, 555,
+ /* 630 */ 15, 618, 186, 543, 303, 421, 35, 206, 432, 423,
+ /* 640 */ 552, 57, 58, 48, 579, 578, 580, 580, 55, 55,
+ /* 650 */ 56, 56, 56, 56, 205, 54, 54, 54, 54, 53,
+ /* 660 */ 53, 52, 52, 52, 51, 233, 309, 569, 569, 260,
+ /* 670 */ 268, 597, 12, 373, 568, 166, 409, 313, 409, 420,
+ /* 680 */ 409, 473, 473, 365, 618, 50, 47, 146, 597, 594,
+ /* 690 */ 468, 412, 166, 412, 351, 412, 587, 581, 32, 598,
+ /* 700 */ 94, 598, 97, 598, 95, 627, 625, 329, 142, 50,
+ /* 710 */ 47, 146, 333, 349, 358, 57, 58, 48, 579, 578,
+ /* 720 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54,
+ /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
+ /* 740 */ 309, 409, 388, 412, 409, 22, 565, 404, 212, 362,
+ /* 750 */ 389, 598, 104, 359, 409, 156, 412, 409, 603, 412,
+ /* 760 */ 537, 331, 569, 569, 598, 103, 493, 598, 105, 412,
+ /* 770 */ 587, 581, 412, 260, 549, 618, 11, 598, 106, 521,
+ /* 780 */ 598, 133, 169, 457, 456, 170, 35, 601, 618, 57,
+ /* 790 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
+ /* 800 */ 56, 56, 409, 54, 54, 54, 54, 53, 53, 52,
+ /* 810 */ 52, 52, 51, 233, 309, 409, 259, 412, 409, 50,
+ /* 820 */ 47, 146, 357, 318, 355, 598, 134, 527, 352, 337,
+ /* 830 */ 412, 409, 356, 412, 357, 409, 357, 618, 598, 98,
+ /* 840 */ 129, 598, 102, 618, 587, 581, 412, 21, 235, 618,
+ /* 850 */ 412, 618, 211, 143, 598, 101, 30, 167, 598, 93,
+ /* 860 */ 350, 535, 203, 57, 58, 48, 579, 578, 580, 580,
+ /* 870 */ 55, 55, 56, 56, 56, 56, 409, 54, 54, 54,
+ /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 409,
+ /* 890 */ 526, 412, 409, 425, 215, 305, 597, 551, 141, 598,
+ /* 900 */ 100, 40, 409, 38, 412, 409, 550, 412, 409, 228,
+ /* 910 */ 220, 314, 598, 77, 500, 598, 96, 412, 587, 581,
+ /* 920 */ 412, 338, 253, 412, 218, 598, 137, 379, 598, 136,
+ /* 930 */ 28, 598, 135, 270, 715, 210, 481, 57, 58, 48,
+ /* 940 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
+ /* 950 */ 409, 54, 54, 54, 54, 53, 53, 52, 52, 52,
+ /* 960 */ 51, 233, 309, 409, 272, 412, 409, 315, 147, 597,
+ /* 970 */ 272, 626, 2, 598, 76, 209, 409, 127, 412, 618,
+ /* 980 */ 126, 412, 409, 621, 235, 618, 598, 90, 374, 598,
+ /* 990 */ 89, 412, 587, 581, 27, 260, 350, 412, 618, 598,
+ /* 1000 */ 75, 321, 541, 541, 125, 598, 88, 320, 278, 597,
+ /* 1010 */ 618, 57, 46, 48, 579, 578, 580, 580, 55, 55,
+ /* 1020 */ 56, 56, 56, 56, 409, 54, 54, 54, 54, 53,
+ /* 1030 */ 53, 52, 52, 52, 51, 233, 309, 409, 450, 412,
+ /* 1040 */ 164, 284, 282, 272, 609, 424, 304, 598, 87, 370,
+ /* 1050 */ 409, 477, 412, 409, 608, 409, 607, 602, 618, 618,
+ /* 1060 */ 598, 99, 586, 585, 122, 412, 587, 581, 412, 618,
+ /* 1070 */ 412, 618, 618, 598, 86, 366, 598, 17, 598, 85,
+ /* 1080 */ 319, 185, 519, 518, 583, 582, 58, 48, 579, 578,
+ /* 1090 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54,
+ /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
+ /* 1110 */ 309, 584, 409, 412, 409, 260, 260, 260, 408, 591,
+ /* 1120 */ 474, 598, 84, 170, 409, 466, 518, 412, 121, 412,
+ /* 1130 */ 618, 618, 618, 618, 618, 598, 83, 598, 72, 412,
+ /* 1140 */ 587, 581, 51, 233, 625, 329, 470, 598, 71, 257,
+ /* 1150 */ 159, 120, 14, 462, 157, 158, 117, 260, 448, 447,
+ /* 1160 */ 446, 48, 579, 578, 580, 580, 55, 55, 56, 56,
+ /* 1170 */ 56, 56, 618, 54, 54, 54, 54, 53, 53, 52,
+ /* 1180 */ 52, 52, 51, 233, 44, 403, 260, 3, 409, 459,
+ /* 1190 */ 260, 413, 619, 118, 398, 10, 25, 24, 554, 348,
+ /* 1200 */ 217, 618, 406, 412, 409, 618, 4, 44, 403, 618,
+ /* 1210 */ 3, 598, 82, 618, 413, 619, 455, 542, 115, 412,
+ /* 1220 */ 538, 401, 536, 274, 506, 406, 251, 598, 81, 216,
+ /* 1230 */ 273, 563, 618, 243, 453, 618, 154, 618, 618, 618,
+ /* 1240 */ 449, 416, 623, 110, 401, 618, 409, 236, 64, 123,
+ /* 1250 */ 487, 41, 42, 531, 563, 204, 409, 267, 43, 411,
+ /* 1260 */ 410, 412, 265, 592, 108, 618, 107, 434, 332, 598,
+ /* 1270 */ 80, 412, 618, 263, 41, 42, 443, 618, 409, 598,
+ /* 1280 */ 70, 43, 411, 410, 433, 261, 592, 149, 618, 597,
+ /* 1290 */ 256, 237, 188, 412, 590, 590, 590, 589, 588, 13,
+ /* 1300 */ 618, 598, 18, 328, 235, 618, 44, 403, 360, 3,
+ /* 1310 */ 418, 461, 339, 413, 619, 227, 124, 590, 590, 590,
+ /* 1320 */ 589, 588, 13, 618, 406, 409, 618, 409, 139, 34,
+ /* 1330 */ 403, 387, 3, 148, 622, 312, 413, 619, 311, 330,
+ /* 1340 */ 412, 460, 412, 401, 180, 353, 412, 406, 598, 79,
+ /* 1350 */ 598, 78, 250, 563, 598, 9, 618, 612, 611, 610,
+ /* 1360 */ 618, 8, 452, 442, 242, 415, 401, 618, 239, 235,
+ /* 1370 */ 179, 238, 428, 41, 42, 288, 563, 618, 618, 618,
+ /* 1380 */ 43, 411, 410, 618, 144, 592, 618, 618, 177, 61,
+ /* 1390 */ 618, 596, 391, 620, 619, 287, 41, 42, 414, 618,
+ /* 1400 */ 293, 30, 393, 43, 411, 410, 292, 618, 592, 31,
+ /* 1410 */ 618, 395, 291, 60, 230, 37, 590, 590, 590, 589,
+ /* 1420 */ 588, 13, 214, 553, 183, 290, 172, 301, 300, 299,
+ /* 1430 */ 178, 297, 595, 563, 451, 29, 285, 390, 540, 590,
+ /* 1440 */ 590, 590, 589, 588, 13, 283, 520, 534, 150, 533,
+ /* 1450 */ 241, 281, 384, 192, 191, 324, 515, 514, 276, 240,
+ /* 1460 */ 510, 523, 307, 511, 128, 592, 509, 225, 226, 486,
+ /* 1470 */ 485, 224, 152, 491, 464, 306, 484, 163, 153, 371,
+ /* 1480 */ 478, 151, 162, 258, 369, 161, 367, 208, 475, 476,
+ /* 1490 */ 26, 160, 465, 140, 361, 131, 590, 590, 590, 116,
+ /* 1500 */ 119, 454, 343, 155, 114, 342, 113, 112, 445, 111,
+ /* 1510 */ 130, 109, 431, 316, 426, 430, 23, 429, 20, 606,
+ /* 1520 */ 190, 507, 255, 341, 244, 63, 294, 593, 310, 570,
+ /* 1530 */ 277, 402, 354, 235, 567, 496, 495, 492, 494, 302,
+ /* 1540 */ 458, 378, 286, 245, 566, 5, 252, 547, 193, 444,
+ /* 1550 */ 233, 340, 207, 524, 368, 505, 334, 522, 499, 399,
+ /* 1560 */ 295, 498, 956, 488,
+};
+static const YYCODETYPE yy_lookahead[] = {
+ /* 0 */ 19, 142, 143, 144, 145, 24, 1, 26, 77, 78,
+ /* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ /* 20 */ 89, 90, 91, 92, 26, 27, 15, 26, 27, 197,
+ /* 30 */ 49, 50, 77, 78, 79, 80, 204, 82, 83, 84,
+ /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 23, 68,
+ /* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 60 */ 79, 80, 166, 82, 83, 84, 85, 86, 87, 88,
+ /* 70 */ 89, 90, 91, 92, 19, 94, 19, 105, 106, 107,
+ /* 80 */ 25, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ /* 90 */ 91, 92, 94, 95, 96, 94, 95, 99, 100, 101,
+ /* 100 */ 112, 205, 114, 115, 49, 50, 22, 23, 110, 54,
+ /* 110 */ 86, 87, 88, 89, 90, 91, 92, 221, 222, 223,
+ /* 120 */ 23, 120, 25, 68, 69, 70, 71, 72, 73, 74,
+ /* 130 */ 75, 76, 77, 78, 79, 80, 22, 82, 83, 84,
+ /* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 92,
+ /* 150 */ 23, 67, 25, 96, 97, 98, 99, 100, 101, 102,
+ /* 160 */ 150, 32, 150, 118, 26, 27, 109, 150, 150, 150,
+ /* 170 */ 41, 161, 162, 180, 181, 165, 113, 165, 49, 50,
+ /* 180 */ 117, 188, 165, 165, 165, 173, 174, 170, 171, 170,
+ /* 190 */ 171, 173, 174, 118, 184, 16, 186, 68, 69, 70,
+ /* 200 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ /* 210 */ 118, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ /* 220 */ 91, 92, 19, 98, 86, 87, 22, 24, 160, 88,
+ /* 230 */ 26, 27, 94, 95, 109, 97, 224, 66, 118, 60,
+ /* 240 */ 150, 62, 104, 23, 106, 25, 229, 230, 229, 230,
+ /* 250 */ 160, 150, 49, 50, 113, 165, 96, 26, 117, 99,
+ /* 260 */ 100, 101, 194, 173, 174, 94, 165, 129, 130, 98,
+ /* 270 */ 110, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ /* 280 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86,
+ /* 290 */ 87, 88, 89, 90, 91, 92, 19, 11, 94, 95,
+ /* 300 */ 129, 130, 131, 118, 150, 215, 150, 150, 150, 25,
+ /* 310 */ 220, 26, 27, 22, 213, 26, 27, 26, 27, 165,
+ /* 320 */ 25, 165, 165, 165, 30, 94, 49, 50, 34, 173,
+ /* 330 */ 174, 173, 174, 88, 89, 90, 91, 92, 7, 8,
+ /* 340 */ 160, 187, 48, 57, 187, 68, 69, 70, 71, 72,
+ /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 23, 82,
+ /* 360 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ /* 370 */ 19, 215, 150, 215, 194, 19, 220, 88, 220, 94,
+ /* 380 */ 95, 23, 160, 94, 95, 94, 95, 165, 26, 27,
+ /* 390 */ 95, 105, 106, 107, 113, 173, 174, 217, 22, 150,
+ /* 400 */ 49, 50, 116, 119, 57, 120, 50, 158, 22, 21,
+ /* 410 */ 161, 162, 232, 136, 165, 120, 194, 237, 23, 68,
+ /* 420 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 430 */ 79, 80, 22, 82, 83, 84, 85, 86, 87, 88,
+ /* 440 */ 89, 90, 91, 92, 19, 23, 12, 112, 23, 114,
+ /* 450 */ 115, 63, 105, 106, 107, 23, 94, 95, 97, 98,
+ /* 460 */ 104, 150, 28, 116, 25, 109, 150, 150, 23, 23,
+ /* 470 */ 112, 25, 114, 115, 49, 50, 165, 150, 44, 11,
+ /* 480 */ 46, 165, 165, 16, 173, 174, 76, 136, 100, 173,
+ /* 490 */ 174, 57, 165, 68, 69, 70, 71, 72, 73, 74,
+ /* 500 */ 75, 76, 77, 78, 79, 80, 166, 82, 83, 84,
+ /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 169,
+ /* 520 */ 170, 171, 23, 12, 23, 214, 138, 60, 150, 62,
+ /* 530 */ 24, 215, 26, 216, 112, 150, 114, 115, 36, 28,
+ /* 540 */ 213, 95, 103, 165, 112, 205, 114, 115, 49, 50,
+ /* 550 */ 165, 173, 174, 51, 23, 44, 25, 46, 173, 174,
+ /* 560 */ 58, 22, 23, 22, 25, 160, 120, 68, 69, 70,
+ /* 570 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ /* 580 */ 230, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ /* 590 */ 91, 92, 19, 215, 22, 23, 23, 25, 163, 194,
+ /* 600 */ 94, 166, 167, 168, 25, 138, 67, 7, 8, 9,
+ /* 610 */ 108, 206, 207, 169, 170, 171, 150, 22, 221, 222,
+ /* 620 */ 223, 26, 49, 50, 86, 87, 23, 161, 162, 23,
+ /* 630 */ 22, 165, 24, 120, 22, 23, 25, 160, 241, 67,
+ /* 640 */ 176, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ /* 650 */ 77, 78, 79, 80, 160, 82, 83, 84, 85, 86,
+ /* 660 */ 87, 88, 89, 90, 91, 92, 19, 129, 130, 150,
+ /* 670 */ 23, 194, 35, 23, 230, 25, 150, 155, 150, 67,
+ /* 680 */ 150, 105, 106, 107, 165, 221, 222, 223, 194, 94,
+ /* 690 */ 23, 165, 25, 165, 217, 165, 49, 50, 25, 173,
+ /* 700 */ 174, 173, 174, 173, 174, 0, 1, 2, 118, 221,
+ /* 710 */ 222, 223, 193, 219, 237, 68, 69, 70, 71, 72,
+ /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
+ /* 730 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ /* 740 */ 19, 150, 19, 165, 150, 24, 166, 167, 168, 227,
+ /* 750 */ 27, 173, 174, 231, 150, 25, 165, 150, 172, 165,
+ /* 760 */ 150, 242, 129, 130, 173, 174, 180, 173, 174, 165,
+ /* 770 */ 49, 50, 165, 150, 176, 165, 35, 173, 174, 165,
+ /* 780 */ 173, 174, 35, 23, 23, 25, 25, 173, 165, 68,
+ /* 790 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 800 */ 79, 80, 150, 82, 83, 84, 85, 86, 87, 88,
+ /* 810 */ 89, 90, 91, 92, 19, 150, 193, 165, 150, 221,
+ /* 820 */ 222, 223, 150, 213, 19, 173, 174, 23, 150, 97,
+ /* 830 */ 165, 150, 27, 165, 150, 150, 150, 165, 173, 174,
+ /* 840 */ 22, 173, 174, 165, 49, 50, 165, 52, 116, 165,
+ /* 850 */ 165, 165, 206, 207, 173, 174, 126, 50, 173, 174,
+ /* 860 */ 128, 27, 160, 68, 69, 70, 71, 72, 73, 74,
+ /* 870 */ 75, 76, 77, 78, 79, 80, 150, 82, 83, 84,
+ /* 880 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 150,
+ /* 890 */ 23, 165, 150, 23, 216, 25, 194, 32, 39, 173,
+ /* 900 */ 174, 135, 150, 137, 165, 150, 41, 165, 150, 52,
+ /* 910 */ 238, 104, 173, 174, 29, 173, 174, 165, 49, 50,
+ /* 920 */ 165, 219, 238, 165, 238, 173, 174, 52, 173, 174,
+ /* 930 */ 22, 173, 174, 23, 23, 160, 25, 68, 69, 70,
+ /* 940 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ /* 950 */ 150, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ /* 960 */ 91, 92, 19, 150, 150, 165, 150, 245, 246, 194,
+ /* 970 */ 150, 144, 145, 173, 174, 160, 150, 22, 165, 165,
+ /* 980 */ 22, 165, 150, 150, 116, 165, 173, 174, 52, 173,
+ /* 990 */ 174, 165, 49, 50, 22, 150, 128, 165, 165, 173,
+ /* 1000 */ 174, 187, 166, 166, 22, 173, 174, 187, 109, 194,
+ /* 1010 */ 165, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ /* 1020 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86,
+ /* 1030 */ 87, 88, 89, 90, 91, 92, 19, 150, 193, 165,
+ /* 1040 */ 102, 205, 205, 150, 150, 247, 248, 173, 174, 19,
+ /* 1050 */ 150, 20, 165, 150, 150, 150, 150, 150, 165, 165,
+ /* 1060 */ 173, 174, 49, 50, 104, 165, 49, 50, 165, 165,
+ /* 1070 */ 165, 165, 165, 173, 174, 43, 173, 174, 173, 174,
+ /* 1080 */ 187, 24, 190, 191, 71, 72, 69, 70, 71, 72,
+ /* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
+ /* 1100 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ /* 1110 */ 19, 98, 150, 165, 150, 150, 150, 150, 150, 150,
+ /* 1120 */ 59, 173, 174, 25, 150, 190, 191, 165, 53, 165,
+ /* 1130 */ 165, 165, 165, 165, 165, 173, 174, 173, 174, 165,
+ /* 1140 */ 49, 50, 91, 92, 1, 2, 53, 173, 174, 138,
+ /* 1150 */ 104, 22, 5, 1, 35, 118, 127, 150, 193, 193,
+ /* 1160 */ 193, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 1170 */ 79, 80, 165, 82, 83, 84, 85, 86, 87, 88,
+ /* 1180 */ 89, 90, 91, 92, 19, 20, 150, 22, 150, 27,
+ /* 1190 */ 150, 26, 27, 108, 150, 22, 76, 76, 150, 25,
+ /* 1200 */ 193, 165, 37, 165, 150, 165, 22, 19, 20, 165,
+ /* 1210 */ 22, 173, 174, 165, 26, 27, 23, 150, 119, 165,
+ /* 1220 */ 150, 56, 150, 150, 150, 37, 16, 173, 174, 193,
+ /* 1230 */ 150, 66, 165, 193, 1, 165, 121, 165, 165, 165,
+ /* 1240 */ 20, 146, 147, 119, 56, 165, 150, 152, 16, 154,
+ /* 1250 */ 150, 86, 87, 88, 66, 160, 150, 150, 93, 94,
+ /* 1260 */ 95, 165, 150, 98, 108, 165, 127, 23, 65, 173,
+ /* 1270 */ 174, 165, 165, 150, 86, 87, 128, 165, 150, 173,
+ /* 1280 */ 174, 93, 94, 95, 23, 150, 98, 15, 165, 194,
+ /* 1290 */ 150, 140, 22, 165, 129, 130, 131, 132, 133, 134,
+ /* 1300 */ 165, 173, 174, 3, 116, 165, 19, 20, 150, 22,
+ /* 1310 */ 4, 150, 217, 26, 27, 179, 179, 129, 130, 131,
+ /* 1320 */ 132, 133, 134, 165, 37, 150, 165, 150, 164, 19,
+ /* 1330 */ 20, 150, 22, 246, 149, 249, 26, 27, 249, 244,
+ /* 1340 */ 165, 150, 165, 56, 6, 150, 165, 37, 173, 174,
+ /* 1350 */ 173, 174, 150, 66, 173, 174, 165, 149, 149, 13,
+ /* 1360 */ 165, 25, 150, 150, 150, 149, 56, 165, 150, 116,
+ /* 1370 */ 151, 150, 150, 86, 87, 150, 66, 165, 165, 165,
+ /* 1380 */ 93, 94, 95, 165, 150, 98, 165, 165, 151, 22,
+ /* 1390 */ 165, 194, 150, 26, 27, 150, 86, 87, 159, 165,
+ /* 1400 */ 199, 126, 123, 93, 94, 95, 200, 165, 98, 124,
+ /* 1410 */ 165, 122, 201, 125, 225, 135, 129, 130, 131, 132,
+ /* 1420 */ 133, 134, 5, 157, 157, 202, 118, 10, 11, 12,
+ /* 1430 */ 13, 14, 203, 66, 17, 104, 210, 121, 211, 129,
+ /* 1440 */ 130, 131, 132, 133, 134, 210, 175, 211, 31, 211,
+ /* 1450 */ 33, 210, 104, 86, 87, 47, 175, 183, 175, 42,
+ /* 1460 */ 103, 94, 178, 177, 22, 98, 175, 92, 228, 175,
+ /* 1470 */ 175, 228, 55, 183, 57, 178, 175, 156, 61, 18,
+ /* 1480 */ 157, 64, 156, 235, 157, 156, 45, 157, 236, 157,
+ /* 1490 */ 135, 156, 189, 68, 157, 218, 129, 130, 131, 22,
+ /* 1500 */ 189, 199, 157, 156, 192, 18, 192, 192, 199, 192,
+ /* 1510 */ 218, 189, 40, 157, 38, 157, 240, 157, 240, 153,
+ /* 1520 */ 196, 181, 105, 106, 107, 243, 198, 166, 111, 230,
+ /* 1530 */ 176, 226, 239, 116, 230, 176, 166, 166, 176, 148,
+ /* 1540 */ 199, 177, 209, 209, 166, 196, 239, 208, 185, 199,
+ /* 1550 */ 92, 209, 233, 173, 234, 182, 139, 173, 182, 191,
+ /* 1560 */ 195, 182, 250, 186,
+};
+#define YY_SHIFT_USE_DFLT (-70)
+#define YY_SHIFT_COUNT (416)
+#define YY_SHIFT_MIN (-69)
+#define YY_SHIFT_MAX (1487)
+static const short yy_shift_ofst[] = {
+ /* 0 */ 1143, 1188, 1417, 1188, 1287, 1287, 138, 138, -2, -19,
+ /* 10 */ 1287, 1287, 1287, 1287, 347, 362, 129, 129, 795, 1165,
+ /* 20 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
+ /* 30 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
+ /* 40 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
+ /* 50 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
+ /* 60 */ 1287, 1287, 286, 362, 362, 538, 538, 231, 1253, 55,
+ /* 70 */ 721, 647, 573, 499, 425, 351, 277, 203, 869, 869,
+ /* 80 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869,
+ /* 90 */ 869, 869, 869, 943, 869, 1017, 1091, 1091, -69, -45,
+ /* 100 */ -45, -45, -45, -45, -1, 24, 245, 362, 362, 362,
+ /* 110 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+ /* 120 */ 362, 362, 362, 388, 356, 362, 362, 362, 362, 362,
+ /* 130 */ 732, 868, 231, 1051, 1458, -70, -70, -70, 1367, 57,
+ /* 140 */ 434, 434, 289, 291, 285, 1, 204, 572, 539, 362,
+ /* 150 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+ /* 160 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+ /* 170 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+ /* 180 */ 362, 506, 506, 506, 705, 1253, 1253, 1253, -70, -70,
+ /* 190 */ -70, 171, 171, 160, 502, 502, 502, 446, 432, 511,
+ /* 200 */ 422, 358, 335, -12, -12, -12, -12, 576, 294, -12,
+ /* 210 */ -12, 295, 595, 141, 600, 730, 723, 723, 805, 730,
+ /* 220 */ 805, 439, 911, 231, 865, 231, 865, 807, 865, 723,
+ /* 230 */ 766, 633, 633, 231, 284, 63, 608, 1476, 1308, 1308,
+ /* 240 */ 1472, 1472, 1308, 1477, 1425, 1275, 1487, 1487, 1487, 1487,
+ /* 250 */ 1308, 1461, 1275, 1477, 1425, 1425, 1308, 1461, 1355, 1441,
+ /* 260 */ 1308, 1308, 1461, 1308, 1461, 1308, 1461, 1442, 1348, 1348,
+ /* 270 */ 1348, 1408, 1375, 1375, 1442, 1348, 1357, 1348, 1408, 1348,
+ /* 280 */ 1348, 1316, 1331, 1316, 1331, 1316, 1331, 1308, 1308, 1280,
+ /* 290 */ 1288, 1289, 1285, 1279, 1275, 1253, 1336, 1346, 1346, 1338,
+ /* 300 */ 1338, 1338, 1338, -70, -70, -70, -70, -70, -70, 1013,
+ /* 310 */ 467, 612, 84, 179, -28, 870, 410, 761, 760, 667,
+ /* 320 */ 650, 531, 220, 361, 331, 125, 127, 97, 1306, 1300,
+ /* 330 */ 1270, 1151, 1272, 1203, 1232, 1261, 1244, 1148, 1174, 1139,
+ /* 340 */ 1156, 1124, 1220, 1115, 1210, 1233, 1099, 1193, 1184, 1174,
+ /* 350 */ 1173, 1029, 1121, 1120, 1085, 1162, 1119, 1037, 1152, 1147,
+ /* 360 */ 1129, 1046, 1011, 1093, 1098, 1075, 1061, 1032, 960, 1057,
+ /* 370 */ 1031, 1030, 899, 938, 982, 936, 972, 958, 910, 955,
+ /* 380 */ 875, 885, 908, 857, 859, 867, 804, 590, 834, 747,
+ /* 390 */ 818, 513, 611, 741, 673, 637, 611, 606, 603, 579,
+ /* 400 */ 501, 541, 468, 386, 445, 395, 376, 281, 185, 120,
+ /* 410 */ 92, 75, 45, 114, 25, 11, 5,
+};
+#define YY_REDUCE_USE_DFLT (-169)
+#define YY_REDUCE_COUNT (308)
+#define YY_REDUCE_MIN (-168)
+#define YY_REDUCE_MAX (1391)
+static const short yy_reduce_ofst[] = {
+ /* 0 */ -141, 90, 1095, 222, 158, 156, 19, 17, 10, -104,
+ /* 10 */ 378, 316, 311, 12, 180, 249, 598, 464, 397, 1181,
+ /* 20 */ 1177, 1175, 1128, 1106, 1096, 1054, 1038, 974, 964, 962,
+ /* 30 */ 948, 905, 903, 900, 887, 874, 832, 826, 816, 813,
+ /* 40 */ 800, 758, 755, 752, 742, 739, 726, 685, 681, 668,
+ /* 50 */ 665, 652, 607, 604, 594, 591, 578, 530, 528, 526,
+ /* 60 */ 385, 18, 477, 466, 519, 444, 350, 435, 405, 488,
+ /* 70 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488,
+ /* 80 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488,
+ /* 90 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488,
+ /* 100 */ 488, 488, 488, 488, 488, 488, 488, 1040, 678, 1036,
+ /* 110 */ 1007, 967, 966, 965, 845, 686, 610, 684, 317, 672,
+ /* 120 */ 893, 327, 623, 522, -7, 820, 814, 157, 154, 101,
+ /* 130 */ 702, 494, 580, 488, 488, 488, 488, 488, 614, 586,
+ /* 140 */ 935, 892, 968, 1245, 1242, 1234, 1225, 798, 798, 1222,
+ /* 150 */ 1221, 1218, 1214, 1213, 1212, 1202, 1195, 1191, 1161, 1158,
+ /* 160 */ 1140, 1135, 1123, 1112, 1107, 1100, 1080, 1074, 1073, 1072,
+ /* 170 */ 1070, 1067, 1048, 1044, 969, 968, 907, 906, 904, 894,
+ /* 180 */ 833, 837, 836, 340, 827, 815, 775, 68, 722, 646,
+ /* 190 */ -168, 1384, 1380, 1377, 1379, 1376, 1373, 1339, 1365, 1368,
+ /* 200 */ 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1320, 1319, 1365,
+ /* 210 */ 1365, 1339, 1378, 1349, 1391, 1350, 1342, 1334, 1307, 1341,
+ /* 220 */ 1293, 1364, 1363, 1371, 1362, 1370, 1359, 1340, 1354, 1333,
+ /* 230 */ 1305, 1304, 1299, 1361, 1328, 1324, 1366, 1282, 1360, 1358,
+ /* 240 */ 1278, 1276, 1356, 1292, 1322, 1309, 1317, 1315, 1314, 1312,
+ /* 250 */ 1345, 1347, 1302, 1277, 1311, 1303, 1337, 1335, 1252, 1248,
+ /* 260 */ 1332, 1330, 1329, 1327, 1326, 1323, 1321, 1297, 1301, 1295,
+ /* 270 */ 1294, 1290, 1243, 1240, 1284, 1291, 1286, 1283, 1274, 1281,
+ /* 280 */ 1271, 1238, 1241, 1236, 1235, 1227, 1226, 1267, 1266, 1189,
+ /* 290 */ 1229, 1223, 1211, 1206, 1201, 1197, 1239, 1237, 1219, 1216,
+ /* 300 */ 1209, 1208, 1185, 1089, 1086, 1087, 1137, 1136, 1164,
+};
+static const YYACTIONTYPE yy_default[] = {
+ /* 0 */ 632, 866, 954, 954, 866, 866, 954, 954, 954, 756,
+ /* 10 */ 954, 954, 954, 864, 954, 954, 784, 784, 928, 954,
+ /* 20 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 30 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 40 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 50 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 60 */ 954, 954, 954, 954, 954, 954, 954, 671, 760, 790,
+ /* 70 */ 954, 954, 954, 954, 954, 954, 954, 954, 927, 929,
+ /* 80 */ 798, 797, 907, 771, 795, 788, 792, 867, 860, 861,
+ /* 90 */ 859, 863, 868, 954, 791, 827, 844, 826, 838, 843,
+ /* 100 */ 850, 842, 839, 829, 828, 830, 831, 954, 954, 954,
+ /* 110 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 120 */ 954, 954, 954, 658, 725, 954, 954, 954, 954, 954,
+ /* 130 */ 954, 954, 954, 832, 833, 847, 846, 845, 954, 663,
+ /* 140 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 150 */ 934, 932, 954, 879, 954, 954, 954, 954, 954, 954,
+ /* 160 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 170 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 180 */ 638, 756, 756, 756, 632, 954, 954, 954, 946, 760,
+ /* 190 */ 750, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 200 */ 954, 954, 954, 800, 739, 917, 919, 954, 900, 737,
+ /* 210 */ 660, 758, 673, 748, 640, 794, 773, 773, 912, 794,
+ /* 220 */ 912, 696, 719, 954, 784, 954, 784, 693, 784, 773,
+ /* 230 */ 862, 954, 954, 954, 757, 748, 954, 939, 764, 764,
+ /* 240 */ 931, 931, 764, 806, 729, 794, 736, 736, 736, 736,
+ /* 250 */ 764, 655, 794, 806, 729, 729, 764, 655, 906, 904,
+ /* 260 */ 764, 764, 655, 764, 655, 764, 655, 872, 727, 727,
+ /* 270 */ 727, 711, 876, 876, 872, 727, 696, 727, 711, 727,
+ /* 280 */ 727, 777, 772, 777, 772, 777, 772, 764, 764, 954,
+ /* 290 */ 789, 778, 787, 785, 794, 954, 714, 648, 648, 637,
+ /* 300 */ 637, 637, 637, 951, 951, 946, 698, 698, 681, 954,
+ /* 310 */ 954, 954, 954, 954, 954, 954, 881, 954, 954, 954,
+ /* 320 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 633,
+ /* 330 */ 941, 954, 954, 938, 954, 954, 954, 954, 799, 954,
+ /* 340 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 916,
+ /* 350 */ 954, 954, 954, 954, 954, 954, 954, 910, 954, 954,
+ /* 360 */ 954, 954, 954, 954, 903, 902, 954, 954, 954, 954,
+ /* 370 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 380 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
+ /* 390 */ 954, 954, 786, 954, 779, 954, 865, 954, 954, 954,
+ /* 400 */ 954, 954, 954, 954, 954, 954, 954, 742, 815, 954,
+ /* 410 */ 814, 818, 813, 665, 954, 646, 954, 629, 634, 950,
+ /* 420 */ 953, 952, 949, 948, 947, 942, 940, 937, 936, 935,
+ /* 430 */ 933, 930, 926, 885, 883, 890, 889, 888, 887, 886,
+ /* 440 */ 884, 882, 880, 801, 796, 793, 925, 878, 738, 735,
+ /* 450 */ 734, 654, 943, 909, 918, 805, 804, 807, 915, 914,
+ /* 460 */ 913, 911, 908, 895, 803, 802, 730, 870, 869, 657,
+ /* 470 */ 899, 898, 897, 901, 905, 896, 766, 656, 653, 662,
+ /* 480 */ 717, 718, 726, 724, 723, 722, 721, 720, 716, 664,
+ /* 490 */ 672, 710, 695, 694, 875, 877, 874, 873, 703, 702,
+ /* 500 */ 708, 707, 706, 705, 704, 701, 700, 699, 692, 691,
+ /* 510 */ 697, 690, 713, 712, 709, 689, 733, 732, 731, 728,
+ /* 520 */ 688, 687, 686, 818, 685, 684, 824, 823, 811, 854,
+ /* 530 */ 753, 752, 751, 763, 762, 775, 774, 809, 808, 776,
+ /* 540 */ 761, 755, 754, 770, 769, 768, 767, 759, 749, 781,
+ /* 550 */ 783, 782, 780, 856, 765, 853, 924, 923, 922, 921,
+ /* 560 */ 920, 858, 857, 825, 822, 676, 677, 893, 892, 894,
+ /* 570 */ 891, 679, 678, 675, 674, 855, 744, 743, 851, 848,
+ /* 580 */ 840, 836, 852, 849, 841, 837, 835, 834, 820, 819,
+ /* 590 */ 817, 816, 812, 821, 667, 745, 741, 740, 810, 747,
+ /* 600 */ 746, 683, 682, 680, 661, 659, 652, 650, 649, 651,
+ /* 610 */ 647, 645, 644, 643, 642, 641, 670, 669, 668, 666,
+ /* 620 */ 665, 639, 636, 635, 631, 630, 628,
+};
+
+/* The next table maps tokens into fallback tokens. If a construct
+** like the following:
+**
+** %fallback ID X Y Z.
+**
+** appears in the grammar, then ID becomes a fallback token for X, Y,
+** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
+** but it does not parse, the type of the token is changed to ID and
+** the parse is retried before an error is thrown.
+*/
+#ifdef YYFALLBACK
+static const YYCODETYPE yyFallback[] = {
+ 0, /* $ => nothing */
+ 0, /* SEMI => nothing */
+ 26, /* EXPLAIN => ID */
+ 26, /* QUERY => ID */
+ 26, /* PLAN => ID */
+ 26, /* BEGIN => ID */
+ 0, /* TRANSACTION => nothing */
+ 26, /* DEFERRED => ID */
+ 26, /* IMMEDIATE => ID */
+ 26, /* EXCLUSIVE => ID */
+ 0, /* COMMIT => nothing */
+ 26, /* END => ID */
+ 26, /* ROLLBACK => ID */
+ 26, /* SAVEPOINT => ID */
+ 26, /* RELEASE => ID */
+ 0, /* TO => nothing */
+ 0, /* TABLE => nothing */
+ 0, /* CREATE => nothing */
+ 26, /* IF => ID */
+ 0, /* NOT => nothing */
+ 0, /* EXISTS => nothing */
+ 26, /* TEMP => ID */
+ 0, /* LP => nothing */
+ 0, /* RP => nothing */
+ 0, /* AS => nothing */
+ 0, /* COMMA => nothing */
+ 0, /* ID => nothing */
+ 0, /* INDEXED => nothing */
+ 26, /* ABORT => ID */
+ 26, /* ACTION => ID */
+ 26, /* AFTER => ID */
+ 26, /* ANALYZE => ID */
+ 26, /* ASC => ID */
+ 26, /* ATTACH => ID */
+ 26, /* BEFORE => ID */
+ 26, /* BY => ID */
+ 26, /* CASCADE => ID */
+ 26, /* CAST => ID */
+ 26, /* COLUMNKW => ID */
+ 26, /* CONFLICT => ID */
+ 26, /* DATABASE => ID */
+ 26, /* DESC => ID */
+ 26, /* DETACH => ID */
+ 26, /* EACH => ID */
+ 26, /* FAIL => ID */
+ 26, /* FOR => ID */
+ 26, /* IGNORE => ID */
+ 26, /* INITIALLY => ID */
+ 26, /* INSTEAD => ID */
+ 26, /* LIKE_KW => ID */
+ 26, /* MATCH => ID */
+ 26, /* NO => ID */
+ 26, /* KEY => ID */
+ 26, /* OF => ID */
+ 26, /* OFFSET => ID */
+ 26, /* PRAGMA => ID */
+ 26, /* RAISE => ID */
+ 26, /* REPLACE => ID */
+ 26, /* RESTRICT => ID */
+ 26, /* ROW => ID */
+ 26, /* TRIGGER => ID */
+ 26, /* VACUUM => ID */
+ 26, /* VIEW => ID */
+ 26, /* VIRTUAL => ID */
+ 26, /* REINDEX => ID */
+ 26, /* RENAME => ID */
+ 26, /* CTIME_KW => ID */
+};
+#endif /* YYFALLBACK */
+
+/* The following structure represents a single element of the
+** parser's stack. Information stored includes:
+**
+** + The state number for the parser at this level of the stack.
+**
+** + The value of the token stored at this level of the stack.
+** (In other words, the "major" token.)
+**
+** + The semantic value stored at this level of the stack. This is
+** the information used by the action routines in the grammar.
+** It is sometimes called the "minor" token.
+*/
+struct yyStackEntry {
+ YYACTIONTYPE stateno; /* The state-number */
+ YYCODETYPE major; /* The major token value. This is the code
+ ** number for the token at this stack level */
+ YYMINORTYPE minor; /* The user-supplied minor token value. This
+ ** is the value of the token */
+};
+typedef struct yyStackEntry yyStackEntry;
+
+/* The state of the parser is completely contained in an instance of
+** the following structure */
+struct yyParser {
+ int yyidx; /* Index of top element in stack */
+#ifdef YYTRACKMAXSTACKDEPTH
+ int yyidxMax; /* Maximum value of yyidx */
+#endif
+ int yyerrcnt; /* Shifts left before out of the error */
+ sqlite3ParserARG_SDECL /* A place to hold %extra_argument */
+#if YYSTACKDEPTH<=0
+ int yystksz; /* Current side of the stack */
+ yyStackEntry *yystack; /* The parser's stack */
+#else
+ yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
+#endif
+};
+typedef struct yyParser yyParser;
+
+#ifndef NDEBUG
+/* #include <stdio.h> */
+static FILE *yyTraceFILE = 0;
+static char *yyTracePrompt = 0;
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/*
+** Turn parser tracing on by giving a stream to which to write the trace
+** and a prompt to preface each trace message. Tracing is turned off
+** by making either argument NULL
+**
+** Inputs:
+** <ul>
+** <li> A FILE* to which trace output should be written.
+** If NULL, then tracing is turned off.
+** <li> A prefix string written at the beginning of every
+** line of trace output. If NULL, then tracing is
+** turned off.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+SQLITE_PRIVATE void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){
+ yyTraceFILE = TraceFILE;
+ yyTracePrompt = zTracePrompt;
+ if( yyTraceFILE==0 ) yyTracePrompt = 0;
+ else if( yyTracePrompt==0 ) yyTraceFILE = 0;
+}
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing shifts, the names of all terminals and nonterminals
+** are required. The following table supplies these names */
+static const char *const yyTokenName[] = {
+ "$", "SEMI", "EXPLAIN", "QUERY",
+ "PLAN", "BEGIN", "TRANSACTION", "DEFERRED",
+ "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END",
+ "ROLLBACK", "SAVEPOINT", "RELEASE", "TO",
+ "TABLE", "CREATE", "IF", "NOT",
+ "EXISTS", "TEMP", "LP", "RP",
+ "AS", "COMMA", "ID", "INDEXED",
+ "ABORT", "ACTION", "AFTER", "ANALYZE",
+ "ASC", "ATTACH", "BEFORE", "BY",
+ "CASCADE", "CAST", "COLUMNKW", "CONFLICT",
+ "DATABASE", "DESC", "DETACH", "EACH",
+ "FAIL", "FOR", "IGNORE", "INITIALLY",
+ "INSTEAD", "LIKE_KW", "MATCH", "NO",
+ "KEY", "OF", "OFFSET", "PRAGMA",
+ "RAISE", "REPLACE", "RESTRICT", "ROW",
+ "TRIGGER", "VACUUM", "VIEW", "VIRTUAL",
+ "REINDEX", "RENAME", "CTIME_KW", "ANY",
+ "OR", "AND", "IS", "BETWEEN",
+ "IN", "ISNULL", "NOTNULL", "NE",
+ "EQ", "GT", "LE", "LT",
+ "GE", "ESCAPE", "BITAND", "BITOR",
+ "LSHIFT", "RSHIFT", "PLUS", "MINUS",
+ "STAR", "SLASH", "REM", "CONCAT",
+ "COLLATE", "BITNOT", "STRING", "JOIN_KW",
+ "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY",
+ "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR",
+ "ON", "INSERT", "DELETE", "UPDATE",
+ "SET", "DEFERRABLE", "FOREIGN", "DROP",
+ "UNION", "ALL", "EXCEPT", "INTERSECT",
+ "SELECT", "DISTINCT", "DOT", "FROM",
+ "JOIN", "USING", "ORDER", "GROUP",
+ "HAVING", "LIMIT", "WHERE", "INTO",
+ "VALUES", "INTEGER", "FLOAT", "BLOB",
+ "REGISTER", "VARIABLE", "CASE", "WHEN",
+ "THEN", "ELSE", "INDEX", "ALTER",
+ "ADD", "error", "input", "cmdlist",
+ "ecmd", "explain", "cmdx", "cmd",
+ "transtype", "trans_opt", "nm", "savepoint_opt",
+ "create_table", "create_table_args", "createkw", "temp",
+ "ifnotexists", "dbnm", "columnlist", "conslist_opt",
+ "select", "column", "columnid", "type",
+ "carglist", "id", "ids", "typetoken",
+ "typename", "signed", "plus_num", "minus_num",
+ "ccons", "term", "expr", "onconf",
+ "sortorder", "autoinc", "idxlist_opt", "refargs",
+ "defer_subclause", "refarg", "refact", "init_deferred_pred_opt",
+ "conslist", "tconscomma", "tcons", "idxlist",
+ "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
+ "ifexists", "fullname", "oneselect", "multiselect_op",
+ "distinct", "selcollist", "from", "where_opt",
+ "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
+ "sclp", "as", "seltablist", "stl_prefix",
+ "joinop", "indexed_opt", "on_opt", "using_opt",
+ "joinop2", "inscollist", "sortlist", "nexprlist",
+ "setlist", "insert_cmd", "inscollist_opt", "valuelist",
+ "exprlist", "likeop", "between_op", "in_op",
+ "case_operand", "case_exprlist", "case_else", "uniqueflag",
+ "collate", "nmnum", "number", "trigger_decl",
+ "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
+ "when_clause", "trigger_cmd", "trnm", "tridxby",
+ "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt",
+ "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken",
+ "lp", "anylist",
+};
+#endif /* NDEBUG */
+
+#ifndef NDEBUG
+/* For tracing reduce actions, the names of all rules are required.
+*/
+static const char *const yyRuleName[] = {
+ /* 0 */ "input ::= cmdlist",
+ /* 1 */ "cmdlist ::= cmdlist ecmd",
+ /* 2 */ "cmdlist ::= ecmd",
+ /* 3 */ "ecmd ::= SEMI",
+ /* 4 */ "ecmd ::= explain cmdx SEMI",
+ /* 5 */ "explain ::=",
+ /* 6 */ "explain ::= EXPLAIN",
+ /* 7 */ "explain ::= EXPLAIN QUERY PLAN",
+ /* 8 */ "cmdx ::= cmd",
+ /* 9 */ "cmd ::= BEGIN transtype trans_opt",
+ /* 10 */ "trans_opt ::=",
+ /* 11 */ "trans_opt ::= TRANSACTION",
+ /* 12 */ "trans_opt ::= TRANSACTION nm",
+ /* 13 */ "transtype ::=",
+ /* 14 */ "transtype ::= DEFERRED",
+ /* 15 */ "transtype ::= IMMEDIATE",
+ /* 16 */ "transtype ::= EXCLUSIVE",
+ /* 17 */ "cmd ::= COMMIT trans_opt",
+ /* 18 */ "cmd ::= END trans_opt",
+ /* 19 */ "cmd ::= ROLLBACK trans_opt",
+ /* 20 */ "savepoint_opt ::= SAVEPOINT",
+ /* 21 */ "savepoint_opt ::=",
+ /* 22 */ "cmd ::= SAVEPOINT nm",
+ /* 23 */ "cmd ::= RELEASE savepoint_opt nm",
+ /* 24 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm",
+ /* 25 */ "cmd ::= create_table create_table_args",
+ /* 26 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm",
+ /* 27 */ "createkw ::= CREATE",
+ /* 28 */ "ifnotexists ::=",
+ /* 29 */ "ifnotexists ::= IF NOT EXISTS",
+ /* 30 */ "temp ::= TEMP",
+ /* 31 */ "temp ::=",
+ /* 32 */ "create_table_args ::= LP columnlist conslist_opt RP",
+ /* 33 */ "create_table_args ::= AS select",
+ /* 34 */ "columnlist ::= columnlist COMMA column",
+ /* 35 */ "columnlist ::= column",
+ /* 36 */ "column ::= columnid type carglist",
+ /* 37 */ "columnid ::= nm",
+ /* 38 */ "id ::= ID",
+ /* 39 */ "id ::= INDEXED",
+ /* 40 */ "ids ::= ID|STRING",
+ /* 41 */ "nm ::= id",
+ /* 42 */ "nm ::= STRING",
+ /* 43 */ "nm ::= JOIN_KW",
+ /* 44 */ "type ::=",
+ /* 45 */ "type ::= typetoken",
+ /* 46 */ "typetoken ::= typename",
+ /* 47 */ "typetoken ::= typename LP signed RP",
+ /* 48 */ "typetoken ::= typename LP signed COMMA signed RP",
+ /* 49 */ "typename ::= ids",
+ /* 50 */ "typename ::= typename ids",
+ /* 51 */ "signed ::= plus_num",
+ /* 52 */ "signed ::= minus_num",
+ /* 53 */ "carglist ::= carglist ccons",
+ /* 54 */ "carglist ::=",
+ /* 55 */ "ccons ::= CONSTRAINT nm",
+ /* 56 */ "ccons ::= DEFAULT term",
+ /* 57 */ "ccons ::= DEFAULT LP expr RP",
+ /* 58 */ "ccons ::= DEFAULT PLUS term",
+ /* 59 */ "ccons ::= DEFAULT MINUS term",
+ /* 60 */ "ccons ::= DEFAULT id",
+ /* 61 */ "ccons ::= NULL onconf",
+ /* 62 */ "ccons ::= NOT NULL onconf",
+ /* 63 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
+ /* 64 */ "ccons ::= UNIQUE onconf",
+ /* 65 */ "ccons ::= CHECK LP expr RP",
+ /* 66 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
+ /* 67 */ "ccons ::= defer_subclause",
+ /* 68 */ "ccons ::= COLLATE ids",
+ /* 69 */ "autoinc ::=",
+ /* 70 */ "autoinc ::= AUTOINCR",
+ /* 71 */ "refargs ::=",
+ /* 72 */ "refargs ::= refargs refarg",
+ /* 73 */ "refarg ::= MATCH nm",
+ /* 74 */ "refarg ::= ON INSERT refact",
+ /* 75 */ "refarg ::= ON DELETE refact",
+ /* 76 */ "refarg ::= ON UPDATE refact",
+ /* 77 */ "refact ::= SET NULL",
+ /* 78 */ "refact ::= SET DEFAULT",
+ /* 79 */ "refact ::= CASCADE",
+ /* 80 */ "refact ::= RESTRICT",
+ /* 81 */ "refact ::= NO ACTION",
+ /* 82 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /* 83 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /* 84 */ "init_deferred_pred_opt ::=",
+ /* 85 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /* 86 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /* 87 */ "conslist_opt ::=",
+ /* 88 */ "conslist_opt ::= COMMA conslist",
+ /* 89 */ "conslist ::= conslist tconscomma tcons",
+ /* 90 */ "conslist ::= tcons",
+ /* 91 */ "tconscomma ::= COMMA",
+ /* 92 */ "tconscomma ::=",
+ /* 93 */ "tcons ::= CONSTRAINT nm",
+ /* 94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
+ /* 95 */ "tcons ::= UNIQUE LP idxlist RP onconf",
+ /* 96 */ "tcons ::= CHECK LP expr RP onconf",
+ /* 97 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
+ /* 98 */ "defer_subclause_opt ::=",
+ /* 99 */ "defer_subclause_opt ::= defer_subclause",
+ /* 100 */ "onconf ::=",
+ /* 101 */ "onconf ::= ON CONFLICT resolvetype",
+ /* 102 */ "orconf ::=",
+ /* 103 */ "orconf ::= OR resolvetype",
+ /* 104 */ "resolvetype ::= raisetype",
+ /* 105 */ "resolvetype ::= IGNORE",
+ /* 106 */ "resolvetype ::= REPLACE",
+ /* 107 */ "cmd ::= DROP TABLE ifexists fullname",
+ /* 108 */ "ifexists ::= IF EXISTS",
+ /* 109 */ "ifexists ::=",
+ /* 110 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
+ /* 111 */ "cmd ::= DROP VIEW ifexists fullname",
+ /* 112 */ "cmd ::= select",
+ /* 113 */ "select ::= oneselect",
+ /* 114 */ "select ::= select multiselect_op oneselect",
+ /* 115 */ "multiselect_op ::= UNION",
+ /* 116 */ "multiselect_op ::= UNION ALL",
+ /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT",
+ /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 119 */ "distinct ::= DISTINCT",
+ /* 120 */ "distinct ::= ALL",
+ /* 121 */ "distinct ::=",
+ /* 122 */ "sclp ::= selcollist COMMA",
+ /* 123 */ "sclp ::=",
+ /* 124 */ "selcollist ::= sclp expr as",
+ /* 125 */ "selcollist ::= sclp STAR",
+ /* 126 */ "selcollist ::= sclp nm DOT STAR",
+ /* 127 */ "as ::= AS nm",
+ /* 128 */ "as ::= ids",
+ /* 129 */ "as ::=",
+ /* 130 */ "from ::=",
+ /* 131 */ "from ::= FROM seltablist",
+ /* 132 */ "stl_prefix ::= seltablist joinop",
+ /* 133 */ "stl_prefix ::=",
+ /* 134 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 135 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 136 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 137 */ "dbnm ::=",
+ /* 138 */ "dbnm ::= DOT nm",
+ /* 139 */ "fullname ::= nm dbnm",
+ /* 140 */ "joinop ::= COMMA|JOIN",
+ /* 141 */ "joinop ::= JOIN_KW JOIN",
+ /* 142 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 143 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 144 */ "on_opt ::= ON expr",
+ /* 145 */ "on_opt ::=",
+ /* 146 */ "indexed_opt ::=",
+ /* 147 */ "indexed_opt ::= INDEXED BY nm",
+ /* 148 */ "indexed_opt ::= NOT INDEXED",
+ /* 149 */ "using_opt ::= USING LP inscollist RP",
+ /* 150 */ "using_opt ::=",
+ /* 151 */ "orderby_opt ::=",
+ /* 152 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 153 */ "sortlist ::= sortlist COMMA expr sortorder",
+ /* 154 */ "sortlist ::= expr sortorder",
+ /* 155 */ "sortorder ::= ASC",
+ /* 156 */ "sortorder ::= DESC",
+ /* 157 */ "sortorder ::=",
+ /* 158 */ "groupby_opt ::=",
+ /* 159 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 160 */ "having_opt ::=",
+ /* 161 */ "having_opt ::= HAVING expr",
+ /* 162 */ "limit_opt ::=",
+ /* 163 */ "limit_opt ::= LIMIT expr",
+ /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 165 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
+ /* 167 */ "where_opt ::=",
+ /* 168 */ "where_opt ::= WHERE expr",
+ /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
+ /* 170 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 171 */ "setlist ::= nm EQ expr",
+ /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
+ /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
+ /* 175 */ "insert_cmd ::= INSERT orconf",
+ /* 176 */ "insert_cmd ::= REPLACE",
+ /* 177 */ "valuelist ::= VALUES LP nexprlist RP",
+ /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP",
+ /* 179 */ "inscollist_opt ::=",
+ /* 180 */ "inscollist_opt ::= LP inscollist RP",
+ /* 181 */ "inscollist ::= inscollist COMMA nm",
+ /* 182 */ "inscollist ::= nm",
+ /* 183 */ "expr ::= term",
+ /* 184 */ "expr ::= LP expr RP",
+ /* 185 */ "term ::= NULL",
+ /* 186 */ "expr ::= id",
+ /* 187 */ "expr ::= JOIN_KW",
+ /* 188 */ "expr ::= nm DOT nm",
+ /* 189 */ "expr ::= nm DOT nm DOT nm",
+ /* 190 */ "term ::= INTEGER|FLOAT|BLOB",
+ /* 191 */ "term ::= STRING",
+ /* 192 */ "expr ::= REGISTER",
+ /* 193 */ "expr ::= VARIABLE",
+ /* 194 */ "expr ::= expr COLLATE ids",
+ /* 195 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 196 */ "expr ::= ID LP distinct exprlist RP",
+ /* 197 */ "expr ::= ID LP STAR RP",
+ /* 198 */ "term ::= CTIME_KW",
+ /* 199 */ "expr ::= expr AND expr",
+ /* 200 */ "expr ::= expr OR expr",
+ /* 201 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 202 */ "expr ::= expr EQ|NE expr",
+ /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 204 */ "expr ::= expr PLUS|MINUS expr",
+ /* 205 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 206 */ "expr ::= expr CONCAT expr",
+ /* 207 */ "likeop ::= LIKE_KW",
+ /* 208 */ "likeop ::= NOT LIKE_KW",
+ /* 209 */ "likeop ::= MATCH",
+ /* 210 */ "likeop ::= NOT MATCH",
+ /* 211 */ "expr ::= expr likeop expr",
+ /* 212 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 213 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 214 */ "expr ::= expr NOT NULL",
+ /* 215 */ "expr ::= expr IS expr",
+ /* 216 */ "expr ::= expr IS NOT expr",
+ /* 217 */ "expr ::= NOT expr",
+ /* 218 */ "expr ::= BITNOT expr",
+ /* 219 */ "expr ::= MINUS expr",
+ /* 220 */ "expr ::= PLUS expr",
+ /* 221 */ "between_op ::= BETWEEN",
+ /* 222 */ "between_op ::= NOT BETWEEN",
+ /* 223 */ "expr ::= expr between_op expr AND expr",
+ /* 224 */ "in_op ::= IN",
+ /* 225 */ "in_op ::= NOT IN",
+ /* 226 */ "expr ::= expr in_op LP exprlist RP",
+ /* 227 */ "expr ::= LP select RP",
+ /* 228 */ "expr ::= expr in_op LP select RP",
+ /* 229 */ "expr ::= expr in_op nm dbnm",
+ /* 230 */ "expr ::= EXISTS LP select RP",
+ /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 233 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 234 */ "case_else ::= ELSE expr",
+ /* 235 */ "case_else ::=",
+ /* 236 */ "case_operand ::= expr",
+ /* 237 */ "case_operand ::=",
+ /* 238 */ "exprlist ::= nexprlist",
+ /* 239 */ "exprlist ::=",
+ /* 240 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 241 */ "nexprlist ::= expr",
+ /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
+ /* 243 */ "uniqueflag ::= UNIQUE",
+ /* 244 */ "uniqueflag ::=",
+ /* 245 */ "idxlist_opt ::=",
+ /* 246 */ "idxlist_opt ::= LP idxlist RP",
+ /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder",
+ /* 248 */ "idxlist ::= nm collate sortorder",
+ /* 249 */ "collate ::=",
+ /* 250 */ "collate ::= COLLATE ids",
+ /* 251 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 252 */ "cmd ::= VACUUM",
+ /* 253 */ "cmd ::= VACUUM nm",
+ /* 254 */ "cmd ::= PRAGMA nm dbnm",
+ /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 259 */ "nmnum ::= plus_num",
+ /* 260 */ "nmnum ::= nm",
+ /* 261 */ "nmnum ::= ON",
+ /* 262 */ "nmnum ::= DELETE",
+ /* 263 */ "nmnum ::= DEFAULT",
+ /* 264 */ "plus_num ::= PLUS number",
+ /* 265 */ "plus_num ::= number",
+ /* 266 */ "minus_num ::= MINUS number",
+ /* 267 */ "number ::= INTEGER|FLOAT",
+ /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 270 */ "trigger_time ::= BEFORE",
+ /* 271 */ "trigger_time ::= AFTER",
+ /* 272 */ "trigger_time ::= INSTEAD OF",
+ /* 273 */ "trigger_time ::=",
+ /* 274 */ "trigger_event ::= DELETE|INSERT",
+ /* 275 */ "trigger_event ::= UPDATE",
+ /* 276 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 277 */ "foreach_clause ::=",
+ /* 278 */ "foreach_clause ::= FOR EACH ROW",
+ /* 279 */ "when_clause ::=",
+ /* 280 */ "when_clause ::= WHEN expr",
+ /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 283 */ "trnm ::= nm",
+ /* 284 */ "trnm ::= nm DOT nm",
+ /* 285 */ "tridxby ::=",
+ /* 286 */ "tridxby ::= INDEXED BY nm",
+ /* 287 */ "tridxby ::= NOT INDEXED",
+ /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
+ /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
+ /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
+ /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
+ /* 292 */ "trigger_cmd ::= select",
+ /* 293 */ "expr ::= RAISE LP IGNORE RP",
+ /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 295 */ "raisetype ::= ROLLBACK",
+ /* 296 */ "raisetype ::= ABORT",
+ /* 297 */ "raisetype ::= FAIL",
+ /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 300 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 301 */ "key_opt ::=",
+ /* 302 */ "key_opt ::= KEY expr",
+ /* 303 */ "database_kw_opt ::= DATABASE",
+ /* 304 */ "database_kw_opt ::=",
+ /* 305 */ "cmd ::= REINDEX",
+ /* 306 */ "cmd ::= REINDEX nm dbnm",
+ /* 307 */ "cmd ::= ANALYZE",
+ /* 308 */ "cmd ::= ANALYZE nm dbnm",
+ /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 311 */ "add_column_fullname ::= fullname",
+ /* 312 */ "kwcolumn_opt ::=",
+ /* 313 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 314 */ "cmd ::= create_vtab",
+ /* 315 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 317 */ "vtabarglist ::= vtabarg",
+ /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 319 */ "vtabarg ::=",
+ /* 320 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 321 */ "vtabargtoken ::= ANY",
+ /* 322 */ "vtabargtoken ::= lp anylist RP",
+ /* 323 */ "lp ::= LP",
+ /* 324 */ "anylist ::=",
+ /* 325 */ "anylist ::= anylist LP anylist RP",
+ /* 326 */ "anylist ::= anylist ANY",
+};
+#endif /* NDEBUG */
+
+
+#if YYSTACKDEPTH<=0
+/*
+** Try to increase the size of the parser stack.
+*/
+static void yyGrowStack(yyParser *p){
+ int newSize;
+ yyStackEntry *pNew;
+
+ newSize = p->yystksz*2 + 100;
+ pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
+ if( pNew ){
+ p->yystack = pNew;
+ p->yystksz = newSize;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
+ yyTracePrompt, p->yystksz);
+ }
+#endif
+ }
+}
+#endif
+
+/*
+** This function allocates a new parser.
+** The only argument is a pointer to a function which works like
+** malloc.
+**
+** Inputs:
+** A pointer to the function used to allocate memory.
+**
+** Outputs:
+** A pointer to a parser. This pointer is used in subsequent calls
+** to sqlite3Parser and sqlite3ParserFree.
+*/
+SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(size_t)){
+ yyParser *pParser;
+ pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
+ if( pParser ){
+ pParser->yyidx = -1;
+#ifdef YYTRACKMAXSTACKDEPTH
+ pParser->yyidxMax = 0;
+#endif
+#if YYSTACKDEPTH<=0
+ pParser->yystack = NULL;
+ pParser->yystksz = 0;
+ yyGrowStack(pParser);
+#endif
+ }
+ return pParser;
+}
+
+/* The following function deletes the value associated with a
+** symbol. The symbol can be either a terminal or nonterminal.
+** "yymajor" is the symbol code, and "yypminor" is a pointer to
+** the value.
+*/
+static void yy_destructor(
+ yyParser *yypParser, /* The parser */
+ YYCODETYPE yymajor, /* Type code for object to destroy */
+ YYMINORTYPE *yypminor /* The object to be destroyed */
+){
+ sqlite3ParserARG_FETCH;
+ switch( yymajor ){
+ /* Here is inserted the actions which take place when a
+ ** terminal or non-terminal is destroyed. This can happen
+ ** when the symbol is popped from the stack during a
+ ** reduce or during error processing or when a parser is
+ ** being destroyed before it is finished parsing.
+ **
+ ** Note: during a reduce, the only symbols destroyed are those
+ ** which appear on the RHS of the rule, but which are not used
+ ** inside the C code.
+ */
+ case 160: /* select */
+ case 194: /* oneselect */
+{
+sqlite3SelectDelete(pParse->db, (yypminor->yy159));
+}
+ break;
+ case 173: /* term */
+ case 174: /* expr */
+{
+sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr);
+}
+ break;
+ case 178: /* idxlist_opt */
+ case 187: /* idxlist */
+ case 197: /* selcollist */
+ case 200: /* groupby_opt */
+ case 202: /* orderby_opt */
+ case 204: /* sclp */
+ case 214: /* sortlist */
+ case 215: /* nexprlist */
+ case 216: /* setlist */
+ case 220: /* exprlist */
+ case 225: /* case_exprlist */
+{
+sqlite3ExprListDelete(pParse->db, (yypminor->yy442));
+}
+ break;
+ case 193: /* fullname */
+ case 198: /* from */
+ case 206: /* seltablist */
+ case 207: /* stl_prefix */
+{
+sqlite3SrcListDelete(pParse->db, (yypminor->yy347));
+}
+ break;
+ case 199: /* where_opt */
+ case 201: /* having_opt */
+ case 210: /* on_opt */
+ case 224: /* case_operand */
+ case 226: /* case_else */
+ case 236: /* when_clause */
+ case 241: /* key_opt */
+{
+sqlite3ExprDelete(pParse->db, (yypminor->yy122));
+}
+ break;
+ case 211: /* using_opt */
+ case 213: /* inscollist */
+ case 218: /* inscollist_opt */
+{
+sqlite3IdListDelete(pParse->db, (yypminor->yy180));
+}
+ break;
+ case 219: /* valuelist */
+{
+
+ sqlite3ExprListDelete(pParse->db, (yypminor->yy487).pList);
+ sqlite3SelectDelete(pParse->db, (yypminor->yy487).pSelect);
+
+}
+ break;
+ case 232: /* trigger_cmd_list */
+ case 237: /* trigger_cmd */
+{
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy327));
+}
+ break;
+ case 234: /* trigger_event */
+{
+sqlite3IdListDelete(pParse->db, (yypminor->yy410).b);
+}
+ break;
+ default: break; /* If no destructor action specified: do nothing */
+ }
+}
+
+/*
+** Pop the parser's stack once.
+**
+** If there is a destructor routine associated with the token which
+** is popped from the stack, then call it.
+**
+** Return the major token number for the symbol popped.
+*/
+static int yy_pop_parser_stack(yyParser *pParser){
+ YYCODETYPE yymajor;
+ yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
+
+ /* There is no mechanism by which the parser stack can be popped below
+ ** empty in SQLite. */
+ if( NEVER(pParser->yyidx<0) ) return 0;
+#ifndef NDEBUG
+ if( yyTraceFILE && pParser->yyidx>=0 ){
+ fprintf(yyTraceFILE,"%sPopping %s\n",
+ yyTracePrompt,
+ yyTokenName[yytos->major]);
+ }
+#endif
+ yymajor = yytos->major;
+ yy_destructor(pParser, yymajor, &yytos->minor);
+ pParser->yyidx--;
+ return yymajor;
+}
+
+/*
+** Deallocate and destroy a parser. Destructors are all called for
+** all stack elements before shutting the parser down.
+**
+** Inputs:
+** <ul>
+** <li> A pointer to the parser. This should be a pointer
+** obtained from sqlite3ParserAlloc.
+** <li> A pointer to a function used to reclaim memory obtained
+** from malloc.
+** </ul>
+*/
+SQLITE_PRIVATE void sqlite3ParserFree(
+ void *p, /* The parser to be deleted */
+ void (*freeProc)(void*) /* Function used to reclaim memory */
+){
+ yyParser *pParser = (yyParser*)p;
+ /* In SQLite, we never try to destroy a parser that was not successfully
+ ** created in the first place. */
+ if( NEVER(pParser==0) ) return;
+ while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
+#if YYSTACKDEPTH<=0
+ free(pParser->yystack);
+#endif
+ (*freeProc)((void*)pParser);
+}
+
+/*
+** Return the peak depth of the stack for a parser.
+*/
+#ifdef YYTRACKMAXSTACKDEPTH
+SQLITE_PRIVATE int sqlite3ParserStackPeak(void *p){
+ yyParser *pParser = (yyParser*)p;
+ return pParser->yyidxMax;
+}
+#endif
+
+/*
+** Find the appropriate action for a parser given the terminal
+** look-ahead token iLookAhead.
+**
+** If the look-ahead token is YYNOCODE, then check to see if the action is
+** independent of the look-ahead. If it is, return the action, otherwise
+** return YY_NO_ACTION.
+*/
+static int yy_find_shift_action(
+ yyParser *pParser, /* The parser */
+ YYCODETYPE iLookAhead /* The look-ahead token */
+){
+ int i;
+ int stateno = pParser->yystack[pParser->yyidx].stateno;
+
+ if( stateno>YY_SHIFT_COUNT
+ || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
+ return yy_default[stateno];
+ }
+ assert( iLookAhead!=YYNOCODE );
+ i += iLookAhead;
+ if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
+ if( iLookAhead>0 ){
+#ifdef YYFALLBACK
+ YYCODETYPE iFallback; /* Fallback token */
+ if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
+ && (iFallback = yyFallback[iLookAhead])!=0 ){
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+ }
+#endif
+ return yy_find_shift_action(pParser, iFallback);
+ }
+#endif
+#ifdef YYWILDCARD
+ {
+ int j = i - iLookAhead + YYWILDCARD;
+ if(
+#if YY_SHIFT_MIN+YYWILDCARD<0
+ j>=0 &&
+#endif
+#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
+ j<YY_ACTTAB_COUNT &&
+#endif
+ yy_lookahead[j]==YYWILDCARD
+ ){
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
+ }
+#endif /* NDEBUG */
+ return yy_action[j];
+ }
+ }
+#endif /* YYWILDCARD */
+ }
+ return yy_default[stateno];
+ }else{
+ return yy_action[i];
+ }
+}
+
+/*
+** Find the appropriate action for a parser given the non-terminal
+** look-ahead token iLookAhead.
+**
+** If the look-ahead token is YYNOCODE, then check to see if the action is
+** independent of the look-ahead. If it is, return the action, otherwise
+** return YY_NO_ACTION.
+*/
+static int yy_find_reduce_action(
+ int stateno, /* Current state number */
+ YYCODETYPE iLookAhead /* The look-ahead token */
+){
+ int i;
+#ifdef YYERRORSYMBOL
+ if( stateno>YY_REDUCE_COUNT ){
+ return yy_default[stateno];
+ }
+#else
+ assert( stateno<=YY_REDUCE_COUNT );
+#endif
+ i = yy_reduce_ofst[stateno];
+ assert( i!=YY_REDUCE_USE_DFLT );
+ assert( iLookAhead!=YYNOCODE );
+ i += iLookAhead;
+#ifdef YYERRORSYMBOL
+ if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
+ return yy_default[stateno];
+ }
+#else
+ assert( i>=0 && i<YY_ACTTAB_COUNT );
+ assert( yy_lookahead[i]==iLookAhead );
+#endif
+ return yy_action[i];
+}
+
+/*
+** The following routine is called if the stack overflows.
+*/
+static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
+ sqlite3ParserARG_FETCH;
+ yypParser->yyidx--;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
+ }
+#endif
+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+ /* Here code is inserted which will execute if the parser
+ ** stack every overflows */
+
+ UNUSED_PARAMETER(yypMinor); /* Silence some compiler warnings */
+ sqlite3ErrorMsg(pParse, "parser stack overflow");
+ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */
+}
+
+/*
+** Perform a shift action.
+*/
+static void yy_shift(
+ yyParser *yypParser, /* The parser to be shifted */
+ int yyNewState, /* The new state to shift in */
+ int yyMajor, /* The major token to shift in */
+ YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
+){
+ yyStackEntry *yytos;
+ yypParser->yyidx++;
+#ifdef YYTRACKMAXSTACKDEPTH
+ if( yypParser->yyidx>yypParser->yyidxMax ){
+ yypParser->yyidxMax = yypParser->yyidx;
+ }
+#endif
+#if YYSTACKDEPTH>0
+ if( yypParser->yyidx>=YYSTACKDEPTH ){
+ yyStackOverflow(yypParser, yypMinor);
+ return;
+ }
+#else
+ if( yypParser->yyidx>=yypParser->yystksz ){
+ yyGrowStack(yypParser);
+ if( yypParser->yyidx>=yypParser->yystksz ){
+ yyStackOverflow(yypParser, yypMinor);
+ return;
+ }
+ }
+#endif
+ yytos = &yypParser->yystack[yypParser->yyidx];
+ yytos->stateno = (YYACTIONTYPE)yyNewState;
+ yytos->major = (YYCODETYPE)yyMajor;
+ yytos->minor = *yypMinor;
+#ifndef NDEBUG
+ if( yyTraceFILE && yypParser->yyidx>0 ){
+ int i;
+ fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
+ fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
+ for(i=1; i<=yypParser->yyidx; i++)
+ fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
+ fprintf(yyTraceFILE,"\n");
+ }
+#endif
+}
+
+/* The following table contains information about every rule that
+** is used during the reduce.
+*/
+static const struct {
+ YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
+ unsigned char nrhs; /* Number of right-hand side symbols in the rule */
+} yyRuleInfo[] = {
+ { 142, 1 },
+ { 143, 2 },
+ { 143, 1 },
+ { 144, 1 },
+ { 144, 3 },
+ { 145, 0 },
+ { 145, 1 },
+ { 145, 3 },
+ { 146, 1 },
+ { 147, 3 },
+ { 149, 0 },
+ { 149, 1 },
+ { 149, 2 },
+ { 148, 0 },
+ { 148, 1 },
+ { 148, 1 },
+ { 148, 1 },
+ { 147, 2 },
+ { 147, 2 },
+ { 147, 2 },
+ { 151, 1 },
+ { 151, 0 },
+ { 147, 2 },
+ { 147, 3 },
+ { 147, 5 },
+ { 147, 2 },
+ { 152, 6 },
+ { 154, 1 },
+ { 156, 0 },
+ { 156, 3 },
+ { 155, 1 },
+ { 155, 0 },
+ { 153, 4 },
+ { 153, 2 },
+ { 158, 3 },
+ { 158, 1 },
+ { 161, 3 },
+ { 162, 1 },
+ { 165, 1 },
+ { 165, 1 },
+ { 166, 1 },
+ { 150, 1 },
+ { 150, 1 },
+ { 150, 1 },
+ { 163, 0 },
+ { 163, 1 },
+ { 167, 1 },
+ { 167, 4 },
+ { 167, 6 },
+ { 168, 1 },
+ { 168, 2 },
+ { 169, 1 },
+ { 169, 1 },
+ { 164, 2 },
+ { 164, 0 },
+ { 172, 2 },
+ { 172, 2 },
+ { 172, 4 },
+ { 172, 3 },
+ { 172, 3 },
+ { 172, 2 },
+ { 172, 2 },
+ { 172, 3 },
+ { 172, 5 },
+ { 172, 2 },
+ { 172, 4 },
+ { 172, 4 },
+ { 172, 1 },
+ { 172, 2 },
+ { 177, 0 },
+ { 177, 1 },
+ { 179, 0 },
+ { 179, 2 },
+ { 181, 2 },
+ { 181, 3 },
+ { 181, 3 },
+ { 181, 3 },
+ { 182, 2 },
+ { 182, 2 },
+ { 182, 1 },
+ { 182, 1 },
+ { 182, 2 },
+ { 180, 3 },
+ { 180, 2 },
+ { 183, 0 },
+ { 183, 2 },
+ { 183, 2 },
+ { 159, 0 },
+ { 159, 2 },
+ { 184, 3 },
+ { 184, 1 },
+ { 185, 1 },
+ { 185, 0 },
+ { 186, 2 },
+ { 186, 7 },
+ { 186, 5 },
+ { 186, 5 },
+ { 186, 10 },
+ { 188, 0 },
+ { 188, 1 },
+ { 175, 0 },
+ { 175, 3 },
+ { 189, 0 },
+ { 189, 2 },
+ { 190, 1 },
+ { 190, 1 },
+ { 190, 1 },
+ { 147, 4 },
+ { 192, 2 },
+ { 192, 0 },
+ { 147, 8 },
+ { 147, 4 },
+ { 147, 1 },
+ { 160, 1 },
+ { 160, 3 },
+ { 195, 1 },
+ { 195, 2 },
+ { 195, 1 },
+ { 194, 9 },
+ { 196, 1 },
+ { 196, 1 },
+ { 196, 0 },
+ { 204, 2 },
+ { 204, 0 },
+ { 197, 3 },
+ { 197, 2 },
+ { 197, 4 },
+ { 205, 2 },
+ { 205, 1 },
+ { 205, 0 },
+ { 198, 0 },
+ { 198, 2 },
+ { 207, 2 },
+ { 207, 0 },
+ { 206, 7 },
+ { 206, 7 },
+ { 206, 7 },
+ { 157, 0 },
+ { 157, 2 },
+ { 193, 2 },
+ { 208, 1 },
+ { 208, 2 },
+ { 208, 3 },
+ { 208, 4 },
+ { 210, 2 },
+ { 210, 0 },
+ { 209, 0 },
+ { 209, 3 },
+ { 209, 2 },
+ { 211, 4 },
+ { 211, 0 },
+ { 202, 0 },
+ { 202, 3 },
+ { 214, 4 },
+ { 214, 2 },
+ { 176, 1 },
+ { 176, 1 },
+ { 176, 0 },
+ { 200, 0 },
+ { 200, 3 },
+ { 201, 0 },
+ { 201, 2 },
+ { 203, 0 },
+ { 203, 2 },
+ { 203, 4 },
+ { 203, 4 },
+ { 147, 5 },
+ { 199, 0 },
+ { 199, 2 },
+ { 147, 7 },
+ { 216, 5 },
+ { 216, 3 },
+ { 147, 5 },
+ { 147, 5 },
+ { 147, 6 },
+ { 217, 2 },
+ { 217, 1 },
+ { 219, 4 },
+ { 219, 5 },
+ { 218, 0 },
+ { 218, 3 },
+ { 213, 3 },
+ { 213, 1 },
+ { 174, 1 },
+ { 174, 3 },
+ { 173, 1 },
+ { 174, 1 },
+ { 174, 1 },
+ { 174, 3 },
+ { 174, 5 },
+ { 173, 1 },
+ { 173, 1 },
+ { 174, 1 },
+ { 174, 1 },
+ { 174, 3 },
+ { 174, 6 },
+ { 174, 5 },
+ { 174, 4 },
+ { 173, 1 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 221, 1 },
+ { 221, 2 },
+ { 221, 1 },
+ { 221, 2 },
+ { 174, 3 },
+ { 174, 5 },
+ { 174, 2 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 4 },
+ { 174, 2 },
+ { 174, 2 },
+ { 174, 2 },
+ { 174, 2 },
+ { 222, 1 },
+ { 222, 2 },
+ { 174, 5 },
+ { 223, 1 },
+ { 223, 2 },
+ { 174, 5 },
+ { 174, 3 },
+ { 174, 5 },
+ { 174, 4 },
+ { 174, 4 },
+ { 174, 5 },
+ { 225, 5 },
+ { 225, 4 },
+ { 226, 2 },
+ { 226, 0 },
+ { 224, 1 },
+ { 224, 0 },
+ { 220, 1 },
+ { 220, 0 },
+ { 215, 3 },
+ { 215, 1 },
+ { 147, 11 },
+ { 227, 1 },
+ { 227, 0 },
+ { 178, 0 },
+ { 178, 3 },
+ { 187, 5 },
+ { 187, 3 },
+ { 228, 0 },
+ { 228, 2 },
+ { 147, 4 },
+ { 147, 1 },
+ { 147, 2 },
+ { 147, 3 },
+ { 147, 5 },
+ { 147, 6 },
+ { 147, 5 },
+ { 147, 6 },
+ { 229, 1 },
+ { 229, 1 },
+ { 229, 1 },
+ { 229, 1 },
+ { 229, 1 },
+ { 170, 2 },
+ { 170, 1 },
+ { 171, 2 },
+ { 230, 1 },
+ { 147, 5 },
+ { 231, 11 },
+ { 233, 1 },
+ { 233, 1 },
+ { 233, 2 },
+ { 233, 0 },
+ { 234, 1 },
+ { 234, 1 },
+ { 234, 3 },
+ { 235, 0 },
+ { 235, 3 },
+ { 236, 0 },
+ { 236, 2 },
+ { 232, 3 },
+ { 232, 2 },
+ { 238, 1 },
+ { 238, 3 },
+ { 239, 0 },
+ { 239, 3 },
+ { 239, 2 },
+ { 237, 7 },
+ { 237, 5 },
+ { 237, 5 },
+ { 237, 5 },
+ { 237, 1 },
+ { 174, 4 },
+ { 174, 6 },
+ { 191, 1 },
+ { 191, 1 },
+ { 191, 1 },
+ { 147, 4 },
+ { 147, 6 },
+ { 147, 3 },
+ { 241, 0 },
+ { 241, 2 },
+ { 240, 1 },
+ { 240, 0 },
+ { 147, 1 },
+ { 147, 3 },
+ { 147, 1 },
+ { 147, 3 },
+ { 147, 6 },
+ { 147, 6 },
+ { 242, 1 },
+ { 243, 0 },
+ { 243, 1 },
+ { 147, 1 },
+ { 147, 4 },
+ { 244, 8 },
+ { 245, 1 },
+ { 245, 3 },
+ { 246, 0 },
+ { 246, 2 },
+ { 247, 1 },
+ { 247, 3 },
+ { 248, 1 },
+ { 249, 0 },
+ { 249, 4 },
+ { 249, 2 },
+};
+
+static void yy_accept(yyParser*); /* Forward Declaration */
+
+/*
+** Perform a reduce action and the shift that must immediately
+** follow the reduce.
+*/
+static void yy_reduce(
+ yyParser *yypParser, /* The parser */
+ int yyruleno /* Number of the rule by which to reduce */
+){
+ int yygoto; /* The next state */
+ int yyact; /* The next action */
+ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
+ yyStackEntry *yymsp; /* The top of the parser's stack */
+ int yysize; /* Amount to pop the stack */
+ sqlite3ParserARG_FETCH;
+ yymsp = &yypParser->yystack[yypParser->yyidx];
+#ifndef NDEBUG
+ if( yyTraceFILE && yyruleno>=0
+ && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
+ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
+ yyRuleName[yyruleno]);
+ }
+#endif /* NDEBUG */
+
+ /* Silence complaints from purify about yygotominor being uninitialized
+ ** in some cases when it is copied into the stack after the following
+ ** switch. yygotominor is uninitialized when a rule reduces that does
+ ** not set the value of its left-hand side nonterminal. Leaving the
+ ** value of the nonterminal uninitialized is utterly harmless as long
+ ** as the value is never used. So really the only thing this code
+ ** accomplishes is to quieten purify.
+ **
+ ** 2007-01-16: The wireshark project (www.wireshark.org) reports that
+ ** without this code, their parser segfaults. I'm not sure what there
+ ** parser is doing to make this happen. This is the second bug report
+ ** from wireshark this week. Clearly they are stressing Lemon in ways
+ ** that it has not been previously stressed... (SQLite ticket #2172)
+ */
+ /*memset(&yygotominor, 0, sizeof(yygotominor));*/
+ yygotominor = yyzerominor;
+
+
+ switch( yyruleno ){
+ /* Beginning here are the reduction cases. A typical example
+ ** follows:
+ ** case 0:
+ ** #line <lineno> <grammarfile>
+ ** { ... } // User supplied code
+ ** #line <lineno> <thisfile>
+ ** break;
+ */
+ case 5: /* explain ::= */
+{ sqlite3BeginParse(pParse, 0); }
+ break;
+ case 6: /* explain ::= EXPLAIN */
+{ sqlite3BeginParse(pParse, 1); }
+ break;
+ case 7: /* explain ::= EXPLAIN QUERY PLAN */
+{ sqlite3BeginParse(pParse, 2); }
+ break;
+ case 8: /* cmdx ::= cmd */
+{ sqlite3FinishCoding(pParse); }
+ break;
+ case 9: /* cmd ::= BEGIN transtype trans_opt */
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy392);}
+ break;
+ case 13: /* transtype ::= */
+{yygotominor.yy392 = TK_DEFERRED;}
+ break;
+ case 14: /* transtype ::= DEFERRED */
+ case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
+ case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
+ case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
+ case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
+{yygotominor.yy392 = yymsp[0].major;}
+ break;
+ case 17: /* cmd ::= COMMIT trans_opt */
+ case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
+{sqlite3CommitTransaction(pParse);}
+ break;
+ case 19: /* cmd ::= ROLLBACK trans_opt */
+{sqlite3RollbackTransaction(pParse);}
+ break;
+ case 22: /* cmd ::= SAVEPOINT nm */
+{
+ sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0);
+}
+ break;
+ case 23: /* cmd ::= RELEASE savepoint_opt nm */
+{
+ sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0);
+}
+ break;
+ case 24: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+{
+ sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
+}
+ break;
+ case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+{
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy392,0,0,yymsp[-2].minor.yy392);
+}
+ break;
+ case 27: /* createkw ::= CREATE */
+{
+ pParse->db->lookaside.bEnabled = 0;
+ yygotominor.yy0 = yymsp[0].minor.yy0;
+}
+ break;
+ case 28: /* ifnotexists ::= */
+ case 31: /* temp ::= */ yytestcase(yyruleno==31);
+ case 69: /* autoinc ::= */ yytestcase(yyruleno==69);
+ case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82);
+ case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
+ case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
+ case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
+ case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
+ case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
+ case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
+{yygotominor.yy392 = 0;}
+ break;
+ case 29: /* ifnotexists ::= IF NOT EXISTS */
+ case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
+ case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
+ case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
+ case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
+ case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
+ case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
+{yygotominor.yy392 = 1;}
+ break;
+ case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
+{
+ sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
+}
+ break;
+ case 33: /* create_table_args ::= AS select */
+{
+ sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy159);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
+}
+ break;
+ case 36: /* column ::= columnid type carglist */
+{
+ yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
+ yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
+}
+ break;
+ case 37: /* columnid ::= nm */
+{
+ sqlite3AddColumn(pParse,&yymsp[0].minor.yy0);
+ yygotominor.yy0 = yymsp[0].minor.yy0;
+ pParse->constraintName.n = 0;
+}
+ break;
+ case 38: /* id ::= ID */
+ case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39);
+ case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40);
+ case 41: /* nm ::= id */ yytestcase(yyruleno==41);
+ case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
+ case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
+ case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
+ case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
+ case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
+ case 128: /* as ::= ids */ yytestcase(yyruleno==128);
+ case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
+ case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
+ case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250);
+ case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259);
+ case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260);
+ case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261);
+ case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262);
+ case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263);
+ case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264);
+ case 265: /* plus_num ::= number */ yytestcase(yyruleno==265);
+ case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
+ case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
+ case 283: /* trnm ::= nm */ yytestcase(yyruleno==283);
+{yygotominor.yy0 = yymsp[0].minor.yy0;}
+ break;
+ case 45: /* type ::= typetoken */
+{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
+ break;
+ case 47: /* typetoken ::= typename LP signed RP */
+{
+ yygotominor.yy0.z = yymsp[-3].minor.yy0.z;
+ yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
+}
+ break;
+ case 48: /* typetoken ::= typename LP signed COMMA signed RP */
+{
+ yygotominor.yy0.z = yymsp[-5].minor.yy0.z;
+ yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
+}
+ break;
+ case 50: /* typename ::= typename ids */
+{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
+ break;
+ case 55: /* ccons ::= CONSTRAINT nm */
+ case 93: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);
+{pParse->constraintName = yymsp[0].minor.yy0;}
+ break;
+ case 56: /* ccons ::= DEFAULT term */
+ case 58: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==58);
+{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
+ break;
+ case 57: /* ccons ::= DEFAULT LP expr RP */
+{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);}
+ break;
+ case 59: /* ccons ::= DEFAULT MINUS term */
+{
+ ExprSpan v;
+ v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0);
+ v.zStart = yymsp[-1].minor.yy0.z;
+ v.zEnd = yymsp[0].minor.yy342.zEnd;
+ sqlite3AddDefaultValue(pParse,&v);
+}
+ break;
+ case 60: /* ccons ::= DEFAULT id */
+{
+ ExprSpan v;
+ spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0);
+ sqlite3AddDefaultValue(pParse,&v);
+}
+ break;
+ case 62: /* ccons ::= NOT NULL onconf */
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);}
+ break;
+ case 63: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);}
+ break;
+ case 64: /* ccons ::= UNIQUE onconf */
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);}
+ break;
+ case 65: /* ccons ::= CHECK LP expr RP */
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);}
+ break;
+ case 66: /* ccons ::= REFERENCES nm idxlist_opt refargs */
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);}
+ break;
+ case 67: /* ccons ::= defer_subclause */
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);}
+ break;
+ case 68: /* ccons ::= COLLATE ids */
+{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
+ break;
+ case 71: /* refargs ::= */
+{ yygotominor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */}
+ break;
+ case 72: /* refargs ::= refargs refarg */
+{ yygotominor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
+ break;
+ case 73: /* refarg ::= MATCH nm */
+ case 74: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==74);
+{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; }
+ break;
+ case 75: /* refarg ::= ON DELETE refact */
+{ yygotominor.yy207.value = yymsp[0].minor.yy392; yygotominor.yy207.mask = 0x0000ff; }
+ break;
+ case 76: /* refarg ::= ON UPDATE refact */
+{ yygotominor.yy207.value = yymsp[0].minor.yy392<<8; yygotominor.yy207.mask = 0x00ff00; }
+ break;
+ case 77: /* refact ::= SET NULL */
+{ yygotominor.yy392 = OE_SetNull; /* EV: R-33326-45252 */}
+ break;
+ case 78: /* refact ::= SET DEFAULT */
+{ yygotominor.yy392 = OE_SetDflt; /* EV: R-33326-45252 */}
+ break;
+ case 79: /* refact ::= CASCADE */
+{ yygotominor.yy392 = OE_Cascade; /* EV: R-33326-45252 */}
+ break;
+ case 80: /* refact ::= RESTRICT */
+{ yygotominor.yy392 = OE_Restrict; /* EV: R-33326-45252 */}
+ break;
+ case 81: /* refact ::= NO ACTION */
+{ yygotominor.yy392 = OE_None; /* EV: R-33326-45252 */}
+ break;
+ case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
+ case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
+ case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
+{yygotominor.yy392 = yymsp[0].minor.yy392;}
+ break;
+ case 87: /* conslist_opt ::= */
+{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
+ break;
+ case 88: /* conslist_opt ::= COMMA conslist */
+{yygotominor.yy0 = yymsp[-1].minor.yy0;}
+ break;
+ case 91: /* tconscomma ::= COMMA */
+{pParse->constraintName.n = 0;}
+ break;
+ case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
+ break;
+ case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
+ break;
+ case 96: /* tcons ::= CHECK LP expr RP onconf */
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
+ break;
+ case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
+{
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
+}
+ break;
+ case 100: /* onconf ::= */
+{yygotominor.yy392 = OE_Default;}
+ break;
+ case 102: /* orconf ::= */
+{yygotominor.yy258 = OE_Default;}
+ break;
+ case 103: /* orconf ::= OR resolvetype */
+{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
+ break;
+ case 105: /* resolvetype ::= IGNORE */
+{yygotominor.yy392 = OE_Ignore;}
+ break;
+ case 106: /* resolvetype ::= REPLACE */
+{yygotominor.yy392 = OE_Replace;}
+ break;
+ case 107: /* cmd ::= DROP TABLE ifexists fullname */
+{
+ sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
+}
+ break;
+ case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
+{
+ sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
+}
+ break;
+ case 111: /* cmd ::= DROP VIEW ifexists fullname */
+{
+ sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
+}
+ break;
+ case 112: /* cmd ::= select */
+{
+ SelectDest dest = {SRT_Output, 0, 0, 0, 0};
+ sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
+ sqlite3ExplainBegin(pParse->pVdbe);
+ sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
+ sqlite3ExplainFinish(pParse->pVdbe);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
+}
+ break;
+ case 113: /* select ::= oneselect */
+{yygotominor.yy159 = yymsp[0].minor.yy159;}
+ break;
+ case 114: /* select ::= select multiselect_op oneselect */
+{
+ if( yymsp[0].minor.yy159 ){
+ yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
+ yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
+ }
+ yygotominor.yy159 = yymsp[0].minor.yy159;
+}
+ break;
+ case 116: /* multiselect_op ::= UNION ALL */
+{yygotominor.yy392 = TK_ALL;}
+ break;
+ case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+{
+ yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
+}
+ break;
+ case 119: /* distinct ::= DISTINCT */
+{yygotominor.yy305 = SF_Distinct;}
+ break;
+ case 120: /* distinct ::= ALL */
+ case 121: /* distinct ::= */ yytestcase(yyruleno==121);
+{yygotominor.yy305 = 0;}
+ break;
+ case 122: /* sclp ::= selcollist COMMA */
+ case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
+{yygotominor.yy442 = yymsp[-1].minor.yy442;}
+ break;
+ case 123: /* sclp ::= */
+ case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
+ case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158);
+ case 239: /* exprlist ::= */ yytestcase(yyruleno==239);
+ case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245);
+{yygotominor.yy442 = 0;}
+ break;
+ case 124: /* selcollist ::= sclp expr as */
+{
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
+}
+ break;
+ case 125: /* selcollist ::= sclp STAR */
+{
+ Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
+}
+ break;
+ case 126: /* selcollist ::= sclp nm DOT STAR */
+{
+ Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
+ Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
+ Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
+}
+ break;
+ case 129: /* as ::= */
+{yygotominor.yy0.n = 0;}
+ break;
+ case 130: /* from ::= */
+{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
+ break;
+ case 131: /* from ::= FROM seltablist */
+{
+ yygotominor.yy347 = yymsp[0].minor.yy347;
+ sqlite3SrcListShiftJoinType(yygotominor.yy347);
+}
+ break;
+ case 132: /* stl_prefix ::= seltablist joinop */
+{
+ yygotominor.yy347 = yymsp[-1].minor.yy347;
+ if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
+}
+ break;
+ case 133: /* stl_prefix ::= */
+{yygotominor.yy347 = 0;}
+ break;
+ case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+{
+ yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+ sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
+}
+ break;
+ case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+{
+ yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+ }
+ break;
+ case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+{
+ if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
+ yygotominor.yy347 = yymsp[-4].minor.yy347;
+ }else if( yymsp[-4].minor.yy347->nSrc==1 ){
+ yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+ if( yygotominor.yy347 ){
+ struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
+ struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
+ pNew->zName = pOld->zName;
+ pNew->zDatabase = pOld->zDatabase;
+ pOld->zName = pOld->zDatabase = 0;
+ }
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
+ }else{
+ Select *pSubquery;
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
+ yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+ }
+ }
+ break;
+ case 137: /* dbnm ::= */
+ case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
+{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
+ break;
+ case 139: /* fullname ::= nm dbnm */
+{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
+ break;
+ case 140: /* joinop ::= COMMA|JOIN */
+{ yygotominor.yy392 = JT_INNER; }
+ break;
+ case 141: /* joinop ::= JOIN_KW JOIN */
+{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+ break;
+ case 142: /* joinop ::= JOIN_KW nm JOIN */
+{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
+ break;
+ case 143: /* joinop ::= JOIN_KW nm nm JOIN */
+{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
+ break;
+ case 144: /* on_opt ::= ON expr */
+ case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161);
+ case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168);
+ case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234);
+ case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236);
+{yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
+ break;
+ case 145: /* on_opt ::= */
+ case 160: /* having_opt ::= */ yytestcase(yyruleno==160);
+ case 167: /* where_opt ::= */ yytestcase(yyruleno==167);
+ case 235: /* case_else ::= */ yytestcase(yyruleno==235);
+ case 237: /* case_operand ::= */ yytestcase(yyruleno==237);
+{yygotominor.yy122 = 0;}
+ break;
+ case 148: /* indexed_opt ::= NOT INDEXED */
+{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
+ break;
+ case 149: /* using_opt ::= USING LP inscollist RP */
+ case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180);
+{yygotominor.yy180 = yymsp[-1].minor.yy180;}
+ break;
+ case 150: /* using_opt ::= */
+ case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179);
+{yygotominor.yy180 = 0;}
+ break;
+ case 152: /* orderby_opt ::= ORDER BY sortlist */
+ case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159);
+ case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238);
+{yygotominor.yy442 = yymsp[0].minor.yy442;}
+ break;
+ case 153: /* sortlist ::= sortlist COMMA expr sortorder */
+{
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
+ if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+}
+ break;
+ case 154: /* sortlist ::= expr sortorder */
+{
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
+ if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
+}
+ break;
+ case 155: /* sortorder ::= ASC */
+ case 157: /* sortorder ::= */ yytestcase(yyruleno==157);
+{yygotominor.yy392 = SQLITE_SO_ASC;}
+ break;
+ case 156: /* sortorder ::= DESC */
+{yygotominor.yy392 = SQLITE_SO_DESC;}
+ break;
+ case 162: /* limit_opt ::= */
+{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
+ break;
+ case 163: /* limit_opt ::= LIMIT expr */
+{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
+ break;
+ case 164: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
+ break;
+ case 165: /* limit_opt ::= LIMIT expr COMMA expr */
+{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
+ break;
+ case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
+{
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
+}
+ break;
+ case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
+{
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list");
+ sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
+}
+ break;
+ case 170: /* setlist ::= setlist COMMA nm EQ expr */
+{
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
+ sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
+}
+ break;
+ case 171: /* setlist ::= nm EQ expr */
+{
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
+ sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
+}
+ break;
+ case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
+{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
+ break;
+ case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
+{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
+ break;
+ case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
+{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
+ break;
+ case 175: /* insert_cmd ::= INSERT orconf */
+{yygotominor.yy258 = yymsp[0].minor.yy258;}
+ break;
+ case 176: /* insert_cmd ::= REPLACE */
+{yygotominor.yy258 = OE_Replace;}
+ break;
+ case 177: /* valuelist ::= VALUES LP nexprlist RP */
+{
+ yygotominor.yy487.pList = yymsp[-1].minor.yy442;
+ yygotominor.yy487.pSelect = 0;
+}
+ break;
+ case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */
+{
+ Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
+ if( yymsp[-4].minor.yy487.pList ){
+ yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
+ yymsp[-4].minor.yy487.pList = 0;
+ }
+ yygotominor.yy487.pList = 0;
+ if( yymsp[-4].minor.yy487.pSelect==0 || pRight==0 ){
+ sqlite3SelectDelete(pParse->db, pRight);
+ sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy487.pSelect);
+ yygotominor.yy487.pSelect = 0;
+ }else{
+ pRight->op = TK_ALL;
+ pRight->pPrior = yymsp[-4].minor.yy487.pSelect;
+ pRight->selFlags |= SF_Values;
+ pRight->pPrior->selFlags |= SF_Values;
+ yygotominor.yy487.pSelect = pRight;
+ }
+}
+ break;
+ case 181: /* inscollist ::= inscollist COMMA nm */
+{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
+ break;
+ case 182: /* inscollist ::= nm */
+{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+ break;
+ case 183: /* expr ::= term */
+{yygotominor.yy342 = yymsp[0].minor.yy342;}
+ break;
+ case 184: /* expr ::= LP expr RP */
+{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
+ break;
+ case 185: /* term ::= NULL */
+ case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190);
+ case 191: /* term ::= STRING */ yytestcase(yyruleno==191);
+{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
+ break;
+ case 186: /* expr ::= id */
+ case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187);
+{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
+ break;
+ case 188: /* expr ::= nm DOT nm */
+{
+ Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
+ Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+ spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 189: /* expr ::= nm DOT nm DOT nm */
+{
+ Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
+ Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
+ Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
+ Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+ spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 192: /* expr ::= REGISTER */
+{
+ /* When doing a nested parse, one can include terms in an expression
+ ** that look like this: #1 #2 ... These terms refer to registers
+ ** in the virtual machine. #N is the N-th register. */
+ if( pParse->nested==0 ){
+ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
+ yygotominor.yy342.pExpr = 0;
+ }else{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
+ if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
+ }
+ spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+}
+ break;
+ case 193: /* expr ::= VARIABLE */
+{
+ spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
+ spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+}
+ break;
+ case 194: /* expr ::= expr COLLATE ids */
+{
+ yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
+ yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+}
+ break;
+ case 195: /* expr ::= CAST LP expr AS typetoken RP */
+{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
+ spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 196: /* expr ::= ID LP distinct exprlist RP */
+{
+ if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
+ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
+ }
+ yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
+ spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+ if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->flags |= EP_Distinct;
+ }
+}
+ break;
+ case 197: /* expr ::= ID LP STAR RP */
+{
+ yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+ spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 198: /* term ::= CTIME_KW */
+{
+ /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
+ ** treated as functions that return constants */
+ yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->op = TK_CONST_FUNC;
+ }
+ spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+}
+ break;
+ case 199: /* expr ::= expr AND expr */
+ case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200);
+ case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201);
+ case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202);
+ case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203);
+ case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204);
+ case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205);
+ case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206);
+{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
+ break;
+ case 207: /* likeop ::= LIKE_KW */
+ case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209);
+{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;}
+ break;
+ case 208: /* likeop ::= NOT LIKE_KW */
+ case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
+{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;}
+ break;
+ case 211: /* expr ::= expr likeop expr */
+{
+ ExprList *pList;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
+ yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
+ if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+ yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
+ yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
+ if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
+}
+ break;
+ case 212: /* expr ::= expr likeop expr ESCAPE expr */
+{
+ ExprList *pList;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
+ yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
+ if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+ yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
+ yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
+ if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
+}
+ break;
+ case 213: /* expr ::= expr ISNULL|NOTNULL */
+{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
+ break;
+ case 214: /* expr ::= expr NOT NULL */
+{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
+ break;
+ case 215: /* expr ::= expr IS expr */
+{
+ spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
+}
+ break;
+ case 216: /* expr ::= expr IS NOT expr */
+{
+ spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
+}
+ break;
+ case 217: /* expr ::= NOT expr */
+ case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218);
+{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+ break;
+ case 219: /* expr ::= MINUS expr */
+{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+ break;
+ case 220: /* expr ::= PLUS expr */
+{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+ break;
+ case 223: /* expr ::= expr between_op expr AND expr */
+{
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->x.pList = pList;
+ }else{
+ sqlite3ExprListDelete(pParse->db, pList);
+ }
+ if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+ yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
+ yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
+}
+ break;
+ case 226: /* expr ::= expr in_op LP exprlist RP */
+{
+ if( yymsp[-1].minor.yy442==0 ){
+ /* Expressions of the form
+ **
+ ** expr1 IN ()
+ ** expr1 NOT IN ()
+ **
+ ** simplify to constants 0 (false) and 1 (true), respectively,
+ ** regardless of the value of expr1.
+ */
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy392]);
+ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy342.pExpr);
+ }else{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->x.pList = yymsp[-1].minor.yy442;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ }else{
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442);
+ }
+ if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+ }
+ yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ }
+ break;
+ case 227: /* expr ::= LP select RP */
+{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
+ ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+ }
+ yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ }
+ break;
+ case 228: /* expr ::= expr in_op LP select RP */
+{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
+ ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+ }
+ if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+ yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ }
+ break;
+ case 229: /* expr ::= expr in_op nm dbnm */
+{
+ SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+ ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ }else{
+ sqlite3SrcListDelete(pParse->db, pSrc);
+ }
+ if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+ yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
+ yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
+ }
+ break;
+ case 230: /* expr ::= EXISTS LP select RP */
+{
+ Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+ if( p ){
+ p->x.pSelect = yymsp[-1].minor.yy159;
+ ExprSetProperty(p, EP_xIsSelect);
+ sqlite3ExprSetHeight(pParse, p);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+ }
+ yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ }
+ break;
+ case 231: /* expr ::= CASE case_operand case_exprlist case_else END */
+{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ }else{
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442);
+ }
+ yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+}
+ break;
+ case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+{
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
+}
+ break;
+ case 233: /* case_exprlist ::= WHEN expr THEN expr */
+{
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
+}
+ break;
+ case 240: /* nexprlist ::= nexprlist COMMA expr */
+{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
+ break;
+ case 241: /* nexprlist ::= expr */
+{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
+ break;
+ case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
+{
+ sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
+ sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
+ &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
+}
+ break;
+ case 243: /* uniqueflag ::= UNIQUE */
+ case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296);
+{yygotominor.yy392 = OE_Abort;}
+ break;
+ case 244: /* uniqueflag ::= */
+{yygotominor.yy392 = OE_None;}
+ break;
+ case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
+{
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
+ sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
+ if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+}
+ break;
+ case 248: /* idxlist ::= nm collate sortorder */
+{
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
+ yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
+ sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
+ if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+}
+ break;
+ case 249: /* collate ::= */
+{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
+ break;
+ case 251: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
+ break;
+ case 252: /* cmd ::= VACUUM */
+ case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253);
+{sqlite3Vacuum(pParse);}
+ break;
+ case 254: /* cmd ::= PRAGMA nm dbnm */
+{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
+ break;
+ case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
+ break;
+ case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
+ break;
+ case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
+ break;
+ case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
+ break;
+ case 268: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+{
+ Token all;
+ all.z = yymsp[-3].minor.yy0.z;
+ all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
+}
+ break;
+ case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+{
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
+ yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
+}
+ break;
+ case 270: /* trigger_time ::= BEFORE */
+ case 273: /* trigger_time ::= */ yytestcase(yyruleno==273);
+{ yygotominor.yy392 = TK_BEFORE; }
+ break;
+ case 271: /* trigger_time ::= AFTER */
+{ yygotominor.yy392 = TK_AFTER; }
+ break;
+ case 272: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy392 = TK_INSTEAD;}
+ break;
+ case 274: /* trigger_event ::= DELETE|INSERT */
+ case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275);
+{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
+ break;
+ case 276: /* trigger_event ::= UPDATE OF inscollist */
+{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
+ break;
+ case 279: /* when_clause ::= */
+ case 301: /* key_opt ::= */ yytestcase(yyruleno==301);
+{ yygotominor.yy122 = 0; }
+ break;
+ case 280: /* when_clause ::= WHEN expr */
+ case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302);
+{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
+ break;
+ case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+{
+ assert( yymsp[-2].minor.yy327!=0 );
+ yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
+ yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
+ yygotominor.yy327 = yymsp[-2].minor.yy327;
+}
+ break;
+ case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */
+{
+ assert( yymsp[-1].minor.yy327!=0 );
+ yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
+ yygotominor.yy327 = yymsp[-1].minor.yy327;
+}
+ break;
+ case 284: /* trnm ::= nm DOT nm */
+{
+ yygotominor.yy0 = yymsp[0].minor.yy0;
+ sqlite3ErrorMsg(pParse,
+ "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
+ "statements within triggers");
+}
+ break;
+ case 286: /* tridxby ::= INDEXED BY nm */
+{
+ sqlite3ErrorMsg(pParse,
+ "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
+ "within triggers");
+}
+ break;
+ case 287: /* tridxby ::= NOT INDEXED */
+{
+ sqlite3ErrorMsg(pParse,
+ "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
+ "within triggers");
+}
+ break;
+ case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
+{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
+ break;
+ case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
+{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
+ break;
+ case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
+{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
+ break;
+ case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
+{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
+ break;
+ case 292: /* trigger_cmd ::= select */
+{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
+ break;
+ case 293: /* expr ::= RAISE LP IGNORE RP */
+{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ if( yygotominor.yy342.pExpr ){
+ yygotominor.yy342.pExpr->affinity = OE_Ignore;
+ }
+ yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+}
+ break;
+ case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */
+{
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ if( yygotominor.yy342.pExpr ) {
+ yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
+ }
+ yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
+ yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+}
+ break;
+ case 295: /* raisetype ::= ROLLBACK */
+{yygotominor.yy392 = OE_Rollback;}
+ break;
+ case 297: /* raisetype ::= FAIL */
+{yygotominor.yy392 = OE_Fail;}
+ break;
+ case 298: /* cmd ::= DROP TRIGGER ifexists fullname */
+{
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
+}
+ break;
+ case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+{
+ sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
+}
+ break;
+ case 300: /* cmd ::= DETACH database_kw_opt expr */
+{
+ sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
+}
+ break;
+ case 305: /* cmd ::= REINDEX */
+{sqlite3Reindex(pParse, 0, 0);}
+ break;
+ case 306: /* cmd ::= REINDEX nm dbnm */
+{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
+ break;
+ case 307: /* cmd ::= ANALYZE */
+{sqlite3Analyze(pParse, 0, 0);}
+ break;
+ case 308: /* cmd ::= ANALYZE nm dbnm */
+{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
+ break;
+ case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+{
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
+}
+ break;
+ case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+{
+ sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
+}
+ break;
+ case 311: /* add_column_fullname ::= fullname */
+{
+ pParse->db->lookaside.bEnabled = 0;
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
+}
+ break;
+ case 314: /* cmd ::= create_vtab */
+{sqlite3VtabFinishParse(pParse,0);}
+ break;
+ case 315: /* cmd ::= create_vtab LP vtabarglist RP */
+{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
+ break;
+ case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+{
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
+}
+ break;
+ case 319: /* vtabarg ::= */
+{sqlite3VtabArgInit(pParse);}
+ break;
+ case 321: /* vtabargtoken ::= ANY */
+ case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322);
+ case 323: /* lp ::= LP */ yytestcase(yyruleno==323);
+{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
+ break;
+ default:
+ /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
+ /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
+ /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
+ /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
+ /* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4);
+ /* (10) trans_opt ::= */ yytestcase(yyruleno==10);
+ /* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11);
+ /* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12);
+ /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
+ /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
+ /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25);
+ /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
+ /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
+ /* (44) type ::= */ yytestcase(yyruleno==44);
+ /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
+ /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
+ /* (53) carglist ::= carglist ccons */ yytestcase(yyruleno==53);
+ /* (54) carglist ::= */ yytestcase(yyruleno==54);
+ /* (61) ccons ::= NULL onconf */ yytestcase(yyruleno==61);
+ /* (89) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==89);
+ /* (90) conslist ::= tcons */ yytestcase(yyruleno==90);
+ /* (92) tconscomma ::= */ yytestcase(yyruleno==92);
+ /* (277) foreach_clause ::= */ yytestcase(yyruleno==277);
+ /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278);
+ /* (285) tridxby ::= */ yytestcase(yyruleno==285);
+ /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303);
+ /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304);
+ /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312);
+ /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313);
+ /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317);
+ /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
+ /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
+ /* (324) anylist ::= */ yytestcase(yyruleno==324);
+ /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
+ /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
+ break;
+ };
+ assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
+ yygoto = yyRuleInfo[yyruleno].lhs;
+ yysize = yyRuleInfo[yyruleno].nrhs;
+ yypParser->yyidx -= yysize;
+ yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
+ if( yyact < YYNSTATE ){
+#ifdef NDEBUG
+ /* If we are not debugging and the reduce action popped at least
+ ** one element off the stack, then we can push the new element back
+ ** onto the stack here, and skip the stack overflow test in yy_shift().
+ ** That gives a significant speed improvement. */
+ if( yysize ){
+ yypParser->yyidx++;
+ yymsp -= yysize-1;
+ yymsp->stateno = (YYACTIONTYPE)yyact;
+ yymsp->major = (YYCODETYPE)yygoto;
+ yymsp->minor = yygotominor;
+ }else
+#endif
+ {
+ yy_shift(yypParser,yyact,yygoto,&yygotominor);
+ }
+ }else{
+ assert( yyact == YYNSTATE + YYNRULE + 1 );
+ yy_accept(yypParser);
+ }
+}
+
+/*
+** The following code executes when the parse fails
+*/
+#ifndef YYNOERRORRECOVERY
+static void yy_parse_failed(
+ yyParser *yypParser /* The parser */
+){
+ sqlite3ParserARG_FETCH;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
+ }
+#endif
+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+ /* Here code is inserted which will be executed whenever the
+ ** parser fails */
+ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+#endif /* YYNOERRORRECOVERY */
+
+/*
+** The following code executes when a syntax error first occurs.
+*/
+static void yy_syntax_error(
+ yyParser *yypParser, /* The parser */
+ int yymajor, /* The major type of the error token */
+ YYMINORTYPE yyminor /* The minor type of the error token */
+){
+ sqlite3ParserARG_FETCH;
+#define TOKEN (yyminor.yy0)
+
+ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
+ assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */
+ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
+ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/*
+** The following is executed when the parser accepts
+*/
+static void yy_accept(
+ yyParser *yypParser /* The parser */
+){
+ sqlite3ParserARG_FETCH;
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
+ }
+#endif
+ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
+ /* Here code is inserted which will be executed whenever the
+ ** parser accepts */
+ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
+}
+
+/* The main parser program.
+** The first argument is a pointer to a structure obtained from
+** "sqlite3ParserAlloc" which describes the current state of the parser.
+** The second argument is the major token number. The third is
+** the minor token. The fourth optional argument is whatever the
+** user wants (and specified in the grammar) and is available for
+** use by the action routines.
+**
+** Inputs:
+** <ul>
+** <li> A pointer to the parser (an opaque structure.)
+** <li> The major token number.
+** <li> The minor token number.
+** <li> An option argument of a grammar-specified type.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+SQLITE_PRIVATE void sqlite3Parser(
+ void *yyp, /* The parser */
+ int yymajor, /* The major token code number */
+ sqlite3ParserTOKENTYPE yyminor /* The value for the token */
+ sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */
+){
+ YYMINORTYPE yyminorunion;
+ int yyact; /* The parser action. */
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
+ int yyendofinput; /* True if we are at the end of input */
+#endif
+#ifdef YYERRORSYMBOL
+ int yyerrorhit = 0; /* True if yymajor has invoked an error */
+#endif
+ yyParser *yypParser; /* The parser */
+
+ /* (re)initialize the parser, if necessary */
+ yypParser = (yyParser*)yyp;
+ if( yypParser->yyidx<0 ){
+#if YYSTACKDEPTH<=0
+ if( yypParser->yystksz <=0 ){
+ /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
+ yyminorunion = yyzerominor;
+ yyStackOverflow(yypParser, &yyminorunion);
+ return;
+ }
+#endif
+ yypParser->yyidx = 0;
+ yypParser->yyerrcnt = -1;
+ yypParser->yystack[0].stateno = 0;
+ yypParser->yystack[0].major = 0;
+ }
+ yyminorunion.yy0 = yyminor;
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
+ yyendofinput = (yymajor==0);
+#endif
+ sqlite3ParserARG_STORE;
+
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
+ }
+#endif
+
+ do{
+ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
+ if( yyact<YYNSTATE ){
+ yy_shift(yypParser,yyact,yymajor,&yyminorunion);
+ yypParser->yyerrcnt--;
+ yymajor = YYNOCODE;
+ }else if( yyact < YYNSTATE + YYNRULE ){
+ yy_reduce(yypParser,yyact-YYNSTATE);
+ }else{
+ assert( yyact == YY_ERROR_ACTION );
+#ifdef YYERRORSYMBOL
+ int yymx;
+#endif
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
+ }
+#endif
+#ifdef YYERRORSYMBOL
+ /* A syntax error has occurred.
+ ** The response to an error depends upon whether or not the
+ ** grammar defines an error token "ERROR".
+ **
+ ** This is what we do if the grammar does define ERROR:
+ **
+ ** * Call the %syntax_error function.
+ **
+ ** * Begin popping the stack until we enter a state where
+ ** it is legal to shift the error symbol, then shift
+ ** the error symbol.
+ **
+ ** * Set the error count to three.
+ **
+ ** * Begin accepting and shifting new tokens. No new error
+ ** processing will occur until three tokens have been
+ ** shifted successfully.
+ **
+ */
+ if( yypParser->yyerrcnt<0 ){
+ yy_syntax_error(yypParser,yymajor,yyminorunion);
+ }
+ yymx = yypParser->yystack[yypParser->yyidx].major;
+ if( yymx==YYERRORSYMBOL || yyerrorhit ){
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sDiscard input token %s\n",
+ yyTracePrompt,yyTokenName[yymajor]);
+ }
+#endif
+ yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
+ yymajor = YYNOCODE;
+ }else{
+ while(
+ yypParser->yyidx >= 0 &&
+ yymx != YYERRORSYMBOL &&
+ (yyact = yy_find_reduce_action(
+ yypParser->yystack[yypParser->yyidx].stateno,
+ YYERRORSYMBOL)) >= YYNSTATE
+ ){
+ yy_pop_parser_stack(yypParser);
+ }
+ if( yypParser->yyidx < 0 || yymajor==0 ){
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+ yy_parse_failed(yypParser);
+ yymajor = YYNOCODE;
+ }else if( yymx!=YYERRORSYMBOL ){
+ YYMINORTYPE u2;
+ u2.YYERRSYMDT = 0;
+ yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
+ }
+ }
+ yypParser->yyerrcnt = 3;
+ yyerrorhit = 1;
+#elif defined(YYNOERRORRECOVERY)
+ /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
+ ** do any kind of error recovery. Instead, simply invoke the syntax
+ ** error routine and continue going as if nothing had happened.
+ **
+ ** Applications can set this macro (for example inside %include) if
+ ** they intend to abandon the parse upon the first syntax error seen.
+ */
+ yy_syntax_error(yypParser,yymajor,yyminorunion);
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+ yymajor = YYNOCODE;
+
+#else /* YYERRORSYMBOL is not defined */
+ /* This is what we do if the grammar does not define ERROR:
+ **
+ ** * Report an error message, and throw away the input token.
+ **
+ ** * If the input token is $, then fail the parse.
+ **
+ ** As before, subsequent error messages are suppressed until
+ ** three input tokens have been successfully shifted.
+ */
+ if( yypParser->yyerrcnt<=0 ){
+ yy_syntax_error(yypParser,yymajor,yyminorunion);
+ }
+ yypParser->yyerrcnt = 3;
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+ if( yyendofinput ){
+ yy_parse_failed(yypParser);
+ }
+ yymajor = YYNOCODE;
+#endif
+ }
+ }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
+ return;
+}
+
+/************** End of parse.c ***********************************************/
+/************** Begin file tokenize.c ****************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** An tokenizer for SQL
+**
+** This file contains C code that splits an SQL input string up into
+** individual tokens and sends those tokens one-by-one over to the
+** parser for analysis.
+*/
+/* #include <stdlib.h> */
+
+/*
+** The charMap() macro maps alphabetic characters into their
+** lower-case ASCII equivalent. On ASCII machines, this is just
+** an upper-to-lower case map. On EBCDIC machines we also need
+** to adjust the encoding. Only alphabetic characters and underscores
+** need to be translated.
+*/
+#ifdef SQLITE_ASCII
+# define charMap(X) sqlite3UpperToLower[(unsigned char)X]
+#endif
+#ifdef SQLITE_EBCDIC
+# define charMap(X) ebcdicToAscii[(unsigned char)X]
+const unsigned char ebcdicToAscii[] = {
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */
+ 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */
+ 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
+ 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */
+ 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */
+ 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */
+};
+#endif
+
+/*
+** The sqlite3KeywordCode function looks up an identifier to determine if
+** it is a keyword. If it is a keyword, the token code of that keyword is
+** returned. If the input is not a keyword, TK_ID is returned.
+**
+** The implementation of this routine was generated by a program,
+** mkkeywordhash.h, located in the tool subdirectory of the distribution.
+** The output of the mkkeywordhash.c program is written into a file
+** named keywordhash.h and then included into this source file by
+** the #include below.
+*/
+/************** Include keywordhash.h in the middle of tokenize.c ************/
+/************** Begin file keywordhash.h *************************************/
+/***** This file contains automatically generated code ******
+**
+** The code in this file has been automatically generated by
+**
+** sqlite/tool/mkkeywordhash.c
+**
+** The code in this file implements a function that determines whether
+** or not a given identifier is really an SQL keyword. The same thing
+** might be implemented more directly using a hand-written hash table.
+** But by using this automatically generated code, the size of the code
+** is substantially reduced. This is important for embedded applications
+** on platforms with limited memory.
+*/
+/* Hash score: 175 */
+static int keywordCode(const char *z, int n){
+ /* zText[] encodes 811 bytes of keywords in 541 bytes */
+ /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
+ /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
+ /* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */
+ /* UNIQUERYATTACHAVINGROUPDATEBEGINNERELEASEBETWEENOTNULLIKE */
+ /* CASCADELETECASECOLLATECREATECURRENT_DATEDETACHIMMEDIATEJOIN */
+ /* SERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHENWHERENAME */
+ /* AFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
+ /* CURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOBYIF */
+ /* ISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUMVIEW */
+ /* INITIALLY */
+ static const char zText[540] = {
+ 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
+ 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
+ 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
+ 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
+ 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N',
+ 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I',
+ 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E',
+ 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
+ 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
+ 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
+ 'U','E','R','Y','A','T','T','A','C','H','A','V','I','N','G','R','O','U',
+ 'P','D','A','T','E','B','E','G','I','N','N','E','R','E','L','E','A','S',
+ 'E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C',
+ 'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L',
+ 'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D',
+ 'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E',
+ 'J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A',
+ 'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U',
+ 'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W',
+ 'H','E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C',
+ 'E','A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R',
+ 'E','M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M',
+ 'M','I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U',
+ 'R','R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M',
+ 'A','R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T',
+ 'D','R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L',
+ 'O','B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S',
+ 'T','R','I','C','T','O','U','T','E','R','I','G','H','T','R','O','L','L',
+ 'B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N','G','V',
+ 'A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L','L','Y',
+ };
+ static const unsigned char aHash[127] = {
+ 72, 101, 114, 70, 0, 45, 0, 0, 78, 0, 73, 0, 0,
+ 42, 12, 74, 15, 0, 113, 81, 50, 108, 0, 19, 0, 0,
+ 118, 0, 116, 111, 0, 22, 89, 0, 9, 0, 0, 66, 67,
+ 0, 65, 6, 0, 48, 86, 98, 0, 115, 97, 0, 0, 44,
+ 0, 99, 24, 0, 17, 0, 119, 49, 23, 0, 5, 106, 25,
+ 92, 0, 0, 121, 102, 56, 120, 53, 28, 51, 0, 87, 0,
+ 96, 26, 0, 95, 0, 0, 0, 91, 88, 93, 84, 105, 14,
+ 39, 104, 0, 77, 0, 18, 85, 107, 32, 0, 117, 76, 109,
+ 58, 46, 80, 0, 0, 90, 40, 0, 112, 0, 36, 0, 0,
+ 29, 0, 82, 59, 60, 0, 20, 57, 0, 52,
+ };
+ static const unsigned char aNext[121] = {
+ 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
+ 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 43, 3, 47,
+ 0, 0, 0, 0, 30, 0, 54, 0, 38, 0, 0, 0, 1,
+ 62, 0, 0, 63, 0, 41, 0, 0, 0, 0, 0, 0, 0,
+ 61, 0, 0, 0, 0, 31, 55, 16, 34, 10, 0, 0, 0,
+ 0, 0, 0, 0, 11, 68, 75, 0, 8, 0, 100, 94, 0,
+ 103, 0, 83, 0, 71, 0, 0, 110, 27, 37, 69, 79, 0,
+ 35, 64, 0, 0,
+ };
+ static const unsigned char aLen[121] = {
+ 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
+ 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
+ 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10,
+ 4, 6, 2, 3, 9, 4, 2, 6, 5, 6, 6, 5, 6,
+ 5, 5, 7, 7, 7, 3, 2, 4, 4, 7, 3, 6, 4,
+ 7, 6, 12, 6, 9, 4, 6, 5, 4, 7, 6, 5, 6,
+ 7, 5, 4, 5, 6, 5, 7, 3, 7, 13, 2, 2, 4,
+ 6, 6, 8, 5, 17, 12, 7, 8, 8, 2, 4, 4, 4,
+ 4, 4, 2, 2, 6, 5, 8, 5, 5, 8, 3, 5, 5,
+ 6, 4, 9, 3,
+ };
+ static const unsigned short int aOffset[121] = {
+ 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
+ 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
+ 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152,
+ 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 189, 194, 197,
+ 203, 206, 210, 217, 223, 223, 223, 226, 229, 233, 234, 238, 244,
+ 248, 255, 261, 273, 279, 288, 290, 296, 301, 303, 310, 315, 320,
+ 326, 332, 337, 341, 344, 350, 354, 361, 363, 370, 372, 374, 383,
+ 387, 393, 399, 407, 412, 412, 428, 435, 442, 443, 450, 454, 458,
+ 462, 466, 469, 471, 473, 479, 483, 491, 495, 500, 508, 511, 516,
+ 521, 527, 531, 536,
+ };
+ static const unsigned char aCode[121] = {
+ TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
+ TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
+ TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
+ TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
+ TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
+ TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
+ TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
+ TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
+ TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
+ TK_OR, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING,
+ TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE,
+ TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL,
+ TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE,
+ TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE,
+ TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE,
+ TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT,
+ TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE,
+ TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN,
+ TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
+ TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT,
+ TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW,
+ TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER,
+ TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
+ TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
+ TK_ALL,
+ };
+ int h, i;
+ if( n<2 ) return TK_ID;
+ h = ((charMap(z[0])*4) ^
+ (charMap(z[n-1])*3) ^
+ n) % 127;
+ for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
+ if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){
+ testcase( i==0 ); /* REINDEX */
+ testcase( i==1 ); /* INDEXED */
+ testcase( i==2 ); /* INDEX */
+ testcase( i==3 ); /* DESC */
+ testcase( i==4 ); /* ESCAPE */
+ testcase( i==5 ); /* EACH */
+ testcase( i==6 ); /* CHECK */
+ testcase( i==7 ); /* KEY */
+ testcase( i==8 ); /* BEFORE */
+ testcase( i==9 ); /* FOREIGN */
+ testcase( i==10 ); /* FOR */
+ testcase( i==11 ); /* IGNORE */
+ testcase( i==12 ); /* REGEXP */
+ testcase( i==13 ); /* EXPLAIN */
+ testcase( i==14 ); /* INSTEAD */
+ testcase( i==15 ); /* ADD */
+ testcase( i==16 ); /* DATABASE */
+ testcase( i==17 ); /* AS */
+ testcase( i==18 ); /* SELECT */
+ testcase( i==19 ); /* TABLE */
+ testcase( i==20 ); /* LEFT */
+ testcase( i==21 ); /* THEN */
+ testcase( i==22 ); /* END */
+ testcase( i==23 ); /* DEFERRABLE */
+ testcase( i==24 ); /* ELSE */
+ testcase( i==25 ); /* EXCEPT */
+ testcase( i==26 ); /* TRANSACTION */
+ testcase( i==27 ); /* ACTION */
+ testcase( i==28 ); /* ON */
+ testcase( i==29 ); /* NATURAL */
+ testcase( i==30 ); /* ALTER */
+ testcase( i==31 ); /* RAISE */
+ testcase( i==32 ); /* EXCLUSIVE */
+ testcase( i==33 ); /* EXISTS */
+ testcase( i==34 ); /* SAVEPOINT */
+ testcase( i==35 ); /* INTERSECT */
+ testcase( i==36 ); /* TRIGGER */
+ testcase( i==37 ); /* REFERENCES */
+ testcase( i==38 ); /* CONSTRAINT */
+ testcase( i==39 ); /* INTO */
+ testcase( i==40 ); /* OFFSET */
+ testcase( i==41 ); /* OF */
+ testcase( i==42 ); /* SET */
+ testcase( i==43 ); /* TEMPORARY */
+ testcase( i==44 ); /* TEMP */
+ testcase( i==45 ); /* OR */
+ testcase( i==46 ); /* UNIQUE */
+ testcase( i==47 ); /* QUERY */
+ testcase( i==48 ); /* ATTACH */
+ testcase( i==49 ); /* HAVING */
+ testcase( i==50 ); /* GROUP */
+ testcase( i==51 ); /* UPDATE */
+ testcase( i==52 ); /* BEGIN */
+ testcase( i==53 ); /* INNER */
+ testcase( i==54 ); /* RELEASE */
+ testcase( i==55 ); /* BETWEEN */
+ testcase( i==56 ); /* NOTNULL */
+ testcase( i==57 ); /* NOT */
+ testcase( i==58 ); /* NO */
+ testcase( i==59 ); /* NULL */
+ testcase( i==60 ); /* LIKE */
+ testcase( i==61 ); /* CASCADE */
+ testcase( i==62 ); /* ASC */
+ testcase( i==63 ); /* DELETE */
+ testcase( i==64 ); /* CASE */
+ testcase( i==65 ); /* COLLATE */
+ testcase( i==66 ); /* CREATE */
+ testcase( i==67 ); /* CURRENT_DATE */
+ testcase( i==68 ); /* DETACH */
+ testcase( i==69 ); /* IMMEDIATE */
+ testcase( i==70 ); /* JOIN */
+ testcase( i==71 ); /* INSERT */
+ testcase( i==72 ); /* MATCH */
+ testcase( i==73 ); /* PLAN */
+ testcase( i==74 ); /* ANALYZE */
+ testcase( i==75 ); /* PRAGMA */
+ testcase( i==76 ); /* ABORT */
+ testcase( i==77 ); /* VALUES */
+ testcase( i==78 ); /* VIRTUAL */
+ testcase( i==79 ); /* LIMIT */
+ testcase( i==80 ); /* WHEN */
+ testcase( i==81 ); /* WHERE */
+ testcase( i==82 ); /* RENAME */
+ testcase( i==83 ); /* AFTER */
+ testcase( i==84 ); /* REPLACE */
+ testcase( i==85 ); /* AND */
+ testcase( i==86 ); /* DEFAULT */
+ testcase( i==87 ); /* AUTOINCREMENT */
+ testcase( i==88 ); /* TO */
+ testcase( i==89 ); /* IN */
+ testcase( i==90 ); /* CAST */
+ testcase( i==91 ); /* COLUMN */
+ testcase( i==92 ); /* COMMIT */
+ testcase( i==93 ); /* CONFLICT */
+ testcase( i==94 ); /* CROSS */
+ testcase( i==95 ); /* CURRENT_TIMESTAMP */
+ testcase( i==96 ); /* CURRENT_TIME */
+ testcase( i==97 ); /* PRIMARY */
+ testcase( i==98 ); /* DEFERRED */
+ testcase( i==99 ); /* DISTINCT */
+ testcase( i==100 ); /* IS */
+ testcase( i==101 ); /* DROP */
+ testcase( i==102 ); /* FAIL */
+ testcase( i==103 ); /* FROM */
+ testcase( i==104 ); /* FULL */
+ testcase( i==105 ); /* GLOB */
+ testcase( i==106 ); /* BY */
+ testcase( i==107 ); /* IF */
+ testcase( i==108 ); /* ISNULL */
+ testcase( i==109 ); /* ORDER */
+ testcase( i==110 ); /* RESTRICT */
+ testcase( i==111 ); /* OUTER */
+ testcase( i==112 ); /* RIGHT */
+ testcase( i==113 ); /* ROLLBACK */
+ testcase( i==114 ); /* ROW */
+ testcase( i==115 ); /* UNION */
+ testcase( i==116 ); /* USING */
+ testcase( i==117 ); /* VACUUM */
+ testcase( i==118 ); /* VIEW */
+ testcase( i==119 ); /* INITIALLY */
+ testcase( i==120 ); /* ALL */
+ return aCode[i];
+ }
+ }
+ return TK_ID;
+}
+SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){
+ return keywordCode((char*)z, n);
+}
+#define SQLITE_N_KEYWORD 121
+
+/************** End of keywordhash.h *****************************************/
+/************** Continuing where we left off in tokenize.c *******************/
+
+
+/*
+** If X is a character that can be used in an identifier then
+** IdChar(X) will be true. Otherwise it is false.
+**
+** For ASCII, any character with the high-order bit set is
+** allowed in an identifier. For 7-bit characters,
+** sqlite3IsIdChar[X] must be 1.
+**
+** For EBCDIC, the rules are more complex but have the same
+** end result.
+**
+** Ticket #1066. the SQL standard does not allow '$' in the
+** middle of identfiers. But many SQL implementations do.
+** SQLite will allow '$' in identifiers for compatibility.
+** But the feature is undocumented.
+*/
+#ifdef SQLITE_ASCII
+#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
+#endif
+#ifdef SQLITE_EBCDIC
+SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[] = {
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */
+};
+#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
+#endif
+
+
+/*
+** Return the length of the token that begins at z[0].
+** Store the token type in *tokenType before returning.
+*/
+SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
+ int i, c;
+ switch( *z ){
+ case ' ': case '\t': case '\n': case '\f': case '\r': {
+ testcase( z[0]==' ' );
+ testcase( z[0]=='\t' );
+ testcase( z[0]=='\n' );
+ testcase( z[0]=='\f' );
+ testcase( z[0]=='\r' );
+ for(i=1; sqlite3Isspace(z[i]); i++){}
+ *tokenType = TK_SPACE;
+ return i;
+ }
+ case '-': {
+ if( z[1]=='-' ){
+ /* IMP: R-50417-27976 -- syntax diagram for comments */
+ for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
+ *tokenType = TK_SPACE; /* IMP: R-22934-25134 */
+ return i;
+ }
+ *tokenType = TK_MINUS;
+ return 1;
+ }
+ case '(': {
+ *tokenType = TK_LP;
+ return 1;
+ }
+ case ')': {
+ *tokenType = TK_RP;
+ return 1;
+ }
+ case ';': {
+ *tokenType = TK_SEMI;
+ return 1;
+ }
+ case '+': {
+ *tokenType = TK_PLUS;
+ return 1;
+ }
+ case '*': {
+ *tokenType = TK_STAR;
+ return 1;
+ }
+ case '/': {
+ if( z[1]!='*' || z[2]==0 ){
+ *tokenType = TK_SLASH;
+ return 1;
+ }
+ /* IMP: R-50417-27976 -- syntax diagram for comments */
+ for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
+ if( c ) i++;
+ *tokenType = TK_SPACE; /* IMP: R-22934-25134 */
+ return i;
+ }
+ case '%': {
+ *tokenType = TK_REM;
+ return 1;
+ }
+ case '=': {
+ *tokenType = TK_EQ;
+ return 1 + (z[1]=='=');
+ }
+ case '<': {
+ if( (c=z[1])=='=' ){
+ *tokenType = TK_LE;
+ return 2;
+ }else if( c=='>' ){
+ *tokenType = TK_NE;
+ return 2;
+ }else if( c=='<' ){
+ *tokenType = TK_LSHIFT;
+ return 2;
+ }else{
+ *tokenType = TK_LT;
+ return 1;
+ }
+ }
+ case '>': {
+ if( (c=z[1])=='=' ){
+ *tokenType = TK_GE;
+ return 2;
+ }else if( c=='>' ){
+ *tokenType = TK_RSHIFT;
+ return 2;
+ }else{
+ *tokenType = TK_GT;
+ return 1;
+ }
+ }
+ case '!': {
+ if( z[1]!='=' ){
+ *tokenType = TK_ILLEGAL;
+ return 2;
+ }else{
+ *tokenType = TK_NE;
+ return 2;
+ }
+ }
+ case '|': {
+ if( z[1]!='|' ){
+ *tokenType = TK_BITOR;
+ return 1;
+ }else{
+ *tokenType = TK_CONCAT;
+ return 2;
+ }
+ }
+ case ',': {
+ *tokenType = TK_COMMA;
+ return 1;
+ }
+ case '&': {
+ *tokenType = TK_BITAND;
+ return 1;
+ }
+ case '~': {
+ *tokenType = TK_BITNOT;
+ return 1;
+ }
+ case '`':
+ case '\'':
+ case '"': {
+ int delim = z[0];
+ testcase( delim=='`' );
+ testcase( delim=='\'' );
+ testcase( delim=='"' );
+ for(i=1; (c=z[i])!=0; i++){
+ if( c==delim ){
+ if( z[i+1]==delim ){
+ i++;
+ }else{
+ break;
+ }
+ }
+ }
+ if( c=='\'' ){
+ *tokenType = TK_STRING;
+ return i+1;
+ }else if( c!=0 ){
+ *tokenType = TK_ID;
+ return i+1;
+ }else{
+ *tokenType = TK_ILLEGAL;
+ return i;
+ }
+ }
+ case '.': {
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ if( !sqlite3Isdigit(z[1]) )
+#endif
+ {
+ *tokenType = TK_DOT;
+ return 1;
+ }
+ /* If the next character is a digit, this is a floating point
+ ** number that begins with ".". Fall thru into the next case */
+ }
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9': {
+ testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
+ testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
+ testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
+ testcase( z[0]=='9' );
+ *tokenType = TK_INTEGER;
+ for(i=0; sqlite3Isdigit(z[i]); i++){}
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ if( z[i]=='.' ){
+ i++;
+ while( sqlite3Isdigit(z[i]) ){ i++; }
+ *tokenType = TK_FLOAT;
+ }
+ if( (z[i]=='e' || z[i]=='E') &&
+ ( sqlite3Isdigit(z[i+1])
+ || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
+ )
+ ){
+ i += 2;
+ while( sqlite3Isdigit(z[i]) ){ i++; }
+ *tokenType = TK_FLOAT;
+ }
+#endif
+ while( IdChar(z[i]) ){
+ *tokenType = TK_ILLEGAL;
+ i++;
+ }
+ return i;
+ }
+ case '[': {
+ for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
+ *tokenType = c==']' ? TK_ID : TK_ILLEGAL;
+ return i;
+ }
+ case '?': {
+ *tokenType = TK_VARIABLE;
+ for(i=1; sqlite3Isdigit(z[i]); i++){}
+ return i;
+ }
+ case '#': {
+ for(i=1; sqlite3Isdigit(z[i]); i++){}
+ if( i>1 ){
+ /* Parameters of the form #NNN (where NNN is a number) are used
+ ** internally by sqlite3NestedParse. */
+ *tokenType = TK_REGISTER;
+ return i;
+ }
+ /* Fall through into the next case if the '#' is not followed by
+ ** a digit. Try to match #AAAA where AAAA is a parameter name. */
+ }
+#ifndef SQLITE_OMIT_TCL_VARIABLE
+ case '$':
+#endif
+ case '@': /* For compatibility with MS SQL Server */
+ case ':': {
+ int n = 0;
+ testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' );
+ *tokenType = TK_VARIABLE;
+ for(i=1; (c=z[i])!=0; i++){
+ if( IdChar(c) ){
+ n++;
+#ifndef SQLITE_OMIT_TCL_VARIABLE
+ }else if( c=='(' && n>0 ){
+ do{
+ i++;
+ }while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' );
+ if( c==')' ){
+ i++;
+ }else{
+ *tokenType = TK_ILLEGAL;
+ }
+ break;
+ }else if( c==':' && z[i+1]==':' ){
+ i++;
+#endif
+ }else{
+ break;
+ }
+ }
+ if( n==0 ) *tokenType = TK_ILLEGAL;
+ return i;
+ }
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+ case 'x': case 'X': {
+ testcase( z[0]=='x' ); testcase( z[0]=='X' );
+ if( z[1]=='\'' ){
+ *tokenType = TK_BLOB;
+ for(i=2; sqlite3Isxdigit(z[i]); i++){}
+ if( z[i]!='\'' || i%2 ){
+ *tokenType = TK_ILLEGAL;
+ while( z[i] && z[i]!='\'' ){ i++; }
+ }
+ if( z[i] ) i++;
+ return i;
+ }
+ /* Otherwise fall through to the next case */
+ }
+#endif
+ default: {
+ if( !IdChar(*z) ){
+ break;
+ }
+ for(i=1; IdChar(z[i]); i++){}
+ *tokenType = keywordCode((char*)z, i);
+ return i;
+ }
+ }
+ *tokenType = TK_ILLEGAL;
+ return 1;
+}
+
+/*
+** Run the parser on the given SQL string. The parser structure is
+** passed in. An SQLITE_ status code is returned. If an error occurs
+** then an and attempt is made to write an error message into
+** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that
+** error message.
+*/
+SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
+ int nErr = 0; /* Number of errors encountered */
+ int i; /* Loop counter */
+ void *pEngine; /* The LEMON-generated LALR(1) parser */
+ int tokenType; /* type of the next token */
+ int lastTokenParsed = -1; /* type of the previous token */
+ u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */
+ sqlite3 *db = pParse->db; /* The database connection */
+ int mxSqlLen; /* Max length of an SQL string */
+
+
+ mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
+ if( db->activeVdbeCnt==0 ){
+ db->u1.isInterrupted = 0;
+ }
+ pParse->rc = SQLITE_OK;
+ pParse->zTail = zSql;
+ i = 0;
+ assert( pzErrMsg!=0 );
+ pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc);
+ if( pEngine==0 ){
+ db->mallocFailed = 1;
+ return SQLITE_NOMEM;
+ }
+ assert( pParse->pNewTable==0 );
+ assert( pParse->pNewTrigger==0 );
+ assert( pParse->nVar==0 );
+ assert( pParse->nzVar==0 );
+ assert( pParse->azVar==0 );
+ enableLookaside = db->lookaside.bEnabled;
+ if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
+ while( !db->mallocFailed && zSql[i]!=0 ){
+ assert( i>=0 );
+ pParse->sLastToken.z = &zSql[i];
+ pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
+ i += pParse->sLastToken.n;
+ if( i>mxSqlLen ){
+ pParse->rc = SQLITE_TOOBIG;
+ break;
+ }
+ switch( tokenType ){
+ case TK_SPACE: {
+ if( db->u1.isInterrupted ){
+ sqlite3ErrorMsg(pParse, "interrupt");
+ pParse->rc = SQLITE_INTERRUPT;
+ goto abort_parse;
+ }
+ break;
+ }
+ case TK_ILLEGAL: {
+ sqlite3DbFree(db, *pzErrMsg);
+ *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"",
+ &pParse->sLastToken);
+ nErr++;
+ goto abort_parse;
+ }
+ case TK_SEMI: {
+ pParse->zTail = &zSql[i];
+ /* Fall thru into the default case */
+ }
+ default: {
+ sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
+ lastTokenParsed = tokenType;
+ if( pParse->rc!=SQLITE_OK ){
+ goto abort_parse;
+ }
+ break;
+ }
+ }
+ }
+abort_parse:
+ if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
+ if( lastTokenParsed!=TK_SEMI ){
+ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
+ pParse->zTail = &zSql[i];
+ }
+ sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
+ }
+#ifdef YYTRACKMAXSTACKDEPTH
+ sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK,
+ sqlite3ParserStackPeak(pEngine)
+ );
+#endif /* YYDEBUG */
+ sqlite3ParserFree(pEngine, sqlite3_free);
+ db->lookaside.bEnabled = enableLookaside;
+ if( db->mallocFailed ){
+ pParse->rc = SQLITE_NOMEM;
+ }
+ if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
+ sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc));
+ }
+ assert( pzErrMsg!=0 );
+ if( pParse->zErrMsg ){
+ *pzErrMsg = pParse->zErrMsg;
+ sqlite3_log(pParse->rc, "%s", *pzErrMsg);
+ pParse->zErrMsg = 0;
+ nErr++;
+ }
+ if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
+ sqlite3VdbeDelete(pParse->pVdbe);
+ pParse->pVdbe = 0;
+ }
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ if( pParse->nested==0 ){
+ sqlite3DbFree(db, pParse->aTableLock);
+ pParse->aTableLock = 0;
+ pParse->nTableLock = 0;
+ }
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3_free(pParse->apVtabLock);
+#endif
+
+ if( !IN_DECLARE_VTAB ){
+ /* If the pParse->declareVtab flag is set, do not delete any table
+ ** structure built up in pParse->pNewTable. The calling code (see vtab.c)
+ ** will take responsibility for freeing the Table structure.
+ */
+ sqlite3DeleteTable(db, pParse->pNewTable);
+ }
+
+ sqlite3DeleteTrigger(db, pParse->pNewTrigger);
+ for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
+ sqlite3DbFree(db, pParse->azVar);
+ sqlite3DbFree(db, pParse->aAlias);
+ while( pParse->pAinc ){
+ AutoincInfo *p = pParse->pAinc;
+ pParse->pAinc = p->pNext;
+ sqlite3DbFree(db, p);
+ }
+ while( pParse->pZombieTab ){
+ Table *p = pParse->pZombieTab;
+ pParse->pZombieTab = p->pNextZombie;
+ sqlite3DeleteTable(db, p);
+ }
+ if( nErr>0 && pParse->rc==SQLITE_OK ){
+ pParse->rc = SQLITE_ERROR;
+ }
+ return nErr;
+}
+
+/************** End of tokenize.c ********************************************/
+/************** Begin file complete.c ****************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** An tokenizer for SQL
+**
+** This file contains C code that implements the sqlite3_complete() API.
+** This code used to be part of the tokenizer.c source file. But by
+** separating it out, the code will be automatically omitted from
+** static links that do not use it.
+*/
+#ifndef SQLITE_OMIT_COMPLETE
+
+/*
+** This is defined in tokenize.c. We just have to import the definition.
+*/
+#ifndef SQLITE_AMALGAMATION
+#ifdef SQLITE_ASCII
+#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
+#endif
+#ifdef SQLITE_EBCDIC
+SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[];
+#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
+#endif
+#endif /* SQLITE_AMALGAMATION */
+
+
+/*
+** Token types used by the sqlite3_complete() routine. See the header
+** comments on that procedure for additional information.
+*/
+#define tkSEMI 0
+#define tkWS 1
+#define tkOTHER 2
+#ifndef SQLITE_OMIT_TRIGGER
+#define tkEXPLAIN 3
+#define tkCREATE 4
+#define tkTEMP 5
+#define tkTRIGGER 6
+#define tkEND 7
+#endif
+
+/*
+** Return TRUE if the given SQL string ends in a semicolon.
+**
+** Special handling is require for CREATE TRIGGER statements.
+** Whenever the CREATE TRIGGER keywords are seen, the statement
+** must end with ";END;".
+**
+** This implementation uses a state machine with 8 states:
+**
+** (0) INVALID We have not yet seen a non-whitespace character.
+**
+** (1) START At the beginning or end of an SQL statement. This routine
+** returns 1 if it ends in the START state and 0 if it ends
+** in any other state.
+**
+** (2) NORMAL We are in the middle of statement which ends with a single
+** semicolon.
+**
+** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
+** a statement.
+**
+** (4) CREATE The keyword CREATE has been seen at the beginning of a
+** statement, possibly preceeded by EXPLAIN and/or followed by
+** TEMP or TEMPORARY
+**
+** (5) TRIGGER We are in the middle of a trigger definition that must be
+** ended by a semicolon, the keyword END, and another semicolon.
+**
+** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at
+** the end of a trigger definition.
+**
+** (7) END We've seen the ";END" of the ";END;" that occurs at the end
+** of a trigger difinition.
+**
+** Transitions between states above are determined by tokens extracted
+** from the input. The following tokens are significant:
+**
+** (0) tkSEMI A semicolon.
+** (1) tkWS Whitespace.
+** (2) tkOTHER Any other SQL token.
+** (3) tkEXPLAIN The "explain" keyword.
+** (4) tkCREATE The "create" keyword.
+** (5) tkTEMP The "temp" or "temporary" keyword.
+** (6) tkTRIGGER The "trigger" keyword.
+** (7) tkEND The "end" keyword.
+**
+** Whitespace never causes a state transition and is always ignored.
+** This means that a SQL string of all whitespace is invalid.
+**
+** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
+** to recognize the end of a trigger can be omitted. All we have to do
+** is look for a semicolon that is not part of an string or comment.
+*/
+SQLITE_API int sqlite3_complete(const char *zSql){
+ u8 state = 0; /* Current state, using numbers defined in header comment */
+ u8 token; /* Value of the next token */
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* A complex statement machine used to detect the end of a CREATE TRIGGER
+ ** statement. This is the normal case.
+ */
+ static const u8 trans[8][8] = {
+ /* Token: */
+ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
+ /* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
+ /* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, },
+ /* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, },
+ /* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, },
+ /* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, },
+ /* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, },
+ /* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, },
+ /* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, },
+ };
+#else
+ /* If triggers are not supported by this compile then the statement machine
+ ** used to detect the end of a statement is much simplier
+ */
+ static const u8 trans[3][3] = {
+ /* Token: */
+ /* State: ** SEMI WS OTHER */
+ /* 0 INVALID: */ { 1, 0, 2, },
+ /* 1 START: */ { 1, 1, 2, },
+ /* 2 NORMAL: */ { 1, 2, 2, },
+ };
+#endif /* SQLITE_OMIT_TRIGGER */
+
+ while( *zSql ){
+ switch( *zSql ){
+ case ';': { /* A semicolon */
+ token = tkSEMI;
+ break;
+ }
+ case ' ':
+ case '\r':
+ case '\t':
+ case '\n':
+ case '\f': { /* White space is ignored */
+ token = tkWS;
+ break;
+ }
+ case '/': { /* C-style comments */
+ if( zSql[1]!='*' ){
+ token = tkOTHER;
+ break;
+ }
+ zSql += 2;
+ while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
+ if( zSql[0]==0 ) return 0;
+ zSql++;
+ token = tkWS;
+ break;
+ }
+ case '-': { /* SQL-style comments from "--" to end of line */
+ if( zSql[1]!='-' ){
+ token = tkOTHER;
+ break;
+ }
+ while( *zSql && *zSql!='\n' ){ zSql++; }
+ if( *zSql==0 ) return state==1;
+ token = tkWS;
+ break;
+ }
+ case '[': { /* Microsoft-style identifiers in [...] */
+ zSql++;
+ while( *zSql && *zSql!=']' ){ zSql++; }
+ if( *zSql==0 ) return 0;
+ token = tkOTHER;
+ break;
+ }
+ case '`': /* Grave-accent quoted symbols used by MySQL */
+ case '"': /* single- and double-quoted strings */
+ case '\'': {
+ int c = *zSql;
+ zSql++;
+ while( *zSql && *zSql!=c ){ zSql++; }
+ if( *zSql==0 ) return 0;
+ token = tkOTHER;
+ break;
+ }
+ default: {
+#ifdef SQLITE_EBCDIC
+ unsigned char c;
+#endif
+ if( IdChar((u8)*zSql) ){
+ /* Keywords and unquoted identifiers */
+ int nId;
+ for(nId=1; IdChar(zSql[nId]); nId++){}
+#ifdef SQLITE_OMIT_TRIGGER
+ token = tkOTHER;
+#else
+ switch( *zSql ){
+ case 'c': case 'C': {
+ if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
+ token = tkCREATE;
+ }else{
+ token = tkOTHER;
+ }
+ break;
+ }
+ case 't': case 'T': {
+ if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
+ token = tkTRIGGER;
+ }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
+ token = tkTEMP;
+ }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
+ token = tkTEMP;
+ }else{
+ token = tkOTHER;
+ }
+ break;
+ }
+ case 'e': case 'E': {
+ if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
+ token = tkEND;
+ }else
+#ifndef SQLITE_OMIT_EXPLAIN
+ if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
+ token = tkEXPLAIN;
+ }else
+#endif
+ {
+ token = tkOTHER;
+ }
+ break;
+ }
+ default: {
+ token = tkOTHER;
+ break;
+ }
+ }
+#endif /* SQLITE_OMIT_TRIGGER */
+ zSql += nId-1;
+ }else{
+ /* Operators and special symbols */
+ token = tkOTHER;
+ }
+ break;
+ }
+ }
+ state = trans[state][token];
+ zSql++;
+ }
+ return state==1;
+}
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** This routine is the same as the sqlite3_complete() routine described
+** above, except that the parameter is required to be UTF-16 encoded, not
+** UTF-8.
+*/
+SQLITE_API int sqlite3_complete16(const void *zSql){
+ sqlite3_value *pVal;
+ char const *zSql8;
+ int rc = SQLITE_NOMEM;
+
+#ifndef SQLITE_OMIT_AUTOINIT
+ rc = sqlite3_initialize();
+ if( rc ) return rc;
+#endif
+ pVal = sqlite3ValueNew(0);
+ sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
+ zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
+ if( zSql8 ){
+ rc = sqlite3_complete(zSql8);
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ sqlite3ValueFree(pVal);
+ return sqlite3ApiExit(0, rc);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+#endif /* SQLITE_OMIT_COMPLETE */
+
+/************** End of complete.c ********************************************/
+/************** Begin file main.c ********************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Main file for the SQLite library. The routines in this file
+** implement the programmer interface to the library. Routines in
+** other files are for internal use by SQLite and should not be
+** accessed by users of the library.
+*/
+
+#ifdef SQLITE_ENABLE_FTS3
+/************** Include fts3.h in the middle of main.c ***********************/
+/************** Begin file fts3.h ********************************************/
+/*
+** 2006 Oct 10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This header file is used by programs that want to link against the
+** FTS3 library. All it does is declare the sqlite3Fts3Init() interface.
+*/
+
+#if 0
+extern "C" {
+#endif /* __cplusplus */
+
+SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db);
+
+#if 0
+} /* extern "C" */
+#endif /* __cplusplus */
+
+/************** End of fts3.h ************************************************/
+/************** Continuing where we left off in main.c ***********************/
+#endif
+#ifdef SQLITE_ENABLE_RTREE
+/************** Include rtree.h in the middle of main.c **********************/
+/************** Begin file rtree.h *******************************************/
+/*
+** 2008 May 26
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This header file is used by programs that want to link against the
+** RTREE library. All it does is declare the sqlite3RtreeInit() interface.
+*/
+
+#if 0
+extern "C" {
+#endif /* __cplusplus */
+
+SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db);
+
+#if 0
+} /* extern "C" */
+#endif /* __cplusplus */
+
+/************** End of rtree.h ***********************************************/
+/************** Continuing where we left off in main.c ***********************/
+#endif
+#ifdef SQLITE_ENABLE_ICU
+/************** Include sqliteicu.h in the middle of main.c ******************/
+/************** Begin file sqliteicu.h ***************************************/
+/*
+** 2008 May 26
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This header file is used by programs that want to link against the
+** ICU extension. All it does is declare the sqlite3IcuInit() interface.
+*/
+
+#if 0
+extern "C" {
+#endif /* __cplusplus */
+
+SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db);
+
+#if 0
+} /* extern "C" */
+#endif /* __cplusplus */
+
+
+/************** End of sqliteicu.h *******************************************/
+/************** Continuing where we left off in main.c ***********************/
+#endif
+
+#ifndef SQLITE_AMALGAMATION
+/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
+** contains the text of SQLITE_VERSION macro.
+*/
+SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
+#endif
+
+/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns
+** a pointer to the to the sqlite3_version[] string constant.
+*/
+SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; }
+
+/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a
+** pointer to a string constant whose value is the same as the
+** SQLITE_SOURCE_ID C preprocessor macro.
+*/
+SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
+
+/* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function
+** returns an integer equal to SQLITE_VERSION_NUMBER.
+*/
+SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
+
+/* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns
+** zero if and only if SQLite was compiled with mutexing code omitted due to
+** the SQLITE_THREADSAFE compile-time option being set to 0.
+*/
+SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
+
+#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
+/*
+** If the following function pointer is not NULL and if
+** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
+** I/O active are written using this function. These messages
+** are intended for debugging activity only.
+*/
+SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0;
+#endif
+
+/*
+** If the following global variable points to a string which is the
+** name of a directory, then that directory will be used to store
+** temporary files.
+**
+** See also the "PRAGMA temp_store_directory" SQL command.
+*/
+SQLITE_API char *sqlite3_temp_directory = 0;
+
+/*
+** If the following global variable points to a string which is the
+** name of a directory, then that directory will be used to store
+** all database files specified with a relative pathname.
+**
+** See also the "PRAGMA data_store_directory" SQL command.
+*/
+SQLITE_API char *sqlite3_data_directory = 0;
+
+/*
+** Initialize SQLite.
+**
+** This routine must be called to initialize the memory allocation,
+** VFS, and mutex subsystems prior to doing any serious work with
+** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
+** this routine will be called automatically by key routines such as
+** sqlite3_open().
+**
+** This routine is a no-op except on its very first call for the process,
+** or for the first call after a call to sqlite3_shutdown.
+**
+** The first thread to call this routine runs the initialization to
+** completion. If subsequent threads call this routine before the first
+** thread has finished the initialization process, then the subsequent
+** threads must block until the first thread finishes with the initialization.
+**
+** The first thread might call this routine recursively. Recursive
+** calls to this routine should not block, of course. Otherwise the
+** initialization process would never complete.
+**
+** Let X be the first thread to enter this routine. Let Y be some other
+** thread. Then while the initial invocation of this routine by X is
+** incomplete, it is required that:
+**
+** * Calls to this routine from Y must block until the outer-most
+** call by X completes.
+**
+** * Recursive calls to this routine from thread X return immediately
+** without blocking.
+*/
+SQLITE_API int sqlite3_initialize(void){
+ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
+ int rc; /* Result code */
+
+#ifdef SQLITE_OMIT_WSD
+ rc = sqlite3_wsd_init(4096, 24);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+#endif
+
+ /* If SQLite is already completely initialized, then this call
+ ** to sqlite3_initialize() should be a no-op. But the initialization
+ ** must be complete. So isInit must not be set until the very end
+ ** of this routine.
+ */
+ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
+
+#ifdef SQLITE_ENABLE_SQLLOG
+ {
+ extern void sqlite3_init_sqllog(void);
+ sqlite3_init_sqllog();
+ }
+#endif
+
+ /* Make sure the mutex subsystem is initialized. If unable to
+ ** initialize the mutex subsystem, return early with the error.
+ ** If the system is so sick that we are unable to allocate a mutex,
+ ** there is not much SQLite is going to be able to do.
+ **
+ ** The mutex subsystem must take care of serializing its own
+ ** initialization.
+ */
+ rc = sqlite3MutexInit();
+ if( rc ) return rc;
+
+ /* Initialize the malloc() system and the recursive pInitMutex mutex.
+ ** This operation is protected by the STATIC_MASTER mutex. Note that
+ ** MutexAlloc() is called for a static mutex prior to initializing the
+ ** malloc subsystem - this implies that the allocation of a static
+ ** mutex must not require support from the malloc subsystem.
+ */
+ MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+ sqlite3_mutex_enter(pMaster);
+ sqlite3GlobalConfig.isMutexInit = 1;
+ if( !sqlite3GlobalConfig.isMallocInit ){
+ rc = sqlite3MallocInit();
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3GlobalConfig.isMallocInit = 1;
+ if( !sqlite3GlobalConfig.pInitMutex ){
+ sqlite3GlobalConfig.pInitMutex =
+ sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+ if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3GlobalConfig.nRefInitMutex++;
+ }
+ sqlite3_mutex_leave(pMaster);
+
+ /* If rc is not SQLITE_OK at this point, then either the malloc
+ ** subsystem could not be initialized or the system failed to allocate
+ ** the pInitMutex mutex. Return an error in either case. */
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* Do the rest of the initialization under the recursive mutex so
+ ** that we will be able to handle recursive calls into
+ ** sqlite3_initialize(). The recursive calls normally come through
+ ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
+ ** recursive calls might also be possible.
+ **
+ ** IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls
+ ** to the xInit method, so the xInit method need not be threadsafe.
+ **
+ ** The following mutex is what serializes access to the appdef pcache xInit
+ ** methods. The sqlite3_pcache_methods.xInit() all is embedded in the
+ ** call to sqlite3PcacheInitialize().
+ */
+ sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
+ if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ sqlite3GlobalConfig.inProgress = 1;
+ memset(pHash, 0, sizeof(sqlite3GlobalFunctions));
+ sqlite3RegisterGlobalFunctions();
+ if( sqlite3GlobalConfig.isPCacheInit==0 ){
+ rc = sqlite3PcacheInitialize();
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3GlobalConfig.isPCacheInit = 1;
+ rc = sqlite3OsInit();
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
+ sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
+ sqlite3GlobalConfig.isInit = 1;
+ }
+ sqlite3GlobalConfig.inProgress = 0;
+ }
+ sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
+
+ /* Go back under the static mutex and clean up the recursive
+ ** mutex to prevent a resource leak.
+ */
+ sqlite3_mutex_enter(pMaster);
+ sqlite3GlobalConfig.nRefInitMutex--;
+ if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
+ assert( sqlite3GlobalConfig.nRefInitMutex==0 );
+ sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
+ sqlite3GlobalConfig.pInitMutex = 0;
+ }
+ sqlite3_mutex_leave(pMaster);
+
+ /* The following is just a sanity check to make sure SQLite has
+ ** been compiled correctly. It is important to run this code, but
+ ** we don't want to run it too often and soak up CPU cycles for no
+ ** reason. So we run it once during initialization.
+ */
+#ifndef NDEBUG
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ /* This section of code's only "output" is via assert() statements. */
+ if ( rc==SQLITE_OK ){
+ u64 x = (((u64)1)<<63)-1;
+ double y;
+ assert(sizeof(x)==8);
+ assert(sizeof(x)==sizeof(y));
+ memcpy(&y, &x, 8);
+ assert( sqlite3IsNaN(y) );
+ }
+#endif
+#endif
+
+ /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
+ ** compile-time option.
+ */
+#ifdef SQLITE_EXTRA_INIT
+ if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
+ int SQLITE_EXTRA_INIT(const char*);
+ rc = SQLITE_EXTRA_INIT(0);
+ }
+#endif
+
+ return rc;
+}
+
+/*
+** Undo the effects of sqlite3_initialize(). Must not be called while
+** there are outstanding database connections or memory allocations or
+** while any part of SQLite is otherwise in use in any thread. This
+** routine is not threadsafe. But it is safe to invoke this routine
+** on when SQLite is already shut down. If SQLite is already shut down
+** when this routine is invoked, then this routine is a harmless no-op.
+*/
+SQLITE_API int sqlite3_shutdown(void){
+ if( sqlite3GlobalConfig.isInit ){
+#ifdef SQLITE_EXTRA_SHUTDOWN
+ void SQLITE_EXTRA_SHUTDOWN(void);
+ SQLITE_EXTRA_SHUTDOWN();
+#endif
+ sqlite3_os_end();
+ sqlite3_reset_auto_extension();
+ sqlite3GlobalConfig.isInit = 0;
+ }
+ if( sqlite3GlobalConfig.isPCacheInit ){
+ sqlite3PcacheShutdown();
+ sqlite3GlobalConfig.isPCacheInit = 0;
+ }
+ if( sqlite3GlobalConfig.isMallocInit ){
+ sqlite3MallocEnd();
+ sqlite3GlobalConfig.isMallocInit = 0;
+
+#ifndef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
+ /* The heap subsystem has now been shutdown and these values are supposed
+ ** to be NULL or point to memory that was obtained from sqlite3_malloc(),
+ ** which would rely on that heap subsystem; therefore, make sure these
+ ** values cannot refer to heap memory that was just invalidated when the
+ ** heap subsystem was shutdown. This is only done if the current call to
+ ** this function resulted in the heap subsystem actually being shutdown.
+ */
+ sqlite3_data_directory = 0;
+ sqlite3_temp_directory = 0;
+#endif
+ }
+ if( sqlite3GlobalConfig.isMutexInit ){
+ sqlite3MutexEnd();
+ sqlite3GlobalConfig.isMutexInit = 0;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** This API allows applications to modify the global configuration of
+** the SQLite library at run-time.
+**
+** This routine should only be called when there are no outstanding
+** database connections or memory allocations. This routine is not
+** threadsafe. Failure to heed these warnings can lead to unpredictable
+** behavior.
+*/
+SQLITE_API int sqlite3_config(int op, ...){
+ va_list ap;
+ int rc = SQLITE_OK;
+
+ /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
+ ** the SQLite library is in use. */
+ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;
+
+ va_start(ap, op);
+ switch( op ){
+
+ /* Mutex configuration options are only available in a threadsafe
+ ** compile.
+ */
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0
+ case SQLITE_CONFIG_SINGLETHREAD: {
+ /* Disable all mutexing */
+ sqlite3GlobalConfig.bCoreMutex = 0;
+ sqlite3GlobalConfig.bFullMutex = 0;
+ break;
+ }
+ case SQLITE_CONFIG_MULTITHREAD: {
+ /* Disable mutexing of database connections */
+ /* Enable mutexing of core data structures */
+ sqlite3GlobalConfig.bCoreMutex = 1;
+ sqlite3GlobalConfig.bFullMutex = 0;
+ break;
+ }
+ case SQLITE_CONFIG_SERIALIZED: {
+ /* Enable all mutexing */
+ sqlite3GlobalConfig.bCoreMutex = 1;
+ sqlite3GlobalConfig.bFullMutex = 1;
+ break;
+ }
+ case SQLITE_CONFIG_MUTEX: {
+ /* Specify an alternative mutex implementation */
+ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
+ break;
+ }
+ case SQLITE_CONFIG_GETMUTEX: {
+ /* Retrieve the current mutex implementation */
+ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex;
+ break;
+ }
+#endif
+
+
+ case SQLITE_CONFIG_MALLOC: {
+ /* Specify an alternative malloc implementation */
+ sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
+ break;
+ }
+ case SQLITE_CONFIG_GETMALLOC: {
+ /* Retrieve the current malloc() implementation */
+ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
+ *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
+ break;
+ }
+ case SQLITE_CONFIG_MEMSTATUS: {
+ /* Enable or disable the malloc status collection */
+ sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
+ break;
+ }
+ case SQLITE_CONFIG_SCRATCH: {
+ /* Designate a buffer for scratch memory space */
+ sqlite3GlobalConfig.pScratch = va_arg(ap, void*);
+ sqlite3GlobalConfig.szScratch = va_arg(ap, int);
+ sqlite3GlobalConfig.nScratch = va_arg(ap, int);
+ break;
+ }
+ case SQLITE_CONFIG_PAGECACHE: {
+ /* Designate a buffer for page cache memory space */
+ sqlite3GlobalConfig.pPage = va_arg(ap, void*);
+ sqlite3GlobalConfig.szPage = va_arg(ap, int);
+ sqlite3GlobalConfig.nPage = va_arg(ap, int);
+ break;
+ }
+
+ case SQLITE_CONFIG_PCACHE: {
+ /* no-op */
+ break;
+ }
+ case SQLITE_CONFIG_GETPCACHE: {
+ /* now an error */
+ rc = SQLITE_ERROR;
+ break;
+ }
+
+ case SQLITE_CONFIG_PCACHE2: {
+ /* Specify an alternative page cache implementation */
+ sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*);
+ break;
+ }
+ case SQLITE_CONFIG_GETPCACHE2: {
+ if( sqlite3GlobalConfig.pcache2.xInit==0 ){
+ sqlite3PCacheSetDefault();
+ }
+ *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2;
+ break;
+ }
+
+#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
+ case SQLITE_CONFIG_HEAP: {
+ /* Designate a buffer for heap memory space */
+ sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
+ sqlite3GlobalConfig.nHeap = va_arg(ap, int);
+ sqlite3GlobalConfig.mnReq = va_arg(ap, int);
+
+ if( sqlite3GlobalConfig.mnReq<1 ){
+ sqlite3GlobalConfig.mnReq = 1;
+ }else if( sqlite3GlobalConfig.mnReq>(1<<12) ){
+ /* cap min request size at 2^12 */
+ sqlite3GlobalConfig.mnReq = (1<<12);
+ }
+
+ if( sqlite3GlobalConfig.pHeap==0 ){
+ /* If the heap pointer is NULL, then restore the malloc implementation
+ ** back to NULL pointers too. This will cause the malloc to go
+ ** back to its default implementation when sqlite3_initialize() is
+ ** run.
+ */
+ memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
+ }else{
+ /* The heap pointer is not NULL, then install one of the
+ ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
+ ** ENABLE_MEMSYS5 is defined, return an error.
+ */
+#ifdef SQLITE_ENABLE_MEMSYS3
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS5
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();
+#endif
+ }
+ break;
+ }
+#endif
+
+ case SQLITE_CONFIG_LOOKASIDE: {
+ sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
+ sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
+ break;
+ }
+
+ /* Record a pointer to the logger funcction and its first argument.
+ ** The default is NULL. Logging is disabled if the function pointer is
+ ** NULL.
+ */
+ case SQLITE_CONFIG_LOG: {
+ /* MSVC is picky about pulling func ptrs from va lists.
+ ** http://support.microsoft.com/kb/47961
+ ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
+ */
+ typedef void(*LOGFUNC_t)(void*,int,const char*);
+ sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
+ sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
+ break;
+ }
+
+ case SQLITE_CONFIG_URI: {
+ sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
+ break;
+ }
+
+ case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
+ sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
+ break;
+ }
+
+#ifdef SQLITE_ENABLE_SQLLOG
+ case SQLITE_CONFIG_SQLLOG: {
+ typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
+ sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
+ sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
+ break;
+ }
+#endif
+
+ default: {
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }
+ va_end(ap);
+ return rc;
+}
+
+/*
+** Set up the lookaside buffers for a database connection.
+** Return SQLITE_OK on success.
+** If lookaside is already active, return SQLITE_BUSY.
+**
+** The sz parameter is the number of bytes in each lookaside slot.
+** The cnt parameter is the number of slots. If pStart is NULL the
+** space for the lookaside memory is obtained from sqlite3_malloc().
+** If pStart is not NULL then it is sz*cnt bytes of memory to use for
+** the lookaside memory.
+*/
+static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
+ void *pStart;
+ if( db->lookaside.nOut ){
+ return SQLITE_BUSY;
+ }
+ /* Free any existing lookaside buffer for this handle before
+ ** allocating a new one so we don't have to have space for
+ ** both at the same time.
+ */
+ if( db->lookaside.bMalloced ){
+ sqlite3_free(db->lookaside.pStart);
+ }
+ /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
+ ** than a pointer to be useful.
+ */
+ sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */
+ if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
+ if( cnt<0 ) cnt = 0;
+ if( sz==0 || cnt==0 ){
+ sz = 0;
+ pStart = 0;
+ }else if( pBuf==0 ){
+ sqlite3BeginBenignMalloc();
+ pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */
+ sqlite3EndBenignMalloc();
+ if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
+ }else{
+ pStart = pBuf;
+ }
+ db->lookaside.pStart = pStart;
+ db->lookaside.pFree = 0;
+ db->lookaside.sz = (u16)sz;
+ if( pStart ){
+ int i;
+ LookasideSlot *p;
+ assert( sz > (int)sizeof(LookasideSlot*) );
+ p = (LookasideSlot*)pStart;
+ for(i=cnt-1; i>=0; i--){
+ p->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = p;
+ p = (LookasideSlot*)&((u8*)p)[sz];
+ }
+ db->lookaside.pEnd = p;
+ db->lookaside.bEnabled = 1;
+ db->lookaside.bMalloced = pBuf==0 ?1:0;
+ }else{
+ db->lookaside.pEnd = 0;
+ db->lookaside.bEnabled = 0;
+ db->lookaside.bMalloced = 0;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Return the mutex associated with a database connection.
+*/
+SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
+ return db->mutex;
+}
+
+/*
+** Free up as much memory as we can from the given database
+** connection.
+*/
+SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){
+ int i;
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3BtreeEnterAll(db);
+ for(i=0; i<db->nDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ Pager *pPager = sqlite3BtreePager(pBt);
+ sqlite3PagerShrink(pPager);
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+
+/*
+** Configuration settings for an individual database connection
+*/
+SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
+ va_list ap;
+ int rc;
+ va_start(ap, op);
+ switch( op ){
+ case SQLITE_DBCONFIG_LOOKASIDE: {
+ void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */
+ int sz = va_arg(ap, int); /* IMP: R-47871-25994 */
+ int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */
+ rc = setupLookaside(db, pBuf, sz, cnt);
+ break;
+ }
+ default: {
+ static const struct {
+ int op; /* The opcode */
+ u32 mask; /* Mask of the bit in sqlite3.flags to set/clear */
+ } aFlagOp[] = {
+ { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
+ { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
+ };
+ unsigned int i;
+ rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
+ for(i=0; i<ArraySize(aFlagOp); i++){
+ if( aFlagOp[i].op==op ){
+ int onoff = va_arg(ap, int);
+ int *pRes = va_arg(ap, int*);
+ int oldFlags = db->flags;
+ if( onoff>0 ){
+ db->flags |= aFlagOp[i].mask;
+ }else if( onoff==0 ){
+ db->flags &= ~aFlagOp[i].mask;
+ }
+ if( oldFlags!=db->flags ){
+ sqlite3ExpirePreparedStatements(db);
+ }
+ if( pRes ){
+ *pRes = (db->flags & aFlagOp[i].mask)!=0;
+ }
+ rc = SQLITE_OK;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ va_end(ap);
+ return rc;
+}
+
+
+/*
+** Return true if the buffer z[0..n-1] contains all spaces.
+*/
+static int allSpaces(const char *z, int n){
+ while( n>0 && z[n-1]==' ' ){ n--; }
+ return n==0;
+}
+
+/*
+** This is the default collating function named "BINARY" which is always
+** available.
+**
+** If the padFlag argument is not NULL then space padding at the end
+** of strings is ignored. This implements the RTRIM collation.
+*/
+static int binCollFunc(
+ void *padFlag,
+ int nKey1, const void *pKey1,
+ int nKey2, const void *pKey2
+){
+ int rc, n;
+ n = nKey1<nKey2 ? nKey1 : nKey2;
+ rc = memcmp(pKey1, pKey2, n);
+ if( rc==0 ){
+ if( padFlag
+ && allSpaces(((char*)pKey1)+n, nKey1-n)
+ && allSpaces(((char*)pKey2)+n, nKey2-n)
+ ){
+ /* Leave rc unchanged at 0 */
+ }else{
+ rc = nKey1 - nKey2;
+ }
+ }
+ return rc;
+}
+
+/*
+** Another built-in collating sequence: NOCASE.
+**
+** This collating sequence is intended to be used for "case independant
+** comparison". SQLite's knowledge of upper and lower case equivalents
+** extends only to the 26 characters used in the English language.
+**
+** At the moment there is only a UTF-8 implementation.
+*/
+static int nocaseCollatingFunc(
+ void *NotUsed,
+ int nKey1, const void *pKey1,
+ int nKey2, const void *pKey2
+){
+ int r = sqlite3StrNICmp(
+ (const char *)pKey1, (const char *)pKey2, (nKey1<nKey2)?nKey1:nKey2);
+ UNUSED_PARAMETER(NotUsed);
+ if( 0==r ){
+ r = nKey1-nKey2;
+ }
+ return r;
+}
+
+/*
+** Return the ROWID of the most recent insert
+*/
+SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
+ return db->lastRowid;
+}
+
+/*
+** Return the number of changes in the most recent call to sqlite3_exec().
+*/
+SQLITE_API int sqlite3_changes(sqlite3 *db){
+ return db->nChange;
+}
+
+/*
+** Return the number of changes since the database handle was opened.
+*/
+SQLITE_API int sqlite3_total_changes(sqlite3 *db){
+ return db->nTotalChange;
+}
+
+/*
+** Close all open savepoints. This function only manipulates fields of the
+** database handle object, it does not close any savepoints that may be open
+** at the b-tree/pager level.
+*/
+SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *db){
+ while( db->pSavepoint ){
+ Savepoint *pTmp = db->pSavepoint;
+ db->pSavepoint = pTmp->pNext;
+ sqlite3DbFree(db, pTmp);
+ }
+ db->nSavepoint = 0;
+ db->nStatement = 0;
+ db->isTransactionSavepoint = 0;
+}
+
+/*
+** Invoke the destructor function associated with FuncDef p, if any. Except,
+** if this is not the last copy of the function, do not invoke it. Multiple
+** copies of a single function are created when create_function() is called
+** with SQLITE_ANY as the encoding.
+*/
+static void functionDestroy(sqlite3 *db, FuncDef *p){
+ FuncDestructor *pDestructor = p->pDestructor;
+ if( pDestructor ){
+ pDestructor->nRef--;
+ if( pDestructor->nRef==0 ){
+ pDestructor->xDestroy(pDestructor->pUserData);
+ sqlite3DbFree(db, pDestructor);
+ }
+ }
+}
+
+/*
+** Disconnect all sqlite3_vtab objects that belong to database connection
+** db. This is called when db is being closed.
+*/
+static void disconnectAllVtab(sqlite3 *db){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ int i;
+ sqlite3BtreeEnterAll(db);
+ for(i=0; i<db->nDb; i++){
+ Schema *pSchema = db->aDb[i].pSchema;
+ if( db->aDb[i].pSchema ){
+ HashElem *p;
+ for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
+ Table *pTab = (Table *)sqliteHashData(p);
+ if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
+ }
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+#else
+ UNUSED_PARAMETER(db);
+#endif
+}
+
+/*
+** Return TRUE if database connection db has unfinalized prepared
+** statements or unfinished sqlite3_backup objects.
+*/
+static int connectionIsBusy(sqlite3 *db){
+ int j;
+ assert( sqlite3_mutex_held(db->mutex) );
+ if( db->pVdbe ) return 1;
+ for(j=0; j<db->nDb; j++){
+ Btree *pBt = db->aDb[j].pBt;
+ if( pBt && sqlite3BtreeIsInBackup(pBt) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Close an existing SQLite database
+*/
+static int sqlite3Close(sqlite3 *db, int forceZombie){
+ if( !db ){
+ return SQLITE_OK;
+ }
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ sqlite3_mutex_enter(db->mutex);
+
+ /* Force xDisconnect calls on all virtual tables */
+ disconnectAllVtab(db);
+
+ /* If a transaction is open, the disconnectAllVtab() call above
+ ** will not have called the xDisconnect() method on any virtual
+ ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
+ ** call will do so. We need to do this before the check for active
+ ** SQL statements below, as the v-table implementation may be storing
+ ** some prepared statements internally.
+ */
+ sqlite3VtabRollback(db);
+
+ /* Legacy behavior (sqlite3_close() behavior) is to return
+ ** SQLITE_BUSY if the connection can not be closed immediately.
+ */
+ if( !forceZombie && connectionIsBusy(db) ){
+ sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized "
+ "statements or unfinished backups");
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_BUSY;
+ }
+
+#ifdef SQLITE_ENABLE_SQLLOG
+ if( sqlite3GlobalConfig.xSqllog ){
+ /* Closing the handle. Fourth parameter is passed the value 2. */
+ sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
+ }
+#endif
+
+ /* Convert the connection into a zombie and then close it.
+ */
+ db->magic = SQLITE_MAGIC_ZOMBIE;
+ sqlite3LeaveMutexAndCloseZombie(db);
+ return SQLITE_OK;
+}
+
+/*
+** Two variations on the public interface for closing a database
+** connection. The sqlite3_close() version returns SQLITE_BUSY and
+** leaves the connection option if there are unfinalized prepared
+** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
+** version forces the connection to become a zombie if there are
+** unclosed resources, and arranges for deallocation when the last
+** prepare statement or sqlite3_backup closes.
+*/
+SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
+SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
+
+
+/*
+** Close the mutex on database connection db.
+**
+** Furthermore, if database connection db is a zombie (meaning that there
+** has been a prior call to sqlite3_close(db) or sqlite3_close_v2(db)) and
+** every sqlite3_stmt has now been finalized and every sqlite3_backup has
+** finished, then free all resources.
+*/
+SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
+ HashElem *i; /* Hash table iterator */
+ int j;
+
+ /* If there are outstanding sqlite3_stmt or sqlite3_backup objects
+ ** or if the connection has not yet been closed by sqlite3_close_v2(),
+ ** then just leave the mutex and return.
+ */
+ if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
+ sqlite3_mutex_leave(db->mutex);
+ return;
+ }
+
+ /* If we reach this point, it means that the database connection has
+ ** closed all sqlite3_stmt and sqlite3_backup objects and has been
+ ** passed to sqlite3_close (meaning that it is a zombie). Therefore,
+ ** go ahead and free all resources.
+ */
+
+ /* Free any outstanding Savepoint structures. */
+ sqlite3CloseSavepoints(db);
+
+ /* Close all database connections */
+ for(j=0; j<db->nDb; j++){
+ struct Db *pDb = &db->aDb[j];
+ if( pDb->pBt ){
+ sqlite3BtreeClose(pDb->pBt);
+ pDb->pBt = 0;
+ if( j!=1 ){
+ pDb->pSchema = 0;
+ }
+ }
+ }
+ /* Clear the TEMP schema separately and last */
+ if( db->aDb[1].pSchema ){
+ sqlite3SchemaClear(db->aDb[1].pSchema);
+ }
+ sqlite3VtabUnlockList(db);
+
+ /* Free up the array of auxiliary databases */
+ sqlite3CollapseDatabaseArray(db);
+ assert( db->nDb<=2 );
+ assert( db->aDb==db->aDbStatic );
+
+ /* Tell the code in notify.c that the connection no longer holds any
+ ** locks and does not require any further unlock-notify callbacks.
+ */
+ sqlite3ConnectionClosed(db);
+
+ for(j=0; j<ArraySize(db->aFunc.a); j++){
+ FuncDef *pNext, *pHash, *p;
+ for(p=db->aFunc.a[j]; p; p=pHash){
+ pHash = p->pHash;
+ while( p ){
+ functionDestroy(db, p);
+ pNext = p->pNext;
+ sqlite3DbFree(db, p);
+ p = pNext;
+ }
+ }
+ }
+ for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
+ CollSeq *pColl = (CollSeq *)sqliteHashData(i);
+ /* Invoke any destructors registered for collation sequence user data. */
+ for(j=0; j<3; j++){
+ if( pColl[j].xDel ){
+ pColl[j].xDel(pColl[j].pUser);
+ }
+ }
+ sqlite3DbFree(db, pColl);
+ }
+ sqlite3HashClear(&db->aCollSeq);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
+ Module *pMod = (Module *)sqliteHashData(i);
+ if( pMod->xDestroy ){
+ pMod->xDestroy(pMod->pAux);
+ }
+ sqlite3DbFree(db, pMod);
+ }
+ sqlite3HashClear(&db->aModule);
+#endif
+
+ sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
+ if( db->pErr ){
+ sqlite3ValueFree(db->pErr);
+ }
+ sqlite3CloseExtensions(db);
+
+ db->magic = SQLITE_MAGIC_ERROR;
+
+ /* The temp-database schema is allocated differently from the other schema
+ ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
+ ** So it needs to be freed here. Todo: Why not roll the temp schema into
+ ** the same sqliteMalloc() as the one that allocates the database
+ ** structure?
+ */
+ sqlite3DbFree(db, db->aDb[1].pSchema);
+ sqlite3_mutex_leave(db->mutex);
+ db->magic = SQLITE_MAGIC_CLOSED;
+ sqlite3_mutex_free(db->mutex);
+ assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */
+ if( db->lookaside.bMalloced ){
+ sqlite3_free(db->lookaside.pStart);
+ }
+ sqlite3_free(db);
+}
+
+/*
+** Rollback all database files. If tripCode is not SQLITE_OK, then
+** any open cursors are invalidated ("tripped" - as in "tripping a circuit
+** breaker") and made to return tripCode if there are any further
+** attempts to use that cursor.
+*/
+SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
+ int i;
+ int inTrans = 0;
+ assert( sqlite3_mutex_held(db->mutex) );
+ sqlite3BeginBenignMalloc();
+ for(i=0; i<db->nDb; i++){
+ Btree *p = db->aDb[i].pBt;
+ if( p ){
+ if( sqlite3BtreeIsInTrans(p) ){
+ inTrans = 1;
+ }
+ sqlite3BtreeRollback(p, tripCode);
+ db->aDb[i].inTrans = 0;
+ }
+ }
+ sqlite3VtabRollback(db);
+ sqlite3EndBenignMalloc();
+
+ if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
+ sqlite3ExpirePreparedStatements(db);
+ sqlite3ResetAllSchemasOfConnection(db);
+ }
+
+ /* Any deferred constraint violations have now been resolved. */
+ db->nDeferredCons = 0;
+
+ /* If one has been configured, invoke the rollback-hook callback */
+ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
+ db->xRollbackCallback(db->pRollbackArg);
+ }
+}
+
+/*
+** Return a static string that describes the kind of error specified in the
+** argument.
+*/
+SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
+ static const char* const aMsg[] = {
+ /* SQLITE_OK */ "not an error",
+ /* SQLITE_ERROR */ "SQL logic error or missing database",
+ /* SQLITE_INTERNAL */ 0,
+ /* SQLITE_PERM */ "access permission denied",
+ /* SQLITE_ABORT */ "callback requested query abort",
+ /* SQLITE_BUSY */ "database is locked",
+ /* SQLITE_LOCKED */ "database table is locked",
+ /* SQLITE_NOMEM */ "out of memory",
+ /* SQLITE_READONLY */ "attempt to write a readonly database",
+ /* SQLITE_INTERRUPT */ "interrupted",
+ /* SQLITE_IOERR */ "disk I/O error",
+ /* SQLITE_CORRUPT */ "database disk image is malformed",
+ /* SQLITE_NOTFOUND */ "unknown operation",
+ /* SQLITE_FULL */ "database or disk is full",
+ /* SQLITE_CANTOPEN */ "unable to open database file",
+ /* SQLITE_PROTOCOL */ "locking protocol",
+ /* SQLITE_EMPTY */ "table contains no data",
+ /* SQLITE_SCHEMA */ "database schema has changed",
+ /* SQLITE_TOOBIG */ "string or blob too big",
+ /* SQLITE_CONSTRAINT */ "constraint failed",
+ /* SQLITE_MISMATCH */ "datatype mismatch",
+ /* SQLITE_MISUSE */ "library routine called out of sequence",
+ /* SQLITE_NOLFS */ "large file support is disabled",
+ /* SQLITE_AUTH */ "authorization denied",
+ /* SQLITE_FORMAT */ "auxiliary database format error",
+ /* SQLITE_RANGE */ "bind or column index out of range",
+ /* SQLITE_NOTADB */ "file is encrypted or is not a database",
+ };
+ const char *zErr = "unknown error";
+ switch( rc ){
+ case SQLITE_ABORT_ROLLBACK: {
+ zErr = "abort due to ROLLBACK";
+ break;
+ }
+ default: {
+ rc &= 0xff;
+ if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){
+ zErr = aMsg[rc];
+ }
+ break;
+ }
+ }
+ return zErr;
+}
+
+/*
+** This routine implements a busy callback that sleeps and tries
+** again until a timeout value is reached. The timeout value is
+** an integer number of milliseconds passed in as the first
+** argument.
+*/
+static int sqliteDefaultBusyCallback(
+ void *ptr, /* Database connection */
+ int count /* Number of times table has been busy */
+){
+#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP)
+ static const u8 delays[] =
+ { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
+ static const u8 totals[] =
+ { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
+# define NDELAY ArraySize(delays)
+ sqlite3 *db = (sqlite3 *)ptr;
+ int timeout = db->busyTimeout;
+ int delay, prior;
+
+ assert( count>=0 );
+ if( count < NDELAY ){
+ delay = delays[count];
+ prior = totals[count];
+ }else{
+ delay = delays[NDELAY-1];
+ prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
+ }
+ if( prior + delay > timeout ){
+ delay = timeout - prior;
+ if( delay<=0 ) return 0;
+ }
+ sqlite3OsSleep(db->pVfs, delay*1000);
+ return 1;
+#else
+ sqlite3 *db = (sqlite3 *)ptr;
+ int timeout = ((sqlite3 *)ptr)->busyTimeout;
+ if( (count+1)*1000 > timeout ){
+ return 0;
+ }
+ sqlite3OsSleep(db->pVfs, 1000000);
+ return 1;
+#endif
+}
+
+/*
+** Invoke the given busy handler.
+**
+** This routine is called when an operation failed with a lock.
+** If this routine returns non-zero, the lock is retried. If it
+** returns 0, the operation aborts with an SQLITE_BUSY error.
+*/
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
+ int rc;
+ if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0;
+ rc = p->xFunc(p->pArg, p->nBusy);
+ if( rc==0 ){
+ p->nBusy = -1;
+ }else{
+ p->nBusy++;
+ }
+ return rc;
+}
+
+/*
+** This routine sets the busy callback for an Sqlite database to the
+** given callback function with the given argument.
+*/
+SQLITE_API int sqlite3_busy_handler(
+ sqlite3 *db,
+ int (*xBusy)(void*,int),
+ void *pArg
+){
+ sqlite3_mutex_enter(db->mutex);
+ db->busyHandler.xFunc = xBusy;
+ db->busyHandler.pArg = pArg;
+ db->busyHandler.nBusy = 0;
+ db->busyTimeout = 0;
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+/*
+** This routine sets the progress callback for an Sqlite database to the
+** given callback function with the given argument. The progress callback will
+** be invoked every nOps opcodes.
+*/
+SQLITE_API void sqlite3_progress_handler(
+ sqlite3 *db,
+ int nOps,
+ int (*xProgress)(void*),
+ void *pArg
+){
+ sqlite3_mutex_enter(db->mutex);
+ if( nOps>0 ){
+ db->xProgress = xProgress;
+ db->nProgressOps = nOps;
+ db->pProgressArg = pArg;
+ }else{
+ db->xProgress = 0;
+ db->nProgressOps = 0;
+ db->pProgressArg = 0;
+ }
+ sqlite3_mutex_leave(db->mutex);
+}
+#endif
+
+
+/*
+** This routine installs a default busy handler that waits for the
+** specified number of milliseconds before returning 0.
+*/
+SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
+ if( ms>0 ){
+ sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
+ db->busyTimeout = ms;
+ }else{
+ sqlite3_busy_handler(db, 0, 0);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Cause any pending operation to stop at its earliest opportunity.
+*/
+SQLITE_API void sqlite3_interrupt(sqlite3 *db){
+ db->u1.isInterrupted = 1;
+}
+
+
+/*
+** This function is exactly the same as sqlite3_create_function(), except
+** that it is designed to be called by internal code. The difference is
+** that if a malloc() fails in sqlite3_create_function(), an error code
+** is returned and the mallocFailed flag cleared.
+*/
+SQLITE_PRIVATE int sqlite3CreateFunc(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int enc,
+ void *pUserData,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value **),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value **),
+ void (*xFinal)(sqlite3_context*),
+ FuncDestructor *pDestructor
+){
+ FuncDef *p;
+ int nName;
+
+ assert( sqlite3_mutex_held(db->mutex) );
+ if( zFunctionName==0 ||
+ (xFunc && (xFinal || xStep)) ||
+ (!xFunc && (xFinal && !xStep)) ||
+ (!xFunc && (!xFinal && xStep)) ||
+ (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
+ (255<(nName = sqlite3Strlen30( zFunctionName))) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+
+#ifndef SQLITE_OMIT_UTF16
+ /* If SQLITE_UTF16 is specified as the encoding type, transform this
+ ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
+ ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
+ **
+ ** If SQLITE_ANY is specified, add three versions of the function
+ ** to the hash table.
+ */
+ if( enc==SQLITE_UTF16 ){
+ enc = SQLITE_UTF16NATIVE;
+ }else if( enc==SQLITE_ANY ){
+ int rc;
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8,
+ pUserData, xFunc, xStep, xFinal, pDestructor);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
+ pUserData, xFunc, xStep, xFinal, pDestructor);
+ }
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ enc = SQLITE_UTF16BE;
+ }
+#else
+ enc = SQLITE_UTF8;
+#endif
+
+ /* Check if an existing function is being overridden or deleted. If so,
+ ** and there are active VMs, then return SQLITE_BUSY. If a function
+ ** is being overridden/deleted but there are no active VMs, allow the
+ ** operation to continue but invalidate all precompiled statements.
+ */
+ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0);
+ if( p && p->iPrefEnc==enc && p->nArg==nArg ){
+ if( db->activeVdbeCnt ){
+ sqlite3Error(db, SQLITE_BUSY,
+ "unable to delete/modify user-function due to active statements");
+ assert( !db->mallocFailed );
+ return SQLITE_BUSY;
+ }else{
+ sqlite3ExpirePreparedStatements(db);
+ }
+ }
+
+ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1);
+ assert(p || db->mallocFailed);
+ if( !p ){
+ return SQLITE_NOMEM;
+ }
+
+ /* If an older version of the function with a configured destructor is
+ ** being replaced invoke the destructor function here. */
+ functionDestroy(db, p);
+
+ if( pDestructor ){
+ pDestructor->nRef++;
+ }
+ p->pDestructor = pDestructor;
+ p->flags = 0;
+ p->xFunc = xFunc;
+ p->xStep = xStep;
+ p->xFinalize = xFinal;
+ p->pUserData = pUserData;
+ p->nArg = (u16)nArg;
+ return SQLITE_OK;
+}
+
+/*
+** Create new user functions.
+*/
+SQLITE_API int sqlite3_create_function(
+ sqlite3 *db,
+ const char *zFunc,
+ int nArg,
+ int enc,
+ void *p,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value **),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value **),
+ void (*xFinal)(sqlite3_context*)
+){
+ return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xFunc, xStep,
+ xFinal, 0);
+}
+
+SQLITE_API int sqlite3_create_function_v2(
+ sqlite3 *db,
+ const char *zFunc,
+ int nArg,
+ int enc,
+ void *p,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value **),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value **),
+ void (*xFinal)(sqlite3_context*),
+ void (*xDestroy)(void *)
+){
+ int rc = SQLITE_ERROR;
+ FuncDestructor *pArg = 0;
+ sqlite3_mutex_enter(db->mutex);
+ if( xDestroy ){
+ pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor));
+ if( !pArg ){
+ xDestroy(p);
+ goto out;
+ }
+ pArg->xDestroy = xDestroy;
+ pArg->pUserData = p;
+ }
+ rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, pArg);
+ if( pArg && pArg->nRef==0 ){
+ assert( rc!=SQLITE_OK );
+ xDestroy(p);
+ sqlite3DbFree(db, pArg);
+ }
+
+ out:
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_API int sqlite3_create_function16(
+ sqlite3 *db,
+ const void *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *p,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*)
+){
+ int rc;
+ char *zFunc8;
+ sqlite3_mutex_enter(db->mutex);
+ assert( !db->mallocFailed );
+ zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
+ rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal,0);
+ sqlite3DbFree(db, zFunc8);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+#endif
+
+
+/*
+** Declare that a function has been overloaded by a virtual table.
+**
+** If the function already exists as a regular global function, then
+** this routine is a no-op. If the function does not exist, then create
+** a new one that always throws a run-time error.
+**
+** When virtual tables intend to provide an overloaded function, they
+** should call this routine to make sure the global function exists.
+** A global function must exist in order for name resolution to work
+** properly.
+*/
+SQLITE_API int sqlite3_overload_function(
+ sqlite3 *db,
+ const char *zName,
+ int nArg
+){
+ int nName = sqlite3Strlen30(zName);
+ int rc = SQLITE_OK;
+ sqlite3_mutex_enter(db->mutex);
+ if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){
+ rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
+ 0, sqlite3InvalidFunction, 0, 0, 0);
+ }
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_TRACE
+/*
+** Register a trace function. The pArg from the previously registered trace
+** is returned.
+**
+** A NULL trace function means that no tracing is executes. A non-NULL
+** trace is a pointer to a function that is invoked at the start of each
+** SQL statement.
+*/
+SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
+ void *pOld;
+ sqlite3_mutex_enter(db->mutex);
+ pOld = db->pTraceArg;
+ db->xTrace = xTrace;
+ db->pTraceArg = pArg;
+ sqlite3_mutex_leave(db->mutex);
+ return pOld;
+}
+/*
+** Register a profile function. The pArg from the previously registered
+** profile function is returned.
+**
+** A NULL profile function means that no profiling is executes. A non-NULL
+** profile is a pointer to a function that is invoked at the conclusion of
+** each SQL statement that is run.
+*/
+SQLITE_API void *sqlite3_profile(
+ sqlite3 *db,
+ void (*xProfile)(void*,const char*,sqlite_uint64),
+ void *pArg
+){
+ void *pOld;
+ sqlite3_mutex_enter(db->mutex);
+ pOld = db->pProfileArg;
+ db->xProfile = xProfile;
+ db->pProfileArg = pArg;
+ sqlite3_mutex_leave(db->mutex);
+ return pOld;
+}
+#endif /* SQLITE_OMIT_TRACE */
+
+/*
+** Register a function to be invoked when a transaction commits.
+** If the invoked function returns non-zero, then the commit becomes a
+** rollback.
+*/
+SQLITE_API void *sqlite3_commit_hook(
+ sqlite3 *db, /* Attach the hook to this database */
+ int (*xCallback)(void*), /* Function to invoke on each commit */
+ void *pArg /* Argument to the function */
+){
+ void *pOld;
+ sqlite3_mutex_enter(db->mutex);
+ pOld = db->pCommitArg;
+ db->xCommitCallback = xCallback;
+ db->pCommitArg = pArg;
+ sqlite3_mutex_leave(db->mutex);
+ return pOld;
+}
+
+/*
+** Register a callback to be invoked each time a row is updated,
+** inserted or deleted using this database connection.
+*/
+SQLITE_API void *sqlite3_update_hook(
+ sqlite3 *db, /* Attach the hook to this database */
+ void (*xCallback)(void*,int,char const *,char const *,sqlite_int64),
+ void *pArg /* Argument to the function */
+){
+ void *pRet;
+ sqlite3_mutex_enter(db->mutex);
+ pRet = db->pUpdateArg;
+ db->xUpdateCallback = xCallback;
+ db->pUpdateArg = pArg;
+ sqlite3_mutex_leave(db->mutex);
+ return pRet;
+}
+
+/*
+** Register a callback to be invoked each time a transaction is rolled
+** back by this database connection.
+*/
+SQLITE_API void *sqlite3_rollback_hook(
+ sqlite3 *db, /* Attach the hook to this database */
+ void (*xCallback)(void*), /* Callback function */
+ void *pArg /* Argument to the function */
+){
+ void *pRet;
+ sqlite3_mutex_enter(db->mutex);
+ pRet = db->pRollbackArg;
+ db->xRollbackCallback = xCallback;
+ db->pRollbackArg = pArg;
+ sqlite3_mutex_leave(db->mutex);
+ return pRet;
+}
+
+#ifndef SQLITE_OMIT_WAL
+/*
+** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
+** Invoke sqlite3_wal_checkpoint if the number of frames in the log file
+** is greater than sqlite3.pWalArg cast to an integer (the value configured by
+** wal_autocheckpoint()).
+*/
+SQLITE_PRIVATE int sqlite3WalDefaultHook(
+ void *pClientData, /* Argument */
+ sqlite3 *db, /* Connection */
+ const char *zDb, /* Database */
+ int nFrame /* Size of WAL */
+){
+ if( nFrame>=SQLITE_PTR_TO_INT(pClientData) ){
+ sqlite3BeginBenignMalloc();
+ sqlite3_wal_checkpoint(db, zDb);
+ sqlite3EndBenignMalloc();
+ }
+ return SQLITE_OK;
+}
+#endif /* SQLITE_OMIT_WAL */
+
+/*
+** Configure an sqlite3_wal_hook() callback to automatically checkpoint
+** a database after committing a transaction if there are nFrame or
+** more frames in the log file. Passing zero or a negative value as the
+** nFrame parameter disables automatic checkpoints entirely.
+**
+** The callback registered by this function replaces any existing callback
+** registered using sqlite3_wal_hook(). Likewise, registering a callback
+** using sqlite3_wal_hook() disables the automatic checkpoint mechanism
+** configured by this function.
+*/
+SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
+#ifdef SQLITE_OMIT_WAL
+ UNUSED_PARAMETER(db);
+ UNUSED_PARAMETER(nFrame);
+#else
+ if( nFrame>0 ){
+ sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame));
+ }else{
+ sqlite3_wal_hook(db, 0, 0);
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** Register a callback to be invoked each time a transaction is written
+** into the write-ahead-log by this database connection.
+*/
+SQLITE_API void *sqlite3_wal_hook(
+ sqlite3 *db, /* Attach the hook to this db handle */
+ int(*xCallback)(void *, sqlite3*, const char*, int),
+ void *pArg /* First argument passed to xCallback() */
+){
+#ifndef SQLITE_OMIT_WAL
+ void *pRet;
+ sqlite3_mutex_enter(db->mutex);
+ pRet = db->pWalArg;
+ db->xWalCallback = xCallback;
+ db->pWalArg = pArg;
+ sqlite3_mutex_leave(db->mutex);
+ return pRet;
+#else
+ return 0;
+#endif
+}
+
+/*
+** Checkpoint database zDb.
+*/
+SQLITE_API int sqlite3_wal_checkpoint_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of attached database (or NULL) */
+ int eMode, /* SQLITE_CHECKPOINT_* value */
+ int *pnLog, /* OUT: Size of WAL log in frames */
+ int *pnCkpt /* OUT: Total number of frames checkpointed */
+){
+#ifdef SQLITE_OMIT_WAL
+ return SQLITE_OK;
+#else
+ int rc; /* Return code */
+ int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
+
+ /* Initialize the output variables to -1 in case an error occurs. */
+ if( pnLog ) *pnLog = -1;
+ if( pnCkpt ) *pnCkpt = -1;
+
+ assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE );
+ assert( SQLITE_CHECKPOINT_FULL<SQLITE_CHECKPOINT_RESTART );
+ assert( SQLITE_CHECKPOINT_PASSIVE+2==SQLITE_CHECKPOINT_RESTART );
+ if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_RESTART ){
+ return SQLITE_MISUSE;
+ }
+
+ sqlite3_mutex_enter(db->mutex);
+ if( zDb && zDb[0] ){
+ iDb = sqlite3FindDbName(db, zDb);
+ }
+ if( iDb<0 ){
+ rc = SQLITE_ERROR;
+ sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb);
+ }else{
+ rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
+ sqlite3Error(db, rc, 0);
+ }
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+#endif
+}
+
+
+/*
+** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
+** to contains a zero-length string, all attached databases are
+** checkpointed.
+*/
+SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
+ return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0);
+}
+
+#ifndef SQLITE_OMIT_WAL
+/*
+** Run a checkpoint on database iDb. This is a no-op if database iDb is
+** not currently open in WAL mode.
+**
+** If a transaction is open on the database being checkpointed, this
+** function returns SQLITE_LOCKED and a checkpoint is not attempted. If
+** an error occurs while running the checkpoint, an SQLite error code is
+** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK.
+**
+** The mutex on database handle db should be held by the caller. The mutex
+** associated with the specific b-tree being checkpointed is taken by
+** this function while the checkpoint is running.
+**
+** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
+** checkpointed. If an error is encountered it is returned immediately -
+** no attempt is made to checkpoint any remaining databases.
+**
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
+*/
+SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
+ int rc = SQLITE_OK; /* Return code */
+ int i; /* Used to iterate through attached dbs */
+ int bBusy = 0; /* True if SQLITE_BUSY has been encountered */
+
+ assert( sqlite3_mutex_held(db->mutex) );
+ assert( !pnLog || *pnLog==-1 );
+ assert( !pnCkpt || *pnCkpt==-1 );
+
+ for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
+ if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
+ rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt);
+ pnLog = 0;
+ pnCkpt = 0;
+ if( rc==SQLITE_BUSY ){
+ bBusy = 1;
+ rc = SQLITE_OK;
+ }
+ }
+ }
+
+ return (rc==SQLITE_OK && bBusy) ? SQLITE_BUSY : rc;
+}
+#endif /* SQLITE_OMIT_WAL */
+
+/*
+** This function returns true if main-memory should be used instead of
+** a temporary file for transient pager files and statement journals.
+** The value returned depends on the value of db->temp_store (runtime
+** parameter) and the compile time value of SQLITE_TEMP_STORE. The
+** following table describes the relationship between these two values
+** and this functions return value.
+**
+** SQLITE_TEMP_STORE db->temp_store Location of temporary database
+** ----------------- -------------- ------------------------------
+** 0 any file (return 0)
+** 1 1 file (return 0)
+** 1 2 memory (return 1)
+** 1 0 file (return 0)
+** 2 1 file (return 0)
+** 2 2 memory (return 1)
+** 2 0 memory (return 1)
+** 3 any memory (return 1)
+*/
+SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){
+#if SQLITE_TEMP_STORE==1
+ return ( db->temp_store==2 );
+#endif
+#if SQLITE_TEMP_STORE==2
+ return ( db->temp_store!=1 );
+#endif
+#if SQLITE_TEMP_STORE==3
+ return 1;
+#endif
+#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3
+ return 0;
+#endif
+}
+
+/*
+** Return UTF-8 encoded English language explanation of the most recent
+** error.
+*/
+SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){
+ const char *z;
+ if( !db ){
+ return sqlite3ErrStr(SQLITE_NOMEM);
+ }
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
+ return sqlite3ErrStr(SQLITE_MISUSE_BKPT);
+ }
+ sqlite3_mutex_enter(db->mutex);
+ if( db->mallocFailed ){
+ z = sqlite3ErrStr(SQLITE_NOMEM);
+ }else{
+ z = (char*)sqlite3_value_text(db->pErr);
+ assert( !db->mallocFailed );
+ if( z==0 ){
+ z = sqlite3ErrStr(db->errCode);
+ }
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return z;
+}
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Return UTF-16 encoded English language explanation of the most recent
+** error.
+*/
+SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
+ static const u16 outOfMem[] = {
+ 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0
+ };
+ static const u16 misuse[] = {
+ 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ',
+ 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ',
+ 'c', 'a', 'l', 'l', 'e', 'd', ' ',
+ 'o', 'u', 't', ' ',
+ 'o', 'f', ' ',
+ 's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 0
+ };
+
+ const void *z;
+ if( !db ){
+ return (void *)outOfMem;
+ }
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
+ return (void *)misuse;
+ }
+ sqlite3_mutex_enter(db->mutex);
+ if( db->mallocFailed ){
+ z = (void *)outOfMem;
+ }else{
+ z = sqlite3_value_text16(db->pErr);
+ if( z==0 ){
+ sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode),
+ SQLITE_UTF8, SQLITE_STATIC);
+ z = sqlite3_value_text16(db->pErr);
+ }
+ /* A malloc() may have failed within the call to sqlite3_value_text16()
+ ** above. If this is the case, then the db->mallocFailed flag needs to
+ ** be cleared before returning. Do this directly, instead of via
+ ** sqlite3ApiExit(), to avoid setting the database handle error message.
+ */
+ db->mallocFailed = 0;
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return z;
+}
+#endif /* SQLITE_OMIT_UTF16 */
+
+/*
+** Return the most recent error code generated by an SQLite routine. If NULL is
+** passed to this function, we assume a malloc() failed during sqlite3_open().
+*/
+SQLITE_API int sqlite3_errcode(sqlite3 *db){
+ if( db && !sqlite3SafetyCheckSickOrOk(db) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ if( !db || db->mallocFailed ){
+ return SQLITE_NOMEM;
+ }
+ return db->errCode & db->errMask;
+}
+SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
+ if( db && !sqlite3SafetyCheckSickOrOk(db) ){
+ return SQLITE_MISUSE_BKPT;
+ }
+ if( !db || db->mallocFailed ){
+ return SQLITE_NOMEM;
+ }
+ return db->errCode;
+}
+
+/*
+** Return a string that describes the kind of error specified in the
+** argument. For now, this simply calls the internal sqlite3ErrStr()
+** function.
+*/
+SQLITE_API const char *sqlite3_errstr(int rc){
+ return sqlite3ErrStr(rc);
+}
+
+/*
+** Create a new collating function for database "db". The name is zName
+** and the encoding is enc.
+*/
+static int createCollation(
+ sqlite3* db,
+ const char *zName,
+ u8 enc,
+ void* pCtx,
+ int(*xCompare)(void*,int,const void*,int,const void*),
+ void(*xDel)(void*)
+){
+ CollSeq *pColl;
+ int enc2;
+ int nName = sqlite3Strlen30(zName);
+
+ assert( sqlite3_mutex_held(db->mutex) );
+
+ /* If SQLITE_UTF16 is specified as the encoding type, transform this
+ ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
+ ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
+ */
+ enc2 = enc;
+ testcase( enc2==SQLITE_UTF16 );
+ testcase( enc2==SQLITE_UTF16_ALIGNED );
+ if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){
+ enc2 = SQLITE_UTF16NATIVE;
+ }
+ if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
+ return SQLITE_MISUSE_BKPT;
+ }
+
+ /* Check if this call is removing or replacing an existing collation
+ ** sequence. If so, and there are active VMs, return busy. If there
+ ** are no active VMs, invalidate any pre-compiled statements.
+ */
+ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
+ if( pColl && pColl->xCmp ){
+ if( db->activeVdbeCnt ){
+ sqlite3Error(db, SQLITE_BUSY,
+ "unable to delete/modify collation sequence due to active statements");
+ return SQLITE_BUSY;
+ }
+ sqlite3ExpirePreparedStatements(db);
+
+ /* If collation sequence pColl was created directly by a call to
+ ** sqlite3_create_collation, and not generated by synthCollSeq(),
+ ** then any copies made by synthCollSeq() need to be invalidated.
+ ** Also, collation destructor - CollSeq.xDel() - function may need
+ ** to be called.
+ */
+ if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){
+ CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
+ int j;
+ for(j=0; j<3; j++){
+ CollSeq *p = &aColl[j];
+ if( p->enc==pColl->enc ){
+ if( p->xDel ){
+ p->xDel(p->pUser);
+ }
+ p->xCmp = 0;
+ }
+ }
+ }
+ }
+
+ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1);
+ if( pColl==0 ) return SQLITE_NOMEM;
+ pColl->xCmp = xCompare;
+ pColl->pUser = pCtx;
+ pColl->xDel = xDel;
+ pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED));
+ sqlite3Error(db, SQLITE_OK, 0);
+ return SQLITE_OK;
+}
+
+
+/*
+** This array defines hard upper bounds on limit values. The
+** initializer must be kept in sync with the SQLITE_LIMIT_*
+** #defines in sqlite3.h.
+*/
+static const int aHardLimit[] = {
+ SQLITE_MAX_LENGTH,
+ SQLITE_MAX_SQL_LENGTH,
+ SQLITE_MAX_COLUMN,
+ SQLITE_MAX_EXPR_DEPTH,
+ SQLITE_MAX_COMPOUND_SELECT,
+ SQLITE_MAX_VDBE_OP,
+ SQLITE_MAX_FUNCTION_ARG,
+ SQLITE_MAX_ATTACHED,
+ SQLITE_MAX_LIKE_PATTERN_LENGTH,
+ SQLITE_MAX_VARIABLE_NUMBER,
+ SQLITE_MAX_TRIGGER_DEPTH,
+};
+
+/*
+** Make sure the hard limits are set to reasonable values
+*/
+#if SQLITE_MAX_LENGTH<100
+# error SQLITE_MAX_LENGTH must be at least 100
+#endif
+#if SQLITE_MAX_SQL_LENGTH<100
+# error SQLITE_MAX_SQL_LENGTH must be at least 100
+#endif
+#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH
+# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH
+#endif
+#if SQLITE_MAX_COMPOUND_SELECT<2
+# error SQLITE_MAX_COMPOUND_SELECT must be at least 2
+#endif
+#if SQLITE_MAX_VDBE_OP<40
+# error SQLITE_MAX_VDBE_OP must be at least 40
+#endif
+#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000
+# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000
+#endif
+#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62
+# error SQLITE_MAX_ATTACHED must be between 0 and 62
+#endif
+#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
+# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
+#endif
+#if SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN must not exceed 32767
+#endif
+#if SQLITE_MAX_TRIGGER_DEPTH<1
+# error SQLITE_MAX_TRIGGER_DEPTH must be at least 1
+#endif
+
+
+/*
+** Change the value of a limit. Report the old value.
+** If an invalid limit index is supplied, report -1.
+** Make no changes but still report the old value if the
+** new limit is negative.
+**
+** A new lower limit does not shrink existing constructs.
+** It merely prevents new constructs that exceed the limit
+** from forming.
+*/
+SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
+ int oldLimit;
+
+
+ /* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME
+ ** there is a hard upper bound set at compile-time by a C preprocessor
+ ** macro called SQLITE_MAX_NAME. (The "_LIMIT_" in the name is changed to
+ ** "_MAX_".)
+ */
+ assert( aHardLimit[SQLITE_LIMIT_LENGTH]==SQLITE_MAX_LENGTH );
+ assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH );
+ assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN );
+ assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH );
+ assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT);
+ assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP );
+ assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG );
+ assert( aHardLimit[SQLITE_LIMIT_ATTACHED]==SQLITE_MAX_ATTACHED );
+ assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]==
+ SQLITE_MAX_LIKE_PATTERN_LENGTH );
+ assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER);
+ assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH );
+ assert( SQLITE_LIMIT_TRIGGER_DEPTH==(SQLITE_N_LIMIT-1) );
+
+
+ if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
+ return -1;
+ }
+ oldLimit = db->aLimit[limitId];
+ if( newLimit>=0 ){ /* IMP: R-52476-28732 */
+ if( newLimit>aHardLimit[limitId] ){
+ newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
+ }
+ db->aLimit[limitId] = newLimit;
+ }
+ return oldLimit; /* IMP: R-53341-35419 */
+}
+
+/*
+** This function is used to parse both URIs and non-URI filenames passed by the
+** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
+** URIs specified as part of ATTACH statements.
+**
+** The first argument to this function is the name of the VFS to use (or
+** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
+** query parameter. The second argument contains the URI (or non-URI filename)
+** itself. When this function is called the *pFlags variable should contain
+** the default flags to open the database handle with. The value stored in
+** *pFlags may be updated before returning if the URI filename contains
+** "cache=xxx" or "mode=xxx" query parameters.
+**
+** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
+** the VFS that should be used to open the database file. *pzFile is set to
+** point to a buffer containing the name of the file to open. It is the
+** responsibility of the caller to eventually call sqlite3_free() to release
+** this buffer.
+**
+** If an error occurs, then an SQLite error code is returned and *pzErrMsg
+** may be set to point to a buffer containing an English language error
+** message. It is the responsibility of the caller to eventually release
+** this buffer by calling sqlite3_free().
+*/
+SQLITE_PRIVATE int sqlite3ParseUri(
+ const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
+ const char *zUri, /* Nul-terminated URI to parse */
+ unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
+ sqlite3_vfs **ppVfs, /* OUT: VFS to use */
+ char **pzFile, /* OUT: Filename component of URI */
+ char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
+){
+ int rc = SQLITE_OK;
+ unsigned int flags = *pFlags;
+ const char *zVfs = zDefaultVfs;
+ char *zFile;
+ char c;
+ int nUri = sqlite3Strlen30(zUri);
+
+ assert( *pzErrMsg==0 );
+
+ if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
+ && nUri>=5 && memcmp(zUri, "file:", 5)==0
+ ){
+ char *zOpt;
+ int eState; /* Parser state when parsing URI */
+ int iIn; /* Input character index */
+ int iOut = 0; /* Output character index */
+ int nByte = nUri+2; /* Bytes of space to allocate */
+
+ /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
+ ** method that there may be extra parameters following the file-name. */
+ flags |= SQLITE_OPEN_URI;
+
+ for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
+ zFile = sqlite3_malloc(nByte);
+ if( !zFile ) return SQLITE_NOMEM;
+
+ /* Discard the scheme and authority segments of the URI. */
+ if( zUri[5]=='/' && zUri[6]=='/' ){
+ iIn = 7;
+ while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
+
+ if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
+ *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
+ iIn-7, &zUri[7]);
+ rc = SQLITE_ERROR;
+ goto parse_uri_out;
+ }
+ }else{
+ iIn = 5;
+ }
+
+ /* Copy the filename and any query parameters into the zFile buffer.
+ ** Decode %HH escape codes along the way.
+ **
+ ** Within this loop, variable eState may be set to 0, 1 or 2, depending
+ ** on the parsing context. As follows:
+ **
+ ** 0: Parsing file-name.
+ ** 1: Parsing name section of a name=value query parameter.
+ ** 2: Parsing value section of a name=value query parameter.
+ */
+ eState = 0;
+ while( (c = zUri[iIn])!=0 && c!='#' ){
+ iIn++;
+ if( c=='%'
+ && sqlite3Isxdigit(zUri[iIn])
+ && sqlite3Isxdigit(zUri[iIn+1])
+ ){
+ int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
+ octet += sqlite3HexToInt(zUri[iIn++]);
+
+ assert( octet>=0 && octet<256 );
+ if( octet==0 ){
+ /* This branch is taken when "%00" appears within the URI. In this
+ ** case we ignore all text in the remainder of the path, name or
+ ** value currently being parsed. So ignore the current character
+ ** and skip to the next "?", "=" or "&", as appropriate. */
+ while( (c = zUri[iIn])!=0 && c!='#'
+ && (eState!=0 || c!='?')
+ && (eState!=1 || (c!='=' && c!='&'))
+ && (eState!=2 || c!='&')
+ ){
+ iIn++;
+ }
+ continue;
+ }
+ c = octet;
+ }else if( eState==1 && (c=='&' || c=='=') ){
+ if( zFile[iOut-1]==0 ){
+ /* An empty option name. Ignore this option altogether. */
+ while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
+ continue;
+ }
+ if( c=='&' ){
+ zFile[iOut++] = '\0';
+ }else{
+ eState = 2;
+ }
+ c = 0;
+ }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
+ c = 0;
+ eState = 1;
+ }
+ zFile[iOut++] = c;
+ }
+ if( eState==1 ) zFile[iOut++] = '\0';
+ zFile[iOut++] = '\0';
+ zFile[iOut++] = '\0';
+
+ /* Check if there were any options specified that should be interpreted
+ ** here. Options that are interpreted here include "vfs" and those that
+ ** correspond to flags that may be passed to the sqlite3_open_v2()
+ ** method. */
+ zOpt = &zFile[sqlite3Strlen30(zFile)+1];
+ while( zOpt[0] ){
+ int nOpt = sqlite3Strlen30(zOpt);
+ char *zVal = &zOpt[nOpt+1];
+ int nVal = sqlite3Strlen30(zVal);
+
+ if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
+ zVfs = zVal;
+ }else{
+ struct OpenMode {
+ const char *z;
+ int mode;
+ } *aMode = 0;
+ char *zModeType = 0;
+ int mask = 0;
+ int limit = 0;
+
+ if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
+ static struct OpenMode aCacheMode[] = {
+ { "shared", SQLITE_OPEN_SHAREDCACHE },
+ { "private", SQLITE_OPEN_PRIVATECACHE },
+ { 0, 0 }
+ };
+
+ mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
+ aMode = aCacheMode;
+ limit = mask;
+ zModeType = "cache";
+ }
+ if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
+ static struct OpenMode aOpenMode[] = {
+ { "ro", SQLITE_OPEN_READONLY },
+ { "rw", SQLITE_OPEN_READWRITE },
+ { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
+ { "memory", SQLITE_OPEN_MEMORY },
+ { 0, 0 }
+ };
+
+ mask = SQLITE_OPEN_READONLY | SQLITE_OPEN_READWRITE
+ | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY;
+ aMode = aOpenMode;
+ limit = mask & flags;
+ zModeType = "access";
+ }
+
+ if( aMode ){
+ int i;
+ int mode = 0;
+ for(i=0; aMode[i].z; i++){
+ const char *z = aMode[i].z;
+ if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
+ mode = aMode[i].mode;
+ break;
+ }
+ }
+ if( mode==0 ){
+ *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
+ rc = SQLITE_ERROR;
+ goto parse_uri_out;
+ }
+ if( (mode & ~SQLITE_OPEN_MEMORY)>limit ){
+ *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
+ zModeType, zVal);
+ rc = SQLITE_PERM;
+ goto parse_uri_out;
+ }
+ flags = (flags & ~mask) | mode;
+ }
+ }
+
+ zOpt = &zVal[nVal+1];
+ }
+
+ }else{
+ zFile = sqlite3_malloc(nUri+2);
+ if( !zFile ) return SQLITE_NOMEM;
+ memcpy(zFile, zUri, nUri);
+ zFile[nUri] = '\0';
+ zFile[nUri+1] = '\0';
+ flags &= ~SQLITE_OPEN_URI;
+ }
+
+ *ppVfs = sqlite3_vfs_find(zVfs);
+ if( *ppVfs==0 ){
+ *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
+ rc = SQLITE_ERROR;
+ }
+ parse_uri_out:
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(zFile);
+ zFile = 0;
+ }
+ *pFlags = flags;
+ *pzFile = zFile;
+ return rc;
+}
+
+
+/*
+** This routine does the work of opening a database on behalf of
+** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
+** is UTF-8 encoded.
+*/
+static int openDatabase(
+ const char *zFilename, /* Database filename UTF-8 encoded */
+ sqlite3 **ppDb, /* OUT: Returned database handle */
+ unsigned int flags, /* Operational flags */
+ const char *zVfs /* Name of the VFS to use */
+){
+ sqlite3 *db; /* Store allocated handle here */
+ int rc; /* Return code */
+ int isThreadsafe; /* True for threadsafe connections */
+ char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
+ char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
+
+ *ppDb = 0;
+#ifndef SQLITE_OMIT_AUTOINIT
+ rc = sqlite3_initialize();
+ if( rc ) return rc;
+#endif
+
+ /* Only allow sensible combinations of bits in the flags argument.
+ ** Throw an error if any non-sense combination is used. If we
+ ** do not block illegal combinations here, it could trigger
+ ** assert() statements in deeper layers. Sensible combinations
+ ** are:
+ **
+ ** 1: SQLITE_OPEN_READONLY
+ ** 2: SQLITE_OPEN_READWRITE
+ ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
+ */
+ assert( SQLITE_OPEN_READONLY == 0x01 );
+ assert( SQLITE_OPEN_READWRITE == 0x02 );
+ assert( SQLITE_OPEN_CREATE == 0x04 );
+ testcase( (1<<(flags&7))==0x02 ); /* READONLY */
+ testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
+ testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
+ if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;
+
+ if( sqlite3GlobalConfig.bCoreMutex==0 ){
+ isThreadsafe = 0;
+ }else if( flags & SQLITE_OPEN_NOMUTEX ){
+ isThreadsafe = 0;
+ }else if( flags & SQLITE_OPEN_FULLMUTEX ){
+ isThreadsafe = 1;
+ }else{
+ isThreadsafe = sqlite3GlobalConfig.bFullMutex;
+ }
+ if( flags & SQLITE_OPEN_PRIVATECACHE ){
+ flags &= ~SQLITE_OPEN_SHAREDCACHE;
+ }else if( sqlite3GlobalConfig.sharedCacheEnabled ){
+ flags |= SQLITE_OPEN_SHAREDCACHE;
+ }
+
+ /* Remove harmful bits from the flags parameter
+ **
+ ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were
+ ** dealt with in the previous code block. Besides these, the only
+ ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY,
+ ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
+ ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
+ ** off all other flags.
+ */
+ flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
+ SQLITE_OPEN_EXCLUSIVE |
+ SQLITE_OPEN_MAIN_DB |
+ SQLITE_OPEN_TEMP_DB |
+ SQLITE_OPEN_TRANSIENT_DB |
+ SQLITE_OPEN_MAIN_JOURNAL |
+ SQLITE_OPEN_TEMP_JOURNAL |
+ SQLITE_OPEN_SUBJOURNAL |
+ SQLITE_OPEN_MASTER_JOURNAL |
+ SQLITE_OPEN_NOMUTEX |
+ SQLITE_OPEN_FULLMUTEX |
+ SQLITE_OPEN_WAL
+ );
+
+ /* Allocate the sqlite data structure */
+ db = sqlite3MallocZero( sizeof(sqlite3) );
+ if( db==0 ) goto opendb_out;
+ if( isThreadsafe ){
+ db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+ if( db->mutex==0 ){
+ sqlite3_free(db);
+ db = 0;
+ goto opendb_out;
+ }
+ }
+ sqlite3_mutex_enter(db->mutex);
+ db->errMask = 0xff;
+ db->nDb = 2;
+ db->magic = SQLITE_MAGIC_BUSY;
+ db->aDb = db->aDbStatic;
+
+ assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
+ memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
+ db->autoCommit = 1;
+ db->nextAutovac = -1;
+ db->nextPagesize = 0;
+ db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
+#if SQLITE_DEFAULT_FILE_FORMAT<4
+ | SQLITE_LegacyFileFmt
+#endif
+#ifdef SQLITE_ENABLE_LOAD_EXTENSION
+ | SQLITE_LoadExtension
+#endif
+#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
+ | SQLITE_RecTriggers
+#endif
+#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS
+ | SQLITE_ForeignKeys
+#endif
+ ;
+ sqlite3HashInit(&db->aCollSeq);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3HashInit(&db->aModule);
+#endif
+
+ /* Add the default collation sequence BINARY. BINARY works for both UTF-8
+ ** and UTF-16, so add a version for each to avoid any unnecessary
+ ** conversions. The only error that can occur here is a malloc() failure.
+ */
+ createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0);
+ createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0);
+ createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
+ createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
+ if( db->mallocFailed ){
+ goto opendb_out;
+ }
+ db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
+ assert( db->pDfltColl!=0 );
+
+ /* Also add a UTF-8 case-insensitive collation sequence. */
+ createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
+
+ /* Parse the filename/URI argument. */
+ db->openFlags = flags;
+ rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+ sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
+ sqlite3_free(zErrMsg);
+ goto opendb_out;
+ }
+
+ /* Open the backend database driver */
+ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
+ flags | SQLITE_OPEN_MAIN_DB);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_IOERR_NOMEM ){
+ rc = SQLITE_NOMEM;
+ }
+ sqlite3Error(db, rc, 0);
+ goto opendb_out;
+ }
+ db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
+ db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
+
+
+ /* The default safety_level for the main database is 'full'; for the temp
+ ** database it is 'NONE'. This matches the pager layer defaults.
+ */
+ db->aDb[0].zName = "main";
+ db->aDb[0].safety_level = 3;
+ db->aDb[1].zName = "temp";
+ db->aDb[1].safety_level = 1;
+
+ db->magic = SQLITE_MAGIC_OPEN;
+ if( db->mallocFailed ){
+ goto opendb_out;
+ }
+
+ /* Register all built-in functions, but do not attempt to read the
+ ** database schema yet. This is delayed until the first time the database
+ ** is accessed.
+ */
+ sqlite3Error(db, SQLITE_OK, 0);
+ sqlite3RegisterBuiltinFunctions(db);
+
+ /* Load automatic extensions - extensions that have been registered
+ ** using the sqlite3_automatic_extension() API.
+ */
+ rc = sqlite3_errcode(db);
+ if( rc==SQLITE_OK ){
+ sqlite3AutoLoadExtensions(db);
+ rc = sqlite3_errcode(db);
+ if( rc!=SQLITE_OK ){
+ goto opendb_out;
+ }
+ }
+
+#ifdef SQLITE_ENABLE_FTS1
+ if( !db->mallocFailed ){
+ extern int sqlite3Fts1Init(sqlite3*);
+ rc = sqlite3Fts1Init(db);
+ }
+#endif
+
+#ifdef SQLITE_ENABLE_FTS2
+ if( !db->mallocFailed && rc==SQLITE_OK ){
+ extern int sqlite3Fts2Init(sqlite3*);
+ rc = sqlite3Fts2Init(db);
+ }
+#endif
+
+#ifdef SQLITE_ENABLE_FTS3
+ if( !db->mallocFailed && rc==SQLITE_OK ){
+ rc = sqlite3Fts3Init(db);
+ }
+#endif
+
+#ifdef SQLITE_ENABLE_ICU
+ if( !db->mallocFailed && rc==SQLITE_OK ){
+ rc = sqlite3IcuInit(db);
+ }
+#endif
+
+#ifdef SQLITE_ENABLE_RTREE
+ if( !db->mallocFailed && rc==SQLITE_OK){
+ rc = sqlite3RtreeInit(db);
+ }
+#endif
+
+ sqlite3Error(db, rc, 0);
+
+ /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
+ ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
+ ** mode. Doing nothing at all also makes NORMAL the default.
+ */
+#ifdef SQLITE_DEFAULT_LOCKING_MODE
+ db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE;
+ sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt),
+ SQLITE_DEFAULT_LOCKING_MODE);
+#endif
+
+ /* Enable the lookaside-malloc subsystem */
+ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
+ sqlite3GlobalConfig.nLookaside);
+
+ sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
+
+opendb_out:
+ sqlite3_free(zOpen);
+ if( db ){
+ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
+ sqlite3_mutex_leave(db->mutex);
+ }
+ rc = sqlite3_errcode(db);
+ assert( db!=0 || rc==SQLITE_NOMEM );
+ if( rc==SQLITE_NOMEM ){
+ sqlite3_close(db);
+ db = 0;
+ }else if( rc!=SQLITE_OK ){
+ db->magic = SQLITE_MAGIC_SICK;
+ }
+ *ppDb = db;
+#ifdef SQLITE_ENABLE_SQLLOG
+ if( sqlite3GlobalConfig.xSqllog ){
+ /* Opening a db handle. Fourth parameter is passed 0. */
+ void *pArg = sqlite3GlobalConfig.pSqllogArg;
+ sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
+ }
+#endif
+ return sqlite3ApiExit(0, rc);
+}
+
+/*
+** Open a new database handle.
+*/
+SQLITE_API int sqlite3_open(
+ const char *zFilename,
+ sqlite3 **ppDb
+){
+ return openDatabase(zFilename, ppDb,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
+}
+SQLITE_API int sqlite3_open_v2(
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb, /* OUT: SQLite db handle */
+ int flags, /* Flags */
+ const char *zVfs /* Name of VFS module to use */
+){
+ return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
+}
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Open a new database handle.
+*/
+SQLITE_API int sqlite3_open16(
+ const void *zFilename,
+ sqlite3 **ppDb
+){
+ char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */
+ sqlite3_value *pVal;
+ int rc;
+
+ assert( zFilename );
+ assert( ppDb );
+ *ppDb = 0;
+#ifndef SQLITE_OMIT_AUTOINIT
+ rc = sqlite3_initialize();
+ if( rc ) return rc;
+#endif
+ pVal = sqlite3ValueNew(0);
+ sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC);
+ zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
+ if( zFilename8 ){
+ rc = openDatabase(zFilename8, ppDb,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
+ assert( *ppDb || rc==SQLITE_NOMEM );
+ if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
+ ENC(*ppDb) = SQLITE_UTF16NATIVE;
+ }
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ sqlite3ValueFree(pVal);
+
+ return sqlite3ApiExit(0, rc);
+}
+#endif /* SQLITE_OMIT_UTF16 */
+
+/*
+** Register a new collation sequence with the database handle db.
+*/
+SQLITE_API int sqlite3_create_collation(
+ sqlite3* db,
+ const char *zName,
+ int enc,
+ void* pCtx,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+){
+ int rc;
+ sqlite3_mutex_enter(db->mutex);
+ assert( !db->mallocFailed );
+ rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, 0);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** Register a new collation sequence with the database handle db.
+*/
+SQLITE_API int sqlite3_create_collation_v2(
+ sqlite3* db,
+ const char *zName,
+ int enc,
+ void* pCtx,
+ int(*xCompare)(void*,int,const void*,int,const void*),
+ void(*xDel)(void*)
+){
+ int rc;
+ sqlite3_mutex_enter(db->mutex);
+ assert( !db->mallocFailed );
+ rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, xDel);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Register a new collation sequence with the database handle db.
+*/
+SQLITE_API int sqlite3_create_collation16(
+ sqlite3* db,
+ const void *zName,
+ int enc,
+ void* pCtx,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+){
+ int rc = SQLITE_OK;
+ char *zName8;
+ sqlite3_mutex_enter(db->mutex);
+ assert( !db->mallocFailed );
+ zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE);
+ if( zName8 ){
+ rc = createCollation(db, zName8, (u8)enc, pCtx, xCompare, 0);
+ sqlite3DbFree(db, zName8);
+ }
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+#endif /* SQLITE_OMIT_UTF16 */
+
+/*
+** Register a collation sequence factory callback with the database handle
+** db. Replace any previously installed collation sequence factory.
+*/
+SQLITE_API int sqlite3_collation_needed(
+ sqlite3 *db,
+ void *pCollNeededArg,
+ void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*)
+){
+ sqlite3_mutex_enter(db->mutex);
+ db->xCollNeeded = xCollNeeded;
+ db->xCollNeeded16 = 0;
+ db->pCollNeededArg = pCollNeededArg;
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Register a collation sequence factory callback with the database handle
+** db. Replace any previously installed collation sequence factory.
+*/
+SQLITE_API int sqlite3_collation_needed16(
+ sqlite3 *db,
+ void *pCollNeededArg,
+ void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*)
+){
+ sqlite3_mutex_enter(db->mutex);
+ db->xCollNeeded = 0;
+ db->xCollNeeded16 = xCollNeeded16;
+ db->pCollNeededArg = pCollNeededArg;
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+#endif /* SQLITE_OMIT_UTF16 */
+
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** This function is now an anachronism. It used to be used to recover from a
+** malloc() failure, but SQLite now does this automatically.
+*/
+SQLITE_API int sqlite3_global_recover(void){
+ return SQLITE_OK;
+}
+#endif
+
+/*
+** Test to see whether or not the database connection is in autocommit
+** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on
+** by default. Autocommit is disabled by a BEGIN statement and reenabled
+** by the next COMMIT or ROLLBACK.
+**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+*/
+SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
+ return db->autoCommit;
+}
+
+/*
+** The following routines are subtitutes for constants SQLITE_CORRUPT,
+** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error
+** constants. They server two purposes:
+**
+** 1. Serve as a convenient place to set a breakpoint in a debugger
+** to detect when version error conditions occurs.
+**
+** 2. Invoke sqlite3_log() to provide the source code location where
+** a low-level error is first detected.
+*/
+SQLITE_PRIVATE int sqlite3CorruptError(int lineno){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_CORRUPT,
+ "database corruption at line %d of [%.10s]",
+ lineno, 20+sqlite3_sourceid());
+ return SQLITE_CORRUPT;
+}
+SQLITE_PRIVATE int sqlite3MisuseError(int lineno){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_MISUSE,
+ "misuse at line %d of [%.10s]",
+ lineno, 20+sqlite3_sourceid());
+ return SQLITE_MISUSE;
+}
+SQLITE_PRIVATE int sqlite3CantopenError(int lineno){
+ testcase( sqlite3GlobalConfig.xLog!=0 );
+ sqlite3_log(SQLITE_CANTOPEN,
+ "cannot open file at line %d of [%.10s]",
+ lineno, 20+sqlite3_sourceid());
+ return SQLITE_CANTOPEN;
+}
+
+
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** This is a convenience routine that makes sure that all thread-specific
+** data for this thread has been deallocated.
+**
+** SQLite no longer uses thread-specific data so this routine is now a
+** no-op. It is retained for historical compatibility.
+*/
+SQLITE_API void sqlite3_thread_cleanup(void){
+}
+#endif
+
+/*
+** Return meta information about a specific column of a database table.
+** See comment in sqlite3.h (sqlite.h.in) for details.
+*/
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+SQLITE_API int sqlite3_table_column_metadata(
+ sqlite3 *db, /* Connection handle */
+ const char *zDbName, /* Database name or NULL */
+ const char *zTableName, /* Table name */
+ const char *zColumnName, /* Column name */
+ char const **pzDataType, /* OUTPUT: Declared data type */
+ char const **pzCollSeq, /* OUTPUT: Collation sequence name */
+ int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
+ int *pPrimaryKey, /* OUTPUT: True if column part of PK */
+ int *pAutoinc /* OUTPUT: True if column is auto-increment */
+){
+ int rc;
+ char *zErrMsg = 0;
+ Table *pTab = 0;
+ Column *pCol = 0;
+ int iCol;
+
+ char const *zDataType = 0;
+ char const *zCollSeq = 0;
+ int notnull = 0;
+ int primarykey = 0;
+ int autoinc = 0;
+
+ /* Ensure the database schema has been loaded */
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3BtreeEnterAll(db);
+ rc = sqlite3Init(db, &zErrMsg);
+ if( SQLITE_OK!=rc ){
+ goto error_out;
+ }
+
+ /* Locate the table in question */
+ pTab = sqlite3FindTable(db, zTableName, zDbName);
+ if( !pTab || pTab->pSelect ){
+ pTab = 0;
+ goto error_out;
+ }
+
+ /* Find the column for which info is requested */
+ if( sqlite3IsRowid(zColumnName) ){
+ iCol = pTab->iPKey;
+ if( iCol>=0 ){
+ pCol = &pTab->aCol[iCol];
+ }
+ }else{
+ for(iCol=0; iCol<pTab->nCol; iCol++){
+ pCol = &pTab->aCol[iCol];
+ if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
+ break;
+ }
+ }
+ if( iCol==pTab->nCol ){
+ pTab = 0;
+ goto error_out;
+ }
+ }
+
+ /* The following block stores the meta information that will be returned
+ ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
+ ** and autoinc. At this point there are two possibilities:
+ **
+ ** 1. The specified column name was rowid", "oid" or "_rowid_"
+ ** and there is no explicitly declared IPK column.
+ **
+ ** 2. The table is not a view and the column name identified an
+ ** explicitly declared column. Copy meta information from *pCol.
+ */
+ if( pCol ){
+ zDataType = pCol->zType;
+ zCollSeq = pCol->zColl;
+ notnull = pCol->notNull!=0;
+ primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
+ autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
+ }else{
+ zDataType = "INTEGER";
+ primarykey = 1;
+ }
+ if( !zCollSeq ){
+ zCollSeq = "BINARY";
+ }
+
+error_out:
+ sqlite3BtreeLeaveAll(db);
+
+ /* Whether the function call succeeded or failed, set the output parameters
+ ** to whatever their local counterparts contain. If an error did occur,
+ ** this has the effect of zeroing all output parameters.
+ */
+ if( pzDataType ) *pzDataType = zDataType;
+ if( pzCollSeq ) *pzCollSeq = zCollSeq;
+ if( pNotNull ) *pNotNull = notnull;
+ if( pPrimaryKey ) *pPrimaryKey = primarykey;
+ if( pAutoinc ) *pAutoinc = autoinc;
+
+ if( SQLITE_OK==rc && !pTab ){
+ sqlite3DbFree(db, zErrMsg);
+ zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName,
+ zColumnName);
+ rc = SQLITE_ERROR;
+ }
+ sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
+ rc = sqlite3ApiExit(db, rc);
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+#endif
+
+/*
+** Sleep for a little while. Return the amount of time slept.
+*/
+SQLITE_API int sqlite3_sleep(int ms){
+ sqlite3_vfs *pVfs;
+ int rc;
+ pVfs = sqlite3_vfs_find(0);
+ if( pVfs==0 ) return 0;
+
+ /* This function works in milliseconds, but the underlying OsSleep()
+ ** API uses microseconds. Hence the 1000's.
+ */
+ rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);
+ return rc;
+}
+
+/*
+** Enable or disable the extended result codes.
+*/
+SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
+ sqlite3_mutex_enter(db->mutex);
+ db->errMask = onoff ? 0xffffffff : 0xff;
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+
+/*
+** Invoke the xFileControl method on a particular database.
+*/
+SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
+ int rc = SQLITE_ERROR;
+ Btree *pBtree;
+
+ sqlite3_mutex_enter(db->mutex);
+ pBtree = sqlite3DbNameToBtree(db, zDbName);
+ if( pBtree ){
+ Pager *pPager;
+ sqlite3_file *fd;
+ sqlite3BtreeEnter(pBtree);
+ pPager = sqlite3BtreePager(pBtree);
+ assert( pPager!=0 );
+ fd = sqlite3PagerFile(pPager);
+ assert( fd!=0 );
+ if( op==SQLITE_FCNTL_FILE_POINTER ){
+ *(sqlite3_file**)pArg = fd;
+ rc = SQLITE_OK;
+ }else if( fd->pMethods ){
+ rc = sqlite3OsFileControl(fd, op, pArg);
+ }else{
+ rc = SQLITE_NOTFOUND;
+ }
+ sqlite3BtreeLeave(pBtree);
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** Interface to the testing logic.
+*/
+SQLITE_API int sqlite3_test_control(int op, ...){
+ int rc = 0;
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+ va_list ap;
+ va_start(ap, op);
+ switch( op ){
+
+ /*
+ ** Save the current state of the PRNG.
+ */
+ case SQLITE_TESTCTRL_PRNG_SAVE: {
+ sqlite3PrngSaveState();
+ break;
+ }
+
+ /*
+ ** Restore the state of the PRNG to the last state saved using
+ ** PRNG_SAVE. If PRNG_SAVE has never before been called, then
+ ** this verb acts like PRNG_RESET.
+ */
+ case SQLITE_TESTCTRL_PRNG_RESTORE: {
+ sqlite3PrngRestoreState();
+ break;
+ }
+
+ /*
+ ** Reset the PRNG back to its uninitialized state. The next call
+ ** to sqlite3_randomness() will reseed the PRNG using a single call
+ ** to the xRandomness method of the default VFS.
+ */
+ case SQLITE_TESTCTRL_PRNG_RESET: {
+ sqlite3PrngResetState();
+ break;
+ }
+
+ /*
+ ** sqlite3_test_control(BITVEC_TEST, size, program)
+ **
+ ** Run a test against a Bitvec object of size. The program argument
+ ** is an array of integers that defines the test. Return -1 on a
+ ** memory allocation error, 0 on success, or non-zero for an error.
+ ** See the sqlite3BitvecBuiltinTest() for additional information.
+ */
+ case SQLITE_TESTCTRL_BITVEC_TEST: {
+ int sz = va_arg(ap, int);
+ int *aProg = va_arg(ap, int*);
+ rc = sqlite3BitvecBuiltinTest(sz, aProg);
+ break;
+ }
+
+ /*
+ ** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
+ **
+ ** Register hooks to call to indicate which malloc() failures
+ ** are benign.
+ */
+ case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
+ typedef void (*void_function)(void);
+ void_function xBenignBegin;
+ void_function xBenignEnd;
+ xBenignBegin = va_arg(ap, void_function);
+ xBenignEnd = va_arg(ap, void_function);
+ sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd);
+ break;
+ }
+
+ /*
+ ** sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X)
+ **
+ ** Set the PENDING byte to the value in the argument, if X>0.
+ ** Make no changes if X==0. Return the value of the pending byte
+ ** as it existing before this routine was called.
+ **
+ ** IMPORTANT: Changing the PENDING byte from 0x40000000 results in
+ ** an incompatible database file format. Changing the PENDING byte
+ ** while any database connection is open results in undefined and
+ ** dileterious behavior.
+ */
+ case SQLITE_TESTCTRL_PENDING_BYTE: {
+ rc = PENDING_BYTE;
+#ifndef SQLITE_OMIT_WSD
+ {
+ unsigned int newVal = va_arg(ap, unsigned int);
+ if( newVal ) sqlite3PendingByte = newVal;
+ }
+#endif
+ break;
+ }
+
+ /*
+ ** sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, int X)
+ **
+ ** This action provides a run-time test to see whether or not
+ ** assert() was enabled at compile-time. If X is true and assert()
+ ** is enabled, then the return value is true. If X is true and
+ ** assert() is disabled, then the return value is zero. If X is
+ ** false and assert() is enabled, then the assertion fires and the
+ ** process aborts. If X is false and assert() is disabled, then the
+ ** return value is zero.
+ */
+ case SQLITE_TESTCTRL_ASSERT: {
+ volatile int x = 0;
+ assert( (x = va_arg(ap,int))!=0 );
+ rc = x;
+ break;
+ }
+
+
+ /*
+ ** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X)
+ **
+ ** This action provides a run-time test to see how the ALWAYS and
+ ** NEVER macros were defined at compile-time.
+ **
+ ** The return value is ALWAYS(X).
+ **
+ ** The recommended test is X==2. If the return value is 2, that means
+ ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the
+ ** default setting. If the return value is 1, then ALWAYS() is either
+ ** hard-coded to true or else it asserts if its argument is false.
+ ** The first behavior (hard-coded to true) is the case if
+ ** SQLITE_TESTCTRL_ASSERT shows that assert() is disabled and the second
+ ** behavior (assert if the argument to ALWAYS() is false) is the case if
+ ** SQLITE_TESTCTRL_ASSERT shows that assert() is enabled.
+ **
+ ** The run-time test procedure might look something like this:
+ **
+ ** if( sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, 2)==2 ){
+ ** // ALWAYS() and NEVER() are no-op pass-through macros
+ ** }else if( sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, 1) ){
+ ** // ALWAYS(x) asserts that x is true. NEVER(x) asserts x is false.
+ ** }else{
+ ** // ALWAYS(x) is a constant 1. NEVER(x) is a constant 0.
+ ** }
+ */
+ case SQLITE_TESTCTRL_ALWAYS: {
+ int x = va_arg(ap,int);
+ rc = ALWAYS(x);
+ break;
+ }
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
+ **
+ ** Set the nReserve size to N for the main database on the database
+ ** connection db.
+ */
+ case SQLITE_TESTCTRL_RESERVE: {
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ int x = va_arg(ap,int);
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0);
+ sqlite3_mutex_leave(db->mutex);
+ break;
+ }
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
+ **
+ ** Enable or disable various optimizations for testing purposes. The
+ ** argument N is a bitmask of optimizations to be disabled. For normal
+ ** operation N should be 0. The idea is that a test program (like the
+ ** SQL Logic Test or SLT test module) can run the same SQL multiple times
+ ** with various optimizations disabled to verify that the same answer
+ ** is obtained in every case.
+ */
+ case SQLITE_TESTCTRL_OPTIMIZATIONS: {
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
+ break;
+ }
+
+#ifdef SQLITE_N_KEYWORD
+ /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord)
+ **
+ ** If zWord is a keyword recognized by the parser, then return the
+ ** number of keywords. Or if zWord is not a keyword, return 0.
+ **
+ ** This test feature is only available in the amalgamation since
+ ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite
+ ** is built using separate source files.
+ */
+ case SQLITE_TESTCTRL_ISKEYWORD: {
+ const char *zWord = va_arg(ap, const char*);
+ int n = sqlite3Strlen30(zWord);
+ rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0;
+ break;
+ }
+#endif
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree);
+ **
+ ** Pass pFree into sqlite3ScratchFree().
+ ** If sz>0 then allocate a scratch buffer into pNew.
+ */
+ case SQLITE_TESTCTRL_SCRATCHMALLOC: {
+ void *pFree, **ppNew;
+ int sz;
+ sz = va_arg(ap, int);
+ ppNew = va_arg(ap, void**);
+ pFree = va_arg(ap, void*);
+ if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
+ sqlite3ScratchFree(pFree);
+ break;
+ }
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
+ **
+ ** If parameter onoff is non-zero, configure the wrappers so that all
+ ** subsequent calls to localtime() and variants fail. If onoff is zero,
+ ** undo this setting.
+ */
+ case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
+ sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
+ break;
+ }
+
+#if defined(SQLITE_ENABLE_TREE_EXPLAIN)
+ /* sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT,
+ ** sqlite3_stmt*,const char**);
+ **
+ ** If compiled with SQLITE_ENABLE_TREE_EXPLAIN, each sqlite3_stmt holds
+ ** a string that describes the optimized parse tree. This test-control
+ ** returns a pointer to that string.
+ */
+ case SQLITE_TESTCTRL_EXPLAIN_STMT: {
+ sqlite3_stmt *pStmt = va_arg(ap, sqlite3_stmt*);
+ const char **pzRet = va_arg(ap, const char**);
+ *pzRet = sqlite3VdbeExplanation((Vdbe*)pStmt);
+ break;
+ }
+#endif
+
+ }
+ va_end(ap);
+#endif /* SQLITE_OMIT_BUILTIN_TEST */
+ return rc;
+}
+
+/*
+** This is a utility routine, useful to VFS implementations, that checks
+** to see if a database file was a URI that contained a specific query
+** parameter, and if so obtains the value of the query parameter.
+**
+** The zFilename argument is the filename pointer passed into the xOpen()
+** method of a VFS implementation. The zParam argument is the name of the
+** query parameter we seek. This routine returns the value of the zParam
+** parameter if it exists. If the parameter does not exist, this routine
+** returns a NULL pointer.
+*/
+SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
+ if( zFilename==0 ) return 0;
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ while( zFilename[0] ){
+ int x = strcmp(zFilename, zParam);
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ if( x==0 ) return zFilename;
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ }
+ return 0;
+}
+
+/*
+** Return a boolean value for a query parameter.
+*/
+SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
+ const char *z = sqlite3_uri_parameter(zFilename, zParam);
+ bDflt = bDflt!=0;
+ return z ? sqlite3GetBoolean(z, bDflt) : bDflt;
+}
+
+/*
+** Return a 64-bit integer value for a query parameter.
+*/
+SQLITE_API sqlite3_int64 sqlite3_uri_int64(
+ const char *zFilename, /* Filename as passed to xOpen */
+ const char *zParam, /* URI parameter sought */
+ sqlite3_int64 bDflt /* return if parameter is missing */
+){
+ const char *z = sqlite3_uri_parameter(zFilename, zParam);
+ sqlite3_int64 v;
+ if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
+ bDflt = v;
+ }
+ return bDflt;
+}
+
+/*
+** Return the Btree pointer identified by zDbName. Return NULL if not found.
+*/
+SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
+ int i;
+ for(i=0; i<db->nDb; i++){
+ if( db->aDb[i].pBt
+ && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0)
+ ){
+ return db->aDb[i].pBt;
+ }
+ }
+ return 0;
+}
+
+/*
+** Return the filename of the database associated with a database
+** connection.
+*/
+SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
+ Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
+ return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
+}
+
+/*
+** Return 1 if database is read-only or 0 if read/write. Return -1 if
+** no such database exists.
+*/
+SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
+ Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
+ return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
+}
+
+/************** End of main.c ************************************************/
+/************** Begin file notify.c ******************************************/
+/*
+** 2009 March 3
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains the implementation of the sqlite3_unlock_notify()
+** API method and its associated functionality.
+*/
+
+/* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+
+/*
+** Public interfaces:
+**
+** sqlite3ConnectionBlocked()
+** sqlite3ConnectionUnlocked()
+** sqlite3ConnectionClosed()
+** sqlite3_unlock_notify()
+*/
+
+#define assertMutexHeld() \
+ assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) )
+
+/*
+** Head of a linked list of all sqlite3 objects created by this process
+** for which either sqlite3.pBlockingConnection or sqlite3.pUnlockConnection
+** is not NULL. This variable may only accessed while the STATIC_MASTER
+** mutex is held.
+*/
+static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0;
+
+#ifndef NDEBUG
+/*
+** This function is a complex assert() that verifies the following
+** properties of the blocked connections list:
+**
+** 1) Each entry in the list has a non-NULL value for either
+** pUnlockConnection or pBlockingConnection, or both.
+**
+** 2) All entries in the list that share a common value for
+** xUnlockNotify are grouped together.
+**
+** 3) If the argument db is not NULL, then none of the entries in the
+** blocked connections list have pUnlockConnection or pBlockingConnection
+** set to db. This is used when closing connection db.
+*/
+static void checkListProperties(sqlite3 *db){
+ sqlite3 *p;
+ for(p=sqlite3BlockedList; p; p=p->pNextBlocked){
+ int seen = 0;
+ sqlite3 *p2;
+
+ /* Verify property (1) */
+ assert( p->pUnlockConnection || p->pBlockingConnection );
+
+ /* Verify property (2) */
+ for(p2=sqlite3BlockedList; p2!=p; p2=p2->pNextBlocked){
+ if( p2->xUnlockNotify==p->xUnlockNotify ) seen = 1;
+ assert( p2->xUnlockNotify==p->xUnlockNotify || !seen );
+ assert( db==0 || p->pUnlockConnection!=db );
+ assert( db==0 || p->pBlockingConnection!=db );
+ }
+ }
+}
+#else
+# define checkListProperties(x)
+#endif
+
+/*
+** Remove connection db from the blocked connections list. If connection
+** db is not currently a part of the list, this function is a no-op.
+*/
+static void removeFromBlockedList(sqlite3 *db){
+ sqlite3 **pp;
+ assertMutexHeld();
+ for(pp=&sqlite3BlockedList; *pp; pp = &(*pp)->pNextBlocked){
+ if( *pp==db ){
+ *pp = (*pp)->pNextBlocked;
+ break;
+ }
+ }
+}
+
+/*
+** Add connection db to the blocked connections list. It is assumed
+** that it is not already a part of the list.
+*/
+static void addToBlockedList(sqlite3 *db){
+ sqlite3 **pp;
+ assertMutexHeld();
+ for(
+ pp=&sqlite3BlockedList;
+ *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
+ pp=&(*pp)->pNextBlocked
+ );
+ db->pNextBlocked = *pp;
+ *pp = db;
+}
+
+/*
+** Obtain the STATIC_MASTER mutex.
+*/
+static void enterMutex(void){
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+ checkListProperties(0);
+}
+
+/*
+** Release the STATIC_MASTER mutex.
+*/
+static void leaveMutex(void){
+ assertMutexHeld();
+ checkListProperties(0);
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+}
+
+/*
+** Register an unlock-notify callback.
+**
+** This is called after connection "db" has attempted some operation
+** but has received an SQLITE_LOCKED error because another connection
+** (call it pOther) in the same process was busy using the same shared
+** cache. pOther is found by looking at db->pBlockingConnection.
+**
+** If there is no blocking connection, the callback is invoked immediately,
+** before this routine returns.
+**
+** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate
+** a deadlock.
+**
+** Otherwise, make arrangements to invoke xNotify when pOther drops
+** its locks.
+**
+** Each call to this routine overrides any prior callbacks registered
+** on the same "db". If xNotify==0 then any prior callbacks are immediately
+** cancelled.
+*/
+SQLITE_API int sqlite3_unlock_notify(
+ sqlite3 *db,
+ void (*xNotify)(void **, int),
+ void *pArg
+){
+ int rc = SQLITE_OK;
+
+ sqlite3_mutex_enter(db->mutex);
+ enterMutex();
+
+ if( xNotify==0 ){
+ removeFromBlockedList(db);
+ db->pBlockingConnection = 0;
+ db->pUnlockConnection = 0;
+ db->xUnlockNotify = 0;
+ db->pUnlockArg = 0;
+ }else if( 0==db->pBlockingConnection ){
+ /* The blocking transaction has been concluded. Or there never was a
+ ** blocking transaction. In either case, invoke the notify callback
+ ** immediately.
+ */
+ xNotify(&pArg, 1);
+ }else{
+ sqlite3 *p;
+
+ for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){}
+ if( p ){
+ rc = SQLITE_LOCKED; /* Deadlock detected. */
+ }else{
+ db->pUnlockConnection = db->pBlockingConnection;
+ db->xUnlockNotify = xNotify;
+ db->pUnlockArg = pArg;
+ removeFromBlockedList(db);
+ addToBlockedList(db);
+ }
+ }
+
+ leaveMutex();
+ assert( !db->mallocFailed );
+ sqlite3Error(db, rc, (rc?"database is deadlocked":0));
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+}
+
+/*
+** This function is called while stepping or preparing a statement
+** associated with connection db. The operation will return SQLITE_LOCKED
+** to the user because it requires a lock that will not be available
+** until connection pBlocker concludes its current transaction.
+*/
+SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
+ enterMutex();
+ if( db->pBlockingConnection==0 && db->pUnlockConnection==0 ){
+ addToBlockedList(db);
+ }
+ db->pBlockingConnection = pBlocker;
+ leaveMutex();
+}
+
+/*
+** This function is called when
+** the transaction opened by database db has just finished. Locks held
+** by database connection db have been released.
+**
+** This function loops through each entry in the blocked connections
+** list and does the following:
+**
+** 1) If the sqlite3.pBlockingConnection member of a list entry is
+** set to db, then set pBlockingConnection=0.
+**
+** 2) If the sqlite3.pUnlockConnection member of a list entry is
+** set to db, then invoke the configured unlock-notify callback and
+** set pUnlockConnection=0.
+**
+** 3) If the two steps above mean that pBlockingConnection==0 and
+** pUnlockConnection==0, remove the entry from the blocked connections
+** list.
+*/
+SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db){
+ void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */
+ int nArg = 0; /* Number of entries in aArg[] */
+ sqlite3 **pp; /* Iterator variable */
+ void **aArg; /* Arguments to the unlock callback */
+ void **aDyn = 0; /* Dynamically allocated space for aArg[] */
+ void *aStatic[16]; /* Starter space for aArg[]. No malloc required */
+
+ aArg = aStatic;
+ enterMutex(); /* Enter STATIC_MASTER mutex */
+
+ /* This loop runs once for each entry in the blocked-connections list. */
+ for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){
+ sqlite3 *p = *pp;
+
+ /* Step 1. */
+ if( p->pBlockingConnection==db ){
+ p->pBlockingConnection = 0;
+ }
+
+ /* Step 2. */
+ if( p->pUnlockConnection==db ){
+ assert( p->xUnlockNotify );
+ if( p->xUnlockNotify!=xUnlockNotify && nArg!=0 ){
+ xUnlockNotify(aArg, nArg);
+ nArg = 0;
+ }
+
+ sqlite3BeginBenignMalloc();
+ assert( aArg==aDyn || (aDyn==0 && aArg==aStatic) );
+ assert( nArg<=(int)ArraySize(aStatic) || aArg==aDyn );
+ if( (!aDyn && nArg==(int)ArraySize(aStatic))
+ || (aDyn && nArg==(int)(sqlite3MallocSize(aDyn)/sizeof(void*)))
+ ){
+ /* The aArg[] array needs to grow. */
+ void **pNew = (void **)sqlite3Malloc(nArg*sizeof(void *)*2);
+ if( pNew ){
+ memcpy(pNew, aArg, nArg*sizeof(void *));
+ sqlite3_free(aDyn);
+ aDyn = aArg = pNew;
+ }else{
+ /* This occurs when the array of context pointers that need to
+ ** be passed to the unlock-notify callback is larger than the
+ ** aStatic[] array allocated on the stack and the attempt to
+ ** allocate a larger array from the heap has failed.
+ **
+ ** This is a difficult situation to handle. Returning an error
+ ** code to the caller is insufficient, as even if an error code
+ ** is returned the transaction on connection db will still be
+ ** closed and the unlock-notify callbacks on blocked connections
+ ** will go unissued. This might cause the application to wait
+ ** indefinitely for an unlock-notify callback that will never
+ ** arrive.
+ **
+ ** Instead, invoke the unlock-notify callback with the context
+ ** array already accumulated. We can then clear the array and
+ ** begin accumulating any further context pointers without
+ ** requiring any dynamic allocation. This is sub-optimal because
+ ** it means that instead of one callback with a large array of
+ ** context pointers the application will receive two or more
+ ** callbacks with smaller arrays of context pointers, which will
+ ** reduce the applications ability to prioritize multiple
+ ** connections. But it is the best that can be done under the
+ ** circumstances.
+ */
+ xUnlockNotify(aArg, nArg);
+ nArg = 0;
+ }
+ }
+ sqlite3EndBenignMalloc();
+
+ aArg[nArg++] = p->pUnlockArg;
+ xUnlockNotify = p->xUnlockNotify;
+ p->pUnlockConnection = 0;
+ p->xUnlockNotify = 0;
+ p->pUnlockArg = 0;
+ }
+
+ /* Step 3. */
+ if( p->pBlockingConnection==0 && p->pUnlockConnection==0 ){
+ /* Remove connection p from the blocked connections list. */
+ *pp = p->pNextBlocked;
+ p->pNextBlocked = 0;
+ }else{
+ pp = &p->pNextBlocked;
+ }
+ }
+
+ if( nArg!=0 ){
+ xUnlockNotify(aArg, nArg);
+ }
+ sqlite3_free(aDyn);
+ leaveMutex(); /* Leave STATIC_MASTER mutex */
+}
+
+/*
+** This is called when the database connection passed as an argument is
+** being closed. The connection is removed from the blocked list.
+*/
+SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
+ sqlite3ConnectionUnlocked(db);
+ enterMutex();
+ removeFromBlockedList(db);
+ checkListProperties(db);
+ leaveMutex();
+}
+#endif
+
+/************** End of notify.c **********************************************/
+/************** Begin file fts3.c ********************************************/
+/*
+** 2006 Oct 10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This is an SQLite module implementing full-text search.
+*/
+
+/*
+** The code in this file is only compiled if:
+**
+** * The FTS3 module is being built as an extension
+** (in which case SQLITE_CORE is not defined), or
+**
+** * The FTS3 module is being built into the core of
+** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
+*/
+
+/* The full-text index is stored in a series of b+tree (-like)
+** structures called segments which map terms to doclists. The
+** structures are like b+trees in layout, but are constructed from the
+** bottom up in optimal fashion and are not updatable. Since trees
+** are built from the bottom up, things will be described from the
+** bottom up.
+**
+**
+**** Varints ****
+** The basic unit of encoding is a variable-length integer called a
+** varint. We encode variable-length integers in little-endian order
+** using seven bits * per byte as follows:
+**
+** KEY:
+** A = 0xxxxxxx 7 bits of data and one flag bit
+** B = 1xxxxxxx 7 bits of data and one flag bit
+**
+** 7 bits - A
+** 14 bits - BA
+** 21 bits - BBA
+** and so on.
+**
+** This is similar in concept to how sqlite encodes "varints" but
+** the encoding is not the same. SQLite varints are big-endian
+** are are limited to 9 bytes in length whereas FTS3 varints are
+** little-endian and can be up to 10 bytes in length (in theory).
+**
+** Example encodings:
+**
+** 1: 0x01
+** 127: 0x7f
+** 128: 0x81 0x00
+**
+**
+**** Document lists ****
+** A doclist (document list) holds a docid-sorted list of hits for a
+** given term. Doclists hold docids and associated token positions.
+** A docid is the unique integer identifier for a single document.
+** A position is the index of a word within the document. The first
+** word of the document has a position of 0.
+**
+** FTS3 used to optionally store character offsets using a compile-time
+** option. But that functionality is no longer supported.
+**
+** A doclist is stored like this:
+**
+** array {
+** varint docid; (delta from previous doclist)
+** array { (position list for column 0)
+** varint position; (2 more than the delta from previous position)
+** }
+** array {
+** varint POS_COLUMN; (marks start of position list for new column)
+** varint column; (index of new column)
+** array {
+** varint position; (2 more than the delta from previous position)
+** }
+** }
+** varint POS_END; (marks end of positions for this document.
+** }
+**
+** Here, array { X } means zero or more occurrences of X, adjacent in
+** memory. A "position" is an index of a token in the token stream
+** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
+** in the same logical place as the position element, and act as sentinals
+** ending a position list array. POS_END is 0. POS_COLUMN is 1.
+** The positions numbers are not stored literally but rather as two more
+** than the difference from the prior position, or the just the position plus
+** 2 for the first position. Example:
+**
+** label: A B C D E F G H I J K
+** value: 123 5 9 1 1 14 35 0 234 72 0
+**
+** The 123 value is the first docid. For column zero in this document
+** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1
+** at D signals the start of a new column; the 1 at E indicates that the
+** new column is column number 1. There are two positions at 12 and 45
+** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The
+** 234 at I is the delta to next docid (357). It has one position 70
+** (72-2) and then terminates with the 0 at K.
+**
+** A "position-list" is the list of positions for multiple columns for
+** a single docid. A "column-list" is the set of positions for a single
+** column. Hence, a position-list consists of one or more column-lists,
+** a document record consists of a docid followed by a position-list and
+** a doclist consists of one or more document records.
+**
+** A bare doclist omits the position information, becoming an
+** array of varint-encoded docids.
+**
+**** Segment leaf nodes ****
+** Segment leaf nodes store terms and doclists, ordered by term. Leaf
+** nodes are written using LeafWriter, and read using LeafReader (to
+** iterate through a single leaf node's data) and LeavesReader (to
+** iterate through a segment's entire leaf layer). Leaf nodes have
+** the format:
+**
+** varint iHeight; (height from leaf level, always 0)
+** varint nTerm; (length of first term)
+** char pTerm[nTerm]; (content of first term)
+** varint nDoclist; (length of term's associated doclist)
+** char pDoclist[nDoclist]; (content of doclist)
+** array {
+** (further terms are delta-encoded)
+** varint nPrefix; (length of prefix shared with previous term)
+** varint nSuffix; (length of unshared suffix)
+** char pTermSuffix[nSuffix];(unshared suffix of next term)
+** varint nDoclist; (length of term's associated doclist)
+** char pDoclist[nDoclist]; (content of doclist)
+** }
+**
+** Here, array { X } means zero or more occurrences of X, adjacent in
+** memory.
+**
+** Leaf nodes are broken into blocks which are stored contiguously in
+** the %_segments table in sorted order. This means that when the end
+** of a node is reached, the next term is in the node with the next
+** greater node id.
+**
+** New data is spilled to a new leaf node when the current node
+** exceeds LEAF_MAX bytes (default 2048). New data which itself is
+** larger than STANDALONE_MIN (default 1024) is placed in a standalone
+** node (a leaf node with a single term and doclist). The goal of
+** these settings is to pack together groups of small doclists while
+** making it efficient to directly access large doclists. The
+** assumption is that large doclists represent terms which are more
+** likely to be query targets.
+**
+** TODO(shess) It may be useful for blocking decisions to be more
+** dynamic. For instance, it may make more sense to have a 2.5k leaf
+** node rather than splitting into 2k and .5k nodes. My intuition is
+** that this might extend through 2x or 4x the pagesize.
+**
+**
+**** Segment interior nodes ****
+** Segment interior nodes store blockids for subtree nodes and terms
+** to describe what data is stored by the each subtree. Interior
+** nodes are written using InteriorWriter, and read using
+** InteriorReader. InteriorWriters are created as needed when
+** SegmentWriter creates new leaf nodes, or when an interior node
+** itself grows too big and must be split. The format of interior
+** nodes:
+**
+** varint iHeight; (height from leaf level, always >0)
+** varint iBlockid; (block id of node's leftmost subtree)
+** optional {
+** varint nTerm; (length of first term)
+** char pTerm[nTerm]; (content of first term)
+** array {
+** (further terms are delta-encoded)
+** varint nPrefix; (length of shared prefix with previous term)
+** varint nSuffix; (length of unshared suffix)
+** char pTermSuffix[nSuffix]; (unshared suffix of next term)
+** }
+** }
+**
+** Here, optional { X } means an optional element, while array { X }
+** means zero or more occurrences of X, adjacent in memory.
+**
+** An interior node encodes n terms separating n+1 subtrees. The
+** subtree blocks are contiguous, so only the first subtree's blockid
+** is encoded. The subtree at iBlockid will contain all terms less
+** than the first term encoded (or all terms if no term is encoded).
+** Otherwise, for terms greater than or equal to pTerm[i] but less
+** than pTerm[i+1], the subtree for that term will be rooted at
+** iBlockid+i. Interior nodes only store enough term data to
+** distinguish adjacent children (if the rightmost term of the left
+** child is "something", and the leftmost term of the right child is
+** "wicked", only "w" is stored).
+**
+** New data is spilled to a new interior node at the same height when
+** the current node exceeds INTERIOR_MAX bytes (default 2048).
+** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing
+** interior nodes and making the tree too skinny. The interior nodes
+** at a given height are naturally tracked by interior nodes at
+** height+1, and so on.
+**
+**
+**** Segment directory ****
+** The segment directory in table %_segdir stores meta-information for
+** merging and deleting segments, and also the root node of the
+** segment's tree.
+**
+** The root node is the top node of the segment's tree after encoding
+** the entire segment, restricted to ROOT_MAX bytes (default 1024).
+** This could be either a leaf node or an interior node. If the top
+** node requires more than ROOT_MAX bytes, it is flushed to %_segments
+** and a new root interior node is generated (which should always fit
+** within ROOT_MAX because it only needs space for 2 varints, the
+** height and the blockid of the previous root).
+**
+** The meta-information in the segment directory is:
+** level - segment level (see below)
+** idx - index within level
+** - (level,idx uniquely identify a segment)
+** start_block - first leaf node
+** leaves_end_block - last leaf node
+** end_block - last block (including interior nodes)
+** root - contents of root node
+**
+** If the root node is a leaf node, then start_block,
+** leaves_end_block, and end_block are all 0.
+**
+**
+**** Segment merging ****
+** To amortize update costs, segments are grouped into levels and
+** merged in batches. Each increase in level represents exponentially
+** more documents.
+**
+** New documents (actually, document updates) are tokenized and
+** written individually (using LeafWriter) to a level 0 segment, with
+** incrementing idx. When idx reaches MERGE_COUNT (default 16), all
+** level 0 segments are merged into a single level 1 segment. Level 1
+** is populated like level 0, and eventually MERGE_COUNT level 1
+** segments are merged to a single level 2 segment (representing
+** MERGE_COUNT^2 updates), and so on.
+**
+** A segment merge traverses all segments at a given level in
+** parallel, performing a straightforward sorted merge. Since segment
+** leaf nodes are written in to the %_segments table in order, this
+** merge traverses the underlying sqlite disk structures efficiently.
+** After the merge, all segment blocks from the merged level are
+** deleted.
+**
+** MERGE_COUNT controls how often we merge segments. 16 seems to be
+** somewhat of a sweet spot for insertion performance. 32 and 64 show
+** very similar performance numbers to 16 on insertion, though they're
+** a tiny bit slower (perhaps due to more overhead in merge-time
+** sorting). 8 is about 20% slower than 16, 4 about 50% slower than
+** 16, 2 about 66% slower than 16.
+**
+** At query time, high MERGE_COUNT increases the number of segments
+** which need to be scanned and merged. For instance, with 100k docs
+** inserted:
+**
+** MERGE_COUNT segments
+** 16 25
+** 8 12
+** 4 10
+** 2 6
+**
+** This appears to have only a moderate impact on queries for very
+** frequent terms (which are somewhat dominated by segment merge
+** costs), and infrequent and non-existent terms still seem to be fast
+** even with many segments.
+**
+** TODO(shess) That said, it would be nice to have a better query-side
+** argument for MERGE_COUNT of 16. Also, it is possible/likely that
+** optimizations to things like doclist merging will swing the sweet
+** spot around.
+**
+**
+**
+**** Handling of deletions and updates ****
+** Since we're using a segmented structure, with no docid-oriented
+** index into the term index, we clearly cannot simply update the term
+** index when a document is deleted or updated. For deletions, we
+** write an empty doclist (varint(docid) varint(POS_END)), for updates
+** we simply write the new doclist. Segment merges overwrite older
+** data for a particular docid with newer data, so deletes or updates
+** will eventually overtake the earlier data and knock it out. The
+** query logic likewise merges doclists so that newer data knocks out
+** older data.
+*/
+
+/************** Include fts3Int.h in the middle of fts3.c ********************/
+/************** Begin file fts3Int.h *****************************************/
+/*
+** 2009 Nov 12
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+*/
+#ifndef _FTSINT_H
+#define _FTSINT_H
+
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+# define NDEBUG 1
+#endif
+
+/*
+** FTS4 is really an extension for FTS3. It is enabled using the
+** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
+** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
+*/
+#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
+# define SQLITE_ENABLE_FTS3
+#endif
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* If not building as part of the core, include sqlite3ext.h. */
+#ifndef SQLITE_CORE
+SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
+#endif
+
+/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
+/************** Begin file fts3_tokenizer.h **********************************/
+/*
+** 2006 July 10
+**
+** The author disclaims copyright to this source code.
+**
+*************************************************************************
+** Defines the interface to tokenizers used by fulltext-search. There
+** are three basic components:
+**
+** sqlite3_tokenizer_module is a singleton defining the tokenizer
+** interface functions. This is essentially the class structure for
+** tokenizers.
+**
+** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
+** including customization information defined at creation time.
+**
+** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
+** tokens from a particular input.
+*/
+#ifndef _FTS3_TOKENIZER_H_
+#define _FTS3_TOKENIZER_H_
+
+/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
+** If tokenizers are to be allowed to call sqlite3_*() functions, then
+** we will need a way to register the API consistently.
+*/
+
+/*
+** Structures used by the tokenizer interface. When a new tokenizer
+** implementation is registered, the caller provides a pointer to
+** an sqlite3_tokenizer_module containing pointers to the callback
+** functions that make up an implementation.
+**
+** When an fts3 table is created, it passes any arguments passed to
+** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
+** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
+** implementation. The xCreate() function in turn returns an
+** sqlite3_tokenizer structure representing the specific tokenizer to
+** be used for the fts3 table (customized by the tokenizer clause arguments).
+**
+** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen()
+** method is called. It returns an sqlite3_tokenizer_cursor object
+** that may be used to tokenize a specific input buffer based on
+** the tokenization rules supplied by a specific sqlite3_tokenizer
+** object.
+*/
+typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
+typedef struct sqlite3_tokenizer sqlite3_tokenizer;
+typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
+
+struct sqlite3_tokenizer_module {
+
+ /*
+ ** Structure version. Should always be set to 0 or 1.
+ */
+ int iVersion;
+
+ /*
+ ** Create a new tokenizer. The values in the argv[] array are the
+ ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL
+ ** TABLE statement that created the fts3 table. For example, if
+ ** the following SQL is executed:
+ **
+ ** CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2)
+ **
+ ** then argc is set to 2, and the argv[] array contains pointers
+ ** to the strings "arg1" and "arg2".
+ **
+ ** This method should return either SQLITE_OK (0), or an SQLite error
+ ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
+ ** to point at the newly created tokenizer structure. The generic
+ ** sqlite3_tokenizer.pModule variable should not be initialized by
+ ** this callback. The caller will do so.
+ */
+ int (*xCreate)(
+ int argc, /* Size of argv array */
+ const char *const*argv, /* Tokenizer argument strings */
+ sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
+ );
+
+ /*
+ ** Destroy an existing tokenizer. The fts3 module calls this method
+ ** exactly once for each successful call to xCreate().
+ */
+ int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
+
+ /*
+ ** Create a tokenizer cursor to tokenize an input buffer. The caller
+ ** is responsible for ensuring that the input buffer remains valid
+ ** until the cursor is closed (using the xClose() method).
+ */
+ int (*xOpen)(
+ sqlite3_tokenizer *pTokenizer, /* Tokenizer object */
+ const char *pInput, int nBytes, /* Input buffer */
+ sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */
+ );
+
+ /*
+ ** Destroy an existing tokenizer cursor. The fts3 module calls this
+ ** method exactly once for each successful call to xOpen().
+ */
+ int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
+
+ /*
+ ** Retrieve the next token from the tokenizer cursor pCursor. This
+ ** method should either return SQLITE_OK and set the values of the
+ ** "OUT" variables identified below, or SQLITE_DONE to indicate that
+ ** the end of the buffer has been reached, or an SQLite error code.
+ **
+ ** *ppToken should be set to point at a buffer containing the
+ ** normalized version of the token (i.e. after any case-folding and/or
+ ** stemming has been performed). *pnBytes should be set to the length
+ ** of this buffer in bytes. The input text that generated the token is
+ ** identified by the byte offsets returned in *piStartOffset and
+ ** *piEndOffset. *piStartOffset should be set to the index of the first
+ ** byte of the token in the input buffer. *piEndOffset should be set
+ ** to the index of the first byte just past the end of the token in
+ ** the input buffer.
+ **
+ ** The buffer *ppToken is set to point at is managed by the tokenizer
+ ** implementation. It is only required to be valid until the next call
+ ** to xNext() or xClose().
+ */
+ /* TODO(shess) current implementation requires pInput to be
+ ** nul-terminated. This should either be fixed, or pInput/nBytes
+ ** should be converted to zInput.
+ */
+ int (*xNext)(
+ sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */
+ const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
+ int *piStartOffset, /* OUT: Byte offset of token in input buffer */
+ int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
+ int *piPosition /* OUT: Number of tokens returned before this one */
+ );
+
+ /***********************************************************************
+ ** Methods below this point are only available if iVersion>=1.
+ */
+
+ /*
+ ** Configure the language id of a tokenizer cursor.
+ */
+ int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
+};
+
+struct sqlite3_tokenizer {
+ const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
+ /* Tokenizer implementations will typically add additional fields */
+};
+
+struct sqlite3_tokenizer_cursor {
+ sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */
+ /* Tokenizer implementations will typically add additional fields */
+};
+
+int fts3_global_term_cnt(int iTerm, int iCol);
+int fts3_term_cnt(int iTerm, int iCol);
+
+
+#endif /* _FTS3_TOKENIZER_H_ */
+
+/************** End of fts3_tokenizer.h **************************************/
+/************** Continuing where we left off in fts3Int.h ********************/
+/************** Include fts3_hash.h in the middle of fts3Int.h ***************/
+/************** Begin file fts3_hash.h ***************************************/
+/*
+** 2001 September 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This is the header file for the generic hash-table implementation
+** used in SQLite. We've modified it slightly to serve as a standalone
+** hash table implementation for the full-text indexing module.
+**
+*/
+#ifndef _FTS3_HASH_H_
+#define _FTS3_HASH_H_
+
+/* Forward declarations of structures. */
+typedef struct Fts3Hash Fts3Hash;
+typedef struct Fts3HashElem Fts3HashElem;
+
+/* A complete hash table is an instance of the following structure.
+** The internals of this structure are intended to be opaque -- client
+** code should not attempt to access or modify the fields of this structure
+** directly. Change this structure only by using the routines below.
+** However, many of the "procedures" and "functions" for modifying and
+** accessing this structure are really macros, so we can't really make
+** this structure opaque.
+*/
+struct Fts3Hash {
+ char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */
+ char copyKey; /* True if copy of key made on insert */
+ int count; /* Number of entries in this table */
+ Fts3HashElem *first; /* The first element of the array */
+ int htsize; /* Number of buckets in the hash table */
+ struct _fts3ht { /* the hash table */
+ int count; /* Number of entries with this hash */
+ Fts3HashElem *chain; /* Pointer to first entry with this hash */
+ } *ht;
+};
+
+/* Each element in the hash table is an instance of the following
+** structure. All elements are stored on a single doubly-linked list.
+**
+** Again, this structure is intended to be opaque, but it can't really
+** be opaque because it is used by macros.
+*/
+struct Fts3HashElem {
+ Fts3HashElem *next, *prev; /* Next and previous elements in the table */
+ void *data; /* Data associated with this element */
+ void *pKey; int nKey; /* Key associated with this element */
+};
+
+/*
+** There are 2 different modes of operation for a hash table:
+**
+** FTS3_HASH_STRING pKey points to a string that is nKey bytes long
+** (including the null-terminator, if any). Case
+** is respected in comparisons.
+**
+** FTS3_HASH_BINARY pKey points to binary data nKey bytes long.
+** memcmp() is used to compare keys.
+**
+** A copy of the key is made if the copyKey parameter to fts3HashInit is 1.
+*/
+#define FTS3_HASH_STRING 1
+#define FTS3_HASH_BINARY 2
+
+/*
+** Access routines. To delete, insert a NULL pointer.
+*/
+SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey);
+SQLITE_PRIVATE void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData);
+SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey);
+SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash*);
+SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const void *, int);
+
+/*
+** Shorthand for the functions above
+*/
+#define fts3HashInit sqlite3Fts3HashInit
+#define fts3HashInsert sqlite3Fts3HashInsert
+#define fts3HashFind sqlite3Fts3HashFind
+#define fts3HashClear sqlite3Fts3HashClear
+#define fts3HashFindElem sqlite3Fts3HashFindElem
+
+/*
+** Macros for looping over all elements of a hash table. The idiom is
+** like this:
+**
+** Fts3Hash h;
+** Fts3HashElem *p;
+** ...
+** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){
+** SomeStructure *pData = fts3HashData(p);
+** // do something with pData
+** }
+*/
+#define fts3HashFirst(H) ((H)->first)
+#define fts3HashNext(E) ((E)->next)
+#define fts3HashData(E) ((E)->data)
+#define fts3HashKey(E) ((E)->pKey)
+#define fts3HashKeysize(E) ((E)->nKey)
+
+/*
+** Number of entries in a hash table
+*/
+#define fts3HashCount(H) ((H)->count)
+
+#endif /* _FTS3_HASH_H_ */
+
+/************** End of fts3_hash.h *******************************************/
+/************** Continuing where we left off in fts3Int.h ********************/
+
+/*
+** This constant controls how often segments are merged. Once there are
+** FTS3_MERGE_COUNT segments of level N, they are merged into a single
+** segment of level N+1.
+*/
+#define FTS3_MERGE_COUNT 16
+
+/*
+** This is the maximum amount of data (in bytes) to store in the
+** Fts3Table.pendingTerms hash table. Normally, the hash table is
+** populated as documents are inserted/updated/deleted in a transaction
+** and used to create a new segment when the transaction is committed.
+** However if this limit is reached midway through a transaction, a new
+** segment is created and the hash table cleared immediately.
+*/
+#define FTS3_MAX_PENDING_DATA (1*1024*1024)
+
+/*
+** Macro to return the number of elements in an array. SQLite has a
+** similar macro called ArraySize(). Use a different name to avoid
+** a collision when building an amalgamation with built-in FTS3.
+*/
+#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0])))
+
+
+#ifndef MIN
+# define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+#ifndef MAX
+# define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+/*
+** Maximum length of a varint encoded integer. The varint format is different
+** from that used by SQLite, so the maximum length is 10, not 9.
+*/
+#define FTS3_VARINT_MAX 10
+
+/*
+** FTS4 virtual tables may maintain multiple indexes - one index of all terms
+** in the document set and zero or more prefix indexes. All indexes are stored
+** as one or more b+-trees in the %_segments and %_segdir tables.
+**
+** It is possible to determine which index a b+-tree belongs to based on the
+** value stored in the "%_segdir.level" column. Given this value L, the index
+** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with
+** level values between 0 and 1023 (inclusive) belong to index 0, all levels
+** between 1024 and 2047 to index 1, and so on.
+**
+** It is considered impossible for an index to use more than 1024 levels. In
+** theory though this may happen, but only after at least
+** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables.
+*/
+#define FTS3_SEGDIR_MAXLEVEL 1024
+#define FTS3_SEGDIR_MAXLEVEL_STR "1024"
+
+/*
+** The testcase() macro is only used by the amalgamation. If undefined,
+** make it a no-op.
+*/
+#ifndef testcase
+# define testcase(X)
+#endif
+
+/*
+** Terminator values for position-lists and column-lists.
+*/
+#define POS_COLUMN (1) /* Column-list terminator */
+#define POS_END (0) /* Position-list terminator */
+
+/*
+** This section provides definitions to allow the
+** FTS3 extension to be compiled outside of the
+** amalgamation.
+*/
+#ifndef SQLITE_AMALGAMATION
+/*
+** Macros indicating that conditional expressions are always true or
+** false.
+*/
+#ifdef SQLITE_COVERAGE_TEST
+# define ALWAYS(x) (1)
+# define NEVER(X) (0)
+#else
+# define ALWAYS(x) (x)
+# define NEVER(x) (x)
+#endif
+
+/*
+** Internal types used by SQLite.
+*/
+typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
+typedef short int i16; /* 2-byte (or larger) signed integer */
+typedef unsigned int u32; /* 4-byte unsigned integer */
+typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
+typedef sqlite3_int64 i64; /* 8-byte signed integer */
+
+/*
+** Macro used to suppress compiler warnings for unused parameters.
+*/
+#define UNUSED_PARAMETER(x) (void)(x)
+
+/*
+** Activate assert() only if SQLITE_TEST is enabled.
+*/
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+# define NDEBUG 1
+#endif
+
+/*
+** The TESTONLY macro is used to enclose variable declarations or
+** other bits of code that are needed to support the arguments
+** within testcase() and assert() macros.
+*/
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+# define TESTONLY(X) X
+#else
+# define TESTONLY(X)
+#endif
+
+#endif /* SQLITE_AMALGAMATION */
+
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3Fts3Corrupt(void);
+# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt()
+#else
+# define FTS_CORRUPT_VTAB SQLITE_CORRUPT_VTAB
+#endif
+
+typedef struct Fts3Table Fts3Table;
+typedef struct Fts3Cursor Fts3Cursor;
+typedef struct Fts3Expr Fts3Expr;
+typedef struct Fts3Phrase Fts3Phrase;
+typedef struct Fts3PhraseToken Fts3PhraseToken;
+
+typedef struct Fts3Doclist Fts3Doclist;
+typedef struct Fts3SegFilter Fts3SegFilter;
+typedef struct Fts3DeferredToken Fts3DeferredToken;
+typedef struct Fts3SegReader Fts3SegReader;
+typedef struct Fts3MultiSegReader Fts3MultiSegReader;
+
+/*
+** A connection to a fulltext index is an instance of the following
+** structure. The xCreate and xConnect methods create an instance
+** of this structure and xDestroy and xDisconnect free that instance.
+** All other methods receive a pointer to the structure as one of their
+** arguments.
+*/
+struct Fts3Table {
+ sqlite3_vtab base; /* Base class used by SQLite core */
+ sqlite3 *db; /* The database connection */
+ const char *zDb; /* logical database name */
+ const char *zName; /* virtual table name */
+ int nColumn; /* number of named columns in virtual table */
+ char **azColumn; /* column names. malloced */
+ sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
+ char *zContentTbl; /* content=xxx option, or NULL */
+ char *zLanguageid; /* languageid=xxx option, or NULL */
+ u8 bAutoincrmerge; /* True if automerge=1 */
+ u32 nLeafAdd; /* Number of leaf blocks added this trans */
+
+ /* Precompiled statements used by the implementation. Each of these
+ ** statements is run and reset within a single virtual table API call.
+ */
+ sqlite3_stmt *aStmt[37];
+
+ char *zReadExprlist;
+ char *zWriteExprlist;
+
+ int nNodeSize; /* Soft limit for node size */
+ u8 bFts4; /* True for FTS4, false for FTS3 */
+ u8 bHasStat; /* True if %_stat table exists */
+ u8 bHasDocsize; /* True if %_docsize table exists */
+ u8 bDescIdx; /* True if doclists are in reverse order */
+ u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */
+ int nPgsz; /* Page size for host database */
+ char *zSegmentsTbl; /* Name of %_segments table */
+ sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
+
+ /*
+ ** The following array of hash tables is used to buffer pending index
+ ** updates during transactions. All pending updates buffered at any one
+ ** time must share a common language-id (see the FTS4 langid= feature).
+ ** The current language id is stored in variable iPrevLangid.
+ **
+ ** A single FTS4 table may have multiple full-text indexes. For each index
+ ** there is an entry in the aIndex[] array. Index 0 is an index of all the
+ ** terms that appear in the document set. Each subsequent index in aIndex[]
+ ** is an index of prefixes of a specific length.
+ **
+ ** Variable nPendingData contains an estimate the memory consumed by the
+ ** pending data structures, including hash table overhead, but not including
+ ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash
+ ** tables are flushed to disk. Variable iPrevDocid is the docid of the most
+ ** recently inserted record.
+ */
+ int nIndex; /* Size of aIndex[] */
+ struct Fts3Index {
+ int nPrefix; /* Prefix length (0 for main terms index) */
+ Fts3Hash hPending; /* Pending terms table for this index */
+ } *aIndex;
+ int nMaxPendingData; /* Max pending data before flush to disk */
+ int nPendingData; /* Current bytes of pending data */
+ sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
+ int iPrevLangid; /* Langid of recently inserted document */
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ /* State variables used for validating that the transaction control
+ ** methods of the virtual table are called at appropriate times. These
+ ** values do not contribute to FTS functionality; they are used for
+ ** verifying the operation of the SQLite core.
+ */
+ int inTransaction; /* True after xBegin but before xCommit/xRollback */
+ int mxSavepoint; /* Largest valid xSavepoint integer */
+#endif
+};
+
+/*
+** When the core wants to read from the virtual table, it creates a
+** virtual table cursor (an instance of the following structure) using
+** the xOpen method. Cursors are destroyed using the xClose method.
+*/
+struct Fts3Cursor {
+ sqlite3_vtab_cursor base; /* Base class used by SQLite core */
+ i16 eSearch; /* Search strategy (see below) */
+ u8 isEof; /* True if at End Of Results */
+ u8 isRequireSeek; /* True if must seek pStmt to %_content row */
+ sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
+ Fts3Expr *pExpr; /* Parsed MATCH query string */
+ int iLangid; /* Language being queried for */
+ int nPhrase; /* Number of matchable phrases in query */
+ Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
+ sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
+ char *pNextId; /* Pointer into the body of aDoclist */
+ char *aDoclist; /* List of docids for full-text queries */
+ int nDoclist; /* Size of buffer at aDoclist */
+ u8 bDesc; /* True to sort in descending order */
+ int eEvalmode; /* An FTS3_EVAL_XX constant */
+ int nRowAvg; /* Average size of database rows, in pages */
+ sqlite3_int64 nDoc; /* Documents in table */
+
+ int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
+ u32 *aMatchinfo; /* Information about most recent match */
+ int nMatchinfo; /* Number of elements in aMatchinfo[] */
+ char *zMatchinfo; /* Matchinfo specification */
+};
+
+#define FTS3_EVAL_FILTER 0
+#define FTS3_EVAL_NEXT 1
+#define FTS3_EVAL_MATCHINFO 2
+
+/*
+** The Fts3Cursor.eSearch member is always set to one of the following.
+** Actualy, Fts3Cursor.eSearch can be greater than or equal to
+** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
+** of the column to be searched. For example, in
+**
+** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
+** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
+**
+** Because the LHS of the MATCH operator is 2nd column "b",
+** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a,
+** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
+** indicating that all columns should be searched,
+** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4.
+*/
+#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
+#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
+#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
+
+
+struct Fts3Doclist {
+ char *aAll; /* Array containing doclist (or NULL) */
+ int nAll; /* Size of a[] in bytes */
+ char *pNextDocid; /* Pointer to next docid */
+
+ sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
+ int bFreeList; /* True if pList should be sqlite3_free()d */
+ char *pList; /* Pointer to position list following iDocid */
+ int nList; /* Length of position list */
+};
+
+/*
+** A "phrase" is a sequence of one or more tokens that must match in
+** sequence. A single token is the base case and the most common case.
+** For a sequence of tokens contained in double-quotes (i.e. "one two three")
+** nToken will be the number of tokens in the string.
+*/
+struct Fts3PhraseToken {
+ char *z; /* Text of the token */
+ int n; /* Number of bytes in buffer z */
+ int isPrefix; /* True if token ends with a "*" character */
+ int bFirst; /* True if token must appear at position 0 */
+
+ /* Variables above this point are populated when the expression is
+ ** parsed (by code in fts3_expr.c). Below this point the variables are
+ ** used when evaluating the expression. */
+ Fts3DeferredToken *pDeferred; /* Deferred token object for this token */
+ Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */
+};
+
+struct Fts3Phrase {
+ /* Cache of doclist for this phrase. */
+ Fts3Doclist doclist;
+ int bIncr; /* True if doclist is loaded incrementally */
+ int iDoclistToken;
+
+ /* Variables below this point are populated by fts3_expr.c when parsing
+ ** a MATCH expression. Everything above is part of the evaluation phase.
+ */
+ int nToken; /* Number of tokens in the phrase */
+ int iColumn; /* Index of column this phrase must match */
+ Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
+};
+
+/*
+** A tree of these objects forms the RHS of a MATCH operator.
+**
+** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
+** points to a malloced buffer, size nDoclist bytes, containing the results
+** of this phrase query in FTS3 doclist format. As usual, the initial
+** "Length" field found in doclists stored on disk is omitted from this
+** buffer.
+**
+** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global
+** matchinfo data. If it is not NULL, it points to an array of size nCol*3,
+** where nCol is the number of columns in the queried FTS table. The array
+** is populated as follows:
+**
+** aMI[iCol*3 + 0] = Undefined
+** aMI[iCol*3 + 1] = Number of occurrences
+** aMI[iCol*3 + 2] = Number of rows containing at least one instance
+**
+** The aMI array is allocated using sqlite3_malloc(). It should be freed
+** when the expression node is.
+*/
+struct Fts3Expr {
+ int eType; /* One of the FTSQUERY_XXX values defined below */
+ int nNear; /* Valid if eType==FTSQUERY_NEAR */
+ Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */
+ Fts3Expr *pLeft; /* Left operand */
+ Fts3Expr *pRight; /* Right operand */
+ Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
+
+ /* The following are used by the fts3_eval.c module. */
+ sqlite3_int64 iDocid; /* Current docid */
+ u8 bEof; /* True this expression is at EOF already */
+ u8 bStart; /* True if iDocid is valid */
+ u8 bDeferred; /* True if this expression is entirely deferred */
+
+ u32 *aMI;
+};
+
+/*
+** Candidate values for Fts3Query.eType. Note that the order of the first
+** four values is in order of precedence when parsing expressions. For
+** example, the following:
+**
+** "a OR b AND c NOT d NEAR e"
+**
+** is equivalent to:
+**
+** "a OR (b AND (c NOT (d NEAR e)))"
+*/
+#define FTSQUERY_NEAR 1
+#define FTSQUERY_NOT 2
+#define FTSQUERY_AND 3
+#define FTSQUERY_OR 4
+#define FTSQUERY_PHRASE 5
+
+
+/* fts3_write.c */
+SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
+SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *);
+SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *);
+SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *);
+SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
+ sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
+SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
+ Fts3Table*,int,const char*,int,int,Fts3SegReader**);
+SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
+SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **);
+SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
+SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
+
+SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
+SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
+
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
+SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
+SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
+SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
+SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
+SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
+#else
+# define sqlite3Fts3FreeDeferredTokens(x)
+# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
+# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
+# define sqlite3Fts3FreeDeferredDoclists(x)
+# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
+#endif
+
+SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
+SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *, int *);
+
+/* Special values interpreted by sqlite3SegReaderCursor() */
+#define FTS3_SEGCURSOR_PENDING -1
+#define FTS3_SEGCURSOR_ALL -2
+
+SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*);
+SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
+SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
+
+SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *,
+ int, int, int, const char *, int, int, int, Fts3MultiSegReader *);
+
+/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
+#define FTS3_SEGMENT_REQUIRE_POS 0x00000001
+#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
+#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
+#define FTS3_SEGMENT_PREFIX 0x00000008
+#define FTS3_SEGMENT_SCAN 0x00000010
+#define FTS3_SEGMENT_FIRST 0x00000020
+
+/* Type passed as 4th argument to SegmentReaderIterate() */
+struct Fts3SegFilter {
+ const char *zTerm;
+ int nTerm;
+ int iCol;
+ int flags;
+};
+
+struct Fts3MultiSegReader {
+ /* Used internally by sqlite3Fts3SegReaderXXX() calls */
+ Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */
+ int nSegment; /* Size of apSegment array */
+ int nAdvance; /* How many seg-readers to advance */
+ Fts3SegFilter *pFilter; /* Pointer to filter object */
+ char *aBuffer; /* Buffer to merge doclists in */
+ int nBuffer; /* Allocated size of aBuffer[] in bytes */
+
+ int iColFilter; /* If >=0, filter for this column */
+ int bRestart;
+
+ /* Used by fts3.c only. */
+ int nCost; /* Cost of running iterator */
+ int bLookup; /* True if a lookup of a single entry. */
+
+ /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */
+ char *zTerm; /* Pointer to term buffer */
+ int nTerm; /* Size of zTerm in bytes */
+ char *aDoclist; /* Pointer to doclist buffer */
+ int nDoclist; /* Size of aDoclist[] in bytes */
+};
+
+SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
+
+/* fts3.c */
+SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
+SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
+SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
+SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
+SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
+SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
+SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
+SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
+SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
+
+/* fts3_tokenizer.c */
+SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
+SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
+SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
+ sqlite3_tokenizer **, char **
+);
+SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char);
+
+/* fts3_snippet.c */
+SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*);
+SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
+ const char *, const char *, int, int
+);
+SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
+
+/* fts3_expr.c */
+SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
+ char **, int, int, int, const char *, int, Fts3Expr **
+);
+SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
+SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
+#endif
+
+SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
+ sqlite3_tokenizer_cursor **
+);
+
+/* fts3_aux.c */
+SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
+
+SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
+
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
+ Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
+ Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
+SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
+SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
+
+/* fts3_unicode2.c (functions generated by parsing unicode text files) */
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int);
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
+#endif
+
+#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
+#endif /* _FTSINT_H */
+
+/************** End of fts3Int.h *********************************************/
+/************** Continuing where we left off in fts3.c ***********************/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
+# define SQLITE_CORE 1
+#endif
+
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+/* #include <stddef.h> */
+/* #include <stdio.h> */
+/* #include <string.h> */
+/* #include <stdarg.h> */
+
+#ifndef SQLITE_CORE
+ SQLITE_EXTENSION_INIT1
+#endif
+
+static int fts3EvalNext(Fts3Cursor *pCsr);
+static int fts3EvalStart(Fts3Cursor *pCsr);
+static int fts3TermSegReaderCursor(
+ Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
+
+/*
+** Write a 64-bit variable-length integer to memory starting at p[0].
+** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
+** The number of bytes written is returned.
+*/
+SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
+ unsigned char *q = (unsigned char *) p;
+ sqlite_uint64 vu = v;
+ do{
+ *q++ = (unsigned char) ((vu & 0x7f) | 0x80);
+ vu >>= 7;
+ }while( vu!=0 );
+ q[-1] &= 0x7f; /* turn off high bit in final byte */
+ assert( q - (unsigned char *)p <= FTS3_VARINT_MAX );
+ return (int) (q - (unsigned char *)p);
+}
+
+/*
+** Read a 64-bit variable-length integer from memory starting at p[0].
+** Return the number of bytes read, or 0 on error.
+** The value is stored in *v.
+*/
+SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
+ const unsigned char *q = (const unsigned char *) p;
+ sqlite_uint64 x = 0, y = 1;
+ while( (*q&0x80)==0x80 && q-(unsigned char *)p<FTS3_VARINT_MAX ){
+ x += y * (*q++ & 0x7f);
+ y <<= 7;
+ }
+ x += y * (*q++);
+ *v = (sqlite_int64) x;
+ return (int) (q - (unsigned char *)p);
+}
+
+/*
+** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to a
+** 32-bit integer before it is returned.
+*/
+SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *p, int *pi){
+ sqlite_int64 i;
+ int ret = sqlite3Fts3GetVarint(p, &i);
+ *pi = (int) i;
+ return ret;
+}
+
+/*
+** Return the number of bytes required to encode v as a varint
+*/
+SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64 v){
+ int i = 0;
+ do{
+ i++;
+ v >>= 7;
+ }while( v!=0 );
+ return i;
+}
+
+/*
+** Convert an SQL-style quoted string into a normal string by removing
+** the quote characters. The conversion is done in-place. If the
+** input does not begin with a quote character, then this routine
+** is a no-op.
+**
+** Examples:
+**
+** "abc" becomes abc
+** 'xyz' becomes xyz
+** [pqr] becomes pqr
+** `mno` becomes mno
+**
+*/
+SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){
+ char quote; /* Quote character (if any ) */
+
+ quote = z[0];
+ if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
+ int iIn = 1; /* Index of next byte to read from input */
+ int iOut = 0; /* Index of next byte to write to output */
+
+ /* If the first byte was a '[', then the close-quote character is a ']' */
+ if( quote=='[' ) quote = ']';
+
+ while( ALWAYS(z[iIn]) ){
+ if( z[iIn]==quote ){
+ if( z[iIn+1]!=quote ) break;
+ z[iOut++] = quote;
+ iIn += 2;
+ }else{
+ z[iOut++] = z[iIn++];
+ }
+ }
+ z[iOut] = '\0';
+ }
+}
+
+/*
+** Read a single varint from the doclist at *pp and advance *pp to point
+** to the first byte past the end of the varint. Add the value of the varint
+** to *pVal.
+*/
+static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
+ sqlite3_int64 iVal;
+ *pp += sqlite3Fts3GetVarint(*pp, &iVal);
+ *pVal += iVal;
+}
+
+/*
+** When this function is called, *pp points to the first byte following a
+** varint that is part of a doclist (or position-list, or any other list
+** of varints). This function moves *pp to point to the start of that varint,
+** and sets *pVal by the varint value.
+**
+** Argument pStart points to the first byte of the doclist that the
+** varint is part of.
+*/
+static void fts3GetReverseVarint(
+ char **pp,
+ char *pStart,
+ sqlite3_int64 *pVal
+){
+ sqlite3_int64 iVal;
+ char *p;
+
+ /* Pointer p now points at the first byte past the varint we are
+ ** interested in. So, unless the doclist is corrupt, the 0x80 bit is
+ ** clear on character p[-1]. */
+ for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
+ p++;
+ *pp = p;
+
+ sqlite3Fts3GetVarint(p, &iVal);
+ *pVal = iVal;
+}
+
+/*
+** The xDisconnect() virtual table method.
+*/
+static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
+ Fts3Table *p = (Fts3Table *)pVtab;
+ int i;
+
+ assert( p->nPendingData==0 );
+ assert( p->pSegments==0 );
+
+ /* Free any prepared statements held */
+ for(i=0; i<SizeofArray(p->aStmt); i++){
+ sqlite3_finalize(p->aStmt[i]);
+ }
+ sqlite3_free(p->zSegmentsTbl);
+ sqlite3_free(p->zReadExprlist);
+ sqlite3_free(p->zWriteExprlist);
+ sqlite3_free(p->zContentTbl);
+ sqlite3_free(p->zLanguageid);
+
+ /* Invoke the tokenizer destructor to free the tokenizer. */
+ p->pTokenizer->pModule->xDestroy(p->pTokenizer);
+
+ sqlite3_free(p);
+ return SQLITE_OK;
+}
+
+/*
+** Construct one or more SQL statements from the format string given
+** and then evaluate those statements. The success code is written
+** into *pRc.
+**
+** If *pRc is initially non-zero then this routine is a no-op.
+*/
+static void fts3DbExec(
+ int *pRc, /* Success code */
+ sqlite3 *db, /* Database in which to run SQL */
+ const char *zFormat, /* Format string for SQL */
+ ... /* Arguments to the format string */
+){
+ va_list ap;
+ char *zSql;
+ if( *pRc ) return;
+ va_start(ap, zFormat);
+ zSql = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ if( zSql==0 ){
+ *pRc = SQLITE_NOMEM;
+ }else{
+ *pRc = sqlite3_exec(db, zSql, 0, 0, 0);
+ sqlite3_free(zSql);
+ }
+}
+
+/*
+** The xDestroy() virtual table method.
+*/
+static int fts3DestroyMethod(sqlite3_vtab *pVtab){
+ Fts3Table *p = (Fts3Table *)pVtab;
+ int rc = SQLITE_OK; /* Return code */
+ const char *zDb = p->zDb; /* Name of database (e.g. "main", "temp") */
+ sqlite3 *db = p->db; /* Database handle */
+
+ /* Drop the shadow tables */
+ if( p->zContentTbl==0 ){
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
+ }
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
+ fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
+
+ /* If everything has worked, invoke fts3DisconnectMethod() to free the
+ ** memory associated with the Fts3Table structure and return SQLITE_OK.
+ ** Otherwise, return an SQLite error code.
+ */
+ return (rc==SQLITE_OK ? fts3DisconnectMethod(pVtab) : rc);
+}
+
+
+/*
+** Invoke sqlite3_declare_vtab() to declare the schema for the FTS3 table
+** passed as the first argument. This is done as part of the xConnect()
+** and xCreate() methods.
+**
+** If *pRc is non-zero when this function is called, it is a no-op.
+** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
+** before returning.
+*/
+static void fts3DeclareVtab(int *pRc, Fts3Table *p){
+ if( *pRc==SQLITE_OK ){
+ int i; /* Iterator variable */
+ int rc; /* Return code */
+ char *zSql; /* SQL statement passed to declare_vtab() */
+ char *zCols; /* List of user defined columns */
+ const char *zLanguageid;
+
+ zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid");
+ sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
+
+ /* Create a list of user columns for the virtual table */
+ zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]);
+ for(i=1; zCols && i<p->nColumn; i++){
+ zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]);
+ }
+
+ /* Create the whole "CREATE TABLE" statement to pass to SQLite */
+ zSql = sqlite3_mprintf(
+ "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
+ zCols, p->zName, zLanguageid
+ );
+ if( !zCols || !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_declare_vtab(p->db, zSql);
+ }
+
+ sqlite3_free(zSql);
+ sqlite3_free(zCols);
+ *pRc = rc;
+ }
+}
+
+/*
+** Create the %_stat table if it does not already exist.
+*/
+SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){
+ fts3DbExec(pRc, p->db,
+ "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'"
+ "(id INTEGER PRIMARY KEY, value BLOB);",
+ p->zDb, p->zName
+ );
+ if( (*pRc)==SQLITE_OK ) p->bHasStat = 1;
+}
+
+/*
+** Create the backing store tables (%_content, %_segments and %_segdir)
+** required by the FTS3 table passed as the only argument. This is done
+** as part of the vtab xCreate() method.
+**
+** If the p->bHasDocsize boolean is true (indicating that this is an
+** FTS4 table, not an FTS3 table) then also create the %_docsize and
+** %_stat tables required by FTS4.
+*/
+static int fts3CreateTables(Fts3Table *p){
+ int rc = SQLITE_OK; /* Return code */
+ int i; /* Iterator variable */
+ sqlite3 *db = p->db; /* The database connection */
+
+ if( p->zContentTbl==0 ){
+ const char *zLanguageid = p->zLanguageid;
+ char *zContentCols; /* Columns of %_content table */
+
+ /* Create a list of user columns for the content table */
+ zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
+ for(i=0; zContentCols && i<p->nColumn; i++){
+ char *z = p->azColumn[i];
+ zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
+ }
+ if( zLanguageid && zContentCols ){
+ zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid);
+ }
+ if( zContentCols==0 ) rc = SQLITE_NOMEM;
+
+ /* Create the content table */
+ fts3DbExec(&rc, db,
+ "CREATE TABLE %Q.'%q_content'(%s)",
+ p->zDb, p->zName, zContentCols
+ );
+ sqlite3_free(zContentCols);
+ }
+
+ /* Create other tables */
+ fts3DbExec(&rc, db,
+ "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",
+ p->zDb, p->zName
+ );
+ fts3DbExec(&rc, db,
+ "CREATE TABLE %Q.'%q_segdir'("
+ "level INTEGER,"
+ "idx INTEGER,"
+ "start_block INTEGER,"
+ "leaves_end_block INTEGER,"
+ "end_block INTEGER,"
+ "root BLOB,"
+ "PRIMARY KEY(level, idx)"
+ ");",
+ p->zDb, p->zName
+ );
+ if( p->bHasDocsize ){
+ fts3DbExec(&rc, db,
+ "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
+ p->zDb, p->zName
+ );
+ }
+ assert( p->bHasStat==p->bFts4 );
+ if( p->bHasStat ){
+ sqlite3Fts3CreateStatTable(&rc, p);
+ }
+ return rc;
+}
+
+/*
+** Store the current database page-size in bytes in p->nPgsz.
+**
+** If *pRc is non-zero when this function is called, it is a no-op.
+** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
+** before returning.
+*/
+static void fts3DatabasePageSize(int *pRc, Fts3Table *p){
+ if( *pRc==SQLITE_OK ){
+ int rc; /* Return code */
+ char *zSql; /* SQL text "PRAGMA %Q.page_size" */
+ sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */
+
+ zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb);
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_step(pStmt);
+ p->nPgsz = sqlite3_column_int(pStmt, 0);
+ rc = sqlite3_finalize(pStmt);
+ }else if( rc==SQLITE_AUTH ){
+ p->nPgsz = 1024;
+ rc = SQLITE_OK;
+ }
+ }
+ assert( p->nPgsz>0 || rc!=SQLITE_OK );
+ sqlite3_free(zSql);
+ *pRc = rc;
+ }
+}
+
+/*
+** "Special" FTS4 arguments are column specifications of the following form:
+**
+** <key> = <value>
+**
+** There may not be whitespace surrounding the "=" character. The <value>
+** term may be quoted, but the <key> may not.
+*/
+static int fts3IsSpecialColumn(
+ const char *z,
+ int *pnKey,
+ char **pzValue
+){
+ char *zValue;
+ const char *zCsr = z;
+
+ while( *zCsr!='=' ){
+ if( *zCsr=='\0' ) return 0;
+ zCsr++;
+ }
+
+ *pnKey = (int)(zCsr-z);
+ zValue = sqlite3_mprintf("%s", &zCsr[1]);
+ if( zValue ){
+ sqlite3Fts3Dequote(zValue);
+ }
+ *pzValue = zValue;
+ return 1;
+}
+
+/*
+** Append the output of a printf() style formatting to an existing string.
+*/
+static void fts3Appendf(
+ int *pRc, /* IN/OUT: Error code */
+ char **pz, /* IN/OUT: Pointer to string buffer */
+ const char *zFormat, /* Printf format string to append */
+ ... /* Arguments for printf format string */
+){
+ if( *pRc==SQLITE_OK ){
+ va_list ap;
+ char *z;
+ va_start(ap, zFormat);
+ z = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ if( z && *pz ){
+ char *z2 = sqlite3_mprintf("%s%s", *pz, z);
+ sqlite3_free(z);
+ z = z2;
+ }
+ if( z==0 ) *pRc = SQLITE_NOMEM;
+ sqlite3_free(*pz);
+ *pz = z;
+ }
+}
+
+/*
+** Return a copy of input string zInput enclosed in double-quotes (") and
+** with all double quote characters escaped. For example:
+**
+** fts3QuoteId("un \"zip\"") -> "un \"\"zip\"\""
+**
+** The pointer returned points to memory obtained from sqlite3_malloc(). It
+** is the callers responsibility to call sqlite3_free() to release this
+** memory.
+*/
+static char *fts3QuoteId(char const *zInput){
+ int nRet;
+ char *zRet;
+ nRet = 2 + (int)strlen(zInput)*2 + 1;
+ zRet = sqlite3_malloc(nRet);
+ if( zRet ){
+ int i;
+ char *z = zRet;
+ *(z++) = '"';
+ for(i=0; zInput[i]; i++){
+ if( zInput[i]=='"' ) *(z++) = '"';
+ *(z++) = zInput[i];
+ }
+ *(z++) = '"';
+ *(z++) = '\0';
+ }
+ return zRet;
+}
+
+/*
+** Return a list of comma separated SQL expressions and a FROM clause that
+** could be used in a SELECT statement such as the following:
+**
+** SELECT <list of expressions> FROM %_content AS x ...
+**
+** to return the docid, followed by each column of text data in order
+** from left to write. If parameter zFunc is not NULL, then instead of
+** being returned directly each column of text data is passed to an SQL
+** function named zFunc first. For example, if zFunc is "unzip" and the
+** table has the three user-defined columns "a", "b", and "c", the following
+** string is returned:
+**
+** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c') FROM %_content AS x"
+**
+** The pointer returned points to a buffer allocated by sqlite3_malloc(). It
+** is the responsibility of the caller to eventually free it.
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and
+** a NULL pointer is returned). Otherwise, if an OOM error is encountered
+** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If
+** no error occurs, *pRc is left unmodified.
+*/
+static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){
+ char *zRet = 0;
+ char *zFree = 0;
+ char *zFunction;
+ int i;
+
+ if( p->zContentTbl==0 ){
+ if( !zFunc ){
+ zFunction = "";
+ }else{
+ zFree = zFunction = fts3QuoteId(zFunc);
+ }
+ fts3Appendf(pRc, &zRet, "docid");
+ for(i=0; i<p->nColumn; i++){
+ fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]);
+ }
+ if( p->zLanguageid ){
+ fts3Appendf(pRc, &zRet, ", x.%Q", "langid");
+ }
+ sqlite3_free(zFree);
+ }else{
+ fts3Appendf(pRc, &zRet, "rowid");
+ for(i=0; i<p->nColumn; i++){
+ fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]);
+ }
+ if( p->zLanguageid ){
+ fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid);
+ }
+ }
+ fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
+ p->zDb,
+ (p->zContentTbl ? p->zContentTbl : p->zName),
+ (p->zContentTbl ? "" : "_content")
+ );
+ return zRet;
+}
+
+/*
+** Return a list of N comma separated question marks, where N is the number
+** of columns in the %_content table (one for the docid plus one for each
+** user-defined text column).
+**
+** If argument zFunc is not NULL, then all but the first question mark
+** is preceded by zFunc and an open bracket, and followed by a closed
+** bracket. For example, if zFunc is "zip" and the FTS3 table has three
+** user-defined text columns, the following string is returned:
+**
+** "?, zip(?), zip(?), zip(?)"
+**
+** The pointer returned points to a buffer allocated by sqlite3_malloc(). It
+** is the responsibility of the caller to eventually free it.
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and
+** a NULL pointer is returned). Otherwise, if an OOM error is encountered
+** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If
+** no error occurs, *pRc is left unmodified.
+*/
+static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
+ char *zRet = 0;
+ char *zFree = 0;
+ char *zFunction;
+ int i;
+
+ if( !zFunc ){
+ zFunction = "";
+ }else{
+ zFree = zFunction = fts3QuoteId(zFunc);
+ }
+ fts3Appendf(pRc, &zRet, "?");
+ for(i=0; i<p->nColumn; i++){
+ fts3Appendf(pRc, &zRet, ",%s(?)", zFunction);
+ }
+ if( p->zLanguageid ){
+ fts3Appendf(pRc, &zRet, ", ?");
+ }
+ sqlite3_free(zFree);
+ return zRet;
+}
+
+/*
+** This function interprets the string at (*pp) as a non-negative integer
+** value. It reads the integer and sets *pnOut to the value read, then
+** sets *pp to point to the byte immediately following the last byte of
+** the integer value.
+**
+** Only decimal digits ('0'..'9') may be part of an integer value.
+**
+** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
+** the output value undefined. Otherwise SQLITE_OK is returned.
+**
+** This function is used when parsing the "prefix=" FTS4 parameter.
+*/
+static int fts3GobbleInt(const char **pp, int *pnOut){
+ const char *p; /* Iterator pointer */
+ int nInt = 0; /* Output value */
+
+ for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
+ nInt = nInt * 10 + (p[0] - '0');
+ }
+ if( p==*pp ) return SQLITE_ERROR;
+ *pnOut = nInt;
+ *pp = p;
+ return SQLITE_OK;
+}
+
+/*
+** This function is called to allocate an array of Fts3Index structures
+** representing the indexes maintained by the current FTS table. FTS tables
+** always maintain the main "terms" index, but may also maintain one or
+** more "prefix" indexes, depending on the value of the "prefix=" parameter
+** (if any) specified as part of the CREATE VIRTUAL TABLE statement.
+**
+** Argument zParam is passed the value of the "prefix=" option if one was
+** specified, or NULL otherwise.
+**
+** If no error occurs, SQLITE_OK is returned and *apIndex set to point to
+** the allocated array. *pnIndex is set to the number of elements in the
+** array. If an error does occur, an SQLite error code is returned.
+**
+** Regardless of whether or not an error is returned, it is the responsibility
+** of the caller to call sqlite3_free() on the output array to free it.
+*/
+static int fts3PrefixParameter(
+ const char *zParam, /* ABC in prefix=ABC parameter to parse */
+ int *pnIndex, /* OUT: size of *apIndex[] array */
+ struct Fts3Index **apIndex /* OUT: Array of indexes for this table */
+){
+ struct Fts3Index *aIndex; /* Allocated array */
+ int nIndex = 1; /* Number of entries in array */
+
+ if( zParam && zParam[0] ){
+ const char *p;
+ nIndex++;
+ for(p=zParam; *p; p++){
+ if( *p==',' ) nIndex++;
+ }
+ }
+
+ aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
+ *apIndex = aIndex;
+ *pnIndex = nIndex;
+ if( !aIndex ){
+ return SQLITE_NOMEM;
+ }
+
+ memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex);
+ if( zParam ){
+ const char *p = zParam;
+ int i;
+ for(i=1; i<nIndex; i++){
+ int nPrefix;
+ if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR;
+ aIndex[i].nPrefix = nPrefix;
+ p++;
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** This function is called when initializing an FTS4 table that uses the
+** content=xxx option. It determines the number of and names of the columns
+** of the new FTS4 table.
+**
+** The third argument passed to this function is the value passed to the
+** config=xxx option (i.e. "xxx"). This function queries the database for
+** a table of that name. If found, the output variables are populated
+** as follows:
+**
+** *pnCol: Set to the number of columns table xxx has,
+**
+** *pnStr: Set to the total amount of space required to store a copy
+** of each columns name, including the nul-terminator.
+**
+** *pazCol: Set to point to an array of *pnCol strings. Each string is
+** the name of the corresponding column in table xxx. The array
+** and its contents are allocated using a single allocation. It
+** is the responsibility of the caller to free this allocation
+** by eventually passing the *pazCol value to sqlite3_free().
+**
+** If the table cannot be found, an error code is returned and the output
+** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is
+** returned (and the output variables are undefined).
+*/
+static int fts3ContentColumns(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */
+ const char *zTbl, /* Name of content table */
+ const char ***pazCol, /* OUT: Malloc'd array of column names */
+ int *pnCol, /* OUT: Size of array *pazCol */
+ int *pnStr /* OUT: Bytes of string content */
+){
+ int rc = SQLITE_OK; /* Return code */
+ char *zSql; /* "SELECT *" statement on zTbl */
+ sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */
+
+ zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl);
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ }
+ sqlite3_free(zSql);
+
+ if( rc==SQLITE_OK ){
+ const char **azCol; /* Output array */
+ int nStr = 0; /* Size of all column names (incl. 0x00) */
+ int nCol; /* Number of table columns */
+ int i; /* Used to iterate through columns */
+
+ /* Loop through the returned columns. Set nStr to the number of bytes of
+ ** space required to store a copy of each column name, including the
+ ** nul-terminator byte. */
+ nCol = sqlite3_column_count(pStmt);
+ for(i=0; i<nCol; i++){
+ const char *zCol = sqlite3_column_name(pStmt, i);
+ nStr += (int)strlen(zCol) + 1;
+ }
+
+ /* Allocate and populate the array to return. */
+ azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
+ if( azCol==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ char *p = (char *)&azCol[nCol];
+ for(i=0; i<nCol; i++){
+ const char *zCol = sqlite3_column_name(pStmt, i);
+ int n = (int)strlen(zCol)+1;
+ memcpy(p, zCol, n);
+ azCol[i] = p;
+ p += n;
+ }
+ }
+ sqlite3_finalize(pStmt);
+
+ /* Set the output variables. */
+ *pnCol = nCol;
+ *pnStr = nStr;
+ *pazCol = azCol;
+ }
+
+ return rc;
+}
+
+/*
+** This function is the implementation of both the xConnect and xCreate
+** methods of the FTS3 virtual table.
+**
+** The argv[] array contains the following:
+**
+** argv[0] -> module name ("fts3" or "fts4")
+** argv[1] -> database name
+** argv[2] -> table name
+** argv[...] -> "column name" and other module argument fields.
+*/
+static int fts3InitVtab(
+ int isCreate, /* True for xCreate, false for xConnect */
+ sqlite3 *db, /* The SQLite database connection */
+ void *pAux, /* Hash table containing tokenizers */
+ int argc, /* Number of elements in argv array */
+ const char * const *argv, /* xCreate/xConnect argument array */
+ sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
+ char **pzErr /* Write any error message here */
+){
+ Fts3Hash *pHash = (Fts3Hash *)pAux;
+ Fts3Table *p = 0; /* Pointer to allocated vtab */
+ int rc = SQLITE_OK; /* Return code */
+ int i; /* Iterator variable */
+ int nByte; /* Size of allocation used for *p */
+ int iCol; /* Column index */
+ int nString = 0; /* Bytes required to hold all column names */
+ int nCol = 0; /* Number of columns in the FTS table */
+ char *zCsr; /* Space for holding column names */
+ int nDb; /* Bytes required to hold database name */
+ int nName; /* Bytes required to hold table name */
+ int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
+ const char **aCol; /* Array of column names */
+ sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
+
+ int nIndex; /* Size of aIndex[] array */
+ struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
+
+ /* The results of parsing supported FTS4 key=value options: */
+ int bNoDocsize = 0; /* True to omit %_docsize table */
+ int bDescIdx = 0; /* True to store descending indexes */
+ char *zPrefix = 0; /* Prefix parameter value (or NULL) */
+ char *zCompress = 0; /* compress=? parameter (or NULL) */
+ char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
+ char *zContent = 0; /* content=? parameter (or NULL) */
+ char *zLanguageid = 0; /* languageid=? parameter (or NULL) */
+
+ assert( strlen(argv[0])==4 );
+ assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
+ || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4)
+ );
+
+ nDb = (int)strlen(argv[1]) + 1;
+ nName = (int)strlen(argv[2]) + 1;
+
+ aCol = (const char **)sqlite3_malloc(sizeof(const char *) * (argc-2) );
+ if( !aCol ) return SQLITE_NOMEM;
+ memset((void *)aCol, 0, sizeof(const char *) * (argc-2));
+
+ /* Loop through all of the arguments passed by the user to the FTS3/4
+ ** module (i.e. all the column names and special arguments). This loop
+ ** does the following:
+ **
+ ** + Figures out the number of columns the FTSX table will have, and
+ ** the number of bytes of space that must be allocated to store copies
+ ** of the column names.
+ **
+ ** + If there is a tokenizer specification included in the arguments,
+ ** initializes the tokenizer pTokenizer.
+ */
+ for(i=3; rc==SQLITE_OK && i<argc; i++){
+ char const *z = argv[i];
+ int nKey;
+ char *zVal;
+
+ /* Check if this is a tokenizer specification */
+ if( !pTokenizer
+ && strlen(z)>8
+ && 0==sqlite3_strnicmp(z, "tokenize", 8)
+ && 0==sqlite3Fts3IsIdChar(z[8])
+ ){
+ rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
+ }
+
+ /* Check if it is an FTS4 special argument. */
+ else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){
+ struct Fts4Option {
+ const char *zOpt;
+ int nOpt;
+ } aFts4Opt[] = {
+ { "matchinfo", 9 }, /* 0 -> MATCHINFO */
+ { "prefix", 6 }, /* 1 -> PREFIX */
+ { "compress", 8 }, /* 2 -> COMPRESS */
+ { "uncompress", 10 }, /* 3 -> UNCOMPRESS */
+ { "order", 5 }, /* 4 -> ORDER */
+ { "content", 7 }, /* 5 -> CONTENT */
+ { "languageid", 10 } /* 6 -> LANGUAGEID */
+ };
+
+ int iOpt;
+ if( !zVal ){
+ rc = SQLITE_NOMEM;
+ }else{
+ for(iOpt=0; iOpt<SizeofArray(aFts4Opt); iOpt++){
+ struct Fts4Option *pOp = &aFts4Opt[iOpt];
+ if( nKey==pOp->nOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){
+ break;
+ }
+ }
+ if( iOpt==SizeofArray(aFts4Opt) ){
+ *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
+ rc = SQLITE_ERROR;
+ }else{
+ switch( iOpt ){
+ case 0: /* MATCHINFO */
+ if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
+ *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
+ rc = SQLITE_ERROR;
+ }
+ bNoDocsize = 1;
+ break;
+
+ case 1: /* PREFIX */
+ sqlite3_free(zPrefix);
+ zPrefix = zVal;
+ zVal = 0;
+ break;
+
+ case 2: /* COMPRESS */
+ sqlite3_free(zCompress);
+ zCompress = zVal;
+ zVal = 0;
+ break;
+
+ case 3: /* UNCOMPRESS */
+ sqlite3_free(zUncompress);
+ zUncompress = zVal;
+ zVal = 0;
+ break;
+
+ case 4: /* ORDER */
+ if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
+ && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
+ ){
+ *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
+ rc = SQLITE_ERROR;
+ }
+ bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
+ break;
+
+ case 5: /* CONTENT */
+ sqlite3_free(zContent);
+ zContent = zVal;
+ zVal = 0;
+ break;
+
+ case 6: /* LANGUAGEID */
+ assert( iOpt==6 );
+ sqlite3_free(zLanguageid);
+ zLanguageid = zVal;
+ zVal = 0;
+ break;
+ }
+ }
+ sqlite3_free(zVal);
+ }
+ }
+
+ /* Otherwise, the argument is a column name. */
+ else {
+ nString += (int)(strlen(z) + 1);
+ aCol[nCol++] = z;
+ }
+ }
+
+ /* If a content=xxx option was specified, the following:
+ **
+ ** 1. Ignore any compress= and uncompress= options.
+ **
+ ** 2. If no column names were specified as part of the CREATE VIRTUAL
+ ** TABLE statement, use all columns from the content table.
+ */
+ if( rc==SQLITE_OK && zContent ){
+ sqlite3_free(zCompress);
+ sqlite3_free(zUncompress);
+ zCompress = 0;
+ zUncompress = 0;
+ if( nCol==0 ){
+ sqlite3_free((void*)aCol);
+ aCol = 0;
+ rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
+
+ /* If a languageid= option was specified, remove the language id
+ ** column from the aCol[] array. */
+ if( rc==SQLITE_OK && zLanguageid ){
+ int j;
+ for(j=0; j<nCol; j++){
+ if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){
+ int k;
+ for(k=j; k<nCol; k++) aCol[k] = aCol[k+1];
+ nCol--;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if( rc!=SQLITE_OK ) goto fts3_init_out;
+
+ if( nCol==0 ){
+ assert( nString==0 );
+ aCol[0] = "content";
+ nString = 8;
+ nCol = 1;
+ }
+
+ if( pTokenizer==0 ){
+ rc = sqlite3Fts3InitTokenizer(pHash, "simple", &pTokenizer, pzErr);
+ if( rc!=SQLITE_OK ) goto fts3_init_out;
+ }
+ assert( pTokenizer );
+
+ rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
+ if( rc==SQLITE_ERROR ){
+ assert( zPrefix );
+ *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
+ }
+ if( rc!=SQLITE_OK ) goto fts3_init_out;
+
+ /* Allocate and populate the Fts3Table structure. */
+ nByte = sizeof(Fts3Table) + /* Fts3Table */
+ nCol * sizeof(char *) + /* azColumn */
+ nIndex * sizeof(struct Fts3Index) + /* aIndex */
+ nName + /* zName */
+ nDb + /* zDb */
+ nString; /* Space for azColumn strings */
+ p = (Fts3Table*)sqlite3_malloc(nByte);
+ if( p==0 ){
+ rc = SQLITE_NOMEM;
+ goto fts3_init_out;
+ }
+ memset(p, 0, nByte);
+ p->db = db;
+ p->nColumn = nCol;
+ p->nPendingData = 0;
+ p->azColumn = (char **)&p[1];
+ p->pTokenizer = pTokenizer;
+ p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
+ p->bHasDocsize = (isFts4 && bNoDocsize==0);
+ p->bHasStat = isFts4;
+ p->bFts4 = isFts4;
+ p->bDescIdx = bDescIdx;
+ p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */
+ p->zContentTbl = zContent;
+ p->zLanguageid = zLanguageid;
+ zContent = 0;
+ zLanguageid = 0;
+ TESTONLY( p->inTransaction = -1 );
+ TESTONLY( p->mxSavepoint = -1 );
+
+ p->aIndex = (struct Fts3Index *)&p->azColumn[nCol];
+ memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex);
+ p->nIndex = nIndex;
+ for(i=0; i<nIndex; i++){
+ fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
+ }
+
+ /* Fill in the zName and zDb fields of the vtab structure. */
+ zCsr = (char *)&p->aIndex[nIndex];
+ p->zName = zCsr;
+ memcpy(zCsr, argv[2], nName);
+ zCsr += nName;
+ p->zDb = zCsr;
+ memcpy(zCsr, argv[1], nDb);
+ zCsr += nDb;
+
+ /* Fill in the azColumn array */
+ for(iCol=0; iCol<nCol; iCol++){
+ char *z;
+ int n = 0;
+ z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
+ memcpy(zCsr, z, n);
+ zCsr[n] = '\0';
+ sqlite3Fts3Dequote(zCsr);
+ p->azColumn[iCol] = zCsr;
+ zCsr += n+1;
+ assert( zCsr <= &((char *)p)[nByte] );
+ }
+
+ if( (zCompress==0)!=(zUncompress==0) ){
+ char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
+ rc = SQLITE_ERROR;
+ *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
+ }
+ p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc);
+ p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
+ if( rc!=SQLITE_OK ) goto fts3_init_out;
+
+ /* If this is an xCreate call, create the underlying tables in the
+ ** database. TODO: For xConnect(), it could verify that said tables exist.
+ */
+ if( isCreate ){
+ rc = fts3CreateTables(p);
+ }
+
+ /* Check to see if a legacy fts3 table has been "upgraded" by the
+ ** addition of a %_stat table so that it can use incremental merge.
+ */
+ if( !isFts4 && !isCreate ){
+ int rc2 = SQLITE_OK;
+ fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
+ p->zDb, p->zName);
+ if( rc2==SQLITE_OK ) p->bHasStat = 1;
+ }
+
+ /* Figure out the page-size for the database. This is required in order to
+ ** estimate the cost of loading large doclists from the database. */
+ fts3DatabasePageSize(&rc, p);
+ p->nNodeSize = p->nPgsz-35;
+
+ /* Declare the table schema to SQLite. */
+ fts3DeclareVtab(&rc, p);
+
+fts3_init_out:
+ sqlite3_free(zPrefix);
+ sqlite3_free(aIndex);
+ sqlite3_free(zCompress);
+ sqlite3_free(zUncompress);
+ sqlite3_free(zContent);
+ sqlite3_free(zLanguageid);
+ sqlite3_free((void *)aCol);
+ if( rc!=SQLITE_OK ){
+ if( p ){
+ fts3DisconnectMethod((sqlite3_vtab *)p);
+ }else if( pTokenizer ){
+ pTokenizer->pModule->xDestroy(pTokenizer);
+ }
+ }else{
+ assert( p->pSegments==0 );
+ *ppVTab = &p->base;
+ }
+ return rc;
+}
+
+/*
+** The xConnect() and xCreate() methods for the virtual table. All the
+** work is done in function fts3InitVtab().
+*/
+static int fts3ConnectMethod(
+ sqlite3 *db, /* Database connection */
+ void *pAux, /* Pointer to tokenizer hash table */
+ int argc, /* Number of elements in argv array */
+ const char * const *argv, /* xCreate/xConnect argument array */
+ sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
+ char **pzErr /* OUT: sqlite3_malloc'd error message */
+){
+ return fts3InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr);
+}
+static int fts3CreateMethod(
+ sqlite3 *db, /* Database connection */
+ void *pAux, /* Pointer to tokenizer hash table */
+ int argc, /* Number of elements in argv array */
+ const char * const *argv, /* xCreate/xConnect argument array */
+ sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
+ char **pzErr /* OUT: sqlite3_malloc'd error message */
+){
+ return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
+}
+
+/*
+** Implementation of the xBestIndex method for FTS3 tables. There
+** are three possible strategies, in order of preference:
+**
+** 1. Direct lookup by rowid or docid.
+** 2. Full-text search using a MATCH operator on a non-docid column.
+** 3. Linear scan of %_content table.
+*/
+static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
+ Fts3Table *p = (Fts3Table *)pVTab;
+ int i; /* Iterator variable */
+ int iCons = -1; /* Index of constraint to use */
+ int iLangidCons = -1; /* Index of langid=x constraint, if present */
+
+ /* By default use a full table scan. This is an expensive option,
+ ** so search through the constraints to see if a more efficient
+ ** strategy is possible.
+ */
+ pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
+ pInfo->estimatedCost = 500000;
+ for(i=0; i<pInfo->nConstraint; i++){
+ struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
+ if( pCons->usable==0 ) continue;
+
+ /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
+ if( iCons<0
+ && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
+ && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
+ ){
+ pInfo->idxNum = FTS3_DOCID_SEARCH;
+ pInfo->estimatedCost = 1.0;
+ iCons = i;
+ }
+
+ /* A MATCH constraint. Use a full-text search.
+ **
+ ** If there is more than one MATCH constraint available, use the first
+ ** one encountered. If there is both a MATCH constraint and a direct
+ ** rowid/docid lookup, prefer the MATCH strategy. This is done even
+ ** though the rowid/docid lookup is faster than a MATCH query, selecting
+ ** it would lead to an "unable to use function MATCH in the requested
+ ** context" error.
+ */
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
+ && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
+ ){
+ pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
+ pInfo->estimatedCost = 2.0;
+ iCons = i;
+ }
+
+ /* Equality constraint on the langid column */
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
+ && pCons->iColumn==p->nColumn + 2
+ ){
+ iLangidCons = i;
+ }
+ }
+
+ if( iCons>=0 ){
+ pInfo->aConstraintUsage[iCons].argvIndex = 1;
+ pInfo->aConstraintUsage[iCons].omit = 1;
+ }
+ if( iLangidCons>=0 ){
+ pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
+ }
+
+ /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
+ ** docid) order. Both ascending and descending are possible.
+ */
+ if( pInfo->nOrderBy==1 ){
+ struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
+ if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){
+ if( pOrder->desc ){
+ pInfo->idxStr = "DESC";
+ }else{
+ pInfo->idxStr = "ASC";
+ }
+ pInfo->orderByConsumed = 1;
+ }
+ }
+
+ assert( p->pSegments==0 );
+ return SQLITE_OK;
+}
+
+/*
+** Implementation of xOpen method.
+*/
+static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
+ sqlite3_vtab_cursor *pCsr; /* Allocated cursor */
+
+ UNUSED_PARAMETER(pVTab);
+
+ /* Allocate a buffer large enough for an Fts3Cursor structure. If the
+ ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
+ ** if the allocation fails, return SQLITE_NOMEM.
+ */
+ *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
+ if( !pCsr ){
+ return SQLITE_NOMEM;
+ }
+ memset(pCsr, 0, sizeof(Fts3Cursor));
+ return SQLITE_OK;
+}
+
+/*
+** Close the cursor. For additional information see the documentation
+** on the xClose method of the virtual table interface.
+*/
+static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
+ Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
+ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
+ sqlite3_finalize(pCsr->pStmt);
+ sqlite3Fts3ExprFree(pCsr->pExpr);
+ sqlite3Fts3FreeDeferredTokens(pCsr);
+ sqlite3_free(pCsr->aDoclist);
+ sqlite3_free(pCsr->aMatchinfo);
+ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+/*
+** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then
+** compose and prepare an SQL statement of the form:
+**
+** "SELECT <columns> FROM %_content WHERE rowid = ?"
+**
+** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
+** it. If an error occurs, return an SQLite error code.
+**
+** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK.
+*/
+static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
+ int rc = SQLITE_OK;
+ if( pCsr->pStmt==0 ){
+ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
+ char *zSql;
+ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
+ if( !zSql ) return SQLITE_NOMEM;
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
+ sqlite3_free(zSql);
+ }
+ *ppStmt = pCsr->pStmt;
+ return rc;
+}
+
+/*
+** Position the pCsr->pStmt statement so that it is on the row
+** of the %_content table that contains the last match. Return
+** SQLITE_OK on success.
+*/
+static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
+ int rc = SQLITE_OK;
+ if( pCsr->isRequireSeek ){
+ sqlite3_stmt *pStmt = 0;
+
+ rc = fts3CursorSeekStmt(pCsr, &pStmt);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
+ pCsr->isRequireSeek = 0;
+ if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
+ return SQLITE_OK;
+ }else{
+ rc = sqlite3_reset(pCsr->pStmt);
+ if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
+ /* If no row was found and no error has occurred, then the %_content
+ ** table is missing a row that is present in the full-text index.
+ ** The data structures are corrupt. */
+ rc = FTS_CORRUPT_VTAB;
+ pCsr->isEof = 1;
+ }
+ }
+ }
+ }
+
+ if( rc!=SQLITE_OK && pContext ){
+ sqlite3_result_error_code(pContext, rc);
+ }
+ return rc;
+}
+
+/*
+** This function is used to process a single interior node when searching
+** a b-tree for a term or term prefix. The node data is passed to this
+** function via the zNode/nNode parameters. The term to search for is
+** passed in zTerm/nTerm.
+**
+** If piFirst is not NULL, then this function sets *piFirst to the blockid
+** of the child node that heads the sub-tree that may contain the term.
+**
+** If piLast is not NULL, then *piLast is set to the right-most child node
+** that heads a sub-tree that may contain a term for which zTerm/nTerm is
+** a prefix.
+**
+** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
+*/
+static int fts3ScanInteriorNode(
+ const char *zTerm, /* Term to select leaves for */
+ int nTerm, /* Size of term zTerm in bytes */
+ const char *zNode, /* Buffer containing segment interior node */
+ int nNode, /* Size of buffer at zNode */
+ sqlite3_int64 *piFirst, /* OUT: Selected child node */
+ sqlite3_int64 *piLast /* OUT: Selected child node */
+){
+ int rc = SQLITE_OK; /* Return code */
+ const char *zCsr = zNode; /* Cursor to iterate through node */
+ const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
+ char *zBuffer = 0; /* Buffer to load terms into */
+ int nAlloc = 0; /* Size of allocated buffer */
+ int isFirstTerm = 1; /* True when processing first term on page */
+ sqlite3_int64 iChild; /* Block id of child node to descend to */
+
+ /* Skip over the 'height' varint that occurs at the start of every
+ ** interior node. Then load the blockid of the left-child of the b-tree
+ ** node into variable iChild.
+ **
+ ** Even if the data structure on disk is corrupted, this (reading two
+ ** varints from the buffer) does not risk an overread. If zNode is a
+ ** root node, then the buffer comes from a SELECT statement. SQLite does
+ ** not make this guarantee explicitly, but in practice there are always
+ ** either more than 20 bytes of allocated space following the nNode bytes of
+ ** contents, or two zero bytes. Or, if the node is read from the %_segments
+ ** table, then there are always 20 bytes of zeroed padding following the
+ ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
+ */
+ zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
+ if( zCsr>zEnd ){
+ return FTS_CORRUPT_VTAB;
+ }
+
+ while( zCsr<zEnd && (piFirst || piLast) ){
+ int cmp; /* memcmp() result */
+ int nSuffix; /* Size of term suffix */
+ int nPrefix = 0; /* Size of term prefix */
+ int nBuffer; /* Total term size */
+
+ /* Load the next term on the node into zBuffer. Use realloc() to expand
+ ** the size of zBuffer if required. */
+ if( !isFirstTerm ){
+ zCsr += sqlite3Fts3GetVarint32(zCsr, &nPrefix);
+ }
+ isFirstTerm = 0;
+ zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
+
+ if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
+ rc = FTS_CORRUPT_VTAB;
+ goto finish_scan;
+ }
+ if( nPrefix+nSuffix>nAlloc ){
+ char *zNew;
+ nAlloc = (nPrefix+nSuffix) * 2;
+ zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
+ if( !zNew ){
+ rc = SQLITE_NOMEM;
+ goto finish_scan;
+ }
+ zBuffer = zNew;
+ }
+ assert( zBuffer );
+ memcpy(&zBuffer[nPrefix], zCsr, nSuffix);
+ nBuffer = nPrefix + nSuffix;
+ zCsr += nSuffix;
+
+ /* Compare the term we are searching for with the term just loaded from
+ ** the interior node. If the specified term is greater than or equal
+ ** to the term from the interior node, then all terms on the sub-tree
+ ** headed by node iChild are smaller than zTerm. No need to search
+ ** iChild.
+ **
+ ** If the interior node term is larger than the specified term, then
+ ** the tree headed by iChild may contain the specified term.
+ */
+ cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
+ if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
+ *piFirst = iChild;
+ piFirst = 0;
+ }
+
+ if( piLast && cmp<0 ){
+ *piLast = iChild;
+ piLast = 0;
+ }
+
+ iChild++;
+ };
+
+ if( piFirst ) *piFirst = iChild;
+ if( piLast ) *piLast = iChild;
+
+ finish_scan:
+ sqlite3_free(zBuffer);
+ return rc;
+}
+
+
+/*
+** The buffer pointed to by argument zNode (size nNode bytes) contains an
+** interior node of a b-tree segment. The zTerm buffer (size nTerm bytes)
+** contains a term. This function searches the sub-tree headed by the zNode
+** node for the range of leaf nodes that may contain the specified term
+** or terms for which the specified term is a prefix.
+**
+** If piLeaf is not NULL, then *piLeaf is set to the blockid of the
+** left-most leaf node in the tree that may contain the specified term.
+** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the
+** right-most leaf node that may contain a term for which the specified
+** term is a prefix.
+**
+** It is possible that the range of returned leaf nodes does not contain
+** the specified term or any terms for which it is a prefix. However, if the
+** segment does contain any such terms, they are stored within the identified
+** range. Because this function only inspects interior segment nodes (and
+** never loads leaf nodes into memory), it is not possible to be sure.
+**
+** If an error occurs, an error code other than SQLITE_OK is returned.
+*/
+static int fts3SelectLeaf(
+ Fts3Table *p, /* Virtual table handle */
+ const char *zTerm, /* Term to select leaves for */
+ int nTerm, /* Size of term zTerm in bytes */
+ const char *zNode, /* Buffer containing segment interior node */
+ int nNode, /* Size of buffer at zNode */
+ sqlite3_int64 *piLeaf, /* Selected leaf node */
+ sqlite3_int64 *piLeaf2 /* Selected leaf node */
+){
+ int rc; /* Return code */
+ int iHeight; /* Height of this node in tree */
+
+ assert( piLeaf || piLeaf2 );
+
+ sqlite3Fts3GetVarint32(zNode, &iHeight);
+ rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
+ assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
+
+ if( rc==SQLITE_OK && iHeight>1 ){
+ char *zBlob = 0; /* Blob read from %_segments table */
+ int nBlob; /* Size of zBlob in bytes */
+
+ if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){
+ rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0);
+ if( rc==SQLITE_OK ){
+ rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0);
+ }
+ sqlite3_free(zBlob);
+ piLeaf = 0;
+ zBlob = 0;
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
+ }
+ sqlite3_free(zBlob);
+ }
+
+ return rc;
+}
+
+/*
+** This function is used to create delta-encoded serialized lists of FTS3
+** varints. Each call to this function appends a single varint to a list.
+*/
+static void fts3PutDeltaVarint(
+ char **pp, /* IN/OUT: Output pointer */
+ sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
+ sqlite3_int64 iVal /* Write this value to the list */
+){
+ assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
+ *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
+ *piPrev = iVal;
+}
+
+/*
+** When this function is called, *ppPoslist is assumed to point to the
+** start of a position-list. After it returns, *ppPoslist points to the
+** first byte after the position-list.
+**
+** A position list is list of positions (delta encoded) and columns for
+** a single document record of a doclist. So, in other words, this
+** routine advances *ppPoslist so that it points to the next docid in
+** the doclist, or to the first byte past the end of the doclist.
+**
+** If pp is not NULL, then the contents of the position list are copied
+** to *pp. *pp is set to point to the first byte past the last byte copied
+** before this function returns.
+*/
+static void fts3PoslistCopy(char **pp, char **ppPoslist){
+ char *pEnd = *ppPoslist;
+ char c = 0;
+
+ /* The end of a position list is marked by a zero encoded as an FTS3
+ ** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by
+ ** a byte with the 0x80 bit set, then it is not a varint 0, but the tail
+ ** of some other, multi-byte, value.
+ **
+ ** The following while-loop moves pEnd to point to the first byte that is not
+ ** immediately preceded by a byte with the 0x80 bit set. Then increments
+ ** pEnd once more so that it points to the byte immediately following the
+ ** last byte in the position-list.
+ */
+ while( *pEnd | c ){
+ c = *pEnd++ & 0x80;
+ testcase( c!=0 && (*pEnd)==0 );
+ }
+ pEnd++; /* Advance past the POS_END terminator byte */
+
+ if( pp ){
+ int n = (int)(pEnd - *ppPoslist);
+ char *p = *pp;
+ memcpy(p, *ppPoslist, n);
+ p += n;
+ *pp = p;
+ }
+ *ppPoslist = pEnd;
+}
+
+/*
+** When this function is called, *ppPoslist is assumed to point to the
+** start of a column-list. After it returns, *ppPoslist points to the
+** to the terminator (POS_COLUMN or POS_END) byte of the column-list.
+**
+** A column-list is list of delta-encoded positions for a single column
+** within a single document within a doclist.
+**
+** The column-list is terminated either by a POS_COLUMN varint (1) or
+** a POS_END varint (0). This routine leaves *ppPoslist pointing to
+** the POS_COLUMN or POS_END that terminates the column-list.
+**
+** If pp is not NULL, then the contents of the column-list are copied
+** to *pp. *pp is set to point to the first byte past the last byte copied
+** before this function returns. The POS_COLUMN or POS_END terminator
+** is not copied into *pp.
+*/
+static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
+ char *pEnd = *ppPoslist;
+ char c = 0;
+
+ /* A column-list is terminated by either a 0x01 or 0x00 byte that is
+ ** not part of a multi-byte varint.
+ */
+ while( 0xFE & (*pEnd | c) ){
+ c = *pEnd++ & 0x80;
+ testcase( c!=0 && ((*pEnd)&0xfe)==0 );
+ }
+ if( pp ){
+ int n = (int)(pEnd - *ppPoslist);
+ char *p = *pp;
+ memcpy(p, *ppPoslist, n);
+ p += n;
+ *pp = p;
+ }
+ *ppPoslist = pEnd;
+}
+
+/*
+** Value used to signify the end of an position-list. This is safe because
+** it is not possible to have a document with 2^31 terms.
+*/
+#define POSITION_LIST_END 0x7fffffff
+
+/*
+** This function is used to help parse position-lists. When this function is
+** called, *pp may point to the start of the next varint in the position-list
+** being parsed, or it may point to 1 byte past the end of the position-list
+** (in which case **pp will be a terminator bytes POS_END (0) or
+** (1)).
+**
+** If *pp points past the end of the current position-list, set *pi to
+** POSITION_LIST_END and return. Otherwise, read the next varint from *pp,
+** increment the current value of *pi by the value read, and set *pp to
+** point to the next value before returning.
+**
+** Before calling this routine *pi must be initialized to the value of
+** the previous position, or zero if we are reading the first position
+** in the position-list. Because positions are delta-encoded, the value
+** of the previous position is needed in order to compute the value of
+** the next position.
+*/
+static void fts3ReadNextPos(
+ char **pp, /* IN/OUT: Pointer into position-list buffer */
+ sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
+){
+ if( (**pp)&0xFE ){
+ fts3GetDeltaVarint(pp, pi);
+ *pi -= 2;
+ }else{
+ *pi = POSITION_LIST_END;
+ }
+}
+
+/*
+** If parameter iCol is not 0, write an POS_COLUMN (1) byte followed by
+** the value of iCol encoded as a varint to *pp. This will start a new
+** column list.
+**
+** Set *pp to point to the byte just after the last byte written before
+** returning (do not modify it if iCol==0). Return the total number of bytes
+** written (0 if iCol==0).
+*/
+static int fts3PutColNumber(char **pp, int iCol){
+ int n = 0; /* Number of bytes written */
+ if( iCol ){
+ char *p = *pp; /* Output pointer */
+ n = 1 + sqlite3Fts3PutVarint(&p[1], iCol);
+ *p = 0x01;
+ *pp = &p[n];
+ }
+ return n;
+}
+
+/*
+** Compute the union of two position lists. The output written
+** into *pp contains all positions of both *pp1 and *pp2 in sorted
+** order and with any duplicates removed. All pointers are
+** updated appropriately. The caller is responsible for insuring
+** that there is enough space in *pp to hold the complete output.
+*/
+static void fts3PoslistMerge(
+ char **pp, /* Output buffer */
+ char **pp1, /* Left input list */
+ char **pp2 /* Right input list */
+){
+ char *p = *pp;
+ char *p1 = *pp1;
+ char *p2 = *pp2;
+
+ while( *p1 || *p2 ){
+ int iCol1; /* The current column index in pp1 */
+ int iCol2; /* The current column index in pp2 */
+
+ if( *p1==POS_COLUMN ) sqlite3Fts3GetVarint32(&p1[1], &iCol1);
+ else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
+ else iCol1 = 0;
+
+ if( *p2==POS_COLUMN ) sqlite3Fts3GetVarint32(&p2[1], &iCol2);
+ else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
+ else iCol2 = 0;
+
+ if( iCol1==iCol2 ){
+ sqlite3_int64 i1 = 0; /* Last position from pp1 */
+ sqlite3_int64 i2 = 0; /* Last position from pp2 */
+ sqlite3_int64 iPrev = 0;
+ int n = fts3PutColNumber(&p, iCol1);
+ p1 += n;
+ p2 += n;
+
+ /* At this point, both p1 and p2 point to the start of column-lists
+ ** for the same column (the column with index iCol1 and iCol2).
+ ** A column-list is a list of non-negative delta-encoded varints, each
+ ** incremented by 2 before being stored. Each list is terminated by a
+ ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists
+ ** and writes the results to buffer p. p is left pointing to the byte
+ ** after the list written. No terminator (POS_END or POS_COLUMN) is
+ ** written to the output.
+ */
+ fts3GetDeltaVarint(&p1, &i1);
+ fts3GetDeltaVarint(&p2, &i2);
+ do {
+ fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
+ iPrev -= 2;
+ if( i1==i2 ){
+ fts3ReadNextPos(&p1, &i1);
+ fts3ReadNextPos(&p2, &i2);
+ }else if( i1<i2 ){
+ fts3ReadNextPos(&p1, &i1);
+ }else{
+ fts3ReadNextPos(&p2, &i2);
+ }
+ }while( i1!=POSITION_LIST_END || i2!=POSITION_LIST_END );
+ }else if( iCol1<iCol2 ){
+ p1 += fts3PutColNumber(&p, iCol1);
+ fts3ColumnlistCopy(&p, &p1);
+ }else{
+ p2 += fts3PutColNumber(&p, iCol2);
+ fts3ColumnlistCopy(&p, &p2);
+ }
+ }
+
+ *p++ = POS_END;
+ *pp = p;
+ *pp1 = p1 + 1;
+ *pp2 = p2 + 1;
+}
+
+/*
+** This function is used to merge two position lists into one. When it is
+** called, *pp1 and *pp2 must both point to position lists. A position-list is
+** the part of a doclist that follows each document id. For example, if a row
+** contains:
+**
+** 'a b c'|'x y z'|'a b b a'
+**
+** Then the position list for this row for token 'b' would consist of:
+**
+** 0x02 0x01 0x02 0x03 0x03 0x00
+**
+** When this function returns, both *pp1 and *pp2 are left pointing to the
+** byte following the 0x00 terminator of their respective position lists.
+**
+** If isSaveLeft is 0, an entry is added to the output position list for
+** each position in *pp2 for which there exists one or more positions in
+** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
+** when the *pp1 token appears before the *pp2 token, but not more than nToken
+** slots before it.
+**
+** e.g. nToken==1 searches for adjacent positions.
+*/
+static int fts3PoslistPhraseMerge(
+ char **pp, /* IN/OUT: Preallocated output buffer */
+ int nToken, /* Maximum difference in token positions */
+ int isSaveLeft, /* Save the left position */
+ int isExact, /* If *pp1 is exactly nTokens before *pp2 */
+ char **pp1, /* IN/OUT: Left input list */
+ char **pp2 /* IN/OUT: Right input list */
+){
+ char *p = *pp;
+ char *p1 = *pp1;
+ char *p2 = *pp2;
+ int iCol1 = 0;
+ int iCol2 = 0;
+
+ /* Never set both isSaveLeft and isExact for the same invocation. */
+ assert( isSaveLeft==0 || isExact==0 );
+
+ assert( p!=0 && *p1!=0 && *p2!=0 );
+ if( *p1==POS_COLUMN ){
+ p1++;
+ p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+ }
+ if( *p2==POS_COLUMN ){
+ p2++;
+ p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+ }
+
+ while( 1 ){
+ if( iCol1==iCol2 ){
+ char *pSave = p;
+ sqlite3_int64 iPrev = 0;
+ sqlite3_int64 iPos1 = 0;
+ sqlite3_int64 iPos2 = 0;
+
+ if( iCol1 ){
+ *p++ = POS_COLUMN;
+ p += sqlite3Fts3PutVarint(p, iCol1);
+ }
+
+ assert( *p1!=POS_END && *p1!=POS_COLUMN );
+ assert( *p2!=POS_END && *p2!=POS_COLUMN );
+ fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
+ fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
+
+ while( 1 ){
+ if( iPos2==iPos1+nToken
+ || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
+ ){
+ sqlite3_int64 iSave;
+ iSave = isSaveLeft ? iPos1 : iPos2;
+ fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2;
+ pSave = 0;
+ assert( p );
+ }
+ if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){
+ if( (*p2&0xFE)==0 ) break;
+ fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
+ }else{
+ if( (*p1&0xFE)==0 ) break;
+ fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
+ }
+ }
+
+ if( pSave ){
+ assert( pp && p );
+ p = pSave;
+ }
+
+ fts3ColumnlistCopy(0, &p1);
+ fts3ColumnlistCopy(0, &p2);
+ assert( (*p1&0xFE)==0 && (*p2&0xFE)==0 );
+ if( 0==*p1 || 0==*p2 ) break;
+
+ p1++;
+ p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+ p2++;
+ p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+ }
+
+ /* Advance pointer p1 or p2 (whichever corresponds to the smaller of
+ ** iCol1 and iCol2) so that it points to either the 0x00 that marks the
+ ** end of the position list, or the 0x01 that precedes the next
+ ** column-number in the position list.
+ */
+ else if( iCol1<iCol2 ){
+ fts3ColumnlistCopy(0, &p1);
+ if( 0==*p1 ) break;
+ p1++;
+ p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+ }else{
+ fts3ColumnlistCopy(0, &p2);
+ if( 0==*p2 ) break;
+ p2++;
+ p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+ }
+ }
+
+ fts3PoslistCopy(0, &p2);
+ fts3PoslistCopy(0, &p1);
+ *pp1 = p1;
+ *pp2 = p2;
+ if( *pp==p ){
+ return 0;
+ }
+ *p++ = 0x00;
+ *pp = p;
+ return 1;
+}
+
+/*
+** Merge two position-lists as required by the NEAR operator. The argument
+** position lists correspond to the left and right phrases of an expression
+** like:
+**
+** "phrase 1" NEAR "phrase number 2"
+**
+** Position list *pp1 corresponds to the left-hand side of the NEAR
+** expression and *pp2 to the right. As usual, the indexes in the position
+** lists are the offsets of the last token in each phrase (tokens "1" and "2"
+** in the example above).
+**
+** The output position list - written to *pp - is a copy of *pp2 with those
+** entries that are not sufficiently NEAR entries in *pp1 removed.
+*/
+static int fts3PoslistNearMerge(
+ char **pp, /* Output buffer */
+ char *aTmp, /* Temporary buffer space */
+ int nRight, /* Maximum difference in token positions */
+ int nLeft, /* Maximum difference in token positions */
+ char **pp1, /* IN/OUT: Left input list */
+ char **pp2 /* IN/OUT: Right input list */
+){
+ char *p1 = *pp1;
+ char *p2 = *pp2;
+
+ char *pTmp1 = aTmp;
+ char *pTmp2;
+ char *aTmp2;
+ int res = 1;
+
+ fts3PoslistPhraseMerge(&pTmp1, nRight, 0, 0, pp1, pp2);
+ aTmp2 = pTmp2 = pTmp1;
+ *pp1 = p1;
+ *pp2 = p2;
+ fts3PoslistPhraseMerge(&pTmp2, nLeft, 1, 0, pp2, pp1);
+ if( pTmp1!=aTmp && pTmp2!=aTmp2 ){
+ fts3PoslistMerge(pp, &aTmp, &aTmp2);
+ }else if( pTmp1!=aTmp ){
+ fts3PoslistCopy(pp, &aTmp);
+ }else if( pTmp2!=aTmp2 ){
+ fts3PoslistCopy(pp, &aTmp2);
+ }else{
+ res = 0;
+ }
+
+ return res;
+}
+
+/*
+** An instance of this function is used to merge together the (potentially
+** large number of) doclists for each term that matches a prefix query.
+** See function fts3TermSelectMerge() for details.
+*/
+typedef struct TermSelect TermSelect;
+struct TermSelect {
+ char *aaOutput[16]; /* Malloc'd output buffers */
+ int anOutput[16]; /* Size each output buffer in bytes */
+};
+
+/*
+** This function is used to read a single varint from a buffer. Parameter
+** pEnd points 1 byte past the end of the buffer. When this function is
+** called, if *pp points to pEnd or greater, then the end of the buffer
+** has been reached. In this case *pp is set to 0 and the function returns.
+**
+** If *pp does not point to or past pEnd, then a single varint is read
+** from *pp. *pp is then set to point 1 byte past the end of the read varint.
+**
+** If bDescIdx is false, the value read is added to *pVal before returning.
+** If it is true, the value read is subtracted from *pVal before this
+** function returns.
+*/
+static void fts3GetDeltaVarint3(
+ char **pp, /* IN/OUT: Point to read varint from */
+ char *pEnd, /* End of buffer */
+ int bDescIdx, /* True if docids are descending */
+ sqlite3_int64 *pVal /* IN/OUT: Integer value */
+){
+ if( *pp>=pEnd ){
+ *pp = 0;
+ }else{
+ sqlite3_int64 iVal;
+ *pp += sqlite3Fts3GetVarint(*pp, &iVal);
+ if( bDescIdx ){
+ *pVal -= iVal;
+ }else{
+ *pVal += iVal;
+ }
+ }
+}
+
+/*
+** This function is used to write a single varint to a buffer. The varint
+** is written to *pp. Before returning, *pp is set to point 1 byte past the
+** end of the value written.
+**
+** If *pbFirst is zero when this function is called, the value written to
+** the buffer is that of parameter iVal.
+**
+** If *pbFirst is non-zero when this function is called, then the value
+** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
+** (if bDescIdx is non-zero).
+**
+** Before returning, this function always sets *pbFirst to 1 and *piPrev
+** to the value of parameter iVal.
+*/
+static void fts3PutDeltaVarint3(
+ char **pp, /* IN/OUT: Output pointer */
+ int bDescIdx, /* True for descending docids */
+ sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
+ int *pbFirst, /* IN/OUT: True after first int written */
+ sqlite3_int64 iVal /* Write this value to the list */
+){
+ sqlite3_int64 iWrite;
+ if( bDescIdx==0 || *pbFirst==0 ){
+ iWrite = iVal - *piPrev;
+ }else{
+ iWrite = *piPrev - iVal;
+ }
+ assert( *pbFirst || *piPrev==0 );
+ assert( *pbFirst==0 || iWrite>0 );
+ *pp += sqlite3Fts3PutVarint(*pp, iWrite);
+ *piPrev = iVal;
+ *pbFirst = 1;
+}
+
+
+/*
+** This macro is used by various functions that merge doclists. The two
+** arguments are 64-bit docid values. If the value of the stack variable
+** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
+** Otherwise, (i2-i1).
+**
+** Using this makes it easier to write code that can merge doclists that are
+** sorted in either ascending or descending order.
+*/
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
+
+/*
+** This function does an "OR" merge of two doclists (output contains all
+** positions contained in either argument doclist). If the docids in the
+** input doclists are sorted in ascending order, parameter bDescDoclist
+** should be false. If they are sorted in ascending order, it should be
+** passed a non-zero value.
+**
+** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer
+** containing the output doclist and SQLITE_OK is returned. In this case
+** *pnOut is set to the number of bytes in the output doclist.
+**
+** If an error occurs, an SQLite error code is returned. The output values
+** are undefined in this case.
+*/
+static int fts3DoclistOrMerge(
+ int bDescDoclist, /* True if arguments are desc */
+ char *a1, int n1, /* First doclist */
+ char *a2, int n2, /* Second doclist */
+ char **paOut, int *pnOut /* OUT: Malloc'd doclist */
+){
+ sqlite3_int64 i1 = 0;
+ sqlite3_int64 i2 = 0;
+ sqlite3_int64 iPrev = 0;
+ char *pEnd1 = &a1[n1];
+ char *pEnd2 = &a2[n2];
+ char *p1 = a1;
+ char *p2 = a2;
+ char *p;
+ char *aOut;
+ int bFirstOut = 0;
+
+ *paOut = 0;
+ *pnOut = 0;
+
+ /* Allocate space for the output. Both the input and output doclists
+ ** are delta encoded. If they are in ascending order (bDescDoclist==0),
+ ** then the first docid in each list is simply encoded as a varint. For
+ ** each subsequent docid, the varint stored is the difference between the
+ ** current and previous docid (a positive number - since the list is in
+ ** ascending order).
+ **
+ ** The first docid written to the output is therefore encoded using the
+ ** same number of bytes as it is in whichever of the input lists it is
+ ** read from. And each subsequent docid read from the same input list
+ ** consumes either the same or less bytes as it did in the input (since
+ ** the difference between it and the previous value in the output must
+ ** be a positive value less than or equal to the delta value read from
+ ** the input list). The same argument applies to all but the first docid
+ ** read from the 'other' list. And to the contents of all position lists
+ ** that will be copied and merged from the input to the output.
+ **
+ ** However, if the first docid copied to the output is a negative number,
+ ** then the encoding of the first docid from the 'other' input list may
+ ** be larger in the output than it was in the input (since the delta value
+ ** may be a larger positive integer than the actual docid).
+ **
+ ** The space required to store the output is therefore the sum of the
+ ** sizes of the two inputs, plus enough space for exactly one of the input
+ ** docids to grow.
+ **
+ ** A symetric argument may be made if the doclists are in descending
+ ** order.
+ */
+ aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
+ if( !aOut ) return SQLITE_NOMEM;
+
+ p = aOut;
+ fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
+ fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
+ while( p1 || p2 ){
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
+
+ if( p2 && p1 && iDiff==0 ){
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
+ fts3PoslistMerge(&p, &p1, &p2);
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
+ }else if( !p2 || (p1 && iDiff<0) ){
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
+ fts3PoslistCopy(&p, &p1);
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
+ }else{
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2);
+ fts3PoslistCopy(&p, &p2);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
+ }
+ }
+
+ *paOut = aOut;
+ *pnOut = (int)(p-aOut);
+ assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
+ return SQLITE_OK;
+}
+
+/*
+** This function does a "phrase" merge of two doclists. In a phrase merge,
+** the output contains a copy of each position from the right-hand input
+** doclist for which there is a position in the left-hand input doclist
+** exactly nDist tokens before it.
+**
+** If the docids in the input doclists are sorted in ascending order,
+** parameter bDescDoclist should be false. If they are sorted in ascending
+** order, it should be passed a non-zero value.
+**
+** The right-hand input doclist is overwritten by this function.
+*/
+static void fts3DoclistPhraseMerge(
+ int bDescDoclist, /* True if arguments are desc */
+ int nDist, /* Distance from left to right (1=adjacent) */
+ char *aLeft, int nLeft, /* Left doclist */
+ char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
+){
+ sqlite3_int64 i1 = 0;
+ sqlite3_int64 i2 = 0;
+ sqlite3_int64 iPrev = 0;
+ char *pEnd1 = &aLeft[nLeft];
+ char *pEnd2 = &aRight[*pnRight];
+ char *p1 = aLeft;
+ char *p2 = aRight;
+ char *p;
+ int bFirstOut = 0;
+ char *aOut = aRight;
+
+ assert( nDist>0 );
+
+ p = aOut;
+ fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
+ fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
+
+ while( p1 && p2 ){
+ sqlite3_int64 iDiff = DOCID_CMP(i1, i2);
+ if( iDiff==0 ){
+ char *pSave = p;
+ sqlite3_int64 iPrevSave = iPrev;
+ int bFirstOutSave = bFirstOut;
+
+ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
+ if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){
+ p = pSave;
+ iPrev = iPrevSave;
+ bFirstOut = bFirstOutSave;
+ }
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
+ }else if( iDiff<0 ){
+ fts3PoslistCopy(0, &p1);
+ fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
+ }else{
+ fts3PoslistCopy(0, &p2);
+ fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
+ }
+ }
+
+ *pnRight = (int)(p - aOut);
+}
+
+/*
+** Argument pList points to a position list nList bytes in size. This
+** function checks to see if the position list contains any entries for
+** a token in position 0 (of any column). If so, it writes argument iDelta
+** to the output buffer pOut, followed by a position list consisting only
+** of the entries from pList at position 0, and terminated by an 0x00 byte.
+** The value returned is the number of bytes written to pOut (if any).
+*/
+SQLITE_PRIVATE int sqlite3Fts3FirstFilter(
+ sqlite3_int64 iDelta, /* Varint that may be written to pOut */
+ char *pList, /* Position list (no 0x00 term) */
+ int nList, /* Size of pList in bytes */
+ char *pOut /* Write output here */
+){
+ int nOut = 0;
+ int bWritten = 0; /* True once iDelta has been written */
+ char *p = pList;
+ char *pEnd = &pList[nList];
+
+ if( *p!=0x01 ){
+ if( *p==0x02 ){
+ nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta);
+ pOut[nOut++] = 0x02;
+ bWritten = 1;
+ }
+ fts3ColumnlistCopy(0, &p);
+ }
+
+ while( p<pEnd && *p==0x01 ){
+ sqlite3_int64 iCol;
+ p++;
+ p += sqlite3Fts3GetVarint(p, &iCol);
+ if( *p==0x02 ){
+ if( bWritten==0 ){
+ nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta);
+ bWritten = 1;
+ }
+ pOut[nOut++] = 0x01;
+ nOut += sqlite3Fts3PutVarint(&pOut[nOut], iCol);
+ pOut[nOut++] = 0x02;
+ }
+ fts3ColumnlistCopy(0, &p);
+ }
+ if( bWritten ){
+ pOut[nOut++] = 0x00;
+ }
+
+ return nOut;
+}
+
+
+/*
+** Merge all doclists in the TermSelect.aaOutput[] array into a single
+** doclist stored in TermSelect.aaOutput[0]. If successful, delete all
+** other doclists (except the aaOutput[0] one) and return SQLITE_OK.
+**
+** If an OOM error occurs, return SQLITE_NOMEM. In this case it is
+** the responsibility of the caller to free any doclists left in the
+** TermSelect.aaOutput[] array.
+*/
+static int fts3TermSelectFinishMerge(Fts3Table *p, TermSelect *pTS){
+ char *aOut = 0;
+ int nOut = 0;
+ int i;
+
+ /* Loop through the doclists in the aaOutput[] array. Merge them all
+ ** into a single doclist.
+ */
+ for(i=0; i<SizeofArray(pTS->aaOutput); i++){
+ if( pTS->aaOutput[i] ){
+ if( !aOut ){
+ aOut = pTS->aaOutput[i];
+ nOut = pTS->anOutput[i];
+ pTS->aaOutput[i] = 0;
+ }else{
+ int nNew;
+ char *aNew;
+
+ int rc = fts3DoclistOrMerge(p->bDescIdx,
+ pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew
+ );
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(aOut);
+ return rc;
+ }
+
+ sqlite3_free(pTS->aaOutput[i]);
+ sqlite3_free(aOut);
+ pTS->aaOutput[i] = 0;
+ aOut = aNew;
+ nOut = nNew;
+ }
+ }
+ }
+
+ pTS->aaOutput[0] = aOut;
+ pTS->anOutput[0] = nOut;
+ return SQLITE_OK;
+}
+
+/*
+** Merge the doclist aDoclist/nDoclist into the TermSelect object passed
+** as the first argument. The merge is an "OR" merge (see function
+** fts3DoclistOrMerge() for details).
+**
+** This function is called with the doclist for each term that matches
+** a queried prefix. It merges all these doclists into one, the doclist
+** for the specified prefix. Since there can be a very large number of
+** doclists to merge, the merging is done pair-wise using the TermSelect
+** object.
+**
+** This function returns SQLITE_OK if the merge is successful, or an
+** SQLite error code (SQLITE_NOMEM) if an error occurs.
+*/
+static int fts3TermSelectMerge(
+ Fts3Table *p, /* FTS table handle */
+ TermSelect *pTS, /* TermSelect object to merge into */
+ char *aDoclist, /* Pointer to doclist */
+ int nDoclist /* Size of aDoclist in bytes */
+){
+ if( pTS->aaOutput[0]==0 ){
+ /* If this is the first term selected, copy the doclist to the output
+ ** buffer using memcpy(). */
+ pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
+ pTS->anOutput[0] = nDoclist;
+ if( pTS->aaOutput[0] ){
+ memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
+ }else{
+ return SQLITE_NOMEM;
+ }
+ }else{
+ char *aMerge = aDoclist;
+ int nMerge = nDoclist;
+ int iOut;
+
+ for(iOut=0; iOut<SizeofArray(pTS->aaOutput); iOut++){
+ if( pTS->aaOutput[iOut]==0 ){
+ assert( iOut>0 );
+ pTS->aaOutput[iOut] = aMerge;
+ pTS->anOutput[iOut] = nMerge;
+ break;
+ }else{
+ char *aNew;
+ int nNew;
+
+ int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
+ pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew
+ );
+ if( rc!=SQLITE_OK ){
+ if( aMerge!=aDoclist ) sqlite3_free(aMerge);
+ return rc;
+ }
+
+ if( aMerge!=aDoclist ) sqlite3_free(aMerge);
+ sqlite3_free(pTS->aaOutput[iOut]);
+ pTS->aaOutput[iOut] = 0;
+
+ aMerge = aNew;
+ nMerge = nNew;
+ if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
+ pTS->aaOutput[iOut] = aMerge;
+ pTS->anOutput[iOut] = nMerge;
+ }
+ }
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Append SegReader object pNew to the end of the pCsr->apSegment[] array.
+*/
+static int fts3SegReaderCursorAppend(
+ Fts3MultiSegReader *pCsr,
+ Fts3SegReader *pNew
+){
+ if( (pCsr->nSegment%16)==0 ){
+ Fts3SegReader **apNew;
+ int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
+ apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
+ if( !apNew ){
+ sqlite3Fts3SegReaderFree(pNew);
+ return SQLITE_NOMEM;
+ }
+ pCsr->apSegment = apNew;
+ }
+ pCsr->apSegment[pCsr->nSegment++] = pNew;
+ return SQLITE_OK;
+}
+
+/*
+** Add seg-reader objects to the Fts3MultiSegReader object passed as the
+** 8th argument.
+**
+** This function returns SQLITE_OK if successful, or an SQLite error code
+** otherwise.
+*/
+static int fts3SegReaderCursor(
+ Fts3Table *p, /* FTS3 table handle */
+ int iLangid, /* Language id */
+ int iIndex, /* Index to search (from 0 to p->nIndex-1) */
+ int iLevel, /* Level of segments to scan */
+ const char *zTerm, /* Term to query for */
+ int nTerm, /* Size of zTerm in bytes */
+ int isPrefix, /* True for a prefix search */
+ int isScan, /* True to scan from zTerm to EOF */
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
+){
+ int rc = SQLITE_OK; /* Error code */
+ sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
+ int rc2; /* Result of sqlite3_reset() */
+
+ /* If iLevel is less than 0 and this is not a scan, include a seg-reader
+ ** for the pending-terms. If this is a scan, then this call must be being
+ ** made by an fts4aux module, not an FTS table. In this case calling
+ ** Fts3SegReaderPending might segfault, as the data structures used by
+ ** fts4aux are not completely populated. So it's easiest to filter these
+ ** calls out here. */
+ if( iLevel<0 && p->aIndex ){
+ Fts3SegReader *pSeg = 0;
+ rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
+ if( rc==SQLITE_OK && pSeg ){
+ rc = fts3SegReaderCursorAppend(pCsr, pSeg);
+ }
+ }
+
+ if( iLevel!=FTS3_SEGCURSOR_PENDING ){
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt);
+ }
+
+ while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
+ Fts3SegReader *pSeg = 0;
+
+ /* Read the values returned by the SELECT into local variables. */
+ sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1);
+ sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2);
+ sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3);
+ int nRoot = sqlite3_column_bytes(pStmt, 4);
+ char const *zRoot = sqlite3_column_blob(pStmt, 4);
+
+ /* If zTerm is not NULL, and this segment is not stored entirely on its
+ ** root node, the range of leaves scanned can be reduced. Do this. */
+ if( iStartBlock && zTerm ){
+ sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
+ rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
+ if( rc!=SQLITE_OK ) goto finished;
+ if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
+ }
+
+ rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
+ (isPrefix==0 && isScan==0),
+ iStartBlock, iLeavesEndBlock,
+ iEndBlock, zRoot, nRoot, &pSeg
+ );
+ if( rc!=SQLITE_OK ) goto finished;
+ rc = fts3SegReaderCursorAppend(pCsr, pSeg);
+ }
+ }
+
+ finished:
+ rc2 = sqlite3_reset(pStmt);
+ if( rc==SQLITE_DONE ) rc = rc2;
+
+ return rc;
+}
+
+/*
+** Set up a cursor object for iterating through a full-text index or a
+** single level therein.
+*/
+SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
+ Fts3Table *p, /* FTS3 table handle */
+ int iLangid, /* Language-id to search */
+ int iIndex, /* Index to search (from 0 to p->nIndex-1) */
+ int iLevel, /* Level of segments to scan */
+ const char *zTerm, /* Term to query for */
+ int nTerm, /* Size of zTerm in bytes */
+ int isPrefix, /* True for a prefix search */
+ int isScan, /* True to scan from zTerm to EOF */
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
+){
+ assert( iIndex>=0 && iIndex<p->nIndex );
+ assert( iLevel==FTS3_SEGCURSOR_ALL
+ || iLevel==FTS3_SEGCURSOR_PENDING
+ || iLevel>=0
+ );
+ assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
+ assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
+ assert( isPrefix==0 || isScan==0 );
+
+ memset(pCsr, 0, sizeof(Fts3MultiSegReader));
+ return fts3SegReaderCursor(
+ p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
+ );
+}
+
+/*
+** In addition to its current configuration, have the Fts3MultiSegReader
+** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+*/
+static int fts3SegReaderCursorAddZero(
+ Fts3Table *p, /* FTS virtual table handle */
+ int iLangid,
+ const char *zTerm, /* Term to scan doclist of */
+ int nTerm, /* Number of bytes in zTerm */
+ Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
+){
+ return fts3SegReaderCursor(p,
+ iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr
+ );
+}
+
+/*
+** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
+** if isPrefix is true, to scan the doclist for all terms for which
+** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
+** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
+** an SQLite error code.
+**
+** It is the responsibility of the caller to free this object by eventually
+** passing it to fts3SegReaderCursorFree()
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+** Output parameter *ppSegcsr is set to 0 if an error occurs.
+*/
+static int fts3TermSegReaderCursor(
+ Fts3Cursor *pCsr, /* Virtual table cursor handle */
+ const char *zTerm, /* Term to query for */
+ int nTerm, /* Size of zTerm in bytes */
+ int isPrefix, /* True for a prefix search */
+ Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
+){
+ Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
+ int rc = SQLITE_NOMEM; /* Return code */
+
+ pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
+ if( pSegcsr ){
+ int i;
+ int bFound = 0; /* True once an index has been found */
+ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
+
+ if( isPrefix ){
+ for(i=1; bFound==0 && i<p->nIndex; i++){
+ if( p->aIndex[i].nPrefix==nTerm ){
+ bFound = 1;
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr
+ );
+ pSegcsr->bLookup = 1;
+ }
+ }
+
+ for(i=1; bFound==0 && i<p->nIndex; i++){
+ if( p->aIndex[i].nPrefix==nTerm+1 ){
+ bFound = 1;
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
+ );
+ if( rc==SQLITE_OK ){
+ rc = fts3SegReaderCursorAddZero(
+ p, pCsr->iLangid, zTerm, nTerm, pSegcsr
+ );
+ }
+ }
+ }
+ }
+
+ if( bFound==0 ){
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
+ );
+ pSegcsr->bLookup = !isPrefix;
+ }
+ }
+
+ *ppSegcsr = pSegcsr;
+ return rc;
+}
+
+/*
+** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
+*/
+static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
+ sqlite3Fts3SegReaderFinish(pSegcsr);
+ sqlite3_free(pSegcsr);
+}
+
+/*
+** This function retrieves the doclist for the specified term (or term
+** prefix) from the database.
+*/
+static int fts3TermSelect(
+ Fts3Table *p, /* Virtual table handle */
+ Fts3PhraseToken *pTok, /* Token to query for */
+ int iColumn, /* Column to query (or -ve for all columns) */
+ int *pnOut, /* OUT: Size of buffer at *ppOut */
+ char **ppOut /* OUT: Malloced result buffer */
+){
+ int rc; /* Return code */
+ Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
+ TermSelect tsc; /* Object for pair-wise doclist merging */
+ Fts3SegFilter filter; /* Segment term filter configuration */
+
+ pSegcsr = pTok->pSegcsr;
+ memset(&tsc, 0, sizeof(TermSelect));
+
+ filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
+ | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
+ | (pTok->bFirst ? FTS3_SEGMENT_FIRST : 0)
+ | (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
+ filter.iCol = iColumn;
+ filter.zTerm = pTok->z;
+ filter.nTerm = pTok->n;
+
+ rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
+ while( SQLITE_OK==rc
+ && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
+ ){
+ rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = fts3TermSelectFinishMerge(p, &tsc);
+ }
+ if( rc==SQLITE_OK ){
+ *ppOut = tsc.aaOutput[0];
+ *pnOut = tsc.anOutput[0];
+ }else{
+ int i;
+ for(i=0; i<SizeofArray(tsc.aaOutput); i++){
+ sqlite3_free(tsc.aaOutput[i]);
+ }
+ }
+
+ fts3SegReaderCursorFree(pSegcsr);
+ pTok->pSegcsr = 0;
+ return rc;
+}
+
+/*
+** This function counts the total number of docids in the doclist stored
+** in buffer aList[], size nList bytes.
+**
+** If the isPoslist argument is true, then it is assumed that the doclist
+** contains a position-list following each docid. Otherwise, it is assumed
+** that the doclist is simply a list of docids stored as delta encoded
+** varints.
+*/
+static int fts3DoclistCountDocids(char *aList, int nList){
+ int nDoc = 0; /* Return value */
+ if( aList ){
+ char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
+ char *p = aList; /* Cursor */
+ while( p<aEnd ){
+ nDoc++;
+ while( (*p++)&0x80 ); /* Skip docid varint */
+ fts3PoslistCopy(0, &p); /* Skip over position list */
+ }
+ }
+
+ return nDoc;
+}
+
+/*
+** Advance the cursor to the next row in the %_content table that
+** matches the search criteria. For a MATCH search, this will be
+** the next row that matches. For a full-table scan, this will be
+** simply the next row in the %_content table. For a docid lookup,
+** this routine simply sets the EOF flag.
+**
+** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
+** even if we reach end-of-file. The fts3EofMethod() will be called
+** subsequently to determine whether or not an EOF was hit.
+*/
+static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
+ int rc;
+ Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
+ if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
+ if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
+ pCsr->isEof = 1;
+ rc = sqlite3_reset(pCsr->pStmt);
+ }else{
+ pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
+ rc = SQLITE_OK;
+ }
+ }else{
+ rc = fts3EvalNext((Fts3Cursor *)pCursor);
+ }
+ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
+ return rc;
+}
+
+/*
+** This is the xFilter interface for the virtual table. See
+** the virtual table xFilter method documentation for additional
+** information.
+**
+** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against
+** the %_content table.
+**
+** If idxNum==FTS3_DOCID_SEARCH then do a docid lookup for a single entry
+** in the %_content table.
+**
+** If idxNum>=FTS3_FULLTEXT_SEARCH then use the full text index. The
+** column on the left-hand side of the MATCH operator is column
+** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand
+** side of the MATCH operator.
+*/
+static int fts3FilterMethod(
+ sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
+ int idxNum, /* Strategy index */
+ const char *idxStr, /* Unused */
+ int nVal, /* Number of elements in apVal */
+ sqlite3_value **apVal /* Arguments for the indexing scheme */
+){
+ int rc;
+ char *zSql; /* SQL statement used to access %_content */
+ Fts3Table *p = (Fts3Table *)pCursor->pVtab;
+ Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
+
+ UNUSED_PARAMETER(idxStr);
+ UNUSED_PARAMETER(nVal);
+
+ assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
+ assert( nVal==0 || nVal==1 || nVal==2 );
+ assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
+ assert( p->pSegments==0 );
+
+ /* In case the cursor has been used before, clear it now. */
+ sqlite3_finalize(pCsr->pStmt);
+ sqlite3_free(pCsr->aDoclist);
+ sqlite3Fts3ExprFree(pCsr->pExpr);
+ memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
+
+ if( idxStr ){
+ pCsr->bDesc = (idxStr[0]=='D');
+ }else{
+ pCsr->bDesc = p->bDescIdx;
+ }
+ pCsr->eSearch = (i16)idxNum;
+
+ if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
+ int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
+ const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
+
+ if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
+ return SQLITE_NOMEM;
+ }
+
+ pCsr->iLangid = 0;
+ if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
+
+ rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
+ p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
+ );
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_ERROR ){
+ static const char *zErr = "malformed MATCH expression: [%s]";
+ p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
+ }
+ return rc;
+ }
+
+ rc = sqlite3Fts3ReadLock(p);
+ if( rc!=SQLITE_OK ) return rc;
+
+ rc = fts3EvalStart(pCsr);
+
+ sqlite3Fts3SegmentsClose(p);
+ if( rc!=SQLITE_OK ) return rc;
+ pCsr->pNextId = pCsr->aDoclist;
+ pCsr->iPrevId = 0;
+ }
+
+ /* Compile a SELECT statement for this cursor. For a full-table-scan, the
+ ** statement loops through all rows of the %_content table. For a
+ ** full-text query or docid lookup, the statement retrieves a single
+ ** row by docid.
+ */
+ if( idxNum==FTS3_FULLSCAN_SEARCH ){
+ zSql = sqlite3_mprintf(
+ "SELECT %s ORDER BY rowid %s",
+ p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
+ );
+ if( zSql ){
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
+ sqlite3_free(zSql);
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ }else if( idxNum==FTS3_DOCID_SEARCH ){
+ rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
+ }
+ }
+ if( rc!=SQLITE_OK ) return rc;
+
+ return fts3NextMethod(pCursor);
+}
+
+/*
+** This is the xEof method of the virtual table. SQLite calls this
+** routine to find out if it has reached the end of a result set.
+*/
+static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
+ return ((Fts3Cursor *)pCursor)->isEof;
+}
+
+/*
+** This is the xRowid method. The SQLite core calls this routine to
+** retrieve the rowid for the current row of the result set. fts3
+** exposes %_content.docid as the rowid for the virtual table. The
+** rowid should be written to *pRowid.
+*/
+static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
+ Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
+ *pRowid = pCsr->iPrevId;
+ return SQLITE_OK;
+}
+
+/*
+** This is the xColumn method, called by SQLite to request a value from
+** the row that the supplied cursor currently points to.
+**
+** If:
+**
+** (iCol < p->nColumn) -> The value of the iCol'th user column.
+** (iCol == p->nColumn) -> Magic column with the same name as the table.
+** (iCol == p->nColumn+1) -> Docid column
+** (iCol == p->nColumn+2) -> Langid column
+*/
+static int fts3ColumnMethod(
+ sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
+ sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
+ int iCol /* Index of column to read value from */
+){
+ int rc = SQLITE_OK; /* Return Code */
+ Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
+ Fts3Table *p = (Fts3Table *)pCursor->pVtab;
+
+ /* The column value supplied by SQLite must be in range. */
+ assert( iCol>=0 && iCol<=p->nColumn+2 );
+
+ if( iCol==p->nColumn+1 ){
+ /* This call is a request for the "docid" column. Since "docid" is an
+ ** alias for "rowid", use the xRowid() method to obtain the value.
+ */
+ sqlite3_result_int64(pCtx, pCsr->iPrevId);
+ }else if( iCol==p->nColumn ){
+ /* The extra column whose name is the same as the table.
+ ** Return a blob which is a pointer to the cursor. */
+ sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
+ }else if( iCol==p->nColumn+2 && pCsr->pExpr ){
+ sqlite3_result_int64(pCtx, pCsr->iLangid);
+ }else{
+ /* The requested column is either a user column (one that contains
+ ** indexed data), or the language-id column. */
+ rc = fts3CursorSeek(0, pCsr);
+
+ if( rc==SQLITE_OK ){
+ if( iCol==p->nColumn+2 ){
+ int iLangid = 0;
+ if( p->zLanguageid ){
+ iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
+ }
+ sqlite3_result_int(pCtx, iLangid);
+ }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
+ sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
+ }
+ }
+ }
+
+ assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
+ return rc;
+}
+
+/*
+** This function is the implementation of the xUpdate callback used by
+** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
+** inserted, updated or deleted.
+*/
+static int fts3UpdateMethod(
+ sqlite3_vtab *pVtab, /* Virtual table handle */
+ int nArg, /* Size of argument array */
+ sqlite3_value **apVal, /* Array of arguments */
+ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
+){
+ return sqlite3Fts3UpdateMethod(pVtab, nArg, apVal, pRowid);
+}
+
+/*
+** Implementation of xSync() method. Flush the contents of the pending-terms
+** hash-table to the database.
+*/
+static int fts3SyncMethod(sqlite3_vtab *pVtab){
+
+ /* Following an incremental-merge operation, assuming that the input
+ ** segments are not completely consumed (the usual case), they are updated
+ ** in place to remove the entries that have already been merged. This
+ ** involves updating the leaf block that contains the smallest unmerged
+ ** entry and each block (if any) between the leaf and the root node. So
+ ** if the height of the input segment b-trees is N, and input segments
+ ** are merged eight at a time, updating the input segments at the end
+ ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually
+ ** small - often between 0 and 2. So the overhead of the incremental
+ ** merge is somewhere between 8 and 24 blocks. To avoid this overhead
+ ** dwarfing the actual productive work accomplished, the incremental merge
+ ** is only attempted if it will write at least 64 leaf blocks. Hence
+ ** nMinMerge.
+ **
+ ** Of course, updating the input segments also involves deleting a bunch
+ ** of blocks from the segments table. But this is not considered overhead
+ ** as it would also be required by a crisis-merge that used the same input
+ ** segments.
+ */
+ const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
+
+ Fts3Table *p = (Fts3Table*)pVtab;
+ int rc = sqlite3Fts3PendingTermsFlush(p);
+
+ if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){
+ int mxLevel = 0; /* Maximum relative level value in db */
+ int A; /* Incr-merge parameter A */
+
+ rc = sqlite3Fts3MaxLevel(p, &mxLevel);
+ assert( rc==SQLITE_OK || mxLevel==0 );
+ A = p->nLeafAdd * mxLevel;
+ A += (A/2);
+ if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
+ }
+ sqlite3Fts3SegmentsClose(p);
+ return rc;
+}
+
+/*
+** Implementation of xBegin() method. This is a no-op.
+*/
+static int fts3BeginMethod(sqlite3_vtab *pVtab){
+ Fts3Table *p = (Fts3Table*)pVtab;
+ UNUSED_PARAMETER(pVtab);
+ assert( p->pSegments==0 );
+ assert( p->nPendingData==0 );
+ assert( p->inTransaction!=1 );
+ TESTONLY( p->inTransaction = 1 );
+ TESTONLY( p->mxSavepoint = -1; );
+ p->nLeafAdd = 0;
+ return SQLITE_OK;
+}
+
+/*
+** Implementation of xCommit() method. This is a no-op. The contents of
+** the pending-terms hash-table have already been flushed into the database
+** by fts3SyncMethod().
+*/
+static int fts3CommitMethod(sqlite3_vtab *pVtab){
+ TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
+ UNUSED_PARAMETER(pVtab);
+ assert( p->nPendingData==0 );
+ assert( p->inTransaction!=0 );
+ assert( p->pSegments==0 );
+ TESTONLY( p->inTransaction = 0 );
+ TESTONLY( p->mxSavepoint = -1; );
+ return SQLITE_OK;
+}
+
+/*
+** Implementation of xRollback(). Discard the contents of the pending-terms
+** hash-table. Any changes made to the database are reverted by SQLite.
+*/
+static int fts3RollbackMethod(sqlite3_vtab *pVtab){
+ Fts3Table *p = (Fts3Table*)pVtab;
+ sqlite3Fts3PendingTermsClear(p);
+ assert( p->inTransaction!=0 );
+ TESTONLY( p->inTransaction = 0 );
+ TESTONLY( p->mxSavepoint = -1; );
+ return SQLITE_OK;
+}
+
+/*
+** When called, *ppPoslist must point to the byte immediately following the
+** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
+** moves *ppPoslist so that it instead points to the first byte of the
+** same position list.
+*/
+static void fts3ReversePoslist(char *pStart, char **ppPoslist){
+ char *p = &(*ppPoslist)[-2];
+ char c = 0;
+
+ while( p>pStart && (c=*p--)==0 );
+ while( p>pStart && (*p & 0x80) | c ){
+ c = *p--;
+ }
+ if( p>pStart ){ p = &p[2]; }
+ while( *p++&0x80 );
+ *ppPoslist = p;
+}
+
+/*
+** Helper function used by the implementation of the overloaded snippet(),
+** offsets() and optimize() SQL functions.
+**
+** If the value passed as the third argument is a blob of size
+** sizeof(Fts3Cursor*), then the blob contents are copied to the
+** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error
+** message is written to context pContext and SQLITE_ERROR returned. The
+** string passed via zFunc is used as part of the error message.
+*/
+static int fts3FunctionArg(
+ sqlite3_context *pContext, /* SQL function call context */
+ const char *zFunc, /* Function name */
+ sqlite3_value *pVal, /* argv[0] passed to function */
+ Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
+){
+ Fts3Cursor *pRet;
+ if( sqlite3_value_type(pVal)!=SQLITE_BLOB
+ || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
+ ){
+ char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
+ sqlite3_result_error(pContext, zErr, -1);
+ sqlite3_free(zErr);
+ return SQLITE_ERROR;
+ }
+ memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
+ *ppCsr = pRet;
+ return SQLITE_OK;
+}
+
+/*
+** Implementation of the snippet() function for FTS3
+*/
+static void fts3SnippetFunc(
+ sqlite3_context *pContext, /* SQLite function call context */
+ int nVal, /* Size of apVal[] array */
+ sqlite3_value **apVal /* Array of arguments */
+){
+ Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
+ const char *zStart = "<b>";
+ const char *zEnd = "</b>";
+ const char *zEllipsis = "<b>...</b>";
+ int iCol = -1;
+ int nToken = 15; /* Default number of tokens in snippet */
+
+ /* There must be at least one argument passed to this function (otherwise
+ ** the non-overloaded version would have been called instead of this one).
+ */
+ assert( nVal>=1 );
+
+ if( nVal>6 ){
+ sqlite3_result_error(pContext,
+ "wrong number of arguments to function snippet()", -1);
+ return;
+ }
+ if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;
+
+ switch( nVal ){
+ case 6: nToken = sqlite3_value_int(apVal[5]);
+ case 5: iCol = sqlite3_value_int(apVal[4]);
+ case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
+ case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
+ case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
+ }
+ if( !zEllipsis || !zEnd || !zStart ){
+ sqlite3_result_error_nomem(pContext);
+ }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
+ sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
+ }
+}
+
+/*
+** Implementation of the offsets() function for FTS3
+*/
+static void fts3OffsetsFunc(
+ sqlite3_context *pContext, /* SQLite function call context */
+ int nVal, /* Size of argument array */
+ sqlite3_value **apVal /* Array of arguments */
+){
+ Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
+
+ UNUSED_PARAMETER(nVal);
+
+ assert( nVal==1 );
+ if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return;
+ assert( pCsr );
+ if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
+ sqlite3Fts3Offsets(pContext, pCsr);
+ }
+}
+
+/*
+** Implementation of the special optimize() function for FTS3. This
+** function merges all segments in the database to a single segment.
+** Example usage is:
+**
+** SELECT optimize(t) FROM t LIMIT 1;
+**
+** where 't' is the name of an FTS3 table.
+*/
+static void fts3OptimizeFunc(
+ sqlite3_context *pContext, /* SQLite function call context */
+ int nVal, /* Size of argument array */
+ sqlite3_value **apVal /* Array of arguments */
+){
+ int rc; /* Return code */
+ Fts3Table *p; /* Virtual table handle */
+ Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */
+
+ UNUSED_PARAMETER(nVal);
+
+ assert( nVal==1 );
+ if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return;
+ p = (Fts3Table *)pCursor->base.pVtab;
+ assert( p );
+
+ rc = sqlite3Fts3Optimize(p);
+
+ switch( rc ){
+ case SQLITE_OK:
+ sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC);
+ break;
+ case SQLITE_DONE:
+ sqlite3_result_text(pContext, "Index already optimal", -1, SQLITE_STATIC);
+ break;
+ default:
+ sqlite3_result_error_code(pContext, rc);
+ break;
+ }
+}
+
+/*
+** Implementation of the matchinfo() function for FTS3
+*/
+static void fts3MatchinfoFunc(
+ sqlite3_context *pContext, /* SQLite function call context */
+ int nVal, /* Size of argument array */
+ sqlite3_value **apVal /* Array of arguments */
+){
+ Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
+ assert( nVal==1 || nVal==2 );
+ if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){
+ const char *zArg = 0;
+ if( nVal>1 ){
+ zArg = (const char *)sqlite3_value_text(apVal[1]);
+ }
+ sqlite3Fts3Matchinfo(pContext, pCsr, zArg);
+ }
+}
+
+/*
+** This routine implements the xFindFunction method for the FTS3
+** virtual table.
+*/
+static int fts3FindFunctionMethod(
+ sqlite3_vtab *pVtab, /* Virtual table handle */
+ int nArg, /* Number of SQL function arguments */
+ const char *zName, /* Name of SQL function */
+ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
+ void **ppArg /* Unused */
+){
+ struct Overloaded {
+ const char *zName;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+ } aOverload[] = {
+ { "snippet", fts3SnippetFunc },
+ { "offsets", fts3OffsetsFunc },
+ { "optimize", fts3OptimizeFunc },
+ { "matchinfo", fts3MatchinfoFunc },
+ };
+ int i; /* Iterator variable */
+
+ UNUSED_PARAMETER(pVtab);
+ UNUSED_PARAMETER(nArg);
+ UNUSED_PARAMETER(ppArg);
+
+ for(i=0; i<SizeofArray(aOverload); i++){
+ if( strcmp(zName, aOverload[i].zName)==0 ){
+ *pxFunc = aOverload[i].xFunc;
+ return 1;
+ }
+ }
+
+ /* No function of the specified name was found. Return 0. */
+ return 0;
+}
+
+/*
+** Implementation of FTS3 xRename method. Rename an fts3 table.
+*/
+static int fts3RenameMethod(
+ sqlite3_vtab *pVtab, /* Virtual table handle */
+ const char *zName /* New name of table */
+){
+ Fts3Table *p = (Fts3Table *)pVtab;
+ sqlite3 *db = p->db; /* Database connection */
+ int rc; /* Return Code */
+
+ /* As it happens, the pending terms table is always empty here. This is
+ ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
+ ** always opens a savepoint transaction. And the xSavepoint() method
+ ** flushes the pending terms table. But leave the (no-op) call to
+ ** PendingTermsFlush() in in case that changes.
+ */
+ assert( p->nPendingData==0 );
+ rc = sqlite3Fts3PendingTermsFlush(p);
+
+ if( p->zContentTbl==0 ){
+ fts3DbExec(&rc, db,
+ "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';",
+ p->zDb, p->zName, zName
+ );
+ }
+
+ if( p->bHasDocsize ){
+ fts3DbExec(&rc, db,
+ "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';",
+ p->zDb, p->zName, zName
+ );
+ }
+ if( p->bHasStat ){
+ fts3DbExec(&rc, db,
+ "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';",
+ p->zDb, p->zName, zName
+ );
+ }
+ fts3DbExec(&rc, db,
+ "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';",
+ p->zDb, p->zName, zName
+ );
+ fts3DbExec(&rc, db,
+ "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
+ p->zDb, p->zName, zName
+ );
+ return rc;
+}
+
+/*
+** The xSavepoint() method.
+**
+** Flush the contents of the pending-terms table to disk.
+*/
+static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
+ int rc = SQLITE_OK;
+ UNUSED_PARAMETER(iSavepoint);
+ assert( ((Fts3Table *)pVtab)->inTransaction );
+ assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
+ TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
+ if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){
+ rc = fts3SyncMethod(pVtab);
+ }
+ return rc;
+}
+
+/*
+** The xRelease() method.
+**
+** This is a no-op.
+*/
+static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
+ TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
+ UNUSED_PARAMETER(iSavepoint);
+ UNUSED_PARAMETER(pVtab);
+ assert( p->inTransaction );
+ assert( p->mxSavepoint >= iSavepoint );
+ TESTONLY( p->mxSavepoint = iSavepoint-1 );
+ return SQLITE_OK;
+}
+
+/*
+** The xRollbackTo() method.
+**
+** Discard the contents of the pending terms table.
+*/
+static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
+ Fts3Table *p = (Fts3Table*)pVtab;
+ UNUSED_PARAMETER(iSavepoint);
+ assert( p->inTransaction );
+ assert( p->mxSavepoint >= iSavepoint );
+ TESTONLY( p->mxSavepoint = iSavepoint );
+ sqlite3Fts3PendingTermsClear(p);
+ return SQLITE_OK;
+}
+
+static const sqlite3_module fts3Module = {
+ /* iVersion */ 2,
+ /* xCreate */ fts3CreateMethod,
+ /* xConnect */ fts3ConnectMethod,
+ /* xBestIndex */ fts3BestIndexMethod,
+ /* xDisconnect */ fts3DisconnectMethod,
+ /* xDestroy */ fts3DestroyMethod,
+ /* xOpen */ fts3OpenMethod,
+ /* xClose */ fts3CloseMethod,
+ /* xFilter */ fts3FilterMethod,
+ /* xNext */ fts3NextMethod,
+ /* xEof */ fts3EofMethod,
+ /* xColumn */ fts3ColumnMethod,
+ /* xRowid */ fts3RowidMethod,
+ /* xUpdate */ fts3UpdateMethod,
+ /* xBegin */ fts3BeginMethod,
+ /* xSync */ fts3SyncMethod,
+ /* xCommit */ fts3CommitMethod,
+ /* xRollback */ fts3RollbackMethod,
+ /* xFindFunction */ fts3FindFunctionMethod,
+ /* xRename */ fts3RenameMethod,
+ /* xSavepoint */ fts3SavepointMethod,
+ /* xRelease */ fts3ReleaseMethod,
+ /* xRollbackTo */ fts3RollbackToMethod,
+};
+
+/*
+** This function is registered as the module destructor (called when an
+** FTS3 enabled database connection is closed). It frees the memory
+** allocated for the tokenizer hash table.
+*/
+static void hashDestroy(void *p){
+ Fts3Hash *pHash = (Fts3Hash *)p;
+ sqlite3Fts3HashClear(pHash);
+ sqlite3_free(pHash);
+}
+
+/*
+** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are
+** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c
+** respectively. The following three forward declarations are for functions
+** declared in these files used to retrieve the respective implementations.
+**
+** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed
+** to by the argument to point to the "simple" tokenizer implementation.
+** And so on.
+*/
+SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
+SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
+#endif
+#ifdef SQLITE_ENABLE_ICU
+SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
+#endif
+
+/*
+** Initialize the fts3 extension. If this extension is built as part
+** of the sqlite library, then this function is called directly by
+** SQLite. If fts3 is built as a dynamically loadable extension, this
+** function is called by the sqlite3_extension_init() entry point.
+*/
+SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
+ int rc = SQLITE_OK;
+ Fts3Hash *pHash = 0;
+ const sqlite3_tokenizer_module *pSimple = 0;
+ const sqlite3_tokenizer_module *pPorter = 0;
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+ const sqlite3_tokenizer_module *pUnicode = 0;
+#endif
+
+#ifdef SQLITE_ENABLE_ICU
+ const sqlite3_tokenizer_module *pIcu = 0;
+ sqlite3Fts3IcuTokenizerModule(&pIcu);
+#endif
+
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+ sqlite3Fts3UnicodeTokenizer(&pUnicode);
+#endif
+
+#ifdef SQLITE_TEST
+ rc = sqlite3Fts3InitTerm(db);
+ if( rc!=SQLITE_OK ) return rc;
+#endif
+
+ rc = sqlite3Fts3InitAux(db);
+ if( rc!=SQLITE_OK ) return rc;
+
+ sqlite3Fts3SimpleTokenizerModule(&pSimple);
+ sqlite3Fts3PorterTokenizerModule(&pPorter);
+
+ /* Allocate and initialize the hash-table used to store tokenizers. */
+ pHash = sqlite3_malloc(sizeof(Fts3Hash));
+ if( !pHash ){
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
+ }
+
+ /* Load the built-in tokenizers into the hash table */
+ if( rc==SQLITE_OK ){
+ if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
+ || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
+
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+ || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
+#endif
+#ifdef SQLITE_ENABLE_ICU
+ || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
+#endif
+ ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+
+#ifdef SQLITE_TEST
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3ExprInitTestInterface(db);
+ }
+#endif
+
+ /* Create the virtual table wrapper around the hash-table and overload
+ ** the two scalar functions. If this is successful, register the
+ ** module with sqlite.
+ */
+ if( SQLITE_OK==rc
+ && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
+ ){
+ rc = sqlite3_create_module_v2(
+ db, "fts3", &fts3Module, (void *)pHash, hashDestroy
+ );
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_module_v2(
+ db, "fts4", &fts3Module, (void *)pHash, 0
+ );
+ }
+ return rc;
+ }
+
+ /* An error has occurred. Delete the hash table and return the error code. */
+ assert( rc!=SQLITE_OK );
+ if( pHash ){
+ sqlite3Fts3HashClear(pHash);
+ sqlite3_free(pHash);
+ }
+ return rc;
+}
+
+/*
+** Allocate an Fts3MultiSegReader for each token in the expression headed
+** by pExpr.
+**
+** An Fts3SegReader object is a cursor that can seek or scan a range of
+** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
+** Fts3SegReader objects internally to provide an interface to seek or scan
+** within the union of all segments of a b-tree. Hence the name.
+**
+** If the allocated Fts3MultiSegReader just seeks to a single entry in a
+** segment b-tree (if the term is not a prefix or it is a prefix for which
+** there exists prefix b-tree of the right length) then it may be traversed
+** and merged incrementally. Otherwise, it has to be merged into an in-memory
+** doclist and then traversed.
+*/
+static void fts3EvalAllocateReaders(
+ Fts3Cursor *pCsr, /* FTS cursor handle */
+ Fts3Expr *pExpr, /* Allocate readers for this expression */
+ int *pnToken, /* OUT: Total number of tokens in phrase. */
+ int *pnOr, /* OUT: Total number of OR nodes in expr. */
+ int *pRc /* IN/OUT: Error code */
+){
+ if( pExpr && SQLITE_OK==*pRc ){
+ if( pExpr->eType==FTSQUERY_PHRASE ){
+ int i;
+ int nToken = pExpr->pPhrase->nToken;
+ *pnToken += nToken;
+ for(i=0; i<nToken; i++){
+ Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
+ int rc = fts3TermSegReaderCursor(pCsr,
+ pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
+ );
+ if( rc!=SQLITE_OK ){
+ *pRc = rc;
+ return;
+ }
+ }
+ assert( pExpr->pPhrase->iDoclistToken==0 );
+ pExpr->pPhrase->iDoclistToken = -1;
+ }else{
+ *pnOr += (pExpr->eType==FTSQUERY_OR);
+ fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
+ fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
+ }
+ }
+}
+
+/*
+** Arguments pList/nList contain the doclist for token iToken of phrase p.
+** It is merged into the main doclist stored in p->doclist.aAll/nAll.
+**
+** This function assumes that pList points to a buffer allocated using
+** sqlite3_malloc(). This function takes responsibility for eventually
+** freeing the buffer.
+*/
+static void fts3EvalPhraseMergeToken(
+ Fts3Table *pTab, /* FTS Table pointer */
+ Fts3Phrase *p, /* Phrase to merge pList/nList into */
+ int iToken, /* Token pList/nList corresponds to */
+ char *pList, /* Pointer to doclist */
+ int nList /* Number of bytes in pList */
+){
+ assert( iToken!=p->iDoclistToken );
+
+ if( pList==0 ){
+ sqlite3_free(p->doclist.aAll);
+ p->doclist.aAll = 0;
+ p->doclist.nAll = 0;
+ }
+
+ else if( p->iDoclistToken<0 ){
+ p->doclist.aAll = pList;
+ p->doclist.nAll = nList;
+ }
+
+ else if( p->doclist.aAll==0 ){
+ sqlite3_free(pList);
+ }
+
+ else {
+ char *pLeft;
+ char *pRight;
+ int nLeft;
+ int nRight;
+ int nDiff;
+
+ if( p->iDoclistToken<iToken ){
+ pLeft = p->doclist.aAll;
+ nLeft = p->doclist.nAll;
+ pRight = pList;
+ nRight = nList;
+ nDiff = iToken - p->iDoclistToken;
+ }else{
+ pRight = p->doclist.aAll;
+ nRight = p->doclist.nAll;
+ pLeft = pList;
+ nLeft = nList;
+ nDiff = p->iDoclistToken - iToken;
+ }
+
+ fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight);
+ sqlite3_free(pLeft);
+ p->doclist.aAll = pRight;
+ p->doclist.nAll = nRight;
+ }
+
+ if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
+}
+
+/*
+** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist
+** does not take deferred tokens into account.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+*/
+static int fts3EvalPhraseLoad(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Phrase *p /* Phrase object */
+){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int iToken;
+ int rc = SQLITE_OK;
+
+ for(iToken=0; rc==SQLITE_OK && iToken<p->nToken; iToken++){
+ Fts3PhraseToken *pToken = &p->aToken[iToken];
+ assert( pToken->pDeferred==0 || pToken->pSegcsr==0 );
+
+ if( pToken->pSegcsr ){
+ int nThis = 0;
+ char *pThis = 0;
+ rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
+ if( rc==SQLITE_OK ){
+ fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
+ }
+ }
+ assert( pToken->pSegcsr==0 );
+ }
+
+ return rc;
+}
+
+/*
+** This function is called on each phrase after the position lists for
+** any deferred tokens have been loaded into memory. It updates the phrases
+** current position list to include only those positions that are really
+** instances of the phrase (after considering deferred tokens). If this
+** means that the phrase does not appear in the current row, doclist.pList
+** and doclist.nList are both zeroed.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+*/
+static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
+ int iToken; /* Used to iterate through phrase tokens */
+ char *aPoslist = 0; /* Position list for deferred tokens */
+ int nPoslist = 0; /* Number of bytes in aPoslist */
+ int iPrev = -1; /* Token number of previous deferred token */
+
+ assert( pPhrase->doclist.bFreeList==0 );
+
+ for(iToken=0; iToken<pPhrase->nToken; iToken++){
+ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
+ Fts3DeferredToken *pDeferred = pToken->pDeferred;
+
+ if( pDeferred ){
+ char *pList;
+ int nList;
+ int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList);
+ if( rc!=SQLITE_OK ) return rc;
+
+ if( pList==0 ){
+ sqlite3_free(aPoslist);
+ pPhrase->doclist.pList = 0;
+ pPhrase->doclist.nList = 0;
+ return SQLITE_OK;
+
+ }else if( aPoslist==0 ){
+ aPoslist = pList;
+ nPoslist = nList;
+
+ }else{
+ char *aOut = pList;
+ char *p1 = aPoslist;
+ char *p2 = aOut;
+
+ assert( iPrev>=0 );
+ fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2);
+ sqlite3_free(aPoslist);
+ aPoslist = pList;
+ nPoslist = (int)(aOut - aPoslist);
+ if( nPoslist==0 ){
+ sqlite3_free(aPoslist);
+ pPhrase->doclist.pList = 0;
+ pPhrase->doclist.nList = 0;
+ return SQLITE_OK;
+ }
+ }
+ iPrev = iToken;
+ }
+ }
+
+ if( iPrev>=0 ){
+ int nMaxUndeferred = pPhrase->iDoclistToken;
+ if( nMaxUndeferred<0 ){
+ pPhrase->doclist.pList = aPoslist;
+ pPhrase->doclist.nList = nPoslist;
+ pPhrase->doclist.iDocid = pCsr->iPrevId;
+ pPhrase->doclist.bFreeList = 1;
+ }else{
+ int nDistance;
+ char *p1;
+ char *p2;
+ char *aOut;
+
+ if( nMaxUndeferred>iPrev ){
+ p1 = aPoslist;
+ p2 = pPhrase->doclist.pList;
+ nDistance = nMaxUndeferred - iPrev;
+ }else{
+ p1 = pPhrase->doclist.pList;
+ p2 = aPoslist;
+ nDistance = iPrev - nMaxUndeferred;
+ }
+
+ aOut = (char *)sqlite3_malloc(nPoslist+8);
+ if( !aOut ){
+ sqlite3_free(aPoslist);
+ return SQLITE_NOMEM;
+ }
+
+ pPhrase->doclist.pList = aOut;
+ if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
+ pPhrase->doclist.bFreeList = 1;
+ pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
+ }else{
+ sqlite3_free(aOut);
+ pPhrase->doclist.pList = 0;
+ pPhrase->doclist.nList = 0;
+ }
+ sqlite3_free(aPoslist);
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** This function is called for each Fts3Phrase in a full-text query
+** expression to initialize the mechanism for returning rows. Once this
+** function has been called successfully on an Fts3Phrase, it may be
+** used with fts3EvalPhraseNext() to iterate through the matching docids.
+**
+** If parameter bOptOk is true, then the phrase may (or may not) use the
+** incremental loading strategy. Otherwise, the entire doclist is loaded into
+** memory within this call.
+**
+** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
+*/
+static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
+ int rc; /* Error code */
+ Fts3PhraseToken *pFirst = &p->aToken[0];
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
+ if( pCsr->bDesc==pTab->bDescIdx
+ && bOptOk==1
+ && p->nToken==1
+ && pFirst->pSegcsr
+ && pFirst->pSegcsr->bLookup
+ && pFirst->bFirst==0
+ ){
+ /* Use the incremental approach. */
+ int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
+ rc = sqlite3Fts3MsrIncrStart(
+ pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
+ p->bIncr = 1;
+
+ }else{
+ /* Load the full doclist for the phrase into memory. */
+ rc = fts3EvalPhraseLoad(pCsr, p);
+ p->bIncr = 0;
+ }
+
+ assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
+ return rc;
+}
+
+/*
+** This function is used to iterate backwards (from the end to start)
+** through doclists. It is used by this module to iterate through phrase
+** doclists in reverse and by the fts3_write.c module to iterate through
+** pending-terms lists when writing to databases with "order=desc".
+**
+** The doclist may be sorted in ascending (parameter bDescIdx==0) or
+** descending (parameter bDescIdx==1) order of docid. Regardless, this
+** function iterates from the end of the doclist to the beginning.
+*/
+SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
+ int bDescIdx, /* True if the doclist is desc */
+ char *aDoclist, /* Pointer to entire doclist */
+ int nDoclist, /* Length of aDoclist in bytes */
+ char **ppIter, /* IN/OUT: Iterator pointer */
+ sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */
+ int *pnList, /* OUT: List length pointer */
+ u8 *pbEof /* OUT: End-of-file flag */
+){
+ char *p = *ppIter;
+
+ assert( nDoclist>0 );
+ assert( *pbEof==0 );
+ assert( p || *piDocid==0 );
+ assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
+
+ if( p==0 ){
+ sqlite3_int64 iDocid = 0;
+ char *pNext = 0;
+ char *pDocid = aDoclist;
+ char *pEnd = &aDoclist[nDoclist];
+ int iMul = 1;
+
+ while( pDocid<pEnd ){
+ sqlite3_int64 iDelta;
+ pDocid += sqlite3Fts3GetVarint(pDocid, &iDelta);
+ iDocid += (iMul * iDelta);
+ pNext = pDocid;
+ fts3PoslistCopy(0, &pDocid);
+ while( pDocid<pEnd && *pDocid==0 ) pDocid++;
+ iMul = (bDescIdx ? -1 : 1);
+ }
+
+ *pnList = (int)(pEnd - pNext);
+ *ppIter = pNext;
+ *piDocid = iDocid;
+ }else{
+ int iMul = (bDescIdx ? -1 : 1);
+ sqlite3_int64 iDelta;
+ fts3GetReverseVarint(&p, aDoclist, &iDelta);
+ *piDocid -= (iMul * iDelta);
+
+ if( p==aDoclist ){
+ *pbEof = 1;
+ }else{
+ char *pSave = p;
+ fts3ReversePoslist(aDoclist, &p);
+ *pnList = (int)(pSave - p);
+ }
+ *ppIter = p;
+ }
+}
+
+/*
+** Iterate forwards through a doclist.
+*/
+SQLITE_PRIVATE void sqlite3Fts3DoclistNext(
+ int bDescIdx, /* True if the doclist is desc */
+ char *aDoclist, /* Pointer to entire doclist */
+ int nDoclist, /* Length of aDoclist in bytes */
+ char **ppIter, /* IN/OUT: Iterator pointer */
+ sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */
+ u8 *pbEof /* OUT: End-of-file flag */
+){
+ char *p = *ppIter;
+
+ assert( nDoclist>0 );
+ assert( *pbEof==0 );
+ assert( p || *piDocid==0 );
+ assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) );
+
+ if( p==0 ){
+ p = aDoclist;
+ p += sqlite3Fts3GetVarint(p, piDocid);
+ }else{
+ fts3PoslistCopy(0, &p);
+ if( p>=&aDoclist[nDoclist] ){
+ *pbEof = 1;
+ }else{
+ sqlite3_int64 iVar;
+ p += sqlite3Fts3GetVarint(p, &iVar);
+ *piDocid += ((bDescIdx ? -1 : 1) * iVar);
+ }
+ }
+
+ *ppIter = p;
+}
+
+/*
+** Attempt to move the phrase iterator to point to the next matching docid.
+** If an error occurs, return an SQLite error code. Otherwise, return
+** SQLITE_OK.
+**
+** If there is no "next" entry and no error occurs, then *pbEof is set to
+** 1 before returning. Otherwise, if no error occurs and the iterator is
+** successfully advanced, *pbEof is set to 0.
+*/
+static int fts3EvalPhraseNext(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Phrase *p, /* Phrase object to advance to next docid */
+ u8 *pbEof /* OUT: Set to 1 if EOF */
+){
+ int rc = SQLITE_OK;
+ Fts3Doclist *pDL = &p->doclist;
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
+ if( p->bIncr ){
+ assert( p->nToken==1 );
+ assert( pDL->pNextDocid==0 );
+ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
+ &pDL->iDocid, &pDL->pList, &pDL->nList
+ );
+ if( rc==SQLITE_OK && !pDL->pList ){
+ *pbEof = 1;
+ }
+ }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
+ sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
+ &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
+ );
+ pDL->pList = pDL->pNextDocid;
+ }else{
+ char *pIter; /* Used to iterate through aAll */
+ char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
+ if( pDL->pNextDocid ){
+ pIter = pDL->pNextDocid;
+ }else{
+ pIter = pDL->aAll;
+ }
+
+ if( pIter>=pEnd ){
+ /* We have already reached the end of this doclist. EOF. */
+ *pbEof = 1;
+ }else{
+ sqlite3_int64 iDelta;
+ pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
+ if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
+ pDL->iDocid += iDelta;
+ }else{
+ pDL->iDocid -= iDelta;
+ }
+ pDL->pList = pIter;
+ fts3PoslistCopy(0, &pIter);
+ pDL->nList = (int)(pIter - pDL->pList);
+
+ /* pIter now points just past the 0x00 that terminates the position-
+ ** list for document pDL->iDocid. However, if this position-list was
+ ** edited in place by fts3EvalNearTrim(), then pIter may not actually
+ ** point to the start of the next docid value. The following line deals
+ ** with this case by advancing pIter past the zero-padding added by
+ ** fts3EvalNearTrim(). */
+ while( pIter<pEnd && *pIter==0 ) pIter++;
+
+ pDL->pNextDocid = pIter;
+ assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
+ *pbEof = 0;
+ }
+ }
+
+ return rc;
+}
+
+/*
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** Otherwise, fts3EvalPhraseStart() is called on all phrases within the
+** expression. Also the Fts3Expr.bDeferred variable is set to true for any
+** expressions for which all descendent tokens are deferred.
+**
+** If parameter bOptOk is zero, then it is guaranteed that the
+** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for
+** each phrase in the expression (subject to deferred token processing).
+** Or, if bOptOk is non-zero, then one or more tokens within the expression
+** may be loaded incrementally, meaning doclist.aAll/nAll is not available.
+**
+** If an error occurs within this function, *pRc is set to an SQLite error
+** code before returning.
+*/
+static void fts3EvalStartReaders(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pExpr, /* Expression to initialize phrases in */
+ int bOptOk, /* True to enable incremental loading */
+ int *pRc /* IN/OUT: Error code */
+){
+ if( pExpr && SQLITE_OK==*pRc ){
+ if( pExpr->eType==FTSQUERY_PHRASE ){
+ int i;
+ int nToken = pExpr->pPhrase->nToken;
+ for(i=0; i<nToken; i++){
+ if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
+ }
+ pExpr->bDeferred = (i==nToken);
+ *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
+ }else{
+ fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
+ fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
+ pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
+ }
+ }
+}
+
+/*
+** An array of the following structures is assembled as part of the process
+** of selecting tokens to defer before the query starts executing (as part
+** of the xFilter() method). There is one element in the array for each
+** token in the FTS expression.
+**
+** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
+** to phrases that are connected only by AND and NEAR operators (not OR or
+** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
+** separately. The root of a tokens AND/NEAR cluster is stored in
+** Fts3TokenAndCost.pRoot.
+*/
+typedef struct Fts3TokenAndCost Fts3TokenAndCost;
+struct Fts3TokenAndCost {
+ Fts3Phrase *pPhrase; /* The phrase the token belongs to */
+ int iToken; /* Position of token in phrase */
+ Fts3PhraseToken *pToken; /* The token itself */
+ Fts3Expr *pRoot; /* Root of NEAR/AND cluster */
+ int nOvfl; /* Number of overflow pages to load doclist */
+ int iCol; /* The column the token must match */
+};
+
+/*
+** This function is used to populate an allocated Fts3TokenAndCost array.
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** Otherwise, if an error occurs during execution, *pRc is set to an
+** SQLite error code.
+*/
+static void fts3EvalTokenCosts(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */
+ Fts3Expr *pExpr, /* Expression to consider */
+ Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */
+ Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */
+ int *pRc /* IN/OUT: Error code */
+){
+ if( *pRc==SQLITE_OK ){
+ if( pExpr->eType==FTSQUERY_PHRASE ){
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ int i;
+ for(i=0; *pRc==SQLITE_OK && i<pPhrase->nToken; i++){
+ Fts3TokenAndCost *pTC = (*ppTC)++;
+ pTC->pPhrase = pPhrase;
+ pTC->iToken = i;
+ pTC->pRoot = pRoot;
+ pTC->pToken = &pPhrase->aToken[i];
+ pTC->iCol = pPhrase->iColumn;
+ *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl);
+ }
+ }else if( pExpr->eType!=FTSQUERY_NOT ){
+ assert( pExpr->eType==FTSQUERY_OR
+ || pExpr->eType==FTSQUERY_AND
+ || pExpr->eType==FTSQUERY_NEAR
+ );
+ assert( pExpr->pLeft && pExpr->pRight );
+ if( pExpr->eType==FTSQUERY_OR ){
+ pRoot = pExpr->pLeft;
+ **ppOr = pRoot;
+ (*ppOr)++;
+ }
+ fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc);
+ if( pExpr->eType==FTSQUERY_OR ){
+ pRoot = pExpr->pRight;
+ **ppOr = pRoot;
+ (*ppOr)++;
+ }
+ fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc);
+ }
+ }
+}
+
+/*
+** Determine the average document (row) size in pages. If successful,
+** write this value to *pnPage and return SQLITE_OK. Otherwise, return
+** an SQLite error code.
+**
+** The average document size in pages is calculated by first calculating
+** determining the average size in bytes, B. If B is less than the amount
+** of data that will fit on a single leaf page of an intkey table in
+** this database, then the average docsize is 1. Otherwise, it is 1 plus
+** the number of overflow pages consumed by a record B bytes in size.
+*/
+static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
+ if( pCsr->nRowAvg==0 ){
+ /* The average document size, which is required to calculate the cost
+ ** of each doclist, has not yet been determined. Read the required
+ ** data from the %_stat table to calculate it.
+ **
+ ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
+ ** varints, where nCol is the number of columns in the FTS3 table.
+ ** The first varint is the number of documents currently stored in
+ ** the table. The following nCol varints contain the total amount of
+ ** data stored in all rows of each column of the table, from left
+ ** to right.
+ */
+ int rc;
+ Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
+ sqlite3_stmt *pStmt;
+ sqlite3_int64 nDoc = 0;
+ sqlite3_int64 nByte = 0;
+ const char *pEnd;
+ const char *a;
+
+ rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
+ if( rc!=SQLITE_OK ) return rc;
+ a = sqlite3_column_blob(pStmt, 0);
+ assert( a );
+
+ pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
+ a += sqlite3Fts3GetVarint(a, &nDoc);
+ while( a<pEnd ){
+ a += sqlite3Fts3GetVarint(a, &nByte);
+ }
+ if( nDoc==0 || nByte==0 ){
+ sqlite3_reset(pStmt);
+ return FTS_CORRUPT_VTAB;
+ }
+
+ pCsr->nDoc = nDoc;
+ pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
+ assert( pCsr->nRowAvg>0 );
+ rc = sqlite3_reset(pStmt);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+
+ *pnPage = pCsr->nRowAvg;
+ return SQLITE_OK;
+}
+
+/*
+** This function is called to select the tokens (if any) that will be
+** deferred. The array aTC[] has already been populated when this is
+** called.
+**
+** This function is called once for each AND/NEAR cluster in the
+** expression. Each invocation determines which tokens to defer within
+** the cluster with root node pRoot. See comments above the definition
+** of struct Fts3TokenAndCost for more details.
+**
+** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken()
+** called on each token to defer. Otherwise, an SQLite error code is
+** returned.
+*/
+static int fts3EvalSelectDeferred(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pRoot, /* Consider tokens with this root node */
+ Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */
+ int nTC /* Number of entries in aTC[] */
+){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int nDocSize = 0; /* Number of pages per doc loaded */
+ int rc = SQLITE_OK; /* Return code */
+ int ii; /* Iterator variable for various purposes */
+ int nOvfl = 0; /* Total overflow pages used by doclists */
+ int nToken = 0; /* Total number of tokens in cluster */
+
+ int nMinEst = 0; /* The minimum count for any phrase so far. */
+ int nLoad4 = 1; /* (Phrases that will be loaded)^4. */
+
+ /* Tokens are never deferred for FTS tables created using the content=xxx
+ ** option. The reason being that it is not guaranteed that the content
+ ** table actually contains the same data as the index. To prevent this from
+ ** causing any problems, the deferred token optimization is completely
+ ** disabled for content=xxx tables. */
+ if( pTab->zContentTbl ){
+ return SQLITE_OK;
+ }
+
+ /* Count the tokens in this AND/NEAR cluster. If none of the doclists
+ ** associated with the tokens spill onto overflow pages, or if there is
+ ** only 1 token, exit early. No tokens to defer in this case. */
+ for(ii=0; ii<nTC; ii++){
+ if( aTC[ii].pRoot==pRoot ){
+ nOvfl += aTC[ii].nOvfl;
+ nToken++;
+ }
+ }
+ if( nOvfl==0 || nToken<2 ) return SQLITE_OK;
+
+ /* Obtain the average docsize (in pages). */
+ rc = fts3EvalAverageDocsize(pCsr, &nDocSize);
+ assert( rc!=SQLITE_OK || nDocSize>0 );
+
+
+ /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
+ ** of the number of overflow pages that will be loaded by the pager layer
+ ** to retrieve the entire doclist for the token from the full-text index.
+ ** Load the doclists for tokens that are either:
+ **
+ ** a. The cheapest token in the entire query (i.e. the one visited by the
+ ** first iteration of this loop), or
+ **
+ ** b. Part of a multi-token phrase.
+ **
+ ** After each token doclist is loaded, merge it with the others from the
+ ** same phrase and count the number of documents that the merged doclist
+ ** contains. Set variable "nMinEst" to the smallest number of documents in
+ ** any phrase doclist for which 1 or more token doclists have been loaded.
+ ** Let nOther be the number of other phrases for which it is certain that
+ ** one or more tokens will not be deferred.
+ **
+ ** Then, for each token, defer it if loading the doclist would result in
+ ** loading N or more overflow pages into memory, where N is computed as:
+ **
+ ** (nMinEst + 4^nOther - 1) / (4^nOther)
+ */
+ for(ii=0; ii<nToken && rc==SQLITE_OK; ii++){
+ int iTC; /* Used to iterate through aTC[] array. */
+ Fts3TokenAndCost *pTC = 0; /* Set to cheapest remaining token. */
+
+ /* Set pTC to point to the cheapest remaining token. */
+ for(iTC=0; iTC<nTC; iTC++){
+ if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
+ && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
+ ){
+ pTC = &aTC[iTC];
+ }
+ }
+ assert( pTC );
+
+ if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
+ /* The number of overflow pages to load for this (and therefore all
+ ** subsequent) tokens is greater than the estimated number of pages
+ ** that will be loaded if all subsequent tokens are deferred.
+ */
+ Fts3PhraseToken *pToken = pTC->pToken;
+ rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol);
+ fts3SegReaderCursorFree(pToken->pSegcsr);
+ pToken->pSegcsr = 0;
+ }else{
+ /* Set nLoad4 to the value of (4^nOther) for the next iteration of the
+ ** for-loop. Except, limit the value to 2^24 to prevent it from
+ ** overflowing the 32-bit integer it is stored in. */
+ if( ii<12 ) nLoad4 = nLoad4*4;
+
+ if( ii==0 || pTC->pPhrase->nToken>1 ){
+ /* Either this is the cheapest token in the entire query, or it is
+ ** part of a multi-token phrase. Either way, the entire doclist will
+ ** (eventually) be loaded into memory. It may as well be now. */
+ Fts3PhraseToken *pToken = pTC->pToken;
+ int nList = 0;
+ char *pList = 0;
+ rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
+ assert( rc==SQLITE_OK || pList==0 );
+ if( rc==SQLITE_OK ){
+ int nCount;
+ fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
+ nCount = fts3DoclistCountDocids(
+ pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
+ );
+ if( ii==0 || nCount<nMinEst ) nMinEst = nCount;
+ }
+ }
+ }
+ pTC->pToken = 0;
+ }
+
+ return rc;
+}
+
+/*
+** This function is called from within the xFilter method. It initializes
+** the full-text query currently stored in pCsr->pExpr. To iterate through
+** the results of a query, the caller does:
+**
+** fts3EvalStart(pCsr);
+** while( 1 ){
+** fts3EvalNext(pCsr);
+** if( pCsr->bEof ) break;
+** ... return row pCsr->iPrevId to the caller ...
+** }
+*/
+static int fts3EvalStart(Fts3Cursor *pCsr){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int rc = SQLITE_OK;
+ int nToken = 0;
+ int nOr = 0;
+
+ /* Allocate a MultiSegReader for each token in the expression. */
+ fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
+
+ /* Determine which, if any, tokens in the expression should be deferred. */
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
+ if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
+ Fts3TokenAndCost *aTC;
+ Fts3Expr **apOr;
+ aTC = (Fts3TokenAndCost *)sqlite3_malloc(
+ sizeof(Fts3TokenAndCost) * nToken
+ + sizeof(Fts3Expr *) * nOr * 2
+ );
+ apOr = (Fts3Expr **)&aTC[nToken];
+
+ if( !aTC ){
+ rc = SQLITE_NOMEM;
+ }else{
+ int ii;
+ Fts3TokenAndCost *pTC = aTC;
+ Fts3Expr **ppOr = apOr;
+
+ fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
+ nToken = (int)(pTC-aTC);
+ nOr = (int)(ppOr-apOr);
+
+ if( rc==SQLITE_OK ){
+ rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken);
+ for(ii=0; rc==SQLITE_OK && ii<nOr; ii++){
+ rc = fts3EvalSelectDeferred(pCsr, apOr[ii], aTC, nToken);
+ }
+ }
+
+ sqlite3_free(aTC);
+ }
+ }
+#endif
+
+ fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
+ return rc;
+}
+
+/*
+** Invalidate the current position list for phrase pPhrase.
+*/
+static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){
+ if( pPhrase->doclist.bFreeList ){
+ sqlite3_free(pPhrase->doclist.pList);
+ }
+ pPhrase->doclist.pList = 0;
+ pPhrase->doclist.nList = 0;
+ pPhrase->doclist.bFreeList = 0;
+}
+
+/*
+** This function is called to edit the position list associated with
+** the phrase object passed as the fifth argument according to a NEAR
+** condition. For example:
+**
+** abc NEAR/5 "def ghi"
+**
+** Parameter nNear is passed the NEAR distance of the expression (5 in
+** the example above). When this function is called, *paPoslist points to
+** the position list, and *pnToken is the number of phrase tokens in, the
+** phrase on the other side of the NEAR operator to pPhrase. For example,
+** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to
+** the position list associated with phrase "abc".
+**
+** All positions in the pPhrase position list that are not sufficiently
+** close to a position in the *paPoslist position list are removed. If this
+** leaves 0 positions, zero is returned. Otherwise, non-zero.
+**
+** Before returning, *paPoslist is set to point to the position lsit
+** associated with pPhrase. And *pnToken is set to the number of tokens in
+** pPhrase.
+*/
+static int fts3EvalNearTrim(
+ int nNear, /* NEAR distance. As in "NEAR/nNear". */
+ char *aTmp, /* Temporary space to use */
+ char **paPoslist, /* IN/OUT: Position list */
+ int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */
+ Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */
+){
+ int nParam1 = nNear + pPhrase->nToken;
+ int nParam2 = nNear + *pnToken;
+ int nNew;
+ char *p2;
+ char *pOut;
+ int res;
+
+ assert( pPhrase->doclist.pList );
+
+ p2 = pOut = pPhrase->doclist.pList;
+ res = fts3PoslistNearMerge(
+ &pOut, aTmp, nParam1, nParam2, paPoslist, &p2
+ );
+ if( res ){
+ nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
+ assert( pPhrase->doclist.pList[nNew]=='\0' );
+ assert( nNew<=pPhrase->doclist.nList && nNew>0 );
+ memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
+ pPhrase->doclist.nList = nNew;
+ *paPoslist = pPhrase->doclist.pList;
+ *pnToken = pPhrase->nToken;
+ }
+
+ return res;
+}
+
+/*
+** This function is a no-op if *pRc is other than SQLITE_OK when it is called.
+** Otherwise, it advances the expression passed as the second argument to
+** point to the next matching row in the database. Expressions iterate through
+** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero,
+** or descending if it is non-zero.
+**
+** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if
+** successful, the following variables in pExpr are set:
+**
+** Fts3Expr.bEof (non-zero if EOF - there is no next row)
+** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row)
+**
+** If the expression is of type FTSQUERY_PHRASE, and the expression is not
+** at EOF, then the following variables are populated with the position list
+** for the phrase for the visited row:
+**
+** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes)
+** FTs3Expr.pPhrase->doclist.pList (pointer to position list)
+**
+** It says above that this function advances the expression to the next
+** matching row. This is usually true, but there are the following exceptions:
+**
+** 1. Deferred tokens are not taken into account. If a phrase consists
+** entirely of deferred tokens, it is assumed to match every row in
+** the db. In this case the position-list is not populated at all.
+**
+** Or, if a phrase contains one or more deferred tokens and one or
+** more non-deferred tokens, then the expression is advanced to the
+** next possible match, considering only non-deferred tokens. In other
+** words, if the phrase is "A B C", and "B" is deferred, the expression
+** is advanced to the next row that contains an instance of "A * C",
+** where "*" may match any single token. The position list in this case
+** is populated as for "A * C" before returning.
+**
+** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
+** advanced to point to the next row that matches "x AND y".
+**
+** See fts3EvalTestDeferredAndNear() for details on testing if a row is
+** really a match, taking into account deferred tokens and NEAR operators.
+*/
+static void fts3EvalNextRow(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Expr *pExpr, /* Expr. to advance to next matching row */
+ int *pRc /* IN/OUT: Error code */
+){
+ if( *pRc==SQLITE_OK ){
+ int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */
+ assert( pExpr->bEof==0 );
+ pExpr->bStart = 1;
+
+ switch( pExpr->eType ){
+ case FTSQUERY_NEAR:
+ case FTSQUERY_AND: {
+ Fts3Expr *pLeft = pExpr->pLeft;
+ Fts3Expr *pRight = pExpr->pRight;
+ assert( !pLeft->bDeferred || !pRight->bDeferred );
+
+ if( pLeft->bDeferred ){
+ /* LHS is entirely deferred. So we assume it matches every row.
+ ** Advance the RHS iterator to find the next row visited. */
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ pExpr->iDocid = pRight->iDocid;
+ pExpr->bEof = pRight->bEof;
+ }else if( pRight->bDeferred ){
+ /* RHS is entirely deferred. So we assume it matches every row.
+ ** Advance the LHS iterator to find the next row visited. */
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ pExpr->iDocid = pLeft->iDocid;
+ pExpr->bEof = pLeft->bEof;
+ }else{
+ /* Neither the RHS or LHS are deferred. */
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
+ sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+ if( iDiff==0 ) break;
+ if( iDiff<0 ){
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ }else{
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }
+ }
+ pExpr->iDocid = pLeft->iDocid;
+ pExpr->bEof = (pLeft->bEof || pRight->bEof);
+ }
+ break;
+ }
+
+ case FTSQUERY_OR: {
+ Fts3Expr *pLeft = pExpr->pLeft;
+ Fts3Expr *pRight = pExpr->pRight;
+ sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+
+ assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
+ assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
+
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }else{
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }
+
+ pExpr->bEof = (pLeft->bEof && pRight->bEof);
+ iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
+ if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
+ pExpr->iDocid = pLeft->iDocid;
+ }else{
+ pExpr->iDocid = pRight->iDocid;
+ }
+
+ break;
+ }
+
+ case FTSQUERY_NOT: {
+ Fts3Expr *pLeft = pExpr->pLeft;
+ Fts3Expr *pRight = pExpr->pRight;
+
+ if( pRight->bStart==0 ){
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ assert( *pRc!=SQLITE_OK || pRight->bStart );
+ }
+
+ fts3EvalNextRow(pCsr, pLeft, pRc);
+ if( pLeft->bEof==0 ){
+ while( !*pRc
+ && !pRight->bEof
+ && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
+ ){
+ fts3EvalNextRow(pCsr, pRight, pRc);
+ }
+ }
+ pExpr->iDocid = pLeft->iDocid;
+ pExpr->bEof = pLeft->bEof;
+ break;
+ }
+
+ default: {
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ fts3EvalInvalidatePoslist(pPhrase);
+ *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
+ pExpr->iDocid = pPhrase->doclist.iDocid;
+ break;
+ }
+ }
+ }
+}
+
+/*
+** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
+** cluster, then this function returns 1 immediately.
+**
+** Otherwise, it checks if the current row really does match the NEAR
+** expression, using the data currently stored in the position lists
+** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
+**
+** If the current row is a match, the position list associated with each
+** phrase in the NEAR expression is edited in place to contain only those
+** phrase instances sufficiently close to their peers to satisfy all NEAR
+** constraints. In this case it returns 1. If the NEAR expression does not
+** match the current row, 0 is returned. The position lists may or may not
+** be edited if 0 is returned.
+*/
+static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
+ int res = 1;
+
+ /* The following block runs if pExpr is the root of a NEAR query.
+ ** For example, the query:
+ **
+ ** "w" NEAR "x" NEAR "y" NEAR "z"
+ **
+ ** which is represented in tree form as:
+ **
+ ** |
+ ** +--NEAR--+ <-- root of NEAR query
+ ** | |
+ ** +--NEAR--+ "z"
+ ** | |
+ ** +--NEAR--+ "y"
+ ** | |
+ ** "w" "x"
+ **
+ ** The right-hand child of a NEAR node is always a phrase. The
+ ** left-hand child may be either a phrase or a NEAR node. There are
+ ** no exceptions to this - it's the way the parser in fts3_expr.c works.
+ */
+ if( *pRc==SQLITE_OK
+ && pExpr->eType==FTSQUERY_NEAR
+ && pExpr->bEof==0
+ && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
+ ){
+ Fts3Expr *p;
+ int nTmp = 0; /* Bytes of temp space */
+ char *aTmp; /* Temp space for PoslistNearMerge() */
+
+ /* Allocate temporary working space. */
+ for(p=pExpr; p->pLeft; p=p->pLeft){
+ nTmp += p->pRight->pPhrase->doclist.nList;
+ }
+ nTmp += p->pPhrase->doclist.nList;
+ if( nTmp==0 ){
+ res = 0;
+ }else{
+ aTmp = sqlite3_malloc(nTmp*2);
+ if( !aTmp ){
+ *pRc = SQLITE_NOMEM;
+ res = 0;
+ }else{
+ char *aPoslist = p->pPhrase->doclist.pList;
+ int nToken = p->pPhrase->nToken;
+
+ for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
+ Fts3Phrase *pPhrase = p->pRight->pPhrase;
+ int nNear = p->nNear;
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ }
+
+ aPoslist = pExpr->pRight->pPhrase->doclist.pList;
+ nToken = pExpr->pRight->pPhrase->nToken;
+ for(p=pExpr->pLeft; p && res; p=p->pLeft){
+ int nNear;
+ Fts3Phrase *pPhrase;
+ assert( p->pParent && p->pParent->pLeft==p );
+ nNear = p->pParent->nNear;
+ pPhrase = (
+ p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
+ );
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ }
+ }
+
+ sqlite3_free(aTmp);
+ }
+ }
+
+ return res;
+}
+
+/*
+** This function is a helper function for fts3EvalTestDeferredAndNear().
+** Assuming no error occurs or has occurred, It returns non-zero if the
+** expression passed as the second argument matches the row that pCsr
+** currently points to, or zero if it does not.
+**
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** If an error occurs during execution of this function, *pRc is set to
+** the appropriate SQLite error code. In this case the returned value is
+** undefined.
+*/
+static int fts3EvalTestExpr(
+ Fts3Cursor *pCsr, /* FTS cursor handle */
+ Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
+ int *pRc /* IN/OUT: Error code */
+){
+ int bHit = 1; /* Return value */
+ if( *pRc==SQLITE_OK ){
+ switch( pExpr->eType ){
+ case FTSQUERY_NEAR:
+ case FTSQUERY_AND:
+ bHit = (
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
+ && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
+ && fts3EvalNearTest(pExpr, pRc)
+ );
+
+ /* If the NEAR expression does not match any rows, zero the doclist for
+ ** all phrases involved in the NEAR. This is because the snippet(),
+ ** offsets() and matchinfo() functions are not supposed to recognize
+ ** any instances of phrases that are part of unmatched NEAR queries.
+ ** For example if this expression:
+ **
+ ** ... MATCH 'a OR (b NEAR c)'
+ **
+ ** is matched against a row containing:
+ **
+ ** 'a b d e'
+ **
+ ** then any snippet() should ony highlight the "a" term, not the "b"
+ ** (as "b" is part of a non-matching NEAR clause).
+ */
+ if( bHit==0
+ && pExpr->eType==FTSQUERY_NEAR
+ && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
+ ){
+ Fts3Expr *p;
+ for(p=pExpr; p->pPhrase==0; p=p->pLeft){
+ if( p->pRight->iDocid==pCsr->iPrevId ){
+ fts3EvalInvalidatePoslist(p->pRight->pPhrase);
+ }
+ }
+ if( p->iDocid==pCsr->iPrevId ){
+ fts3EvalInvalidatePoslist(p->pPhrase);
+ }
+ }
+
+ break;
+
+ case FTSQUERY_OR: {
+ int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
+ int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
+ bHit = bHit1 || bHit2;
+ break;
+ }
+
+ case FTSQUERY_NOT:
+ bHit = (
+ fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
+ && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
+ );
+ break;
+
+ default: {
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
+ if( pCsr->pDeferred
+ && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
+ ){
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
+ if( pExpr->bDeferred ){
+ fts3EvalInvalidatePoslist(pPhrase);
+ }
+ *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
+ bHit = (pPhrase->doclist.pList!=0);
+ pExpr->iDocid = pCsr->iPrevId;
+ }else
+#endif
+ {
+ bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
+ }
+ break;
+ }
+ }
+ }
+ return bHit;
+}
+
+/*
+** This function is called as the second part of each xNext operation when
+** iterating through the results of a full-text query. At this point the
+** cursor points to a row that matches the query expression, with the
+** following caveats:
+**
+** * Up until this point, "NEAR" operators in the expression have been
+** treated as "AND".
+**
+** * Deferred tokens have not yet been considered.
+**
+** If *pRc is not SQLITE_OK when this function is called, it immediately
+** returns 0. Otherwise, it tests whether or not after considering NEAR
+** operators and deferred tokens the current row is still a match for the
+** expression. It returns 1 if both of the following are true:
+**
+** 1. *pRc is SQLITE_OK when this function returns, and
+**
+** 2. After scanning the current FTS table row for the deferred tokens,
+** it is determined that the row does *not* match the query.
+**
+** Or, if no error occurs and it seems the current row does match the FTS
+** query, return 0.
+*/
+static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){
+ int rc = *pRc;
+ int bMiss = 0;
+ if( rc==SQLITE_OK ){
+
+ /* If there are one or more deferred tokens, load the current row into
+ ** memory and scan it to determine the position list for each deferred
+ ** token. Then, see if this row is really a match, considering deferred
+ ** tokens and NEAR operators (neither of which were taken into account
+ ** earlier, by fts3EvalNextRow()).
+ */
+ if( pCsr->pDeferred ){
+ rc = fts3CursorSeek(0, pCsr);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
+ }
+ }
+ bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
+
+ /* Free the position-lists accumulated for each deferred token above. */
+ sqlite3Fts3FreeDeferredDoclists(pCsr);
+ *pRc = rc;
+ }
+ return (rc==SQLITE_OK && bMiss);
+}
+
+/*
+** Advance to the next document that matches the FTS expression in
+** Fts3Cursor.pExpr.
+*/
+static int fts3EvalNext(Fts3Cursor *pCsr){
+ int rc = SQLITE_OK; /* Return Code */
+ Fts3Expr *pExpr = pCsr->pExpr;
+ assert( pCsr->isEof==0 );
+ if( pExpr==0 ){
+ pCsr->isEof = 1;
+ }else{
+ do {
+ if( pCsr->isRequireSeek==0 ){
+ sqlite3_reset(pCsr->pStmt);
+ }
+ assert( sqlite3_data_count(pCsr->pStmt)==0 );
+ fts3EvalNextRow(pCsr, pExpr, &rc);
+ pCsr->isEof = pExpr->bEof;
+ pCsr->isRequireSeek = 1;
+ pCsr->isMatchinfoNeeded = 1;
+ pCsr->iPrevId = pExpr->iDocid;
+ }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
+ }
+ return rc;
+}
+
+/*
+** Restart interation for expression pExpr so that the next call to
+** fts3EvalNext() visits the first row. Do not allow incremental
+** loading or merging of phrase doclists for this iteration.
+**
+** If *pRc is other than SQLITE_OK when this function is called, it is
+** a no-op. If an error occurs within this function, *pRc is set to an
+** SQLite error code before returning.
+*/
+static void fts3EvalRestart(
+ Fts3Cursor *pCsr,
+ Fts3Expr *pExpr,
+ int *pRc
+){
+ if( pExpr && *pRc==SQLITE_OK ){
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+
+ if( pPhrase ){
+ fts3EvalInvalidatePoslist(pPhrase);
+ if( pPhrase->bIncr ){
+ assert( pPhrase->nToken==1 );
+ assert( pPhrase->aToken[0].pSegcsr );
+ sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
+ *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
+ }
+
+ pPhrase->doclist.pNextDocid = 0;
+ pPhrase->doclist.iDocid = 0;
+ }
+
+ pExpr->iDocid = 0;
+ pExpr->bEof = 0;
+ pExpr->bStart = 0;
+
+ fts3EvalRestart(pCsr, pExpr->pLeft, pRc);
+ fts3EvalRestart(pCsr, pExpr->pRight, pRc);
+ }
+}
+
+/*
+** After allocating the Fts3Expr.aMI[] array for each phrase in the
+** expression rooted at pExpr, the cursor iterates through all rows matched
+** by pExpr, calling this function for each row. This function increments
+** the values in Fts3Expr.aMI[] according to the position-list currently
+** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
+** expression nodes.
+*/
+static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
+ if( pExpr ){
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ if( pPhrase && pPhrase->doclist.pList ){
+ int iCol = 0;
+ char *p = pPhrase->doclist.pList;
+
+ assert( *p );
+ while( 1 ){
+ u8 c = 0;
+ int iCnt = 0;
+ while( 0xFE & (*p | c) ){
+ if( (c&0x80)==0 ) iCnt++;
+ c = *p++ & 0x80;
+ }
+
+ /* aMI[iCol*3 + 1] = Number of occurrences
+ ** aMI[iCol*3 + 2] = Number of rows containing at least one instance
+ */
+ pExpr->aMI[iCol*3 + 1] += iCnt;
+ pExpr->aMI[iCol*3 + 2] += (iCnt>0);
+ if( *p==0x00 ) break;
+ p++;
+ p += sqlite3Fts3GetVarint32(p, &iCol);
+ }
+ }
+
+ fts3EvalUpdateCounts(pExpr->pLeft);
+ fts3EvalUpdateCounts(pExpr->pRight);
+ }
+}
+
+/*
+** Expression pExpr must be of type FTSQUERY_PHRASE.
+**
+** If it is not already allocated and populated, this function allocates and
+** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part
+** of a NEAR expression, then it also allocates and populates the same array
+** for all other phrases that are part of the NEAR expression.
+**
+** SQLITE_OK is returned if the aMI[] array is successfully allocated and
+** populated. Otherwise, if an error occurs, an SQLite error code is returned.
+*/
+static int fts3EvalGatherStats(
+ Fts3Cursor *pCsr, /* Cursor object */
+ Fts3Expr *pExpr /* FTSQUERY_PHRASE expression */
+){
+ int rc = SQLITE_OK; /* Return code */
+
+ assert( pExpr->eType==FTSQUERY_PHRASE );
+ if( pExpr->aMI==0 ){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ Fts3Expr *pRoot; /* Root of NEAR expression */
+ Fts3Expr *p; /* Iterator used for several purposes */
+
+ sqlite3_int64 iPrevId = pCsr->iPrevId;
+ sqlite3_int64 iDocid;
+ u8 bEof;
+
+ /* Find the root of the NEAR expression */
+ pRoot = pExpr;
+ while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){
+ pRoot = pRoot->pParent;
+ }
+ iDocid = pRoot->iDocid;
+ bEof = pRoot->bEof;
+ assert( pRoot->bStart );
+
+ /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */
+ for(p=pRoot; p; p=p->pLeft){
+ Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
+ assert( pE->aMI==0 );
+ pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
+ if( !pE->aMI ) return SQLITE_NOMEM;
+ memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
+ }
+
+ fts3EvalRestart(pCsr, pRoot, &rc);
+
+ while( pCsr->isEof==0 && rc==SQLITE_OK ){
+
+ do {
+ /* Ensure the %_content statement is reset. */
+ if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt);
+ assert( sqlite3_data_count(pCsr->pStmt)==0 );
+
+ /* Advance to the next document */
+ fts3EvalNextRow(pCsr, pRoot, &rc);
+ pCsr->isEof = pRoot->bEof;
+ pCsr->isRequireSeek = 1;
+ pCsr->isMatchinfoNeeded = 1;
+ pCsr->iPrevId = pRoot->iDocid;
+ }while( pCsr->isEof==0
+ && pRoot->eType==FTSQUERY_NEAR
+ && fts3EvalTestDeferredAndNear(pCsr, &rc)
+ );
+
+ if( rc==SQLITE_OK && pCsr->isEof==0 ){
+ fts3EvalUpdateCounts(pRoot);
+ }
+ }
+
+ pCsr->isEof = 0;
+ pCsr->iPrevId = iPrevId;
+
+ if( bEof ){
+ pRoot->bEof = bEof;
+ }else{
+ /* Caution: pRoot may iterate through docids in ascending or descending
+ ** order. For this reason, even though it seems more defensive, the
+ ** do loop can not be written:
+ **
+ ** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
+ */
+ fts3EvalRestart(pCsr, pRoot, &rc);
+ do {
+ fts3EvalNextRow(pCsr, pRoot, &rc);
+ assert( pRoot->bEof==0 );
+ }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
+ fts3EvalTestDeferredAndNear(pCsr, &rc);
+ }
+ }
+ return rc;
+}
+
+/*
+** This function is used by the matchinfo() module to query a phrase
+** expression node for the following information:
+**
+** 1. The total number of occurrences of the phrase in each column of
+** the FTS table (considering all rows), and
+**
+** 2. For each column, the number of rows in the table for which the
+** column contains at least one instance of the phrase.
+**
+** If no error occurs, SQLITE_OK is returned and the values for each column
+** written into the array aiOut as follows:
+**
+** aiOut[iCol*3 + 1] = Number of occurrences
+** aiOut[iCol*3 + 2] = Number of rows containing at least one instance
+**
+** Caveats:
+**
+** * If a phrase consists entirely of deferred tokens, then all output
+** values are set to the number of documents in the table. In other
+** words we assume that very common tokens occur exactly once in each
+** column of each row of the table.
+**
+** * If a phrase contains some deferred tokens (and some non-deferred
+** tokens), count the potential occurrence identified by considering
+** the non-deferred tokens instead of actual phrase occurrences.
+**
+** * If the phrase is part of a NEAR expression, then only phrase instances
+** that meet the NEAR constraint are included in the counts.
+*/
+SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
+ Fts3Cursor *pCsr, /* FTS cursor handle */
+ Fts3Expr *pExpr, /* Phrase expression */
+ u32 *aiOut /* Array to write results into (see above) */
+){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int rc = SQLITE_OK;
+ int iCol;
+
+ if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
+ assert( pCsr->nDoc>0 );
+ for(iCol=0; iCol<pTab->nColumn; iCol++){
+ aiOut[iCol*3 + 1] = (u32)pCsr->nDoc;
+ aiOut[iCol*3 + 2] = (u32)pCsr->nDoc;
+ }
+ }else{
+ rc = fts3EvalGatherStats(pCsr, pExpr);
+ if( rc==SQLITE_OK ){
+ assert( pExpr->aMI );
+ for(iCol=0; iCol<pTab->nColumn; iCol++){
+ aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1];
+ aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2];
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+** The expression pExpr passed as the second argument to this function
+** must be of type FTSQUERY_PHRASE.
+**
+** The returned value is either NULL or a pointer to a buffer containing
+** a position-list indicating the occurrences of the phrase in column iCol
+** of the current row.
+**
+** More specifically, the returned buffer contains 1 varint for each
+** occurrence of the phrase in the column, stored using the normal (delta+2)
+** compression and is terminated by either an 0x01 or 0x00 byte. For example,
+** if the requested column contains "a b X c d X X" and the position-list
+** for 'X' is requested, the buffer returned may contain:
+**
+** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00
+**
+** This function works regardless of whether or not the phrase is deferred,
+** incremental, or neither.
+*/
+SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
+ Fts3Cursor *pCsr, /* FTS3 cursor object */
+ Fts3Expr *pExpr, /* Phrase to return doclist for */
+ int iCol, /* Column to return position list for */
+ char **ppOut /* OUT: Pointer to position list */
+){
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ char *pIter;
+ int iThis;
+ sqlite3_int64 iDocid;
+
+ /* If this phrase is applies specifically to some column other than
+ ** column iCol, return a NULL pointer. */
+ *ppOut = 0;
+ assert( iCol>=0 && iCol<pTab->nColumn );
+ if( (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) ){
+ return SQLITE_OK;
+ }
+
+ iDocid = pExpr->iDocid;
+ pIter = pPhrase->doclist.pList;
+ if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
+ int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
+ int bOr = 0;
+ u8 bEof = 0;
+ Fts3Expr *p;
+
+ /* Check if this phrase descends from an OR expression node. If not,
+ ** return NULL. Otherwise, the entry that corresponds to docid
+ ** pCsr->iPrevId may lie earlier in the doclist buffer. */
+ for(p=pExpr->pParent; p; p=p->pParent){
+ if( p->eType==FTSQUERY_OR ) bOr = 1;
+ }
+ if( bOr==0 ) return SQLITE_OK;
+
+ /* This is the descendent of an OR node. In this case we cannot use
+ ** an incremental phrase. Load the entire doclist for the phrase
+ ** into memory in this case. */
+ if( pPhrase->bIncr ){
+ int rc = SQLITE_OK;
+ int bEofSave = pExpr->bEof;
+ fts3EvalRestart(pCsr, pExpr, &rc);
+ while( rc==SQLITE_OK && !pExpr->bEof ){
+ fts3EvalNextRow(pCsr, pExpr, &rc);
+ if( bEofSave==0 && pExpr->iDocid==iDocid ) break;
+ }
+ pIter = pPhrase->doclist.pList;
+ assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
+ if( rc!=SQLITE_OK ) return rc;
+ }
+
+ if( pExpr->bEof ){
+ pIter = 0;
+ iDocid = 0;
+ }
+ bEof = (pPhrase->doclist.nAll==0);
+ assert( bDescDoclist==0 || bDescDoclist==1 );
+ assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
+
+ if( pCsr->bDesc==bDescDoclist ){
+ int dummy;
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
+ sqlite3Fts3DoclistPrev(
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
+ &pIter, &iDocid, &dummy, &bEof
+ );
+ }
+ }else{
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
+ sqlite3Fts3DoclistNext(
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
+ &pIter, &iDocid, &bEof
+ );
+ }
+ }
+
+ if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
+ }
+ if( pIter==0 ) return SQLITE_OK;
+
+ if( *pIter==0x01 ){
+ pIter++;
+ pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+ }else{
+ iThis = 0;
+ }
+ while( iThis<iCol ){
+ fts3ColumnlistCopy(0, &pIter);
+ if( *pIter==0x00 ) return 0;
+ pIter++;
+ pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+ }
+
+ *ppOut = ((iCol==iThis)?pIter:0);
+ return SQLITE_OK;
+}
+
+/*
+** Free all components of the Fts3Phrase structure that were allocated by
+** the eval module. Specifically, this means to free:
+**
+** * the contents of pPhrase->doclist, and
+** * any Fts3MultiSegReader objects held by phrase tokens.
+*/
+SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){
+ if( pPhrase ){
+ int i;
+ sqlite3_free(pPhrase->doclist.aAll);
+ fts3EvalInvalidatePoslist(pPhrase);
+ memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist));
+ for(i=0; i<pPhrase->nToken; i++){
+ fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr);
+ pPhrase->aToken[i].pSegcsr = 0;
+ }
+ }
+}
+
+
+/*
+** Return SQLITE_CORRUPT_VTAB.
+*/
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
+ return SQLITE_CORRUPT_VTAB;
+}
+#endif
+
+#if !SQLITE_CORE
+/*
+** Initialize API pointer table, if required.
+*/
+SQLITE_API int sqlite3_extension_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi)
+ return sqlite3Fts3Init(db);
+}
+#endif
+
+#endif
+
+/************** End of fts3.c ************************************************/
+/************** Begin file fts3_aux.c ****************************************/
+/*
+** 2011 Jan 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <string.h> */
+/* #include <assert.h> */
+
+typedef struct Fts3auxTable Fts3auxTable;
+typedef struct Fts3auxCursor Fts3auxCursor;
+
+struct Fts3auxTable {
+ sqlite3_vtab base; /* Base class used by SQLite core */
+ Fts3Table *pFts3Tab;
+};
+
+struct Fts3auxCursor {
+ sqlite3_vtab_cursor base; /* Base class used by SQLite core */
+ Fts3MultiSegReader csr; /* Must be right after "base" */
+ Fts3SegFilter filter;
+ char *zStop;
+ int nStop; /* Byte-length of string zStop */
+ int isEof; /* True if cursor is at EOF */
+ sqlite3_int64 iRowid; /* Current rowid */
+
+ int iCol; /* Current value of 'col' column */
+ int nStat; /* Size of aStat[] array */
+ struct Fts3auxColstats {
+ sqlite3_int64 nDoc; /* 'documents' values for current csr row */
+ sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */
+ } *aStat;
+};
+
+/*
+** Schema of the terms table.
+*/
+#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)"
+
+/*
+** This function does all the work for both the xConnect and xCreate methods.
+** These tables have no persistent representation of their own, so xConnect
+** and xCreate are identical operations.
+*/
+static int fts3auxConnectMethod(
+ sqlite3 *db, /* Database connection */
+ void *pUnused, /* Unused */
+ int argc, /* Number of elements in argv array */
+ const char * const *argv, /* xCreate/xConnect argument array */
+ sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
+ char **pzErr /* OUT: sqlite3_malloc'd error message */
+){
+ char const *zDb; /* Name of database (e.g. "main") */
+ char const *zFts3; /* Name of fts3 table */
+ int nDb; /* Result of strlen(zDb) */
+ int nFts3; /* Result of strlen(zFts3) */
+ int nByte; /* Bytes of space to allocate here */
+ int rc; /* value returned by declare_vtab() */
+ Fts3auxTable *p; /* Virtual table object to return */
+
+ UNUSED_PARAMETER(pUnused);
+
+ /* The user should specify a single argument - the name of an fts3 table. */
+ if( argc!=4 ){
+ *pzErr = sqlite3_mprintf(
+ "wrong number of arguments to fts4aux constructor"
+ );
+ return SQLITE_ERROR;
+ }
+
+ zDb = argv[1];
+ nDb = (int)strlen(zDb);
+ zFts3 = argv[3];
+ nFts3 = (int)strlen(zFts3);
+
+ rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
+ if( rc!=SQLITE_OK ) return rc;
+
+ nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
+ p = (Fts3auxTable *)sqlite3_malloc(nByte);
+ if( !p ) return SQLITE_NOMEM;
+ memset(p, 0, nByte);
+
+ p->pFts3Tab = (Fts3Table *)&p[1];
+ p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
+ p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
+ p->pFts3Tab->db = db;
+ p->pFts3Tab->nIndex = 1;
+
+ memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
+ memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
+ sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
+
+ *ppVtab = (sqlite3_vtab *)p;
+ return SQLITE_OK;
+}
+
+/*
+** This function does the work for both the xDisconnect and xDestroy methods.
+** These tables have no persistent representation of their own, so xDisconnect
+** and xDestroy are identical operations.
+*/
+static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){
+ Fts3auxTable *p = (Fts3auxTable *)pVtab;
+ Fts3Table *pFts3 = p->pFts3Tab;
+ int i;
+
+ /* Free any prepared statements held */
+ for(i=0; i<SizeofArray(pFts3->aStmt); i++){
+ sqlite3_finalize(pFts3->aStmt[i]);
+ }
+ sqlite3_free(pFts3->zSegmentsTbl);
+ sqlite3_free(p);
+ return SQLITE_OK;
+}
+
+#define FTS4AUX_EQ_CONSTRAINT 1
+#define FTS4AUX_GE_CONSTRAINT 2
+#define FTS4AUX_LE_CONSTRAINT 4
+
+/*
+** xBestIndex - Analyze a WHERE and ORDER BY clause.
+*/
+static int fts3auxBestIndexMethod(
+ sqlite3_vtab *pVTab,
+ sqlite3_index_info *pInfo
+){
+ int i;
+ int iEq = -1;
+ int iGe = -1;
+ int iLe = -1;
+
+ UNUSED_PARAMETER(pVTab);
+
+ /* This vtab delivers always results in "ORDER BY term ASC" order. */
+ if( pInfo->nOrderBy==1
+ && pInfo->aOrderBy[0].iColumn==0
+ && pInfo->aOrderBy[0].desc==0
+ ){
+ pInfo->orderByConsumed = 1;
+ }
+
+ /* Search for equality and range constraints on the "term" column. */
+ for(i=0; i<pInfo->nConstraint; i++){
+ if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){
+ int op = pInfo->aConstraint[i].op;
+ if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
+ }
+ }
+
+ if( iEq>=0 ){
+ pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
+ pInfo->aConstraintUsage[iEq].argvIndex = 1;
+ pInfo->estimatedCost = 5;
+ }else{
+ pInfo->idxNum = 0;
+ pInfo->estimatedCost = 20000;
+ if( iGe>=0 ){
+ pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
+ pInfo->aConstraintUsage[iGe].argvIndex = 1;
+ pInfo->estimatedCost /= 2;
+ }
+ if( iLe>=0 ){
+ pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
+ pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0);
+ pInfo->estimatedCost /= 2;
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** xOpen - Open a cursor.
+*/
+static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
+ Fts3auxCursor *pCsr; /* Pointer to cursor object to return */
+
+ UNUSED_PARAMETER(pVTab);
+
+ pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor));
+ if( !pCsr ) return SQLITE_NOMEM;
+ memset(pCsr, 0, sizeof(Fts3auxCursor));
+
+ *ppCsr = (sqlite3_vtab_cursor *)pCsr;
+ return SQLITE_OK;
+}
+
+/*
+** xClose - Close a cursor.
+*/
+static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
+ Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
+ Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
+
+ sqlite3Fts3SegmentsClose(pFts3);
+ sqlite3Fts3SegReaderFinish(&pCsr->csr);
+ sqlite3_free((void *)pCsr->filter.zTerm);
+ sqlite3_free(pCsr->zStop);
+ sqlite3_free(pCsr->aStat);
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
+ if( nSize>pCsr->nStat ){
+ struct Fts3auxColstats *aNew;
+ aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
+ sizeof(struct Fts3auxColstats) * nSize
+ );
+ if( aNew==0 ) return SQLITE_NOMEM;
+ memset(&aNew[pCsr->nStat], 0,
+ sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat)
+ );
+ pCsr->aStat = aNew;
+ pCsr->nStat = nSize;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** xNext - Advance the cursor to the next row, if any.
+*/
+static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
+ Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
+ Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
+ int rc;
+
+ /* Increment our pretend rowid value. */
+ pCsr->iRowid++;
+
+ for(pCsr->iCol++; pCsr->iCol<pCsr->nStat; pCsr->iCol++){
+ if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK;
+ }
+
+ rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr);
+ if( rc==SQLITE_ROW ){
+ int i = 0;
+ int nDoclist = pCsr->csr.nDoclist;
+ char *aDoclist = pCsr->csr.aDoclist;
+ int iCol;
+
+ int eState = 0;
+
+ if( pCsr->zStop ){
+ int n = (pCsr->nStop<pCsr->csr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm;
+ int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n);
+ if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){
+ pCsr->isEof = 1;
+ return SQLITE_OK;
+ }
+ }
+
+ if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
+ memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
+ iCol = 0;
+
+ while( i<nDoclist ){
+ sqlite3_int64 v = 0;
+
+ i += sqlite3Fts3GetVarint(&aDoclist[i], &v);
+ switch( eState ){
+ /* State 0. In this state the integer just read was a docid. */
+ case 0:
+ pCsr->aStat[0].nDoc++;
+ eState = 1;
+ iCol = 0;
+ break;
+
+ /* State 1. In this state we are expecting either a 1, indicating
+ ** that the following integer will be a column number, or the
+ ** start of a position list for column 0.
+ **
+ ** The only difference between state 1 and state 2 is that if the
+ ** integer encountered in state 1 is not 0 or 1, then we need to
+ ** increment the column 0 "nDoc" count for this term.
+ */
+ case 1:
+ assert( iCol==0 );
+ if( v>1 ){
+ pCsr->aStat[1].nDoc++;
+ }
+ eState = 2;
+ /* fall through */
+
+ case 2:
+ if( v==0 ){ /* 0x00. Next integer will be a docid. */
+ eState = 0;
+ }else if( v==1 ){ /* 0x01. Next integer will be a column number. */
+ eState = 3;
+ }else{ /* 2 or greater. A position. */
+ pCsr->aStat[iCol+1].nOcc++;
+ pCsr->aStat[0].nOcc++;
+ }
+ break;
+
+ /* State 3. The integer just read is a column number. */
+ default: assert( eState==3 );
+ iCol = (int)v;
+ if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
+ pCsr->aStat[iCol+1].nDoc++;
+ eState = 2;
+ break;
+ }
+ }
+
+ pCsr->iCol = 0;
+ rc = SQLITE_OK;
+ }else{
+ pCsr->isEof = 1;
+ }
+ return rc;
+}
+
+/*
+** xFilter - Initialize a cursor to point at the start of its data.
+*/
+static int fts3auxFilterMethod(
+ sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
+ int idxNum, /* Strategy index */
+ const char *idxStr, /* Unused */
+ int nVal, /* Number of elements in apVal */
+ sqlite3_value **apVal /* Arguments for the indexing scheme */
+){
+ Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
+ Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
+ int rc;
+ int isScan;
+
+ UNUSED_PARAMETER(nVal);
+ UNUSED_PARAMETER(idxStr);
+
+ assert( idxStr==0 );
+ assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
+ || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
+ || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
+ );
+ isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT);
+
+ /* In case this cursor is being reused, close and zero it. */
+ testcase(pCsr->filter.zTerm);
+ sqlite3Fts3SegReaderFinish(&pCsr->csr);
+ sqlite3_free((void *)pCsr->filter.zTerm);
+ sqlite3_free(pCsr->aStat);
+ memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
+
+ pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
+ if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
+
+ if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){
+ const unsigned char *zStr = sqlite3_value_text(apVal[0]);
+ if( zStr ){
+ pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
+ pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
+ if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
+ }
+ }
+ if( idxNum&FTS4AUX_LE_CONSTRAINT ){
+ int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0;
+ pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
+ pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
+ if( pCsr->zStop==0 ) return SQLITE_NOMEM;
+ }
+
+ rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
+ pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
+ );
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
+ }
+
+ if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor);
+ return rc;
+}
+
+/*
+** xEof - Return true if the cursor is at EOF, or false otherwise.
+*/
+static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){
+ Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
+ return pCsr->isEof;
+}
+
+/*
+** xColumn - Return a column value.
+*/
+static int fts3auxColumnMethod(
+ sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
+ sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
+ int iCol /* Index of column to read value from */
+){
+ Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
+
+ assert( p->isEof==0 );
+ if( iCol==0 ){ /* Column "term" */
+ sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
+ }else if( iCol==1 ){ /* Column "col" */
+ if( p->iCol ){
+ sqlite3_result_int(pContext, p->iCol-1);
+ }else{
+ sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC);
+ }
+ }else if( iCol==2 ){ /* Column "documents" */
+ sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc);
+ }else{ /* Column "occurrences" */
+ sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc);
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** xRowid - Return the current rowid for the cursor.
+*/
+static int fts3auxRowidMethod(
+ sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
+ sqlite_int64 *pRowid /* OUT: Rowid value */
+){
+ Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
+ *pRowid = pCsr->iRowid;
+ return SQLITE_OK;
+}
+
+/*
+** Register the fts3aux module with database connection db. Return SQLITE_OK
+** if successful or an error code if sqlite3_create_module() fails.
+*/
+SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){
+ static const sqlite3_module fts3aux_module = {
+ 0, /* iVersion */
+ fts3auxConnectMethod, /* xCreate */
+ fts3auxConnectMethod, /* xConnect */
+ fts3auxBestIndexMethod, /* xBestIndex */
+ fts3auxDisconnectMethod, /* xDisconnect */
+ fts3auxDisconnectMethod, /* xDestroy */
+ fts3auxOpenMethod, /* xOpen */
+ fts3auxCloseMethod, /* xClose */
+ fts3auxFilterMethod, /* xFilter */
+ fts3auxNextMethod, /* xNext */
+ fts3auxEofMethod, /* xEof */
+ fts3auxColumnMethod, /* xColumn */
+ fts3auxRowidMethod, /* xRowid */
+ 0, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindFunction */
+ 0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0 /* xRollbackTo */
+ };
+ int rc; /* Return code */
+
+ rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0);
+ return rc;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_aux.c ********************************************/
+/************** Begin file fts3_expr.c ***************************************/
+/*
+** 2008 Nov 28
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This module contains code that implements a parser for fts3 query strings
+** (the right-hand argument to the MATCH operator). Because the supported
+** syntax is relatively simple, the whole tokenizer/parser system is
+** hand-coded.
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/*
+** By default, this module parses the legacy syntax that has been
+** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS
+** is defined, then it uses the new syntax. The differences between
+** the new and the old syntaxes are:
+**
+** a) The new syntax supports parenthesis. The old does not.
+**
+** b) The new syntax supports the AND and NOT operators. The old does not.
+**
+** c) The old syntax supports the "-" token qualifier. This is not
+** supported by the new syntax (it is replaced by the NOT operator).
+**
+** d) When using the old syntax, the OR operator has a greater precedence
+** than an implicit AND. When using the new, both implicity and explicit
+** AND operators have a higher precedence than OR.
+**
+** If compiled with SQLITE_TEST defined, then this module exports the
+** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable
+** to zero causes the module to use the old syntax. If it is set to
+** non-zero the new syntax is activated. This is so both syntaxes can
+** be tested using a single build of testfixture.
+**
+** The following describes the syntax supported by the fts3 MATCH
+** operator in a similar format to that used by the lemon parser
+** generator. This module does not use actually lemon, it uses a
+** custom parser.
+**
+** query ::= andexpr (OR andexpr)*.
+**
+** andexpr ::= notexpr (AND? notexpr)*.
+**
+** notexpr ::= nearexpr (NOT nearexpr|-TOKEN)*.
+** notexpr ::= LP query RP.
+**
+** nearexpr ::= phrase (NEAR distance_opt nearexpr)*.
+**
+** distance_opt ::= .
+** distance_opt ::= / INTEGER.
+**
+** phrase ::= TOKEN.
+** phrase ::= COLUMN:TOKEN.
+** phrase ::= "TOKEN TOKEN TOKEN...".
+*/
+
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_fts3_enable_parentheses = 0;
+#else
+# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
+# define sqlite3_fts3_enable_parentheses 1
+# else
+# define sqlite3_fts3_enable_parentheses 0
+# endif
+#endif
+
+/*
+** Default span for NEAR operators.
+*/
+#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
+
+/* #include <string.h> */
+/* #include <assert.h> */
+
+/*
+** isNot:
+** This variable is used by function getNextNode(). When getNextNode() is
+** called, it sets ParseContext.isNot to true if the 'next node' is a
+** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
+** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
+** zero.
+*/
+typedef struct ParseContext ParseContext;
+struct ParseContext {
+ sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
+ int iLangid; /* Language id used with tokenizer */
+ const char **azCol; /* Array of column names for fts3 table */
+ int bFts4; /* True to allow FTS4-only syntax */
+ int nCol; /* Number of entries in azCol[] */
+ int iDefaultCol; /* Default column to query */
+ int isNot; /* True if getNextNode() sees a unary - */
+ sqlite3_context *pCtx; /* Write error message here */
+ int nNest; /* Number of nested brackets */
+};
+
+/*
+** This function is equivalent to the standard isspace() function.
+**
+** The standard isspace() can be awkward to use safely, because although it
+** is defined to accept an argument of type int, its behavior when passed
+** an integer that falls outside of the range of the unsigned char type
+** is undefined (and sometimes, "undefined" means segfault). This wrapper
+** is defined to accept an argument of type char, and always returns 0 for
+** any values that fall outside of the range of the unsigned char type (i.e.
+** negative values).
+*/
+static int fts3isspace(char c){
+ return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
+}
+
+/*
+** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
+** zero the memory before returning a pointer to it. If unsuccessful,
+** return NULL.
+*/
+static void *fts3MallocZero(int nByte){
+ void *pRet = sqlite3_malloc(nByte);
+ if( pRet ) memset(pRet, 0, nByte);
+ return pRet;
+}
+
+SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
+ sqlite3_tokenizer *pTokenizer,
+ int iLangid,
+ const char *z,
+ int n,
+ sqlite3_tokenizer_cursor **ppCsr
+){
+ sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
+ sqlite3_tokenizer_cursor *pCsr = 0;
+ int rc;
+
+ rc = pModule->xOpen(pTokenizer, z, n, &pCsr);
+ assert( rc==SQLITE_OK || pCsr==0 );
+ if( rc==SQLITE_OK ){
+ pCsr->pTokenizer = pTokenizer;
+ if( pModule->iVersion>=1 ){
+ rc = pModule->xLanguageid(pCsr, iLangid);
+ if( rc!=SQLITE_OK ){
+ pModule->xClose(pCsr);
+ pCsr = 0;
+ }
+ }
+ }
+ *ppCsr = pCsr;
+ return rc;
+}
+
+
+/*
+** Extract the next token from buffer z (length n) using the tokenizer
+** and other information (column names etc.) in pParse. Create an Fts3Expr
+** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
+** single token and set *ppExpr to point to it. If the end of the buffer is
+** reached before a token is found, set *ppExpr to zero. It is the
+** responsibility of the caller to eventually deallocate the allocated
+** Fts3Expr structure (if any) by passing it to sqlite3_free().
+**
+** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation
+** fails.
+*/
+static int getNextToken(
+ ParseContext *pParse, /* fts3 query parse context */
+ int iCol, /* Value for Fts3Phrase.iColumn */
+ const char *z, int n, /* Input string */
+ Fts3Expr **ppExpr, /* OUT: expression */
+ int *pnConsumed /* OUT: Number of bytes consumed */
+){
+ sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
+ sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
+ int rc;
+ sqlite3_tokenizer_cursor *pCursor;
+ Fts3Expr *pRet = 0;
+ int nConsumed = 0;
+
+ rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
+ if( rc==SQLITE_OK ){
+ const char *zToken;
+ int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
+ int nByte; /* total space to allocate */
+
+ rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
+ if( rc==SQLITE_OK ){
+ nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
+ pRet = (Fts3Expr *)fts3MallocZero(nByte);
+ if( !pRet ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pRet->eType = FTSQUERY_PHRASE;
+ pRet->pPhrase = (Fts3Phrase *)&pRet[1];
+ pRet->pPhrase->nToken = 1;
+ pRet->pPhrase->iColumn = iCol;
+ pRet->pPhrase->aToken[0].n = nToken;
+ pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
+ memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
+
+ if( iEnd<n && z[iEnd]=='*' ){
+ pRet->pPhrase->aToken[0].isPrefix = 1;
+ iEnd++;
+ }
+
+ while( 1 ){
+ if( !sqlite3_fts3_enable_parentheses
+ && iStart>0 && z[iStart-1]=='-'
+ ){
+ pParse->isNot = 1;
+ iStart--;
+ }else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){
+ pRet->pPhrase->aToken[0].bFirst = 1;
+ iStart--;
+ }else{
+ break;
+ }
+ }
+
+ }
+ nConsumed = iEnd;
+ }
+
+ pModule->xClose(pCursor);
+ }
+
+ *pnConsumed = nConsumed;
+ *ppExpr = pRet;
+ return rc;
+}
+
+
+/*
+** Enlarge a memory allocation. If an out-of-memory allocation occurs,
+** then free the old allocation.
+*/
+static void *fts3ReallocOrFree(void *pOrig, int nNew){
+ void *pRet = sqlite3_realloc(pOrig, nNew);
+ if( !pRet ){
+ sqlite3_free(pOrig);
+ }
+ return pRet;
+}
+
+/*
+** Buffer zInput, length nInput, contains the contents of a quoted string
+** that appeared as part of an fts3 query expression. Neither quote character
+** is included in the buffer. This function attempts to tokenize the entire
+** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE
+** containing the results.
+**
+** If successful, SQLITE_OK is returned and *ppExpr set to point at the
+** allocated Fts3Expr structure. Otherwise, either SQLITE_NOMEM (out of memory
+** error) or SQLITE_ERROR (tokenization error) is returned and *ppExpr set
+** to 0.
+*/
+static int getNextString(
+ ParseContext *pParse, /* fts3 query parse context */
+ const char *zInput, int nInput, /* Input string */
+ Fts3Expr **ppExpr /* OUT: expression */
+){
+ sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
+ sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
+ int rc;
+ Fts3Expr *p = 0;
+ sqlite3_tokenizer_cursor *pCursor = 0;
+ char *zTemp = 0;
+ int nTemp = 0;
+
+ const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
+ int nToken = 0;
+
+ /* The final Fts3Expr data structure, including the Fts3Phrase,
+ ** Fts3PhraseToken structures token buffers are all stored as a single
+ ** allocation so that the expression can be freed with a single call to
+ ** sqlite3_free(). Setting this up requires a two pass approach.
+ **
+ ** The first pass, in the block below, uses a tokenizer cursor to iterate
+ ** through the tokens in the expression. This pass uses fts3ReallocOrFree()
+ ** to assemble data in two dynamic buffers:
+ **
+ ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase
+ ** structure, followed by the array of Fts3PhraseToken
+ ** structures. This pass only populates the Fts3PhraseToken array.
+ **
+ ** Buffer zTemp: Contains copies of all tokens.
+ **
+ ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
+ ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
+ ** structures.
+ */
+ rc = sqlite3Fts3OpenTokenizer(
+ pTokenizer, pParse->iLangid, zInput, nInput, &pCursor);
+ if( rc==SQLITE_OK ){
+ int ii;
+ for(ii=0; rc==SQLITE_OK; ii++){
+ const char *zByte;
+ int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0;
+ rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
+ if( rc==SQLITE_OK ){
+ Fts3PhraseToken *pToken;
+
+ p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
+ if( !p ) goto no_mem;
+
+ zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
+ if( !zTemp ) goto no_mem;
+
+ assert( nToken==ii );
+ pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
+ memset(pToken, 0, sizeof(Fts3PhraseToken));
+
+ memcpy(&zTemp[nTemp], zByte, nByte);
+ nTemp += nByte;
+
+ pToken->n = nByte;
+ pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
+ pToken->bFirst = (iBegin>0 && zInput[iBegin-1]=='^');
+ nToken = ii+1;
+ }
+ }
+
+ pModule->xClose(pCursor);
+ pCursor = 0;
+ }
+
+ if( rc==SQLITE_DONE ){
+ int jj;
+ char *zBuf = 0;
+
+ p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
+ if( !p ) goto no_mem;
+ memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
+ p->eType = FTSQUERY_PHRASE;
+ p->pPhrase = (Fts3Phrase *)&p[1];
+ p->pPhrase->iColumn = pParse->iDefaultCol;
+ p->pPhrase->nToken = nToken;
+
+ zBuf = (char *)&p->pPhrase->aToken[nToken];
+ if( zTemp ){
+ memcpy(zBuf, zTemp, nTemp);
+ sqlite3_free(zTemp);
+ }else{
+ assert( nTemp==0 );
+ }
+
+ for(jj=0; jj<p->pPhrase->nToken; jj++){
+ p->pPhrase->aToken[jj].z = zBuf;
+ zBuf += p->pPhrase->aToken[jj].n;
+ }
+ rc = SQLITE_OK;
+ }
+
+ *ppExpr = p;
+ return rc;
+no_mem:
+
+ if( pCursor ){
+ pModule->xClose(pCursor);
+ }
+ sqlite3_free(zTemp);
+ sqlite3_free(p);
+ *ppExpr = 0;
+ return SQLITE_NOMEM;
+}
+
+/*
+** Function getNextNode(), which is called by fts3ExprParse(), may itself
+** call fts3ExprParse(). So this forward declaration is required.
+*/
+static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
+
+/*
+** The output variable *ppExpr is populated with an allocated Fts3Expr
+** structure, or set to 0 if the end of the input buffer is reached.
+**
+** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM
+** if a malloc failure occurs, or SQLITE_ERROR if a parse error is encountered.
+** If SQLITE_ERROR is returned, pContext is populated with an error message.
+*/
+static int getNextNode(
+ ParseContext *pParse, /* fts3 query parse context */
+ const char *z, int n, /* Input string */
+ Fts3Expr **ppExpr, /* OUT: expression */
+ int *pnConsumed /* OUT: Number of bytes consumed */
+){
+ static const struct Fts3Keyword {
+ char *z; /* Keyword text */
+ unsigned char n; /* Length of the keyword */
+ unsigned char parenOnly; /* Only valid in paren mode */
+ unsigned char eType; /* Keyword code */
+ } aKeyword[] = {
+ { "OR" , 2, 0, FTSQUERY_OR },
+ { "AND", 3, 1, FTSQUERY_AND },
+ { "NOT", 3, 1, FTSQUERY_NOT },
+ { "NEAR", 4, 0, FTSQUERY_NEAR }
+ };
+ int ii;
+ int iCol;
+ int iColLen;
+ int rc;
+ Fts3Expr *pRet = 0;
+
+ const char *zInput = z;
+ int nInput = n;
+
+ pParse->isNot = 0;
+
+ /* Skip over any whitespace before checking for a keyword, an open or
+ ** close bracket, or a quoted string.
+ */
+ while( nInput>0 && fts3isspace(*zInput) ){
+ nInput--;
+ zInput++;
+ }
+ if( nInput==0 ){
+ return SQLITE_DONE;
+ }
+
+ /* See if we are dealing with a keyword. */
+ for(ii=0; ii<(int)(sizeof(aKeyword)/sizeof(struct Fts3Keyword)); ii++){
+ const struct Fts3Keyword *pKey = &aKeyword[ii];
+
+ if( (pKey->parenOnly & ~sqlite3_fts3_enable_parentheses)!=0 ){
+ continue;
+ }
+
+ if( nInput>=pKey->n && 0==memcmp(zInput, pKey->z, pKey->n) ){
+ int nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM;
+ int nKey = pKey->n;
+ char cNext;
+
+ /* If this is a "NEAR" keyword, check for an explicit nearness. */
+ if( pKey->eType==FTSQUERY_NEAR ){
+ assert( nKey==4 );
+ if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
+ nNear = 0;
+ for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
+ nNear = nNear * 10 + (zInput[nKey] - '0');
+ }
+ }
+ }
+
+ /* At this point this is probably a keyword. But for that to be true,
+ ** the next byte must contain either whitespace, an open or close
+ ** parenthesis, a quote character, or EOF.
+ */
+ cNext = zInput[nKey];
+ if( fts3isspace(cNext)
+ || cNext=='"' || cNext=='(' || cNext==')' || cNext==0
+ ){
+ pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
+ if( !pRet ){
+ return SQLITE_NOMEM;
+ }
+ pRet->eType = pKey->eType;
+ pRet->nNear = nNear;
+ *ppExpr = pRet;
+ *pnConsumed = (int)((zInput - z) + nKey);
+ return SQLITE_OK;
+ }
+
+ /* Turns out that wasn't a keyword after all. This happens if the
+ ** user has supplied a token such as "ORacle". Continue.
+ */
+ }
+ }
+
+ /* Check for an open bracket. */
+ if( sqlite3_fts3_enable_parentheses ){
+ if( *zInput=='(' ){
+ int nConsumed;
+ pParse->nNest++;
+ rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed);
+ if( rc==SQLITE_OK && !*ppExpr ){
+ rc = SQLITE_DONE;
+ }
+ *pnConsumed = (int)((zInput - z) + 1 + nConsumed);
+ return rc;
+ }
+
+ /* Check for a close bracket. */
+ if( *zInput==')' ){
+ pParse->nNest--;
+ *pnConsumed = (int)((zInput - z) + 1);
+ return SQLITE_DONE;
+ }
+ }
+
+ /* See if we are dealing with a quoted phrase. If this is the case, then
+ ** search for the closing quote and pass the whole string to getNextString()
+ ** for processing. This is easy to do, as fts3 has no syntax for escaping
+ ** a quote character embedded in a string.
+ */
+ if( *zInput=='"' ){
+ for(ii=1; ii<nInput && zInput[ii]!='"'; ii++);
+ *pnConsumed = (int)((zInput - z) + ii + 1);
+ if( ii==nInput ){
+ return SQLITE_ERROR;
+ }
+ return getNextString(pParse, &zInput[1], ii-1, ppExpr);
+ }
+
+
+ /* If control flows to this point, this must be a regular token, or
+ ** the end of the input. Read a regular token using the sqlite3_tokenizer
+ ** interface. Before doing so, figure out if there is an explicit
+ ** column specifier for the token.
+ **
+ ** TODO: Strangely, it is not possible to associate a column specifier
+ ** with a quoted phrase, only with a single token. Not sure if this was
+ ** an implementation artifact or an intentional decision when fts3 was
+ ** first implemented. Whichever it was, this module duplicates the
+ ** limitation.
+ */
+ iCol = pParse->iDefaultCol;
+ iColLen = 0;
+ for(ii=0; ii<pParse->nCol; ii++){
+ const char *zStr = pParse->azCol[ii];
+ int nStr = (int)strlen(zStr);
+ if( nInput>nStr && zInput[nStr]==':'
+ && sqlite3_strnicmp(zStr, zInput, nStr)==0
+ ){
+ iCol = ii;
+ iColLen = (int)((zInput - z) + nStr + 1);
+ break;
+ }
+ }
+ rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed);
+ *pnConsumed += iColLen;
+ return rc;
+}
+
+/*
+** The argument is an Fts3Expr structure for a binary operator (any type
+** except an FTSQUERY_PHRASE). Return an integer value representing the
+** precedence of the operator. Lower values have a higher precedence (i.e.
+** group more tightly). For example, in the C language, the == operator
+** groups more tightly than ||, and would therefore have a higher precedence.
+**
+** When using the new fts3 query syntax (when SQLITE_ENABLE_FTS3_PARENTHESIS
+** is defined), the order of the operators in precedence from highest to
+** lowest is:
+**
+** NEAR
+** NOT
+** AND (including implicit ANDs)
+** OR
+**
+** Note that when using the old query syntax, the OR operator has a higher
+** precedence than the AND operator.
+*/
+static int opPrecedence(Fts3Expr *p){
+ assert( p->eType!=FTSQUERY_PHRASE );
+ if( sqlite3_fts3_enable_parentheses ){
+ return p->eType;
+ }else if( p->eType==FTSQUERY_NEAR ){
+ return 1;
+ }else if( p->eType==FTSQUERY_OR ){
+ return 2;
+ }
+ assert( p->eType==FTSQUERY_AND );
+ return 3;
+}
+
+/*
+** Argument ppHead contains a pointer to the current head of a query
+** expression tree being parsed. pPrev is the expression node most recently
+** inserted into the tree. This function adds pNew, which is always a binary
+** operator node, into the expression tree based on the relative precedence
+** of pNew and the existing nodes of the tree. This may result in the head
+** of the tree changing, in which case *ppHead is set to the new root node.
+*/
+static void insertBinaryOperator(
+ Fts3Expr **ppHead, /* Pointer to the root node of a tree */
+ Fts3Expr *pPrev, /* Node most recently inserted into the tree */
+ Fts3Expr *pNew /* New binary node to insert into expression tree */
+){
+ Fts3Expr *pSplit = pPrev;
+ while( pSplit->pParent && opPrecedence(pSplit->pParent)<=opPrecedence(pNew) ){
+ pSplit = pSplit->pParent;
+ }
+
+ if( pSplit->pParent ){
+ assert( pSplit->pParent->pRight==pSplit );
+ pSplit->pParent->pRight = pNew;
+ pNew->pParent = pSplit->pParent;
+ }else{
+ *ppHead = pNew;
+ }
+ pNew->pLeft = pSplit;
+ pSplit->pParent = pNew;
+}
+
+/*
+** Parse the fts3 query expression found in buffer z, length n. This function
+** returns either when the end of the buffer is reached or an unmatched
+** closing bracket - ')' - is encountered.
+**
+** If successful, SQLITE_OK is returned, *ppExpr is set to point to the
+** parsed form of the expression and *pnConsumed is set to the number of
+** bytes read from buffer z. Otherwise, *ppExpr is set to 0 and SQLITE_NOMEM
+** (out of memory error) or SQLITE_ERROR (parse error) is returned.
+*/
+static int fts3ExprParse(
+ ParseContext *pParse, /* fts3 query parse context */
+ const char *z, int n, /* Text of MATCH query */
+ Fts3Expr **ppExpr, /* OUT: Parsed query structure */
+ int *pnConsumed /* OUT: Number of bytes consumed */
+){
+ Fts3Expr *pRet = 0;
+ Fts3Expr *pPrev = 0;
+ Fts3Expr *pNotBranch = 0; /* Only used in legacy parse mode */
+ int nIn = n;
+ const char *zIn = z;
+ int rc = SQLITE_OK;
+ int isRequirePhrase = 1;
+
+ while( rc==SQLITE_OK ){
+ Fts3Expr *p = 0;
+ int nByte = 0;
+ rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
+ if( rc==SQLITE_OK ){
+ int isPhrase;
+
+ if( !sqlite3_fts3_enable_parentheses
+ && p->eType==FTSQUERY_PHRASE && pParse->isNot
+ ){
+ /* Create an implicit NOT operator. */
+ Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
+ if( !pNot ){
+ sqlite3Fts3ExprFree(p);
+ rc = SQLITE_NOMEM;
+ goto exprparse_out;
+ }
+ pNot->eType = FTSQUERY_NOT;
+ pNot->pRight = p;
+ if( pNotBranch ){
+ pNot->pLeft = pNotBranch;
+ }
+ pNotBranch = pNot;
+ p = pPrev;
+ }else{
+ int eType = p->eType;
+ isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
+
+ /* The isRequirePhrase variable is set to true if a phrase or
+ ** an expression contained in parenthesis is required. If a
+ ** binary operator (AND, OR, NOT or NEAR) is encounted when
+ ** isRequirePhrase is set, this is a syntax error.
+ */
+ if( !isPhrase && isRequirePhrase ){
+ sqlite3Fts3ExprFree(p);
+ rc = SQLITE_ERROR;
+ goto exprparse_out;
+ }
+
+ if( isPhrase && !isRequirePhrase ){
+ /* Insert an implicit AND operator. */
+ Fts3Expr *pAnd;
+ assert( pRet && pPrev );
+ pAnd = fts3MallocZero(sizeof(Fts3Expr));
+ if( !pAnd ){
+ sqlite3Fts3ExprFree(p);
+ rc = SQLITE_NOMEM;
+ goto exprparse_out;
+ }
+ pAnd->eType = FTSQUERY_AND;
+ insertBinaryOperator(&pRet, pPrev, pAnd);
+ pPrev = pAnd;
+ }
+
+ /* This test catches attempts to make either operand of a NEAR
+ ** operator something other than a phrase. For example, either of
+ ** the following:
+ **
+ ** (bracketed expression) NEAR phrase
+ ** phrase NEAR (bracketed expression)
+ **
+ ** Return an error in either case.
+ */
+ if( pPrev && (
+ (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE)
+ || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR)
+ )){
+ sqlite3Fts3ExprFree(p);
+ rc = SQLITE_ERROR;
+ goto exprparse_out;
+ }
+
+ if( isPhrase ){
+ if( pRet ){
+ assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
+ pPrev->pRight = p;
+ p->pParent = pPrev;
+ }else{
+ pRet = p;
+ }
+ }else{
+ insertBinaryOperator(&pRet, pPrev, p);
+ }
+ isRequirePhrase = !isPhrase;
+ }
+ assert( nByte>0 );
+ }
+ assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) );
+ nIn -= nByte;
+ zIn += nByte;
+ pPrev = p;
+ }
+
+ if( rc==SQLITE_DONE && pRet && isRequirePhrase ){
+ rc = SQLITE_ERROR;
+ }
+
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ if( !sqlite3_fts3_enable_parentheses && pNotBranch ){
+ if( !pRet ){
+ rc = SQLITE_ERROR;
+ }else{
+ Fts3Expr *pIter = pNotBranch;
+ while( pIter->pLeft ){
+ pIter = pIter->pLeft;
+ }
+ pIter->pLeft = pRet;
+ pRet = pNotBranch;
+ }
+ }
+ }
+ *pnConsumed = n - nIn;
+
+exprparse_out:
+ if( rc!=SQLITE_OK ){
+ sqlite3Fts3ExprFree(pRet);
+ sqlite3Fts3ExprFree(pNotBranch);
+ pRet = 0;
+ }
+ *ppExpr = pRet;
+ return rc;
+}
+
+/*
+** Parameters z and n contain a pointer to and length of a buffer containing
+** an fts3 query expression, respectively. This function attempts to parse the
+** query expression and create a tree of Fts3Expr structures representing the
+** parsed expression. If successful, *ppExpr is set to point to the head
+** of the parsed expression tree and SQLITE_OK is returned. If an error
+** occurs, either SQLITE_NOMEM (out-of-memory error) or SQLITE_ERROR (parse
+** error) is returned and *ppExpr is set to 0.
+**
+** If parameter n is a negative number, then z is assumed to point to a
+** nul-terminated string and the length is determined using strlen().
+**
+** The first parameter, pTokenizer, is passed the fts3 tokenizer module to
+** use to normalize query tokens while parsing the expression. The azCol[]
+** array, which is assumed to contain nCol entries, should contain the names
+** of each column in the target fts3 table, in order from left to right.
+** Column names must be nul-terminated strings.
+**
+** The iDefaultCol parameter should be passed the index of the table column
+** that appears on the left-hand-side of the MATCH operator (the default
+** column to match against for tokens for which a column name is not explicitly
+** specified as part of the query string), or -1 if tokens may by default
+** match any table column.
+*/
+SQLITE_PRIVATE int sqlite3Fts3ExprParse(
+ sqlite3_tokenizer *pTokenizer, /* Tokenizer module */
+ int iLangid, /* Language id for tokenizer */
+ char **azCol, /* Array of column names for fts3 table */
+ int bFts4, /* True to allow FTS4-only syntax */
+ int nCol, /* Number of entries in azCol[] */
+ int iDefaultCol, /* Default column to query */
+ const char *z, int n, /* Text of MATCH query */
+ Fts3Expr **ppExpr /* OUT: Parsed query structure */
+){
+ int nParsed;
+ int rc;
+ ParseContext sParse;
+
+ memset(&sParse, 0, sizeof(ParseContext));
+ sParse.pTokenizer = pTokenizer;
+ sParse.iLangid = iLangid;
+ sParse.azCol = (const char **)azCol;
+ sParse.nCol = nCol;
+ sParse.iDefaultCol = iDefaultCol;
+ sParse.bFts4 = bFts4;
+ if( z==0 ){
+ *ppExpr = 0;
+ return SQLITE_OK;
+ }
+ if( n<0 ){
+ n = (int)strlen(z);
+ }
+ rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed);
+
+ /* Check for mismatched parenthesis */
+ if( rc==SQLITE_OK && sParse.nNest ){
+ rc = SQLITE_ERROR;
+ sqlite3Fts3ExprFree(*ppExpr);
+ *ppExpr = 0;
+ }
+
+ return rc;
+}
+
+/*
+** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse().
+*/
+SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){
+ if( p ){
+ assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
+ sqlite3Fts3ExprFree(p->pLeft);
+ sqlite3Fts3ExprFree(p->pRight);
+ sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
+ sqlite3_free(p->aMI);
+ sqlite3_free(p);
+ }
+}
+
+/****************************************************************************
+*****************************************************************************
+** Everything after this point is just test code.
+*/
+
+#ifdef SQLITE_TEST
+
+/* #include <stdio.h> */
+
+/*
+** Function to query the hash-table of tokenizers (see README.tokenizers).
+*/
+static int queryTestTokenizer(
+ sqlite3 *db,
+ const char *zName,
+ const sqlite3_tokenizer_module **pp
+){
+ int rc;
+ sqlite3_stmt *pStmt;
+ const char zSql[] = "SELECT fts3_tokenizer(?)";
+
+ *pp = 0;
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
+ memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
+ }
+ }
+
+ return sqlite3_finalize(pStmt);
+}
+
+/*
+** Return a pointer to a buffer containing a text representation of the
+** expression passed as the first argument. The buffer is obtained from
+** sqlite3_malloc(). It is the responsibility of the caller to use
+** sqlite3_free() to release the memory. If an OOM condition is encountered,
+** NULL is returned.
+**
+** If the second argument is not NULL, then its contents are prepended to
+** the returned expression text and then freed using sqlite3_free().
+*/
+static char *exprToString(Fts3Expr *pExpr, char *zBuf){
+ switch( pExpr->eType ){
+ case FTSQUERY_PHRASE: {
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ int i;
+ zBuf = sqlite3_mprintf(
+ "%zPHRASE %d 0", zBuf, pPhrase->iColumn);
+ for(i=0; zBuf && i<pPhrase->nToken; i++){
+ zBuf = sqlite3_mprintf("%z %.*s%s", zBuf,
+ pPhrase->aToken[i].n, pPhrase->aToken[i].z,
+ (pPhrase->aToken[i].isPrefix?"+":"")
+ );
+ }
+ return zBuf;
+ }
+
+ case FTSQUERY_NEAR:
+ zBuf = sqlite3_mprintf("%zNEAR/%d ", zBuf, pExpr->nNear);
+ break;
+ case FTSQUERY_NOT:
+ zBuf = sqlite3_mprintf("%zNOT ", zBuf);
+ break;
+ case FTSQUERY_AND:
+ zBuf = sqlite3_mprintf("%zAND ", zBuf);
+ break;
+ case FTSQUERY_OR:
+ zBuf = sqlite3_mprintf("%zOR ", zBuf);
+ break;
+ }
+
+ if( zBuf ) zBuf = sqlite3_mprintf("%z{", zBuf);
+ if( zBuf ) zBuf = exprToString(pExpr->pLeft, zBuf);
+ if( zBuf ) zBuf = sqlite3_mprintf("%z} {", zBuf);
+
+ if( zBuf ) zBuf = exprToString(pExpr->pRight, zBuf);
+ if( zBuf ) zBuf = sqlite3_mprintf("%z}", zBuf);
+
+ return zBuf;
+}
+
+/*
+** This is the implementation of a scalar SQL function used to test the
+** expression parser. It should be called as follows:
+**
+** fts3_exprtest(<tokenizer>, <expr>, <column 1>, ...);
+**
+** The first argument, <tokenizer>, is the name of the fts3 tokenizer used
+** to parse the query expression (see README.tokenizers). The second argument
+** is the query expression to parse. Each subsequent argument is the name
+** of a column of the fts3 table that the query expression may refer to.
+** For example:
+**
+** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2');
+*/
+static void fts3ExprTest(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3_tokenizer_module const *pModule = 0;
+ sqlite3_tokenizer *pTokenizer = 0;
+ int rc;
+ char **azCol = 0;
+ const char *zExpr;
+ int nExpr;
+ int nCol;
+ int ii;
+ Fts3Expr *pExpr;
+ char *zBuf = 0;
+ sqlite3 *db = sqlite3_context_db_handle(context);
+
+ if( argc<3 ){
+ sqlite3_result_error(context,
+ "Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1
+ );
+ return;
+ }
+
+ rc = queryTestTokenizer(db,
+ (const char *)sqlite3_value_text(argv[0]), &pModule);
+ if( rc==SQLITE_NOMEM ){
+ sqlite3_result_error_nomem(context);
+ goto exprtest_out;
+ }else if( !pModule ){
+ sqlite3_result_error(context, "No such tokenizer module", -1);
+ goto exprtest_out;
+ }
+
+ rc = pModule->xCreate(0, 0, &pTokenizer);
+ assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
+ if( rc==SQLITE_NOMEM ){
+ sqlite3_result_error_nomem(context);
+ goto exprtest_out;
+ }
+ pTokenizer->pModule = pModule;
+
+ zExpr = (const char *)sqlite3_value_text(argv[1]);
+ nExpr = sqlite3_value_bytes(argv[1]);
+ nCol = argc-2;
+ azCol = (char **)sqlite3_malloc(nCol*sizeof(char *));
+ if( !azCol ){
+ sqlite3_result_error_nomem(context);
+ goto exprtest_out;
+ }
+ for(ii=0; ii<nCol; ii++){
+ azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
+ }
+
+ rc = sqlite3Fts3ExprParse(
+ pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
+ );
+ if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
+ sqlite3_result_error(context, "Error parsing expression", -1);
+ }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ sqlite3_free(zBuf);
+ }
+
+ sqlite3Fts3ExprFree(pExpr);
+
+exprtest_out:
+ if( pModule && pTokenizer ){
+ rc = pModule->xDestroy(pTokenizer);
+ }
+ sqlite3_free(azCol);
+}
+
+/*
+** Register the query expression parser test function fts3_exprtest()
+** with database connection db.
+*/
+SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
+ return sqlite3_create_function(
+ db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0
+ );
+}
+
+#endif
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_expr.c *******************************************/
+/************** Begin file fts3_hash.c ***************************************/
+/*
+** 2001 September 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This is the implementation of generic hash-tables used in SQLite.
+** We've modified it slightly to serve as a standalone hash table
+** implementation for the full-text indexing module.
+*/
+
+/*
+** The code in this file is only compiled if:
+**
+** * The FTS3 module is being built as an extension
+** (in which case SQLITE_CORE is not defined), or
+**
+** * The FTS3 module is being built into the core of
+** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+/* #include <string.h> */
+
+
+/*
+** Malloc and Free functions
+*/
+static void *fts3HashMalloc(int n){
+ void *p = sqlite3_malloc(n);
+ if( p ){
+ memset(p, 0, n);
+ }
+ return p;
+}
+static void fts3HashFree(void *p){
+ sqlite3_free(p);
+}
+
+/* Turn bulk memory into a hash table object by initializing the
+** fields of the Hash structure.
+**
+** "pNew" is a pointer to the hash table that is to be initialized.
+** keyClass is one of the constants
+** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass
+** determines what kind of key the hash table will use. "copyKey" is
+** true if the hash table should make its own private copy of keys and
+** false if it should just use the supplied pointer.
+*/
+SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){
+ assert( pNew!=0 );
+ assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY );
+ pNew->keyClass = keyClass;
+ pNew->copyKey = copyKey;
+ pNew->first = 0;
+ pNew->count = 0;
+ pNew->htsize = 0;
+ pNew->ht = 0;
+}
+
+/* Remove all entries from a hash table. Reclaim all memory.
+** Call this routine to delete a hash table or to reset a hash table
+** to the empty state.
+*/
+SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash *pH){
+ Fts3HashElem *elem; /* For looping over all elements of the table */
+
+ assert( pH!=0 );
+ elem = pH->first;
+ pH->first = 0;
+ fts3HashFree(pH->ht);
+ pH->ht = 0;
+ pH->htsize = 0;
+ while( elem ){
+ Fts3HashElem *next_elem = elem->next;
+ if( pH->copyKey && elem->pKey ){
+ fts3HashFree(elem->pKey);
+ }
+ fts3HashFree(elem);
+ elem = next_elem;
+ }
+ pH->count = 0;
+}
+
+/*
+** Hash and comparison functions when the mode is FTS3_HASH_STRING
+*/
+static int fts3StrHash(const void *pKey, int nKey){
+ const char *z = (const char *)pKey;
+ int h = 0;
+ if( nKey<=0 ) nKey = (int) strlen(z);
+ while( nKey > 0 ){
+ h = (h<<3) ^ h ^ *z++;
+ nKey--;
+ }
+ return h & 0x7fffffff;
+}
+static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
+ if( n1!=n2 ) return 1;
+ return strncmp((const char*)pKey1,(const char*)pKey2,n1);
+}
+
+/*
+** Hash and comparison functions when the mode is FTS3_HASH_BINARY
+*/
+static int fts3BinHash(const void *pKey, int nKey){
+ int h = 0;
+ const char *z = (const char *)pKey;
+ while( nKey-- > 0 ){
+ h = (h<<3) ^ h ^ *(z++);
+ }
+ return h & 0x7fffffff;
+}
+static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){
+ if( n1!=n2 ) return 1;
+ return memcmp(pKey1,pKey2,n1);
+}
+
+/*
+** Return a pointer to the appropriate hash function given the key class.
+**
+** The C syntax in this function definition may be unfamilar to some
+** programmers, so we provide the following additional explanation:
+**
+** The name of the function is "ftsHashFunction". The function takes a
+** single parameter "keyClass". The return value of ftsHashFunction()
+** is a pointer to another function. Specifically, the return value
+** of ftsHashFunction() is a pointer to a function that takes two parameters
+** with types "const void*" and "int" and returns an "int".
+*/
+static int (*ftsHashFunction(int keyClass))(const void*,int){
+ if( keyClass==FTS3_HASH_STRING ){
+ return &fts3StrHash;
+ }else{
+ assert( keyClass==FTS3_HASH_BINARY );
+ return &fts3BinHash;
+ }
+}
+
+/*
+** Return a pointer to the appropriate hash function given the key class.
+**
+** For help in interpreted the obscure C code in the function definition,
+** see the header comment on the previous function.
+*/
+static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){
+ if( keyClass==FTS3_HASH_STRING ){
+ return &fts3StrCompare;
+ }else{
+ assert( keyClass==FTS3_HASH_BINARY );
+ return &fts3BinCompare;
+ }
+}
+
+/* Link an element into the hash table
+*/
+static void fts3HashInsertElement(
+ Fts3Hash *pH, /* The complete hash table */
+ struct _fts3ht *pEntry, /* The entry into which pNew is inserted */
+ Fts3HashElem *pNew /* The element to be inserted */
+){
+ Fts3HashElem *pHead; /* First element already in pEntry */
+ pHead = pEntry->chain;
+ if( pHead ){
+ pNew->next = pHead;
+ pNew->prev = pHead->prev;
+ if( pHead->prev ){ pHead->prev->next = pNew; }
+ else { pH->first = pNew; }
+ pHead->prev = pNew;
+ }else{
+ pNew->next = pH->first;
+ if( pH->first ){ pH->first->prev = pNew; }
+ pNew->prev = 0;
+ pH->first = pNew;
+ }
+ pEntry->count++;
+ pEntry->chain = pNew;
+}
+
+
+/* Resize the hash table so that it cantains "new_size" buckets.
+** "new_size" must be a power of 2. The hash table might fail
+** to resize if sqliteMalloc() fails.
+**
+** Return non-zero if a memory allocation error occurs.
+*/
+static int fts3Rehash(Fts3Hash *pH, int new_size){
+ struct _fts3ht *new_ht; /* The new hash table */
+ Fts3HashElem *elem, *next_elem; /* For looping over existing elements */
+ int (*xHash)(const void*,int); /* The hash function */
+
+ assert( (new_size & (new_size-1))==0 );
+ new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) );
+ if( new_ht==0 ) return 1;
+ fts3HashFree(pH->ht);
+ pH->ht = new_ht;
+ pH->htsize = new_size;
+ xHash = ftsHashFunction(pH->keyClass);
+ for(elem=pH->first, pH->first=0; elem; elem = next_elem){
+ int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
+ next_elem = elem->next;
+ fts3HashInsertElement(pH, &new_ht[h], elem);
+ }
+ return 0;
+}
+
+/* This function (for internal use only) locates an element in an
+** hash table that matches the given key. The hash for this key has
+** already been computed and is passed as the 4th parameter.
+*/
+static Fts3HashElem *fts3FindElementByHash(
+ const Fts3Hash *pH, /* The pH to be searched */
+ const void *pKey, /* The key we are searching for */
+ int nKey,
+ int h /* The hash for this key. */
+){
+ Fts3HashElem *elem; /* Used to loop thru the element list */
+ int count; /* Number of elements left to test */
+ int (*xCompare)(const void*,int,const void*,int); /* comparison function */
+
+ if( pH->ht ){
+ struct _fts3ht *pEntry = &pH->ht[h];
+ elem = pEntry->chain;
+ count = pEntry->count;
+ xCompare = ftsCompareFunction(pH->keyClass);
+ while( count-- && elem ){
+ if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
+ return elem;
+ }
+ elem = elem->next;
+ }
+ }
+ return 0;
+}
+
+/* Remove a single entry from the hash table given a pointer to that
+** element and a hash on the element's key.
+*/
+static void fts3RemoveElementByHash(
+ Fts3Hash *pH, /* The pH containing "elem" */
+ Fts3HashElem* elem, /* The element to be removed from the pH */
+ int h /* Hash value for the element */
+){
+ struct _fts3ht *pEntry;
+ if( elem->prev ){
+ elem->prev->next = elem->next;
+ }else{
+ pH->first = elem->next;
+ }
+ if( elem->next ){
+ elem->next->prev = elem->prev;
+ }
+ pEntry = &pH->ht[h];
+ if( pEntry->chain==elem ){
+ pEntry->chain = elem->next;
+ }
+ pEntry->count--;
+ if( pEntry->count<=0 ){
+ pEntry->chain = 0;
+ }
+ if( pH->copyKey && elem->pKey ){
+ fts3HashFree(elem->pKey);
+ }
+ fts3HashFree( elem );
+ pH->count--;
+ if( pH->count<=0 ){
+ assert( pH->first==0 );
+ assert( pH->count==0 );
+ fts3HashClear(pH);
+ }
+}
+
+SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(
+ const Fts3Hash *pH,
+ const void *pKey,
+ int nKey
+){
+ int h; /* A hash on key */
+ int (*xHash)(const void*,int); /* The hash function */
+
+ if( pH==0 || pH->ht==0 ) return 0;
+ xHash = ftsHashFunction(pH->keyClass);
+ assert( xHash!=0 );
+ h = (*xHash)(pKey,nKey);
+ assert( (pH->htsize & (pH->htsize-1))==0 );
+ return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
+}
+
+/*
+** Attempt to locate an element of the hash table pH with a key
+** that matches pKey,nKey. Return the data for this element if it is
+** found, or NULL if there is no match.
+*/
+SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
+ Fts3HashElem *pElem; /* The element that matches key (if any) */
+
+ pElem = sqlite3Fts3HashFindElem(pH, pKey, nKey);
+ return pElem ? pElem->data : 0;
+}
+
+/* Insert an element into the hash table pH. The key is pKey,nKey
+** and the data is "data".
+**
+** If no element exists with a matching key, then a new
+** element is created. A copy of the key is made if the copyKey
+** flag is set. NULL is returned.
+**
+** If another element already exists with the same key, then the
+** new data replaces the old data and the old data is returned.
+** The key is not copied in this instance. If a malloc fails, then
+** the new data is returned and the hash table is unchanged.
+**
+** If the "data" parameter to this function is NULL, then the
+** element corresponding to "key" is removed from the hash table.
+*/
+SQLITE_PRIVATE void *sqlite3Fts3HashInsert(
+ Fts3Hash *pH, /* The hash table to insert into */
+ const void *pKey, /* The key */
+ int nKey, /* Number of bytes in the key */
+ void *data /* The data */
+){
+ int hraw; /* Raw hash value of the key */
+ int h; /* the hash of the key modulo hash table size */
+ Fts3HashElem *elem; /* Used to loop thru the element list */
+ Fts3HashElem *new_elem; /* New element added to the pH */
+ int (*xHash)(const void*,int); /* The hash function */
+
+ assert( pH!=0 );
+ xHash = ftsHashFunction(pH->keyClass);
+ assert( xHash!=0 );
+ hraw = (*xHash)(pKey, nKey);
+ assert( (pH->htsize & (pH->htsize-1))==0 );
+ h = hraw & (pH->htsize-1);
+ elem = fts3FindElementByHash(pH,pKey,nKey,h);
+ if( elem ){
+ void *old_data = elem->data;
+ if( data==0 ){
+ fts3RemoveElementByHash(pH,elem,h);
+ }else{
+ elem->data = data;
+ }
+ return old_data;
+ }
+ if( data==0 ) return 0;
+ if( (pH->htsize==0 && fts3Rehash(pH,8))
+ || (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2))
+ ){
+ pH->count = 0;
+ return data;
+ }
+ assert( pH->htsize>0 );
+ new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) );
+ if( new_elem==0 ) return data;
+ if( pH->copyKey && pKey!=0 ){
+ new_elem->pKey = fts3HashMalloc( nKey );
+ if( new_elem->pKey==0 ){
+ fts3HashFree(new_elem);
+ return data;
+ }
+ memcpy((void*)new_elem->pKey, pKey, nKey);
+ }else{
+ new_elem->pKey = (void*)pKey;
+ }
+ new_elem->nKey = nKey;
+ pH->count++;
+ assert( pH->htsize>0 );
+ assert( (pH->htsize & (pH->htsize-1))==0 );
+ h = hraw & (pH->htsize-1);
+ fts3HashInsertElement(pH, &pH->ht[h], new_elem);
+ new_elem->data = data;
+ return 0;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_hash.c *******************************************/
+/************** Begin file fts3_porter.c *************************************/
+/*
+** 2006 September 30
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Implementation of the full-text-search tokenizer that implements
+** a Porter stemmer.
+*/
+
+/*
+** The code in this file is only compiled if:
+**
+** * The FTS3 module is being built as an extension
+** (in which case SQLITE_CORE is not defined), or
+**
+** * The FTS3 module is being built into the core of
+** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+/* #include <stdio.h> */
+/* #include <string.h> */
+
+
+/*
+** Class derived from sqlite3_tokenizer
+*/
+typedef struct porter_tokenizer {
+ sqlite3_tokenizer base; /* Base class */
+} porter_tokenizer;
+
+/*
+** Class derived from sqlite3_tokenizer_cursor
+*/
+typedef struct porter_tokenizer_cursor {
+ sqlite3_tokenizer_cursor base;
+ const char *zInput; /* input we are tokenizing */
+ int nInput; /* size of the input */
+ int iOffset; /* current position in zInput */
+ int iToken; /* index of next token to be returned */
+ char *zToken; /* storage for current token */
+ int nAllocated; /* space allocated to zToken buffer */
+} porter_tokenizer_cursor;
+
+
+/*
+** Create a new tokenizer instance.
+*/
+static int porterCreate(
+ int argc, const char * const *argv,
+ sqlite3_tokenizer **ppTokenizer
+){
+ porter_tokenizer *t;
+
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
+
+ t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t));
+ if( t==NULL ) return SQLITE_NOMEM;
+ memset(t, 0, sizeof(*t));
+ *ppTokenizer = &t->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destroy a tokenizer
+*/
+static int porterDestroy(sqlite3_tokenizer *pTokenizer){
+ sqlite3_free(pTokenizer);
+ return SQLITE_OK;
+}
+
+/*
+** Prepare to begin tokenizing a particular string. The input
+** string to be tokenized is zInput[0..nInput-1]. A cursor
+** used to incrementally tokenize this string is returned in
+** *ppCursor.
+*/
+static int porterOpen(
+ sqlite3_tokenizer *pTokenizer, /* The tokenizer */
+ const char *zInput, int nInput, /* String to be tokenized */
+ sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
+){
+ porter_tokenizer_cursor *c;
+
+ UNUSED_PARAMETER(pTokenizer);
+
+ c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
+ if( c==NULL ) return SQLITE_NOMEM;
+
+ c->zInput = zInput;
+ if( zInput==0 ){
+ c->nInput = 0;
+ }else if( nInput<0 ){
+ c->nInput = (int)strlen(zInput);
+ }else{
+ c->nInput = nInput;
+ }
+ c->iOffset = 0; /* start tokenizing at the beginning */
+ c->iToken = 0;
+ c->zToken = NULL; /* no space allocated, yet. */
+ c->nAllocated = 0;
+
+ *ppCursor = &c->base;
+ return SQLITE_OK;
+}
+
+/*
+** Close a tokenization cursor previously opened by a call to
+** porterOpen() above.
+*/
+static int porterClose(sqlite3_tokenizer_cursor *pCursor){
+ porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
+ sqlite3_free(c->zToken);
+ sqlite3_free(c);
+ return SQLITE_OK;
+}
+/*
+** Vowel or consonant
+*/
+static const char cType[] = {
+ 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 2, 1
+};
+
+/*
+** isConsonant() and isVowel() determine if their first character in
+** the string they point to is a consonant or a vowel, according
+** to Porter ruls.
+**
+** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
+** 'Y' is a consonant unless it follows another consonant,
+** in which case it is a vowel.
+**
+** In these routine, the letters are in reverse order. So the 'y' rule
+** is that 'y' is a consonant unless it is followed by another
+** consonent.
+*/
+static int isVowel(const char*);
+static int isConsonant(const char *z){
+ int j;
+ char x = *z;
+ if( x==0 ) return 0;
+ assert( x>='a' && x<='z' );
+ j = cType[x-'a'];
+ if( j<2 ) return j;
+ return z[1]==0 || isVowel(z + 1);
+}
+static int isVowel(const char *z){
+ int j;
+ char x = *z;
+ if( x==0 ) return 0;
+ assert( x>='a' && x<='z' );
+ j = cType[x-'a'];
+ if( j<2 ) return 1-j;
+ return isConsonant(z + 1);
+}
+
+/*
+** Let any sequence of one or more vowels be represented by V and let
+** C be sequence of one or more consonants. Then every word can be
+** represented as:
+**
+** [C] (VC){m} [V]
+**
+** In prose: A word is an optional consonant followed by zero or
+** vowel-consonant pairs followed by an optional vowel. "m" is the
+** number of vowel consonant pairs. This routine computes the value
+** of m for the first i bytes of a word.
+**
+** Return true if the m-value for z is 1 or more. In other words,
+** return true if z contains at least one vowel that is followed
+** by a consonant.
+**
+** In this routine z[] is in reverse order. So we are really looking
+** for an instance of of a consonant followed by a vowel.
+*/
+static int m_gt_0(const char *z){
+ while( isVowel(z) ){ z++; }
+ if( *z==0 ) return 0;
+ while( isConsonant(z) ){ z++; }
+ return *z!=0;
+}
+
+/* Like mgt0 above except we are looking for a value of m which is
+** exactly 1
+*/
+static int m_eq_1(const char *z){
+ while( isVowel(z) ){ z++; }
+ if( *z==0 ) return 0;
+ while( isConsonant(z) ){ z++; }
+ if( *z==0 ) return 0;
+ while( isVowel(z) ){ z++; }
+ if( *z==0 ) return 1;
+ while( isConsonant(z) ){ z++; }
+ return *z==0;
+}
+
+/* Like mgt0 above except we are looking for a value of m>1 instead
+** or m>0
+*/
+static int m_gt_1(const char *z){
+ while( isVowel(z) ){ z++; }
+ if( *z==0 ) return 0;
+ while( isConsonant(z) ){ z++; }
+ if( *z==0 ) return 0;
+ while( isVowel(z) ){ z++; }
+ if( *z==0 ) return 0;
+ while( isConsonant(z) ){ z++; }
+ return *z!=0;
+}
+
+/*
+** Return TRUE if there is a vowel anywhere within z[0..n-1]
+*/
+static int hasVowel(const char *z){
+ while( isConsonant(z) ){ z++; }
+ return *z!=0;
+}
+
+/*
+** Return TRUE if the word ends in a double consonant.
+**
+** The text is reversed here. So we are really looking at
+** the first two characters of z[].
+*/
+static int doubleConsonant(const char *z){
+ return isConsonant(z) && z[0]==z[1];
+}
+
+/*
+** Return TRUE if the word ends with three letters which
+** are consonant-vowel-consonent and where the final consonant
+** is not 'w', 'x', or 'y'.
+**
+** The word is reversed here. So we are really checking the
+** first three letters and the first one cannot be in [wxy].
+*/
+static int star_oh(const char *z){
+ return
+ isConsonant(z) &&
+ z[0]!='w' && z[0]!='x' && z[0]!='y' &&
+ isVowel(z+1) &&
+ isConsonant(z+2);
+}
+
+/*
+** If the word ends with zFrom and xCond() is true for the stem
+** of the word that preceeds the zFrom ending, then change the
+** ending to zTo.
+**
+** The input word *pz and zFrom are both in reverse order. zTo
+** is in normal order.
+**
+** Return TRUE if zFrom matches. Return FALSE if zFrom does not
+** match. Not that TRUE is returned even if xCond() fails and
+** no substitution occurs.
+*/
+static int stem(
+ char **pz, /* The word being stemmed (Reversed) */
+ const char *zFrom, /* If the ending matches this... (Reversed) */
+ const char *zTo, /* ... change the ending to this (not reversed) */
+ int (*xCond)(const char*) /* Condition that must be true */
+){
+ char *z = *pz;
+ while( *zFrom && *zFrom==*z ){ z++; zFrom++; }
+ if( *zFrom!=0 ) return 0;
+ if( xCond && !xCond(z) ) return 1;
+ while( *zTo ){
+ *(--z) = *(zTo++);
+ }
+ *pz = z;
+ return 1;
+}
+
+/*
+** This is the fallback stemmer used when the porter stemmer is
+** inappropriate. The input word is copied into the output with
+** US-ASCII case folding. If the input word is too long (more
+** than 20 bytes if it contains no digits or more than 6 bytes if
+** it contains digits) then word is truncated to 20 or 6 bytes
+** by taking 10 or 3 bytes from the beginning and end.
+*/
+static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
+ int i, mx, j;
+ int hasDigit = 0;
+ for(i=0; i<nIn; i++){
+ char c = zIn[i];
+ if( c>='A' && c<='Z' ){
+ zOut[i] = c - 'A' + 'a';
+ }else{
+ if( c>='0' && c<='9' ) hasDigit = 1;
+ zOut[i] = c;
+ }
+ }
+ mx = hasDigit ? 3 : 10;
+ if( nIn>mx*2 ){
+ for(j=mx, i=nIn-mx; i<nIn; i++, j++){
+ zOut[j] = zOut[i];
+ }
+ i = j;
+ }
+ zOut[i] = 0;
+ *pnOut = i;
+}
+
+
+/*
+** Stem the input word zIn[0..nIn-1]. Store the output in zOut.
+** zOut is at least big enough to hold nIn bytes. Write the actual
+** size of the output word (exclusive of the '\0' terminator) into *pnOut.
+**
+** Any upper-case characters in the US-ASCII character set ([A-Z])
+** are converted to lower case. Upper-case UTF characters are
+** unchanged.
+**
+** Words that are longer than about 20 bytes are stemmed by retaining
+** a few bytes from the beginning and the end of the word. If the
+** word contains digits, 3 bytes are taken from the beginning and
+** 3 bytes from the end. For long words without digits, 10 bytes
+** are taken from each end. US-ASCII case folding still applies.
+**
+** If the input word contains not digits but does characters not
+** in [a-zA-Z] then no stemming is attempted and this routine just
+** copies the input into the input into the output with US-ASCII
+** case folding.
+**
+** Stemming never increases the length of the word. So there is
+** no chance of overflowing the zOut buffer.
+*/
+static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
+ int i, j;
+ char zReverse[28];
+ char *z, *z2;
+ if( nIn<3 || nIn>=(int)sizeof(zReverse)-7 ){
+ /* The word is too big or too small for the porter stemmer.
+ ** Fallback to the copy stemmer */
+ copy_stemmer(zIn, nIn, zOut, pnOut);
+ return;
+ }
+ for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){
+ char c = zIn[i];
+ if( c>='A' && c<='Z' ){
+ zReverse[j] = c + 'a' - 'A';
+ }else if( c>='a' && c<='z' ){
+ zReverse[j] = c;
+ }else{
+ /* The use of a character not in [a-zA-Z] means that we fallback
+ ** to the copy stemmer */
+ copy_stemmer(zIn, nIn, zOut, pnOut);
+ return;
+ }
+ }
+ memset(&zReverse[sizeof(zReverse)-5], 0, 5);
+ z = &zReverse[j+1];
+
+
+ /* Step 1a */
+ if( z[0]=='s' ){
+ if(
+ !stem(&z, "sess", "ss", 0) &&
+ !stem(&z, "sei", "i", 0) &&
+ !stem(&z, "ss", "ss", 0)
+ ){
+ z++;
+ }
+ }
+
+ /* Step 1b */
+ z2 = z;
+ if( stem(&z, "dee", "ee", m_gt_0) ){
+ /* Do nothing. The work was all in the test */
+ }else if(
+ (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
+ && z!=z2
+ ){
+ if( stem(&z, "ta", "ate", 0) ||
+ stem(&z, "lb", "ble", 0) ||
+ stem(&z, "zi", "ize", 0) ){
+ /* Do nothing. The work was all in the test */
+ }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){
+ z++;
+ }else if( m_eq_1(z) && star_oh(z) ){
+ *(--z) = 'e';
+ }
+ }
+
+ /* Step 1c */
+ if( z[0]=='y' && hasVowel(z+1) ){
+ z[0] = 'i';
+ }
+
+ /* Step 2 */
+ switch( z[1] ){
+ case 'a':
+ stem(&z, "lanoita", "ate", m_gt_0) ||
+ stem(&z, "lanoit", "tion", m_gt_0);
+ break;
+ case 'c':
+ stem(&z, "icne", "ence", m_gt_0) ||
+ stem(&z, "icna", "ance", m_gt_0);
+ break;
+ case 'e':
+ stem(&z, "rezi", "ize", m_gt_0);
+ break;
+ case 'g':
+ stem(&z, "igol", "log", m_gt_0);
+ break;
+ case 'l':
+ stem(&z, "ilb", "ble", m_gt_0) ||
+ stem(&z, "illa", "al", m_gt_0) ||
+ stem(&z, "iltne", "ent", m_gt_0) ||
+ stem(&z, "ile", "e", m_gt_0) ||
+ stem(&z, "ilsuo", "ous", m_gt_0);
+ break;
+ case 'o':
+ stem(&z, "noitazi", "ize", m_gt_0) ||
+ stem(&z, "noita", "ate", m_gt_0) ||
+ stem(&z, "rota", "ate", m_gt_0);
+ break;
+ case 's':
+ stem(&z, "msila", "al", m_gt_0) ||
+ stem(&z, "ssenevi", "ive", m_gt_0) ||
+ stem(&z, "ssenluf", "ful", m_gt_0) ||
+ stem(&z, "ssensuo", "ous", m_gt_0);
+ break;
+ case 't':
+ stem(&z, "itila", "al", m_gt_0) ||
+ stem(&z, "itivi", "ive", m_gt_0) ||
+ stem(&z, "itilib", "ble", m_gt_0);
+ break;
+ }
+
+ /* Step 3 */
+ switch( z[0] ){
+ case 'e':
+ stem(&z, "etaci", "ic", m_gt_0) ||
+ stem(&z, "evita", "", m_gt_0) ||
+ stem(&z, "ezila", "al", m_gt_0);
+ break;
+ case 'i':
+ stem(&z, "itici", "ic", m_gt_0);
+ break;
+ case 'l':
+ stem(&z, "laci", "ic", m_gt_0) ||
+ stem(&z, "luf", "", m_gt_0);
+ break;
+ case 's':
+ stem(&z, "ssen", "", m_gt_0);
+ break;
+ }
+
+ /* Step 4 */
+ switch( z[1] ){
+ case 'a':
+ if( z[0]=='l' && m_gt_1(z+2) ){
+ z += 2;
+ }
+ break;
+ case 'c':
+ if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){
+ z += 4;
+ }
+ break;
+ case 'e':
+ if( z[0]=='r' && m_gt_1(z+2) ){
+ z += 2;
+ }
+ break;
+ case 'i':
+ if( z[0]=='c' && m_gt_1(z+2) ){
+ z += 2;
+ }
+ break;
+ case 'l':
+ if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){
+ z += 4;
+ }
+ break;
+ case 'n':
+ if( z[0]=='t' ){
+ if( z[2]=='a' ){
+ if( m_gt_1(z+3) ){
+ z += 3;
+ }
+ }else if( z[2]=='e' ){
+ stem(&z, "tneme", "", m_gt_1) ||
+ stem(&z, "tnem", "", m_gt_1) ||
+ stem(&z, "tne", "", m_gt_1);
+ }
+ }
+ break;
+ case 'o':
+ if( z[0]=='u' ){
+ if( m_gt_1(z+2) ){
+ z += 2;
+ }
+ }else if( z[3]=='s' || z[3]=='t' ){
+ stem(&z, "noi", "", m_gt_1);
+ }
+ break;
+ case 's':
+ if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){
+ z += 3;
+ }
+ break;
+ case 't':
+ stem(&z, "eta", "", m_gt_1) ||
+ stem(&z, "iti", "", m_gt_1);
+ break;
+ case 'u':
+ if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
+ z += 3;
+ }
+ break;
+ case 'v':
+ case 'z':
+ if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){
+ z += 3;
+ }
+ break;
+ }
+
+ /* Step 5a */
+ if( z[0]=='e' ){
+ if( m_gt_1(z+1) ){
+ z++;
+ }else if( m_eq_1(z+1) && !star_oh(z+1) ){
+ z++;
+ }
+ }
+
+ /* Step 5b */
+ if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){
+ z++;
+ }
+
+ /* z[] is now the stemmed word in reverse order. Flip it back
+ ** around into forward order and return.
+ */
+ *pnOut = i = (int)strlen(z);
+ zOut[i] = 0;
+ while( *z ){
+ zOut[--i] = *(z++);
+ }
+}
+
+/*
+** Characters that can be part of a token. We assume any character
+** whose value is greater than 0x80 (any UTF character) can be
+** part of a token. In other words, delimiters all must have
+** values of 0x7f or lower.
+*/
+static const char porterIdChar[] = {
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
+};
+#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30]))
+
+/*
+** Extract the next token from a tokenization cursor. The cursor must
+** have been opened by a prior call to porterOpen().
+*/
+static int porterNext(
+ sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */
+ const char **pzToken, /* OUT: *pzToken is the token text */
+ int *pnBytes, /* OUT: Number of bytes in token */
+ int *piStartOffset, /* OUT: Starting offset of token */
+ int *piEndOffset, /* OUT: Ending offset of token */
+ int *piPosition /* OUT: Position integer of token */
+){
+ porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
+ const char *z = c->zInput;
+
+ while( c->iOffset<c->nInput ){
+ int iStartOffset, ch;
+
+ /* Scan past delimiter characters */
+ while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
+ c->iOffset++;
+ }
+
+ /* Count non-delimiter characters. */
+ iStartOffset = c->iOffset;
+ while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
+ c->iOffset++;
+ }
+
+ if( c->iOffset>iStartOffset ){
+ int n = c->iOffset-iStartOffset;
+ if( n>c->nAllocated ){
+ char *pNew;
+ c->nAllocated = n+20;
+ pNew = sqlite3_realloc(c->zToken, c->nAllocated);
+ if( !pNew ) return SQLITE_NOMEM;
+ c->zToken = pNew;
+ }
+ porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
+ *pzToken = c->zToken;
+ *piStartOffset = iStartOffset;
+ *piEndOffset = c->iOffset;
+ *piPosition = c->iToken++;
+ return SQLITE_OK;
+ }
+ }
+ return SQLITE_DONE;
+}
+
+/*
+** The set of routines that implement the porter-stemmer tokenizer
+*/
+static const sqlite3_tokenizer_module porterTokenizerModule = {
+ 0,
+ porterCreate,
+ porterDestroy,
+ porterOpen,
+ porterClose,
+ porterNext,
+ 0
+};
+
+/*
+** Allocate a new porter tokenizer. Return a pointer to the new
+** tokenizer in *ppModule
+*/
+SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(
+ sqlite3_tokenizer_module const**ppModule
+){
+ *ppModule = &porterTokenizerModule;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_porter.c *****************************************/
+/************** Begin file fts3_tokenizer.c **********************************/
+/*
+** 2007 June 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This is part of an SQLite module implementing full-text search.
+** This particular file implements the generic tokenizer interface.
+*/
+
+/*
+** The code in this file is only compiled if:
+**
+** * The FTS3 module is being built as an extension
+** (in which case SQLITE_CORE is not defined), or
+**
+** * The FTS3 module is being built into the core of
+** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <assert.h> */
+/* #include <string.h> */
+
+/*
+** Implementation of the SQL scalar function for accessing the underlying
+** hash table. This function may be called as follows:
+**
+** SELECT <function-name>(<key-name>);
+** SELECT <function-name>(<key-name>, <pointer>);
+**
+** where <function-name> is the name passed as the second argument
+** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer').
+**
+** If the <pointer> argument is specified, it must be a blob value
+** containing a pointer to be stored as the hash data corresponding
+** to the string <key-name>. If <pointer> is not specified, then
+** the string <key-name> must already exist in the has table. Otherwise,
+** an error is returned.
+**
+** Whether or not the <pointer> argument is specified, the value returned
+** is a blob containing the pointer stored as the hash data corresponding
+** to string <key-name> (after the hash-table is updated, if applicable).
+*/
+static void scalarFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ Fts3Hash *pHash;
+ void *pPtr = 0;
+ const unsigned char *zName;
+ int nName;
+
+ assert( argc==1 || argc==2 );
+
+ pHash = (Fts3Hash *)sqlite3_user_data(context);
+
+ zName = sqlite3_value_text(argv[0]);
+ nName = sqlite3_value_bytes(argv[0])+1;
+
+ if( argc==2 ){
+ void *pOld;
+ int n = sqlite3_value_bytes(argv[1]);
+ if( n!=sizeof(pPtr) ){
+ sqlite3_result_error(context, "argument type mismatch", -1);
+ return;
+ }
+ pPtr = *(void **)sqlite3_value_blob(argv[1]);
+ pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr);
+ if( pOld==pPtr ){
+ sqlite3_result_error(context, "out of memory", -1);
+ return;
+ }
+ }else{
+ pPtr = sqlite3Fts3HashFind(pHash, zName, nName);
+ if( !pPtr ){
+ char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
+ sqlite3_result_error(context, zErr, -1);
+ sqlite3_free(zErr);
+ return;
+ }
+ }
+
+ sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
+}
+
+SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){
+ static const char isFtsIdChar[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
+ };
+ return (c&0x80 || isFtsIdChar[(int)(c)]);
+}
+
+SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *zStr, int *pn){
+ const char *z1;
+ const char *z2 = 0;
+
+ /* Find the start of the next token. */
+ z1 = zStr;
+ while( z2==0 ){
+ char c = *z1;
+ switch( c ){
+ case '\0': return 0; /* No more tokens here */
+ case '\'':
+ case '"':
+ case '`': {
+ z2 = z1;
+ while( *++z2 && (*z2!=c || *++z2==c) );
+ break;
+ }
+ case '[':
+ z2 = &z1[1];
+ while( *z2 && z2[0]!=']' ) z2++;
+ if( *z2 ) z2++;
+ break;
+
+ default:
+ if( sqlite3Fts3IsIdChar(*z1) ){
+ z2 = &z1[1];
+ while( sqlite3Fts3IsIdChar(*z2) ) z2++;
+ }else{
+ z1++;
+ }
+ }
+ }
+
+ *pn = (int)(z2-z1);
+ return z1;
+}
+
+SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
+ Fts3Hash *pHash, /* Tokenizer hash table */
+ const char *zArg, /* Tokenizer name */
+ sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
+ char **pzErr /* OUT: Set to malloced error message */
+){
+ int rc;
+ char *z = (char *)zArg;
+ int n = 0;
+ char *zCopy;
+ char *zEnd; /* Pointer to nul-term of zCopy */
+ sqlite3_tokenizer_module *m;
+
+ zCopy = sqlite3_mprintf("%s", zArg);
+ if( !zCopy ) return SQLITE_NOMEM;
+ zEnd = &zCopy[strlen(zCopy)];
+
+ z = (char *)sqlite3Fts3NextToken(zCopy, &n);
+ z[n] = '\0';
+ sqlite3Fts3Dequote(z);
+
+ m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1);
+ if( !m ){
+ *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z);
+ rc = SQLITE_ERROR;
+ }else{
+ char const **aArg = 0;
+ int iArg = 0;
+ z = &z[n+1];
+ while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){
+ int nNew = sizeof(char *)*(iArg+1);
+ char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew);
+ if( !aNew ){
+ sqlite3_free(zCopy);
+ sqlite3_free((void *)aArg);
+ return SQLITE_NOMEM;
+ }
+ aArg = aNew;
+ aArg[iArg++] = z;
+ z[n] = '\0';
+ sqlite3Fts3Dequote(z);
+ z = &z[n+1];
+ }
+ rc = m->xCreate(iArg, aArg, ppTok);
+ assert( rc!=SQLITE_OK || *ppTok );
+ if( rc!=SQLITE_OK ){
+ *pzErr = sqlite3_mprintf("unknown tokenizer");
+ }else{
+ (*ppTok)->pModule = m;
+ }
+ sqlite3_free((void *)aArg);
+ }
+
+ sqlite3_free(zCopy);
+ return rc;
+}
+
+
+#ifdef SQLITE_TEST
+
+/* #include <tcl.h> */
+/* #include <string.h> */
+
+/*
+** Implementation of a special SQL scalar function for testing tokenizers
+** designed to be used in concert with the Tcl testing framework. This
+** function must be called with two or more arguments:
+**
+** SELECT <function-name>(<key-name>, ..., <input-string>);
+**
+** where <function-name> is the name passed as the second argument
+** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer')
+** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test').
+**
+** The return value is a string that may be interpreted as a Tcl
+** list. For each token in the <input-string>, three elements are
+** added to the returned list. The first is the token position, the
+** second is the token text (folded, stemmed, etc.) and the third is the
+** substring of <input-string> associated with the token. For example,
+** using the built-in "simple" tokenizer:
+**
+** SELECT fts_tokenizer_test('simple', 'I don't see how');
+**
+** will return the string:
+**
+** "{0 i I 1 dont don't 2 see see 3 how how}"
+**
+*/
+static void testFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ Fts3Hash *pHash;
+ sqlite3_tokenizer_module *p;
+ sqlite3_tokenizer *pTokenizer = 0;
+ sqlite3_tokenizer_cursor *pCsr = 0;
+
+ const char *zErr = 0;
+
+ const char *zName;
+ int nName;
+ const char *zInput;
+ int nInput;
+
+ const char *azArg[64];
+
+ const char *zToken;
+ int nToken = 0;
+ int iStart = 0;
+ int iEnd = 0;
+ int iPos = 0;
+ int i;
+
+ Tcl_Obj *pRet;
+
+ if( argc<2 ){
+ sqlite3_result_error(context, "insufficient arguments", -1);
+ return;
+ }
+
+ nName = sqlite3_value_bytes(argv[0]);
+ zName = (const char *)sqlite3_value_text(argv[0]);
+ nInput = sqlite3_value_bytes(argv[argc-1]);
+ zInput = (const char *)sqlite3_value_text(argv[argc-1]);
+
+ pHash = (Fts3Hash *)sqlite3_user_data(context);
+ p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
+
+ if( !p ){
+ char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
+ sqlite3_result_error(context, zErr, -1);
+ sqlite3_free(zErr);
+ return;
+ }
+
+ pRet = Tcl_NewObj();
+ Tcl_IncrRefCount(pRet);
+
+ for(i=1; i<argc-1; i++){
+ azArg[i-1] = (const char *)sqlite3_value_text(argv[i]);
+ }
+
+ if( SQLITE_OK!=p->xCreate(argc-2, azArg, &pTokenizer) ){
+ zErr = "error in xCreate()";
+ goto finish;
+ }
+ pTokenizer->pModule = p;
+ if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){
+ zErr = "error in xOpen()";
+ goto finish;
+ }
+
+ while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
+ Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
+ Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
+ zToken = &zInput[iStart];
+ nToken = iEnd-iStart;
+ Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
+ }
+
+ if( SQLITE_OK!=p->xClose(pCsr) ){
+ zErr = "error in xClose()";
+ goto finish;
+ }
+ if( SQLITE_OK!=p->xDestroy(pTokenizer) ){
+ zErr = "error in xDestroy()";
+ goto finish;
+ }
+
+finish:
+ if( zErr ){
+ sqlite3_result_error(context, zErr, -1);
+ }else{
+ sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT);
+ }
+ Tcl_DecrRefCount(pRet);
+}
+
+static
+int registerTokenizer(
+ sqlite3 *db,
+ char *zName,
+ const sqlite3_tokenizer_module *p
+){
+ int rc;
+ sqlite3_stmt *pStmt;
+ const char zSql[] = "SELECT fts3_tokenizer(?, ?)";
+
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
+ sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC);
+ sqlite3_step(pStmt);
+
+ return sqlite3_finalize(pStmt);
+}
+
+static
+int queryTokenizer(
+ sqlite3 *db,
+ char *zName,
+ const sqlite3_tokenizer_module **pp
+){
+ int rc;
+ sqlite3_stmt *pStmt;
+ const char zSql[] = "SELECT fts3_tokenizer(?)";
+
+ *pp = 0;
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
+ memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
+ }
+ }
+
+ return sqlite3_finalize(pStmt);
+}
+
+SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
+
+/*
+** Implementation of the scalar function fts3_tokenizer_internal_test().
+** This function is used for testing only, it is not included in the
+** build unless SQLITE_TEST is defined.
+**
+** The purpose of this is to test that the fts3_tokenizer() function
+** can be used as designed by the C-code in the queryTokenizer and
+** registerTokenizer() functions above. These two functions are repeated
+** in the README.tokenizer file as an example, so it is important to
+** test them.
+**
+** To run the tests, evaluate the fts3_tokenizer_internal_test() scalar
+** function with no arguments. An assert() will fail if a problem is
+** detected. i.e.:
+**
+** SELECT fts3_tokenizer_internal_test();
+**
+*/
+static void intTestFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int rc;
+ const sqlite3_tokenizer_module *p1;
+ const sqlite3_tokenizer_module *p2;
+ sqlite3 *db = (sqlite3 *)sqlite3_user_data(context);
+
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
+
+ /* Test the query function */
+ sqlite3Fts3SimpleTokenizerModule(&p1);
+ rc = queryTokenizer(db, "simple", &p2);
+ assert( rc==SQLITE_OK );
+ assert( p1==p2 );
+ rc = queryTokenizer(db, "nosuchtokenizer", &p2);
+ assert( rc==SQLITE_ERROR );
+ assert( p2==0 );
+ assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") );
+
+ /* Test the storage function */
+ rc = registerTokenizer(db, "nosuchtokenizer", p1);
+ assert( rc==SQLITE_OK );
+ rc = queryTokenizer(db, "nosuchtokenizer", &p2);
+ assert( rc==SQLITE_OK );
+ assert( p2==p1 );
+
+ sqlite3_result_text(context, "ok", -1, SQLITE_STATIC);
+}
+
+#endif
+
+/*
+** Set up SQL objects in database db used to access the contents of
+** the hash table pointed to by argument pHash. The hash table must
+** been initialized to use string keys, and to take a private copy
+** of the key when a value is inserted. i.e. by a call similar to:
+**
+** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
+**
+** This function adds a scalar function (see header comment above
+** scalarFunc() in this file for details) and, if ENABLE_TABLE is
+** defined at compilation time, a temporary virtual table (see header
+** comment above struct HashTableVtab) to the database schema. Both
+** provide read/write access to the contents of *pHash.
+**
+** The third argument to this function, zName, is used as the name
+** of both the scalar and, if created, the virtual table.
+*/
+SQLITE_PRIVATE int sqlite3Fts3InitHashTable(
+ sqlite3 *db,
+ Fts3Hash *pHash,
+ const char *zName
+){
+ int rc = SQLITE_OK;
+ void *p = (void *)pHash;
+ const int any = SQLITE_ANY;
+
+#ifdef SQLITE_TEST
+ char *zTest = 0;
+ char *zTest2 = 0;
+ void *pdb = (void *)db;
+ zTest = sqlite3_mprintf("%s_test", zName);
+ zTest2 = sqlite3_mprintf("%s_internal_test", zName);
+ if( !zTest || !zTest2 ){
+ rc = SQLITE_NOMEM;
+ }
+#endif
+
+ if( SQLITE_OK==rc ){
+ rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0);
+ }
+ if( SQLITE_OK==rc ){
+ rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0);
+ }
+#ifdef SQLITE_TEST
+ if( SQLITE_OK==rc ){
+ rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0);
+ }
+ if( SQLITE_OK==rc ){
+ rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0);
+ }
+#endif
+
+#ifdef SQLITE_TEST
+ sqlite3_free(zTest);
+ sqlite3_free(zTest2);
+#endif
+
+ return rc;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_tokenizer.c **************************************/
+/************** Begin file fts3_tokenizer1.c *********************************/
+/*
+** 2006 Oct 10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** Implementation of the "simple" full-text-search tokenizer.
+*/
+
+/*
+** The code in this file is only compiled if:
+**
+** * The FTS3 module is being built as an extension
+** (in which case SQLITE_CORE is not defined), or
+**
+** * The FTS3 module is being built into the core of
+** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+/* #include <stdio.h> */
+/* #include <string.h> */
+
+
+typedef struct simple_tokenizer {
+ sqlite3_tokenizer base;
+ char delim[128]; /* flag ASCII delimiters */
+} simple_tokenizer;
+
+typedef struct simple_tokenizer_cursor {
+ sqlite3_tokenizer_cursor base;
+ const char *pInput; /* input we are tokenizing */
+ int nBytes; /* size of the input */
+ int iOffset; /* current position in pInput */
+ int iToken; /* index of next token to be returned */
+ char *pToken; /* storage for current token */
+ int nTokenAllocated; /* space allocated to zToken buffer */
+} simple_tokenizer_cursor;
+
+
+static int simpleDelim(simple_tokenizer *t, unsigned char c){
+ return c<0x80 && t->delim[c];
+}
+static int fts3_isalnum(int x){
+ return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z');
+}
+
+/*
+** Create a new tokenizer instance.
+*/
+static int simpleCreate(
+ int argc, const char * const *argv,
+ sqlite3_tokenizer **ppTokenizer
+){
+ simple_tokenizer *t;
+
+ t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t));
+ if( t==NULL ) return SQLITE_NOMEM;
+ memset(t, 0, sizeof(*t));
+
+ /* TODO(shess) Delimiters need to remain the same from run to run,
+ ** else we need to reindex. One solution would be a meta-table to
+ ** track such information in the database, then we'd only want this
+ ** information on the initial create.
+ */
+ if( argc>1 ){
+ int i, n = (int)strlen(argv[1]);
+ for(i=0; i<n; i++){
+ unsigned char ch = argv[1][i];
+ /* We explicitly don't support UTF-8 delimiters for now. */
+ if( ch>=0x80 ){
+ sqlite3_free(t);
+ return SQLITE_ERROR;
+ }
+ t->delim[ch] = 1;
+ }
+ } else {
+ /* Mark non-alphanumeric ASCII characters as delimiters */
+ int i;
+ for(i=1; i<0x80; i++){
+ t->delim[i] = !fts3_isalnum(i) ? -1 : 0;
+ }
+ }
+
+ *ppTokenizer = &t->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destroy a tokenizer
+*/
+static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
+ sqlite3_free(pTokenizer);
+ return SQLITE_OK;
+}
+
+/*
+** Prepare to begin tokenizing a particular string. The input
+** string to be tokenized is pInput[0..nBytes-1]. A cursor
+** used to incrementally tokenize this string is returned in
+** *ppCursor.
+*/
+static int simpleOpen(
+ sqlite3_tokenizer *pTokenizer, /* The tokenizer */
+ const char *pInput, int nBytes, /* String to be tokenized */
+ sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
+){
+ simple_tokenizer_cursor *c;
+
+ UNUSED_PARAMETER(pTokenizer);
+
+ c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
+ if( c==NULL ) return SQLITE_NOMEM;
+
+ c->pInput = pInput;
+ if( pInput==0 ){
+ c->nBytes = 0;
+ }else if( nBytes<0 ){
+ c->nBytes = (int)strlen(pInput);
+ }else{
+ c->nBytes = nBytes;
+ }
+ c->iOffset = 0; /* start tokenizing at the beginning */
+ c->iToken = 0;
+ c->pToken = NULL; /* no space allocated, yet. */
+ c->nTokenAllocated = 0;
+
+ *ppCursor = &c->base;
+ return SQLITE_OK;
+}
+
+/*
+** Close a tokenization cursor previously opened by a call to
+** simpleOpen() above.
+*/
+static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
+ simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
+ sqlite3_free(c->pToken);
+ sqlite3_free(c);
+ return SQLITE_OK;
+}
+
+/*
+** Extract the next token from a tokenization cursor. The cursor must
+** have been opened by a prior call to simpleOpen().
+*/
+static int simpleNext(
+ sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
+ const char **ppToken, /* OUT: *ppToken is the token text */
+ int *pnBytes, /* OUT: Number of bytes in token */
+ int *piStartOffset, /* OUT: Starting offset of token */
+ int *piEndOffset, /* OUT: Ending offset of token */
+ int *piPosition /* OUT: Position integer of token */
+){
+ simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
+ simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
+ unsigned char *p = (unsigned char *)c->pInput;
+
+ while( c->iOffset<c->nBytes ){
+ int iStartOffset;
+
+ /* Scan past delimiter characters */
+ while( c->iOffset<c->nBytes && simpleDelim(t, p[c->iOffset]) ){
+ c->iOffset++;
+ }
+
+ /* Count non-delimiter characters. */
+ iStartOffset = c->iOffset;
+ while( c->iOffset<c->nBytes && !simpleDelim(t, p[c->iOffset]) ){
+ c->iOffset++;
+ }
+
+ if( c->iOffset>iStartOffset ){
+ int i, n = c->iOffset-iStartOffset;
+ if( n>c->nTokenAllocated ){
+ char *pNew;
+ c->nTokenAllocated = n+20;
+ pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
+ if( !pNew ) return SQLITE_NOMEM;
+ c->pToken = pNew;
+ }
+ for(i=0; i<n; i++){
+ /* TODO(shess) This needs expansion to handle UTF-8
+ ** case-insensitivity.
+ */
+ unsigned char ch = p[iStartOffset+i];
+ c->pToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch);
+ }
+ *ppToken = c->pToken;
+ *pnBytes = n;
+ *piStartOffset = iStartOffset;
+ *piEndOffset = c->iOffset;
+ *piPosition = c->iToken++;
+
+ return SQLITE_OK;
+ }
+ }
+ return SQLITE_DONE;
+}
+
+/*
+** The set of routines that implement the simple tokenizer
+*/
+static const sqlite3_tokenizer_module simpleTokenizerModule = {
+ 0,
+ simpleCreate,
+ simpleDestroy,
+ simpleOpen,
+ simpleClose,
+ simpleNext,
+ 0,
+};
+
+/*
+** Allocate a new simple tokenizer. Return a pointer to the new
+** tokenizer in *ppModule
+*/
+SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(
+ sqlite3_tokenizer_module const**ppModule
+){
+ *ppModule = &simpleTokenizerModule;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_tokenizer1.c *************************************/
+/************** Begin file fts3_write.c **************************************/
+/*
+** 2009 Oct 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file is part of the SQLite FTS3 extension module. Specifically,
+** this file contains code to insert, update and delete rows from FTS3
+** tables. It also contains code to merge FTS3 b-tree segments. Some
+** of the sub-routines used to merge segments are also used by the query
+** code in fts3.c.
+*/
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <string.h> */
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+
+
+#define FTS_MAX_APPENDABLE_HEIGHT 16
+
+/*
+** When full-text index nodes are loaded from disk, the buffer that they
+** are loaded into has the following number of bytes of padding at the end
+** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
+** of 920 bytes is allocated for it.
+**
+** This means that if we have a pointer into a buffer containing node data,
+** it is always safe to read up to two varints from it without risking an
+** overread, even if the node data is corrupted.
+*/
+#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2)
+
+/*
+** Under certain circumstances, b-tree nodes (doclists) can be loaded into
+** memory incrementally instead of all at once. This can be a big performance
+** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext()
+** method before retrieving all query results (as may happen, for example,
+** if a query has a LIMIT clause).
+**
+** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
+** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
+** The code is written so that the hard lower-limit for each of these values
+** is 1. Clearly such small values would be inefficient, but can be useful
+** for testing purposes.
+**
+** If this module is built with SQLITE_TEST defined, these constants may
+** be overridden at runtime for testing purposes. File fts3_test.c contains
+** a Tcl interface to read and write the values.
+*/
+#ifdef SQLITE_TEST
+int test_fts3_node_chunksize = (4*1024);
+int test_fts3_node_chunk_threshold = (4*1024)*4;
+# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
+# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
+#else
+# define FTS3_NODE_CHUNKSIZE (4*1024)
+# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
+#endif
+
+/*
+** The two values that may be meaningfully bound to the :1 parameter in
+** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
+*/
+#define FTS_STAT_DOCTOTAL 0
+#define FTS_STAT_INCRMERGEHINT 1
+#define FTS_STAT_AUTOINCRMERGE 2
+
+/*
+** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic
+** and incremental merge operation that takes place. This is used for
+** debugging FTS only, it should not usually be turned on in production
+** systems.
+*/
+#ifdef FTS3_LOG_MERGES
+static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){
+ sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel);
+}
+#else
+#define fts3LogMerge(x, y)
+#endif
+
+
+typedef struct PendingList PendingList;
+typedef struct SegmentNode SegmentNode;
+typedef struct SegmentWriter SegmentWriter;
+
+/*
+** An instance of the following data structure is used to build doclists
+** incrementally. See function fts3PendingListAppend() for details.
+*/
+struct PendingList {
+ int nData;
+ char *aData;
+ int nSpace;
+ sqlite3_int64 iLastDocid;
+ sqlite3_int64 iLastCol;
+ sqlite3_int64 iLastPos;
+};
+
+
+/*
+** Each cursor has a (possibly empty) linked list of the following objects.
+*/
+struct Fts3DeferredToken {
+ Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */
+ int iCol; /* Column token must occur in */
+ Fts3DeferredToken *pNext; /* Next in list of deferred tokens */
+ PendingList *pList; /* Doclist is assembled here */
+};
+
+/*
+** An instance of this structure is used to iterate through the terms on
+** a contiguous set of segment b-tree leaf nodes. Although the details of
+** this structure are only manipulated by code in this file, opaque handles
+** of type Fts3SegReader* are also used by code in fts3.c to iterate through
+** terms when querying the full-text index. See functions:
+**
+** sqlite3Fts3SegReaderNew()
+** sqlite3Fts3SegReaderFree()
+** sqlite3Fts3SegReaderIterate()
+**
+** Methods used to manipulate Fts3SegReader structures:
+**
+** fts3SegReaderNext()
+** fts3SegReaderFirstDocid()
+** fts3SegReaderNextDocid()
+*/
+struct Fts3SegReader {
+ int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
+ u8 bLookup; /* True for a lookup only */
+ u8 rootOnly; /* True for a root-only reader */
+
+ sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */
+ sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */
+ sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
+ sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
+
+ char *aNode; /* Pointer to node data (or NULL) */
+ int nNode; /* Size of buffer at aNode (or 0) */
+ int nPopulate; /* If >0, bytes of buffer aNode[] loaded */
+ sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */
+
+ Fts3HashElem **ppNextElem;
+
+ /* Variables set by fts3SegReaderNext(). These may be read directly
+ ** by the caller. They are valid from the time SegmentReaderNew() returns
+ ** until SegmentReaderNext() returns something other than SQLITE_OK
+ ** (i.e. SQLITE_DONE).
+ */
+ int nTerm; /* Number of bytes in current term */
+ char *zTerm; /* Pointer to current term */
+ int nTermAlloc; /* Allocated size of zTerm buffer */
+ char *aDoclist; /* Pointer to doclist of current entry */
+ int nDoclist; /* Size of doclist in current entry */
+
+ /* The following variables are used by fts3SegReaderNextDocid() to iterate
+ ** through the current doclist (aDoclist/nDoclist).
+ */
+ char *pOffsetList;
+ int nOffsetList; /* For descending pending seg-readers only */
+ sqlite3_int64 iDocid;
+};
+
+#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
+#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0)
+
+/*
+** An instance of this structure is used to create a segment b-tree in the
+** database. The internal details of this type are only accessed by the
+** following functions:
+**
+** fts3SegWriterAdd()
+** fts3SegWriterFlush()
+** fts3SegWriterFree()
+*/
+struct SegmentWriter {
+ SegmentNode *pTree; /* Pointer to interior tree structure */
+ sqlite3_int64 iFirst; /* First slot in %_segments written */
+ sqlite3_int64 iFree; /* Next free slot in %_segments */
+ char *zTerm; /* Pointer to previous term buffer */
+ int nTerm; /* Number of bytes in zTerm */
+ int nMalloc; /* Size of malloc'd buffer at zMalloc */
+ char *zMalloc; /* Malloc'd space (possibly) used for zTerm */
+ int nSize; /* Size of allocation at aData */
+ int nData; /* Bytes of data in aData */
+ char *aData; /* Pointer to block from malloc() */
+};
+
+/*
+** Type SegmentNode is used by the following three functions to create
+** the interior part of the segment b+-tree structures (everything except
+** the leaf nodes). These functions and type are only ever used by code
+** within the fts3SegWriterXXX() family of functions described above.
+**
+** fts3NodeAddTerm()
+** fts3NodeWrite()
+** fts3NodeFree()
+**
+** When a b+tree is written to the database (either as a result of a merge
+** or the pending-terms table being flushed), leaves are written into the
+** database file as soon as they are completely populated. The interior of
+** the tree is assembled in memory and written out only once all leaves have
+** been populated and stored. This is Ok, as the b+-tree fanout is usually
+** very large, meaning that the interior of the tree consumes relatively
+** little memory.
+*/
+struct SegmentNode {
+ SegmentNode *pParent; /* Parent node (or NULL for root node) */
+ SegmentNode *pRight; /* Pointer to right-sibling */
+ SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */
+ int nEntry; /* Number of terms written to node so far */
+ char *zTerm; /* Pointer to previous term buffer */
+ int nTerm; /* Number of bytes in zTerm */
+ int nMalloc; /* Size of malloc'd buffer at zMalloc */
+ char *zMalloc; /* Malloc'd space (possibly) used for zTerm */
+ int nData; /* Bytes of valid data so far */
+ char *aData; /* Node data */
+};
+
+/*
+** Valid values for the second argument to fts3SqlStmt().
+*/
+#define SQL_DELETE_CONTENT 0
+#define SQL_IS_EMPTY 1
+#define SQL_DELETE_ALL_CONTENT 2
+#define SQL_DELETE_ALL_SEGMENTS 3
+#define SQL_DELETE_ALL_SEGDIR 4
+#define SQL_DELETE_ALL_DOCSIZE 5
+#define SQL_DELETE_ALL_STAT 6
+#define SQL_SELECT_CONTENT_BY_ROWID 7
+#define SQL_NEXT_SEGMENT_INDEX 8
+#define SQL_INSERT_SEGMENTS 9
+#define SQL_NEXT_SEGMENTS_ID 10
+#define SQL_INSERT_SEGDIR 11
+#define SQL_SELECT_LEVEL 12
+#define SQL_SELECT_LEVEL_RANGE 13
+#define SQL_SELECT_LEVEL_COUNT 14
+#define SQL_SELECT_SEGDIR_MAX_LEVEL 15
+#define SQL_DELETE_SEGDIR_LEVEL 16
+#define SQL_DELETE_SEGMENTS_RANGE 17
+#define SQL_CONTENT_INSERT 18
+#define SQL_DELETE_DOCSIZE 19
+#define SQL_REPLACE_DOCSIZE 20
+#define SQL_SELECT_DOCSIZE 21
+#define SQL_SELECT_STAT 22
+#define SQL_REPLACE_STAT 23
+
+#define SQL_SELECT_ALL_PREFIX_LEVEL 24
+#define SQL_DELETE_ALL_TERMS_SEGDIR 25
+#define SQL_DELETE_SEGDIR_RANGE 26
+#define SQL_SELECT_ALL_LANGID 27
+#define SQL_FIND_MERGE_LEVEL 28
+#define SQL_MAX_LEAF_NODE_ESTIMATE 29
+#define SQL_DELETE_SEGDIR_ENTRY 30
+#define SQL_SHIFT_SEGDIR_ENTRY 31
+#define SQL_SELECT_SEGDIR 32
+#define SQL_CHOMP_SEGDIR 33
+#define SQL_SEGMENT_IS_APPENDABLE 34
+#define SQL_SELECT_INDEXES 35
+#define SQL_SELECT_MXLEVEL 36
+
+/*
+** This function is used to obtain an SQLite prepared statement handle
+** for the statement identified by the second argument. If successful,
+** *pp is set to the requested statement handle and SQLITE_OK returned.
+** Otherwise, an SQLite error code is returned and *pp is set to 0.
+**
+** If argument apVal is not NULL, then it must point to an array with
+** at least as many entries as the requested statement has bound
+** parameters. The values are bound to the statements parameters before
+** returning.
+*/
+static int fts3SqlStmt(
+ Fts3Table *p, /* Virtual table handle */
+ int eStmt, /* One of the SQL_XXX constants above */
+ sqlite3_stmt **pp, /* OUT: Statement handle */
+ sqlite3_value **apVal /* Values to bind to statement */
+){
+ const char *azSql[] = {
+/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?",
+/* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)",
+/* 2 */ "DELETE FROM %Q.'%q_content'",
+/* 3 */ "DELETE FROM %Q.'%q_segments'",
+/* 4 */ "DELETE FROM %Q.'%q_segdir'",
+/* 5 */ "DELETE FROM %Q.'%q_docsize'",
+/* 6 */ "DELETE FROM %Q.'%q_stat'",
+/* 7 */ "SELECT %s WHERE rowid=?",
+/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
+/* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
+/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
+/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
+
+ /* Return segments in order from oldest to newest.*/
+/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
+ "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
+/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
+ "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?"
+ "ORDER BY level DESC, idx ASC",
+
+/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
+/* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
+
+/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
+/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
+/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)",
+/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
+/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
+/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
+/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?",
+/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)",
+/* 24 */ "",
+/* 25 */ "",
+
+/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
+/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
+
+/* This statement is used to determine which level to read the input from
+** when performing an incremental merge. It returns the absolute level number
+** of the oldest level in the db that contains at least ? segments. Or,
+** if no level in the FTS index contains more than ? segments, the statement
+** returns zero rows. */
+/* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?"
+ " ORDER BY (level %% 1024) ASC LIMIT 1",
+
+/* Estimate the upper limit on the number of leaf nodes in a new segment
+** created by merging the oldest :2 segments from absolute level :1. See
+** function sqlite3Fts3Incrmerge() for details. */
+/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
+ " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
+
+/* SQL_DELETE_SEGDIR_ENTRY
+** Delete the %_segdir entry on absolute level :1 with index :2. */
+/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
+
+/* SQL_SHIFT_SEGDIR_ENTRY
+** Modify the idx value for the segment with idx=:3 on absolute level :2
+** to :1. */
+/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?",
+
+/* SQL_SELECT_SEGDIR
+** Read a single entry from the %_segdir table. The entry from absolute
+** level :1 with index value :2. */
+/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
+ "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
+
+/* SQL_CHOMP_SEGDIR
+** Update the start_block (:1) and root (:2) fields of the %_segdir
+** entry located on absolute level :3 with index :4. */
+/* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?"
+ "WHERE level = ? AND idx = ?",
+
+/* SQL_SEGMENT_IS_APPENDABLE
+** Return a single row if the segment with end_block=? is appendable. Or
+** no rows otherwise. */
+/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL",
+
+/* SQL_SELECT_INDEXES
+** Return the list of valid segment indexes for absolute level ? */
+/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC",
+
+/* SQL_SELECT_MXLEVEL
+** Return the largest relative level in the FTS index or indexes. */
+/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'"
+ };
+ int rc = SQLITE_OK;
+ sqlite3_stmt *pStmt;
+
+ assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
+ assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
+
+ pStmt = p->aStmt[eStmt];
+ if( !pStmt ){
+ char *zSql;
+ if( eStmt==SQL_CONTENT_INSERT ){
+ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
+ }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
+ zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
+ }else{
+ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
+ }
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL);
+ sqlite3_free(zSql);
+ assert( rc==SQLITE_OK || pStmt==0 );
+ p->aStmt[eStmt] = pStmt;
+ }
+ }
+ if( apVal ){
+ int i;
+ int nParam = sqlite3_bind_parameter_count(pStmt);
+ for(i=0; rc==SQLITE_OK && i<nParam; i++){
+ rc = sqlite3_bind_value(pStmt, i+1, apVal[i]);
+ }
+ }
+ *pp = pStmt;
+ return rc;
+}
+
+
+static int fts3SelectDocsize(
+ Fts3Table *pTab, /* FTS3 table handle */
+ sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */
+ sqlite3_stmt **ppStmt /* OUT: Statement handle */
+){
+ sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */
+ int rc; /* Return code */
+
+ rc = fts3SqlStmt(pTab, SQL_SELECT_DOCSIZE, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pStmt, 1, iDocid);
+ rc = sqlite3_step(pStmt);
+ if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
+ rc = sqlite3_reset(pStmt);
+ if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
+ pStmt = 0;
+ }else{
+ rc = SQLITE_OK;
+ }
+ }
+
+ *ppStmt = pStmt;
+ return rc;
+}
+
+SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(
+ Fts3Table *pTab, /* Fts3 table handle */
+ sqlite3_stmt **ppStmt /* OUT: Statement handle */
+){
+ sqlite3_stmt *pStmt = 0;
+ int rc;
+ rc = fts3SqlStmt(pTab, SQL_SELECT_STAT, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
+ if( sqlite3_step(pStmt)!=SQLITE_ROW
+ || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB
+ ){
+ rc = sqlite3_reset(pStmt);
+ if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB;
+ pStmt = 0;
+ }
+ }
+ *ppStmt = pStmt;
+ return rc;
+}
+
+SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(
+ Fts3Table *pTab, /* Fts3 table handle */
+ sqlite3_int64 iDocid, /* Docid to read size data for */
+ sqlite3_stmt **ppStmt /* OUT: Statement handle */
+){
+ return fts3SelectDocsize(pTab, iDocid, ppStmt);
+}
+
+/*
+** Similar to fts3SqlStmt(). Except, after binding the parameters in
+** array apVal[] to the SQL statement identified by eStmt, the statement
+** is executed.
+**
+** Returns SQLITE_OK if the statement is successfully executed, or an
+** SQLite error code otherwise.
+*/
+static void fts3SqlExec(
+ int *pRC, /* Result code */
+ Fts3Table *p, /* The FTS3 table */
+ int eStmt, /* Index of statement to evaluate */
+ sqlite3_value **apVal /* Parameters to bind */
+){
+ sqlite3_stmt *pStmt;
+ int rc;
+ if( *pRC ) return;
+ rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
+ if( rc==SQLITE_OK ){
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ }
+ *pRC = rc;
+}
+
+
+/*
+** This function ensures that the caller has obtained a shared-cache
+** table-lock on the %_content table. This is required before reading
+** data from the fts3 table. If this lock is not acquired first, then
+** the caller may end up holding read-locks on the %_segments and %_segdir
+** tables, but no read-lock on the %_content table. If this happens
+** a second connection will be able to write to the fts3 table, but
+** attempting to commit those writes might return SQLITE_LOCKED or
+** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain
+** write-locks on the %_segments and %_segdir ** tables).
+**
+** We try to avoid this because if FTS3 returns any error when committing
+** a transaction, the whole transaction will be rolled back. And this is
+** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can
+** still happen if the user reads data directly from the %_segments or
+** %_segdir tables instead of going through FTS3 though.
+**
+** This reasoning does not apply to a content=xxx table.
+*/
+SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){
+ int rc; /* Return code */
+ sqlite3_stmt *pStmt; /* Statement used to obtain lock */
+
+ if( p->zContentTbl==0 ){
+ rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_null(pStmt, 1);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ }
+ }else{
+ rc = SQLITE_OK;
+ }
+
+ return rc;
+}
+
+/*
+** FTS maintains a separate indexes for each language-id (a 32-bit integer).
+** Within each language id, a separate index is maintained to store the
+** document terms, and each configured prefix size (configured the FTS
+** "prefix=" option). And each index consists of multiple levels ("relative
+** levels").
+**
+** All three of these values (the language id, the specific index and the
+** level within the index) are encoded in 64-bit integer values stored
+** in the %_segdir table on disk. This function is used to convert three
+** separate component values into the single 64-bit integer value that
+** can be used to query the %_segdir table.
+**
+** Specifically, each language-id/index combination is allocated 1024
+** 64-bit integer level values ("absolute levels"). The main terms index
+** for language-id 0 is allocate values 0-1023. The first prefix index
+** (if any) for language-id 0 is allocated values 1024-2047. And so on.
+** Language 1 indexes are allocated immediately following language 0.
+**
+** So, for a system with nPrefix prefix indexes configured, the block of
+** absolute levels that corresponds to language-id iLangid and index
+** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024).
+*/
+static sqlite3_int64 getAbsoluteLevel(
+ Fts3Table *p, /* FTS3 table handle */
+ int iLangid, /* Language id */
+ int iIndex, /* Index in p->aIndex[] */
+ int iLevel /* Level of segments */
+){
+ sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
+ assert( iLangid>=0 );
+ assert( p->nIndex>0 );
+ assert( iIndex>=0 && iIndex<p->nIndex );
+
+ iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL;
+ return iBase + iLevel;
+}
+
+/*
+** Set *ppStmt to a statement handle that may be used to iterate through
+** all rows in the %_segdir table, from oldest to newest. If successful,
+** return SQLITE_OK. If an error occurs while preparing the statement,
+** return an SQLite error code.
+**
+** There is only ever one instance of this SQL statement compiled for
+** each FTS3 table.
+**
+** The statement returns the following columns from the %_segdir table:
+**
+** 0: idx
+** 1: start_block
+** 2: leaves_end_block
+** 3: end_block
+** 4: root
+*/
+SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(
+ Fts3Table *p, /* FTS3 table */
+ int iLangid, /* Language being queried */
+ int iIndex, /* Index for p->aIndex[] */
+ int iLevel, /* Level to select (relative level) */
+ sqlite3_stmt **ppStmt /* OUT: Compiled statement */
+){
+ int rc;
+ sqlite3_stmt *pStmt = 0;
+
+ assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 );
+ assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
+ assert( iIndex>=0 && iIndex<p->nIndex );
+
+ if( iLevel<0 ){
+ /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
+ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
+ sqlite3_bind_int64(pStmt, 2,
+ getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
+ );
+ }
+ }else{
+ /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
+ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel));
+ }
+ }
+ *ppStmt = pStmt;
+ return rc;
+}
+
+
+/*
+** Append a single varint to a PendingList buffer. SQLITE_OK is returned
+** if successful, or an SQLite error code otherwise.
+**
+** This function also serves to allocate the PendingList structure itself.
+** For example, to create a new PendingList structure containing two
+** varints:
+**
+** PendingList *p = 0;
+** fts3PendingListAppendVarint(&p, 1);
+** fts3PendingListAppendVarint(&p, 2);
+*/
+static int fts3PendingListAppendVarint(
+ PendingList **pp, /* IN/OUT: Pointer to PendingList struct */
+ sqlite3_int64 i /* Value to append to data */
+){
+ PendingList *p = *pp;
+
+ /* Allocate or grow the PendingList as required. */
+ if( !p ){
+ p = sqlite3_malloc(sizeof(*p) + 100);
+ if( !p ){
+ return SQLITE_NOMEM;
+ }
+ p->nSpace = 100;
+ p->aData = (char *)&p[1];
+ p->nData = 0;
+ }
+ else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){
+ int nNew = p->nSpace * 2;
+ p = sqlite3_realloc(p, sizeof(*p) + nNew);
+ if( !p ){
+ sqlite3_free(*pp);
+ *pp = 0;
+ return SQLITE_NOMEM;
+ }
+ p->nSpace = nNew;
+ p->aData = (char *)&p[1];
+ }
+
+ /* Append the new serialized varint to the end of the list. */
+ p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i);
+ p->aData[p->nData] = '\0';
+ *pp = p;
+ return SQLITE_OK;
+}
+
+/*
+** Add a docid/column/position entry to a PendingList structure. Non-zero
+** is returned if the structure is sqlite3_realloced as part of adding
+** the entry. Otherwise, zero.
+**
+** If an OOM error occurs, *pRc is set to SQLITE_NOMEM before returning.
+** Zero is always returned in this case. Otherwise, if no OOM error occurs,
+** it is set to SQLITE_OK.
+*/
+static int fts3PendingListAppend(
+ PendingList **pp, /* IN/OUT: PendingList structure */
+ sqlite3_int64 iDocid, /* Docid for entry to add */
+ sqlite3_int64 iCol, /* Column for entry to add */
+ sqlite3_int64 iPos, /* Position of term for entry to add */
+ int *pRc /* OUT: Return code */
+){
+ PendingList *p = *pp;
+ int rc = SQLITE_OK;
+
+ assert( !p || p->iLastDocid<=iDocid );
+
+ if( !p || p->iLastDocid!=iDocid ){
+ sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
+ if( p ){
+ assert( p->nData<p->nSpace );
+ assert( p->aData[p->nData]==0 );
+ p->nData++;
+ }
+ if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iDelta)) ){
+ goto pendinglistappend_out;
+ }
+ p->iLastCol = -1;
+ p->iLastPos = 0;
+ p->iLastDocid = iDocid;
+ }
+ if( iCol>0 && p->iLastCol!=iCol ){
+ if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, 1))
+ || SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iCol))
+ ){
+ goto pendinglistappend_out;
+ }
+ p->iLastCol = iCol;
+ p->iLastPos = 0;
+ }
+ if( iCol>=0 ){
+ assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) );
+ rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos);
+ if( rc==SQLITE_OK ){
+ p->iLastPos = iPos;
+ }
+ }
+
+ pendinglistappend_out:
+ *pRc = rc;
+ if( p!=*pp ){
+ *pp = p;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** Free a PendingList object allocated by fts3PendingListAppend().
+*/
+static void fts3PendingListDelete(PendingList *pList){
+ sqlite3_free(pList);
+}
+
+/*
+** Add an entry to one of the pending-terms hash tables.
+*/
+static int fts3PendingTermsAddOne(
+ Fts3Table *p,
+ int iCol,
+ int iPos,
+ Fts3Hash *pHash, /* Pending terms hash table to add entry to */
+ const char *zToken,
+ int nToken
+){
+ PendingList *pList;
+ int rc = SQLITE_OK;
+
+ pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
+ if( pList ){
+ p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
+ }
+ if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
+ if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
+ /* Malloc failed while inserting the new entry. This can only
+ ** happen if there was no previous entry for this token.
+ */
+ assert( 0==fts3HashFind(pHash, zToken, nToken) );
+ sqlite3_free(pList);
+ rc = SQLITE_NOMEM;
+ }
+ }
+ if( rc==SQLITE_OK ){
+ p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
+ }
+ return rc;
+}
+
+/*
+** Tokenize the nul-terminated string zText and add all tokens to the
+** pending-terms hash-table. The docid used is that currently stored in
+** p->iPrevDocid, and the column is specified by argument iCol.
+**
+** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
+*/
+static int fts3PendingTermsAdd(
+ Fts3Table *p, /* Table into which text will be inserted */
+ int iLangid, /* Language id to use */
+ const char *zText, /* Text of document to be inserted */
+ int iCol, /* Column into which text is being inserted */
+ u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */
+){
+ int rc;
+ int iStart = 0;
+ int iEnd = 0;
+ int iPos = 0;
+ int nWord = 0;
+
+ char const *zToken;
+ int nToken = 0;
+
+ sqlite3_tokenizer *pTokenizer = p->pTokenizer;
+ sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
+ sqlite3_tokenizer_cursor *pCsr;
+ int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
+ const char**,int*,int*,int*,int*);
+
+ assert( pTokenizer && pModule );
+
+ /* If the user has inserted a NULL value, this function may be called with
+ ** zText==0. In this case, add zero token entries to the hash table and
+ ** return early. */
+ if( zText==0 ){
+ *pnWord = 0;
+ return SQLITE_OK;
+ }
+
+ rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ xNext = pModule->xNext;
+ while( SQLITE_OK==rc
+ && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
+ ){
+ int i;
+ if( iPos>=nWord ) nWord = iPos+1;
+
+ /* Positions cannot be negative; we use -1 as a terminator internally.
+ ** Tokens must have a non-zero length.
+ */
+ if( iPos<0 || !zToken || nToken<=0 ){
+ rc = SQLITE_ERROR;
+ break;
+ }
+
+ /* Add the term to the terms index */
+ rc = fts3PendingTermsAddOne(
+ p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
+ );
+
+ /* Add the term to each of the prefix indexes that it is not too
+ ** short for. */
+ for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
+ struct Fts3Index *pIndex = &p->aIndex[i];
+ if( nToken<pIndex->nPrefix ) continue;
+ rc = fts3PendingTermsAddOne(
+ p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
+ );
+ }
+ }
+
+ pModule->xClose(pCsr);
+ *pnWord += nWord;
+ return (rc==SQLITE_DONE ? SQLITE_OK : rc);
+}
+
+/*
+** Calling this function indicates that subsequent calls to
+** fts3PendingTermsAdd() are to add term/position-list pairs for the
+** contents of the document with docid iDocid.
+*/
+static int fts3PendingTermsDocid(
+ Fts3Table *p, /* Full-text table handle */
+ int iLangid, /* Language id of row being written */
+ sqlite_int64 iDocid /* Docid of row being written */
+){
+ assert( iLangid>=0 );
+
+ /* TODO(shess) Explore whether partially flushing the buffer on
+ ** forced-flush would provide better performance. I suspect that if
+ ** we ordered the doclists by size and flushed the largest until the
+ ** buffer was half empty, that would let the less frequent terms
+ ** generate longer doclists.
+ */
+ if( iDocid<=p->iPrevDocid
+ || p->iPrevLangid!=iLangid
+ || p->nPendingData>p->nMaxPendingData
+ ){
+ int rc = sqlite3Fts3PendingTermsFlush(p);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ p->iPrevDocid = iDocid;
+ p->iPrevLangid = iLangid;
+ return SQLITE_OK;
+}
+
+/*
+** Discard the contents of the pending-terms hash tables.
+*/
+SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
+ int i;
+ for(i=0; i<p->nIndex; i++){
+ Fts3HashElem *pElem;
+ Fts3Hash *pHash = &p->aIndex[i].hPending;
+ for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){
+ PendingList *pList = (PendingList *)fts3HashData(pElem);
+ fts3PendingListDelete(pList);
+ }
+ fts3HashClear(pHash);
+ }
+ p->nPendingData = 0;
+}
+
+/*
+** This function is called by the xUpdate() method as part of an INSERT
+** operation. It adds entries for each term in the new record to the
+** pendingTerms hash table.
+**
+** Argument apVal is the same as the similarly named argument passed to
+** fts3InsertData(). Parameter iDocid is the docid of the new row.
+*/
+static int fts3InsertTerms(
+ Fts3Table *p,
+ int iLangid,
+ sqlite3_value **apVal,
+ u32 *aSz
+){
+ int i; /* Iterator variable */
+ for(i=2; i<p->nColumn+2; i++){
+ const char *zText = (const char *)sqlite3_value_text(apVal[i]);
+ int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** This function is called by the xUpdate() method for an INSERT operation.
+** The apVal parameter is passed a copy of the apVal argument passed by
+** SQLite to the xUpdate() method. i.e:
+**
+** apVal[0] Not used for INSERT.
+** apVal[1] rowid
+** apVal[2] Left-most user-defined column
+** ...
+** apVal[p->nColumn+1] Right-most user-defined column
+** apVal[p->nColumn+2] Hidden column with same name as table
+** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid)
+** apVal[p->nColumn+4] Hidden languageid column
+*/
+static int fts3InsertData(
+ Fts3Table *p, /* Full-text table */
+ sqlite3_value **apVal, /* Array of values to insert */
+ sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */
+){
+ int rc; /* Return code */
+ sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */
+
+ if( p->zContentTbl ){
+ sqlite3_value *pRowid = apVal[p->nColumn+3];
+ if( sqlite3_value_type(pRowid)==SQLITE_NULL ){
+ pRowid = apVal[1];
+ }
+ if( sqlite3_value_type(pRowid)!=SQLITE_INTEGER ){
+ return SQLITE_CONSTRAINT;
+ }
+ *piDocid = sqlite3_value_int64(pRowid);
+ return SQLITE_OK;
+ }
+
+ /* Locate the statement handle used to insert data into the %_content
+ ** table. The SQL for this statement is:
+ **
+ ** INSERT INTO %_content VALUES(?, ?, ?, ...)
+ **
+ ** The statement features N '?' variables, where N is the number of user
+ ** defined columns in the FTS3 table, plus one for the docid field.
+ */
+ rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
+ if( rc==SQLITE_OK && p->zLanguageid ){
+ rc = sqlite3_bind_int(
+ pContentInsert, p->nColumn+2,
+ sqlite3_value_int(apVal[p->nColumn+4])
+ );
+ }
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* There is a quirk here. The users INSERT statement may have specified
+ ** a value for the "rowid" field, for the "docid" field, or for both.
+ ** Which is a problem, since "rowid" and "docid" are aliases for the
+ ** same value. For example:
+ **
+ ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2);
+ **
+ ** In FTS3, this is an error. It is an error to specify non-NULL values
+ ** for both docid and some other rowid alias.
+ */
+ if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){
+ if( SQLITE_NULL==sqlite3_value_type(apVal[0])
+ && SQLITE_NULL!=sqlite3_value_type(apVal[1])
+ ){
+ /* A rowid/docid conflict. */
+ return SQLITE_ERROR;
+ }
+ rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+
+ /* Execute the statement to insert the record. Set *piDocid to the
+ ** new docid value.
+ */
+ sqlite3_step(pContentInsert);
+ rc = sqlite3_reset(pContentInsert);
+
+ *piDocid = sqlite3_last_insert_rowid(p->db);
+ return rc;
+}
+
+
+
+/*
+** Remove all data from the FTS3 table. Clear the hash table containing
+** pending terms.
+*/
+static int fts3DeleteAll(Fts3Table *p, int bContent){
+ int rc = SQLITE_OK; /* Return code */
+
+ /* Discard the contents of the pending-terms hash table. */
+ sqlite3Fts3PendingTermsClear(p);
+
+ /* Delete everything from the shadow tables. Except, leave %_content as
+ ** is if bContent is false. */
+ assert( p->zContentTbl==0 || bContent==0 );
+ if( bContent ) fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0);
+ fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0);
+ fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
+ if( p->bHasDocsize ){
+ fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0);
+ }
+ if( p->bHasStat ){
+ fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
+ }
+ return rc;
+}
+
+/*
+**
+*/
+static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){
+ int iLangid = 0;
+ if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1);
+ return iLangid;
+}
+
+/*
+** The first element in the apVal[] array is assumed to contain the docid
+** (an integer) of a row about to be deleted. Remove all terms from the
+** full-text index.
+*/
+static void fts3DeleteTerms(
+ int *pRC, /* Result code */
+ Fts3Table *p, /* The FTS table to delete from */
+ sqlite3_value *pRowid, /* The docid to be deleted */
+ u32 *aSz, /* Sizes of deleted document written here */
+ int *pbFound /* OUT: Set to true if row really does exist */
+){
+ int rc;
+ sqlite3_stmt *pSelect;
+
+ assert( *pbFound==0 );
+ if( *pRC ) return;
+ rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
+ if( rc==SQLITE_OK ){
+ if( SQLITE_ROW==sqlite3_step(pSelect) ){
+ int i;
+ int iLangid = langidFromSelect(p, pSelect);
+ rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
+ for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
+ const char *zText = (const char *)sqlite3_column_text(pSelect, i);
+ rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
+ aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3_reset(pSelect);
+ *pRC = rc;
+ return;
+ }
+ *pbFound = 1;
+ }
+ rc = sqlite3_reset(pSelect);
+ }else{
+ sqlite3_reset(pSelect);
+ }
+ *pRC = rc;
+}
+
+/*
+** Forward declaration to account for the circular dependency between
+** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
+*/
+static int fts3SegmentMerge(Fts3Table *, int, int, int);
+
+/*
+** This function allocates a new level iLevel index in the segdir table.
+** Usually, indexes are allocated within a level sequentially starting
+** with 0, so the allocated index is one greater than the value returned
+** by:
+**
+** SELECT max(idx) FROM %_segdir WHERE level = :iLevel
+**
+** However, if there are already FTS3_MERGE_COUNT indexes at the requested
+** level, they are merged into a single level (iLevel+1) segment and the
+** allocated index is 0.
+**
+** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
+** returned. Otherwise, an SQLite error code is returned.
+*/
+static int fts3AllocateSegdirIdx(
+ Fts3Table *p,
+ int iLangid, /* Language id */
+ int iIndex, /* Index for p->aIndex */
+ int iLevel,
+ int *piIdx
+){
+ int rc; /* Return Code */
+ sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */
+ int iNext = 0; /* Result of query pNextIdx */
+
+ assert( iLangid>=0 );
+ assert( p->nIndex>=1 );
+
+ /* Set variable iNext to the next available segdir index at level iLevel. */
+ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(
+ pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
+ );
+ if( SQLITE_ROW==sqlite3_step(pNextIdx) ){
+ iNext = sqlite3_column_int(pNextIdx, 0);
+ }
+ rc = sqlite3_reset(pNextIdx);
+ }
+
+ if( rc==SQLITE_OK ){
+ /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already
+ ** full, merge all segments in level iLevel into a single iLevel+1
+ ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
+ ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
+ */
+ if( iNext>=FTS3_MERGE_COUNT ){
+ fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
+ rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
+ *piIdx = 0;
+ }else{
+ *piIdx = iNext;
+ }
+ }
+
+ return rc;
+}
+
+/*
+** The %_segments table is declared as follows:
+**
+** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB)
+**
+** This function reads data from a single row of the %_segments table. The
+** specific row is identified by the iBlockid parameter. If paBlob is not
+** NULL, then a buffer is allocated using sqlite3_malloc() and populated
+** with the contents of the blob stored in the "block" column of the
+** identified table row is. Whether or not paBlob is NULL, *pnBlob is set
+** to the size of the blob in bytes before returning.
+**
+** If an error occurs, or the table does not contain the specified row,
+** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If
+** paBlob is non-NULL, then it is the responsibility of the caller to
+** eventually free the returned buffer.
+**
+** This function may leave an open sqlite3_blob* handle in the
+** Fts3Table.pSegments variable. This handle is reused by subsequent calls
+** to this function. The handle may be closed by calling the
+** sqlite3Fts3SegmentsClose() function. Reusing a blob handle is a handy
+** performance improvement, but the blob handle should always be closed
+** before control is returned to the user (to prevent a lock being held
+** on the database file for longer than necessary). Thus, any virtual table
+** method (xFilter etc.) that may directly or indirectly call this function
+** must call sqlite3Fts3SegmentsClose() before returning.
+*/
+SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
+ Fts3Table *p, /* FTS3 table handle */
+ sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */
+ char **paBlob, /* OUT: Blob data in malloc'd buffer */
+ int *pnBlob, /* OUT: Size of blob data */
+ int *pnLoad /* OUT: Bytes actually loaded */
+){
+ int rc; /* Return code */
+
+ /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */
+ assert( pnBlob );
+
+ if( p->pSegments ){
+ rc = sqlite3_blob_reopen(p->pSegments, iBlockid);
+ }else{
+ if( 0==p->zSegmentsTbl ){
+ p->zSegmentsTbl = sqlite3_mprintf("%s_segments", p->zName);
+ if( 0==p->zSegmentsTbl ) return SQLITE_NOMEM;
+ }
+ rc = sqlite3_blob_open(
+ p->db, p->zDb, p->zSegmentsTbl, "block", iBlockid, 0, &p->pSegments
+ );
+ }
+
+ if( rc==SQLITE_OK ){
+ int nByte = sqlite3_blob_bytes(p->pSegments);
+ *pnBlob = nByte;
+ if( paBlob ){
+ char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
+ if( !aByte ){
+ rc = SQLITE_NOMEM;
+ }else{
+ if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){
+ nByte = FTS3_NODE_CHUNKSIZE;
+ *pnLoad = nByte;
+ }
+ rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0);
+ memset(&aByte[nByte], 0, FTS3_NODE_PADDING);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(aByte);
+ aByte = 0;
+ }
+ }
+ *paBlob = aByte;
+ }
+ }
+
+ return rc;
+}
+
+/*
+** Close the blob handle at p->pSegments, if it is open. See comments above
+** the sqlite3Fts3ReadBlock() function for details.
+*/
+SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){
+ sqlite3_blob_close(p->pSegments);
+ p->pSegments = 0;
+}
+
+static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
+ int nRead; /* Number of bytes to read */
+ int rc; /* Return code */
+
+ nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
+ rc = sqlite3_blob_read(
+ pReader->pBlob,
+ &pReader->aNode[pReader->nPopulate],
+ nRead,
+ pReader->nPopulate
+ );
+
+ if( rc==SQLITE_OK ){
+ pReader->nPopulate += nRead;
+ memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING);
+ if( pReader->nPopulate==pReader->nNode ){
+ sqlite3_blob_close(pReader->pBlob);
+ pReader->pBlob = 0;
+ pReader->nPopulate = 0;
+ }
+ }
+ return rc;
+}
+
+static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
+ int rc = SQLITE_OK;
+ assert( !pReader->pBlob
+ || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
+ );
+ while( pReader->pBlob && rc==SQLITE_OK
+ && (pFrom - pReader->aNode + nByte)>pReader->nPopulate
+ ){
+ rc = fts3SegReaderIncrRead(pReader);
+ }
+ return rc;
+}
+
+/*
+** Set an Fts3SegReader cursor to point at EOF.
+*/
+static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
+ if( !fts3SegReaderIsRootOnly(pSeg) ){
+ sqlite3_free(pSeg->aNode);
+ sqlite3_blob_close(pSeg->pBlob);
+ pSeg->pBlob = 0;
+ }
+ pSeg->aNode = 0;
+}
+
+/*
+** Move the iterator passed as the first argument to the next term in the
+** segment. If successful, SQLITE_OK is returned. If there is no next term,
+** SQLITE_DONE. Otherwise, an SQLite error code.
+*/
+static int fts3SegReaderNext(
+ Fts3Table *p,
+ Fts3SegReader *pReader,
+ int bIncr
+){
+ int rc; /* Return code of various sub-routines */
+ char *pNext; /* Cursor variable */
+ int nPrefix; /* Number of bytes in term prefix */
+ int nSuffix; /* Number of bytes in term suffix */
+
+ if( !pReader->aDoclist ){
+ pNext = pReader->aNode;
+ }else{
+ pNext = &pReader->aDoclist[pReader->nDoclist];
+ }
+
+ if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
+
+ if( fts3SegReaderIsPending(pReader) ){
+ Fts3HashElem *pElem = *(pReader->ppNextElem);
+ if( pElem==0 ){
+ pReader->aNode = 0;
+ }else{
+ PendingList *pList = (PendingList *)fts3HashData(pElem);
+ pReader->zTerm = (char *)fts3HashKey(pElem);
+ pReader->nTerm = fts3HashKeysize(pElem);
+ pReader->nNode = pReader->nDoclist = pList->nData + 1;
+ pReader->aNode = pReader->aDoclist = pList->aData;
+ pReader->ppNextElem++;
+ assert( pReader->aNode );
+ }
+ return SQLITE_OK;
+ }
+
+ fts3SegReaderSetEof(pReader);
+
+ /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
+ ** blocks have already been traversed. */
+ assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
+ if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
+ return SQLITE_OK;
+ }
+
+ rc = sqlite3Fts3ReadBlock(
+ p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
+ (bIncr ? &pReader->nPopulate : 0)
+ );
+ if( rc!=SQLITE_OK ) return rc;
+ assert( pReader->pBlob==0 );
+ if( bIncr && pReader->nPopulate<pReader->nNode ){
+ pReader->pBlob = p->pSegments;
+ p->pSegments = 0;
+ }
+ pNext = pReader->aNode;
+ }
+
+ assert( !fts3SegReaderIsPending(pReader) );
+
+ rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
+ ** safe (no risk of overread) even if the node data is corrupted. */
+ pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
+ pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
+ if( nPrefix<0 || nSuffix<=0
+ || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
+ ){
+ return FTS_CORRUPT_VTAB;
+ }
+
+ if( nPrefix+nSuffix>pReader->nTermAlloc ){
+ int nNew = (nPrefix+nSuffix)*2;
+ char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
+ if( !zNew ){
+ return SQLITE_NOMEM;
+ }
+ pReader->zTerm = zNew;
+ pReader->nTermAlloc = nNew;
+ }
+
+ rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX);
+ if( rc!=SQLITE_OK ) return rc;
+
+ memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
+ pReader->nTerm = nPrefix+nSuffix;
+ pNext += nSuffix;
+ pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
+ pReader->aDoclist = pNext;
+ pReader->pOffsetList = 0;
+
+ /* Check that the doclist does not appear to extend past the end of the
+ ** b-tree node. And that the final byte of the doclist is 0x00. If either
+ ** of these statements is untrue, then the data structure is corrupt.
+ */
+ if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
+ || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
+ ){
+ return FTS_CORRUPT_VTAB;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Set the SegReader to point to the first docid in the doclist associated
+** with the current term.
+*/
+static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){
+ int rc = SQLITE_OK;
+ assert( pReader->aDoclist );
+ assert( !pReader->pOffsetList );
+ if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
+ u8 bEof = 0;
+ pReader->iDocid = 0;
+ pReader->nOffsetList = 0;
+ sqlite3Fts3DoclistPrev(0,
+ pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
+ &pReader->iDocid, &pReader->nOffsetList, &bEof
+ );
+ }else{
+ rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX);
+ if( rc==SQLITE_OK ){
+ int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid);
+ pReader->pOffsetList = &pReader->aDoclist[n];
+ }
+ }
+ return rc;
+}
+
+/*
+** Advance the SegReader to point to the next docid in the doclist
+** associated with the current term.
+**
+** If arguments ppOffsetList and pnOffsetList are not NULL, then
+** *ppOffsetList is set to point to the first column-offset list
+** in the doclist entry (i.e. immediately past the docid varint).
+** *pnOffsetList is set to the length of the set of column-offset
+** lists, not including the nul-terminator byte. For example:
+*/
+static int fts3SegReaderNextDocid(
+ Fts3Table *pTab,
+ Fts3SegReader *pReader, /* Reader to advance to next docid */
+ char **ppOffsetList, /* OUT: Pointer to current position-list */
+ int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */
+){
+ int rc = SQLITE_OK;
+ char *p = pReader->pOffsetList;
+ char c = 0;
+
+ assert( p );
+
+ if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){
+ /* A pending-terms seg-reader for an FTS4 table that uses order=desc.
+ ** Pending-terms doclists are always built up in ascending order, so
+ ** we have to iterate through them backwards here. */
+ u8 bEof = 0;
+ if( ppOffsetList ){
+ *ppOffsetList = pReader->pOffsetList;
+ *pnOffsetList = pReader->nOffsetList - 1;
+ }
+ sqlite3Fts3DoclistPrev(0,
+ pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid,
+ &pReader->nOffsetList, &bEof
+ );
+ if( bEof ){
+ pReader->pOffsetList = 0;
+ }else{
+ pReader->pOffsetList = p;
+ }
+ }else{
+ char *pEnd = &pReader->aDoclist[pReader->nDoclist];
+
+ /* Pointer p currently points at the first byte of an offset list. The
+ ** following block advances it to point one byte past the end of
+ ** the same offset list. */
+ while( 1 ){
+
+ /* The following line of code (and the "p++" below the while() loop) is
+ ** normally all that is required to move pointer p to the desired
+ ** position. The exception is if this node is being loaded from disk
+ ** incrementally and pointer "p" now points to the first byte passed
+ ** the populated part of pReader->aNode[].
+ */
+ while( *p | c ) c = *p++ & 0x80;
+ assert( *p==0 );
+
+ if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
+ rc = fts3SegReaderIncrRead(pReader);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ p++;
+
+ /* If required, populate the output variables with a pointer to and the
+ ** size of the previous offset-list.
+ */
+ if( ppOffsetList ){
+ *ppOffsetList = pReader->pOffsetList;
+ *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
+ }
+
+ /* List may have been edited in place by fts3EvalNearTrim() */
+ while( p<pEnd && *p==0 ) p++;
+
+ /* If there are no more entries in the doclist, set pOffsetList to
+ ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
+ ** Fts3SegReader.pOffsetList to point to the next offset list before
+ ** returning.
+ */
+ if( p>=pEnd ){
+ pReader->pOffsetList = 0;
+ }else{
+ rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
+ if( rc==SQLITE_OK ){
+ sqlite3_int64 iDelta;
+ pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
+ if( pTab->bDescIdx ){
+ pReader->iDocid -= iDelta;
+ }else{
+ pReader->iDocid += iDelta;
+ }
+ }
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+
+SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(
+ Fts3Cursor *pCsr,
+ Fts3MultiSegReader *pMsr,
+ int *pnOvfl
+){
+ Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
+ int nOvfl = 0;
+ int ii;
+ int rc = SQLITE_OK;
+ int pgsz = p->nPgsz;
+
+ assert( p->bFts4 );
+ assert( pgsz>0 );
+
+ for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
+ Fts3SegReader *pReader = pMsr->apSegment[ii];
+ if( !fts3SegReaderIsPending(pReader)
+ && !fts3SegReaderIsRootOnly(pReader)
+ ){
+ sqlite3_int64 jj;
+ for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
+ int nBlob;
+ rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0);
+ if( rc!=SQLITE_OK ) break;
+ if( (nBlob+35)>pgsz ){
+ nOvfl += (nBlob + 34)/pgsz;
+ }
+ }
+ }
+ }
+ *pnOvfl = nOvfl;
+ return rc;
+}
+
+/*
+** Free all allocations associated with the iterator passed as the
+** second argument.
+*/
+SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
+ if( pReader && !fts3SegReaderIsPending(pReader) ){
+ sqlite3_free(pReader->zTerm);
+ if( !fts3SegReaderIsRootOnly(pReader) ){
+ sqlite3_free(pReader->aNode);
+ sqlite3_blob_close(pReader->pBlob);
+ }
+ }
+ sqlite3_free(pReader);
+}
+
+/*
+** Allocate a new SegReader object.
+*/
+SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
+ int iAge, /* Segment "age". */
+ int bLookup, /* True for a lookup only */
+ sqlite3_int64 iStartLeaf, /* First leaf to traverse */
+ sqlite3_int64 iEndLeaf, /* Final leaf to traverse */
+ sqlite3_int64 iEndBlock, /* Final block of segment */
+ const char *zRoot, /* Buffer containing root node */
+ int nRoot, /* Size of buffer containing root node */
+ Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */
+){
+ Fts3SegReader *pReader; /* Newly allocated SegReader object */
+ int nExtra = 0; /* Bytes to allocate segment root node */
+
+ assert( iStartLeaf<=iEndLeaf );
+ if( iStartLeaf==0 ){
+ nExtra = nRoot + FTS3_NODE_PADDING;
+ }
+
+ pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
+ if( !pReader ){
+ return SQLITE_NOMEM;
+ }
+ memset(pReader, 0, sizeof(Fts3SegReader));
+ pReader->iIdx = iAge;
+ pReader->bLookup = bLookup!=0;
+ pReader->iStartBlock = iStartLeaf;
+ pReader->iLeafEndBlock = iEndLeaf;
+ pReader->iEndBlock = iEndBlock;
+
+ if( nExtra ){
+ /* The entire segment is stored in the root node. */
+ pReader->aNode = (char *)&pReader[1];
+ pReader->rootOnly = 1;
+ pReader->nNode = nRoot;
+ memcpy(pReader->aNode, zRoot, nRoot);
+ memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
+ }else{
+ pReader->iCurrentBlock = iStartLeaf-1;
+ }
+ *ppReader = pReader;
+ return SQLITE_OK;
+}
+
+/*
+** This is a comparison function used as a qsort() callback when sorting
+** an array of pending terms by term. This occurs as part of flushing
+** the contents of the pending-terms hash table to the database.
+*/
+static int fts3CompareElemByTerm(const void *lhs, const void *rhs){
+ char *z1 = fts3HashKey(*(Fts3HashElem **)lhs);
+ char *z2 = fts3HashKey(*(Fts3HashElem **)rhs);
+ int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs);
+ int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs);
+
+ int n = (n1<n2 ? n1 : n2);
+ int c = memcmp(z1, z2, n);
+ if( c==0 ){
+ c = n1 - n2;
+ }
+ return c;
+}
+
+/*
+** This function is used to allocate an Fts3SegReader that iterates through
+** a subset of the terms stored in the Fts3Table.pendingTerms array.
+**
+** If the isPrefixIter parameter is zero, then the returned SegReader iterates
+** through each term in the pending-terms table. Or, if isPrefixIter is
+** non-zero, it iterates through each term and its prefixes. For example, if
+** the pending terms hash table contains the terms "sqlite", "mysql" and
+** "firebird", then the iterator visits the following 'terms' (in the order
+** shown):
+**
+** f fi fir fire fireb firebi firebir firebird
+** m my mys mysq mysql
+** s sq sql sqli sqlit sqlite
+**
+** Whereas if isPrefixIter is zero, the terms visited are:
+**
+** firebird mysql sqlite
+*/
+SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
+ Fts3Table *p, /* Virtual table handle */
+ int iIndex, /* Index for p->aIndex */
+ const char *zTerm, /* Term to search for */
+ int nTerm, /* Size of buffer zTerm */
+ int bPrefix, /* True for a prefix iterator */
+ Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */
+){
+ Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */
+ Fts3HashElem *pE; /* Iterator variable */
+ Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */
+ int nElem = 0; /* Size of array at aElem */
+ int rc = SQLITE_OK; /* Return Code */
+ Fts3Hash *pHash;
+
+ pHash = &p->aIndex[iIndex].hPending;
+ if( bPrefix ){
+ int nAlloc = 0; /* Size of allocated array at aElem */
+
+ for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
+ char *zKey = (char *)fts3HashKey(pE);
+ int nKey = fts3HashKeysize(pE);
+ if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){
+ if( nElem==nAlloc ){
+ Fts3HashElem **aElem2;
+ nAlloc += 16;
+ aElem2 = (Fts3HashElem **)sqlite3_realloc(
+ aElem, nAlloc*sizeof(Fts3HashElem *)
+ );
+ if( !aElem2 ){
+ rc = SQLITE_NOMEM;
+ nElem = 0;
+ break;
+ }
+ aElem = aElem2;
+ }
+
+ aElem[nElem++] = pE;
+ }
+ }
+
+ /* If more than one term matches the prefix, sort the Fts3HashElem
+ ** objects in term order using qsort(). This uses the same comparison
+ ** callback as is used when flushing terms to disk.
+ */
+ if( nElem>1 ){
+ qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm);
+ }
+
+ }else{
+ /* The query is a simple term lookup that matches at most one term in
+ ** the index. All that is required is a straight hash-lookup.
+ **
+ ** Because the stack address of pE may be accessed via the aElem pointer
+ ** below, the "Fts3HashElem *pE" must be declared so that it is valid
+ ** within this entire function, not just this "else{...}" block.
+ */
+ pE = fts3HashFindElem(pHash, zTerm, nTerm);
+ if( pE ){
+ aElem = &pE;
+ nElem = 1;
+ }
+ }
+
+ if( nElem>0 ){
+ int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *);
+ pReader = (Fts3SegReader *)sqlite3_malloc(nByte);
+ if( !pReader ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(pReader, 0, nByte);
+ pReader->iIdx = 0x7FFFFFFF;
+ pReader->ppNextElem = (Fts3HashElem **)&pReader[1];
+ memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *));
+ }
+ }
+
+ if( bPrefix ){
+ sqlite3_free(aElem);
+ }
+ *ppReader = pReader;
+ return rc;
+}
+
+/*
+** Compare the entries pointed to by two Fts3SegReader structures.
+** Comparison is as follows:
+**
+** 1) EOF is greater than not EOF.
+**
+** 2) The current terms (if any) are compared using memcmp(). If one
+** term is a prefix of another, the longer term is considered the
+** larger.
+**
+** 3) By segment age. An older segment is considered larger.
+*/
+static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
+ int rc;
+ if( pLhs->aNode && pRhs->aNode ){
+ int rc2 = pLhs->nTerm - pRhs->nTerm;
+ if( rc2<0 ){
+ rc = memcmp(pLhs->zTerm, pRhs->zTerm, pLhs->nTerm);
+ }else{
+ rc = memcmp(pLhs->zTerm, pRhs->zTerm, pRhs->nTerm);
+ }
+ if( rc==0 ){
+ rc = rc2;
+ }
+ }else{
+ rc = (pLhs->aNode==0) - (pRhs->aNode==0);
+ }
+ if( rc==0 ){
+ rc = pRhs->iIdx - pLhs->iIdx;
+ }
+ assert( rc!=0 );
+ return rc;
+}
+
+/*
+** A different comparison function for SegReader structures. In this
+** version, it is assumed that each SegReader points to an entry in
+** a doclist for identical terms. Comparison is made as follows:
+**
+** 1) EOF (end of doclist in this case) is greater than not EOF.
+**
+** 2) By current docid.
+**
+** 3) By segment age. An older segment is considered larger.
+*/
+static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
+ int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
+ if( rc==0 ){
+ if( pLhs->iDocid==pRhs->iDocid ){
+ rc = pRhs->iIdx - pLhs->iIdx;
+ }else{
+ rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1;
+ }
+ }
+ assert( pLhs->aNode && pRhs->aNode );
+ return rc;
+}
+static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
+ int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
+ if( rc==0 ){
+ if( pLhs->iDocid==pRhs->iDocid ){
+ rc = pRhs->iIdx - pLhs->iIdx;
+ }else{
+ rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1;
+ }
+ }
+ assert( pLhs->aNode && pRhs->aNode );
+ return rc;
+}
+
+/*
+** Compare the term that the Fts3SegReader object passed as the first argument
+** points to with the term specified by arguments zTerm and nTerm.
+**
+** If the pSeg iterator is already at EOF, return 0. Otherwise, return
+** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are
+** equal, or +ve if the pSeg term is greater than zTerm/nTerm.
+*/
+static int fts3SegReaderTermCmp(
+ Fts3SegReader *pSeg, /* Segment reader object */
+ const char *zTerm, /* Term to compare to */
+ int nTerm /* Size of term zTerm in bytes */
+){
+ int res = 0;
+ if( pSeg->aNode ){
+ if( pSeg->nTerm>nTerm ){
+ res = memcmp(pSeg->zTerm, zTerm, nTerm);
+ }else{
+ res = memcmp(pSeg->zTerm, zTerm, pSeg->nTerm);
+ }
+ if( res==0 ){
+ res = pSeg->nTerm-nTerm;
+ }
+ }
+ return res;
+}
+
+/*
+** Argument apSegment is an array of nSegment elements. It is known that
+** the final (nSegment-nSuspect) members are already in sorted order
+** (according to the comparison function provided). This function shuffles
+** the array around until all entries are in sorted order.
+*/
+static void fts3SegReaderSort(
+ Fts3SegReader **apSegment, /* Array to sort entries of */
+ int nSegment, /* Size of apSegment array */
+ int nSuspect, /* Unsorted entry count */
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) /* Comparison function */
+){
+ int i; /* Iterator variable */
+
+ assert( nSuspect<=nSegment );
+
+ if( nSuspect==nSegment ) nSuspect--;
+ for(i=nSuspect-1; i>=0; i--){
+ int j;
+ for(j=i; j<(nSegment-1); j++){
+ Fts3SegReader *pTmp;
+ if( xCmp(apSegment[j], apSegment[j+1])<0 ) break;
+ pTmp = apSegment[j+1];
+ apSegment[j+1] = apSegment[j];
+ apSegment[j] = pTmp;
+ }
+ }
+
+#ifndef NDEBUG
+ /* Check that the list really is sorted now. */
+ for(i=0; i<(nSuspect-1); i++){
+ assert( xCmp(apSegment[i], apSegment[i+1])<0 );
+ }
+#endif
+}
+
+/*
+** Insert a record into the %_segments table.
+*/
+static int fts3WriteSegment(
+ Fts3Table *p, /* Virtual table handle */
+ sqlite3_int64 iBlock, /* Block id for new block */
+ char *z, /* Pointer to buffer containing block data */
+ int n /* Size of buffer z in bytes */
+){
+ sqlite3_stmt *pStmt;
+ int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pStmt, 1, iBlock);
+ sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ }
+ return rc;
+}
+
+/*
+** Find the largest relative level number in the table. If successful, set
+** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs,
+** set *pnMax to zero and return an SQLite error code.
+*/
+SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){
+ int rc;
+ int mxLevel = 0;
+ sqlite3_stmt *pStmt = 0;
+
+ rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ mxLevel = sqlite3_column_int(pStmt, 0);
+ }
+ rc = sqlite3_reset(pStmt);
+ }
+ *pnMax = mxLevel;
+ return rc;
+}
+
+/*
+** Insert a record into the %_segdir table.
+*/
+static int fts3WriteSegdir(
+ Fts3Table *p, /* Virtual table handle */
+ sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */
+ int iIdx, /* Value for "idx" field */
+ sqlite3_int64 iStartBlock, /* Value for "start_block" field */
+ sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
+ sqlite3_int64 iEndBlock, /* Value for "end_block" field */
+ char *zRoot, /* Blob value for "root" field */
+ int nRoot /* Number of bytes in buffer zRoot */
+){
+ sqlite3_stmt *pStmt;
+ int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pStmt, 1, iLevel);
+ sqlite3_bind_int(pStmt, 2, iIdx);
+ sqlite3_bind_int64(pStmt, 3, iStartBlock);
+ sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
+ sqlite3_bind_int64(pStmt, 5, iEndBlock);
+ sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ }
+ return rc;
+}
+
+/*
+** Return the size of the common prefix (if any) shared by zPrev and
+** zNext, in bytes. For example,
+**
+** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3
+** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2
+** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0
+*/
+static int fts3PrefixCompress(
+ const char *zPrev, /* Buffer containing previous term */
+ int nPrev, /* Size of buffer zPrev in bytes */
+ const char *zNext, /* Buffer containing next term */
+ int nNext /* Size of buffer zNext in bytes */
+){
+ int n;
+ UNUSED_PARAMETER(nNext);
+ for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
+ return n;
+}
+
+/*
+** Add term zTerm to the SegmentNode. It is guaranteed that zTerm is larger
+** (according to memcmp) than the previous term.
+*/
+static int fts3NodeAddTerm(
+ Fts3Table *p, /* Virtual table handle */
+ SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
+ int isCopyTerm, /* True if zTerm/nTerm is transient */
+ const char *zTerm, /* Pointer to buffer containing term */
+ int nTerm /* Size of term in bytes */
+){
+ SegmentNode *pTree = *ppTree;
+ int rc;
+ SegmentNode *pNew;
+
+ /* First try to append the term to the current node. Return early if
+ ** this is possible.
+ */
+ if( pTree ){
+ int nData = pTree->nData; /* Current size of node in bytes */
+ int nReq = nData; /* Required space after adding zTerm */
+ int nPrefix; /* Number of bytes of prefix compression */
+ int nSuffix; /* Suffix length */
+
+ nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
+ nSuffix = nTerm-nPrefix;
+
+ nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
+ if( nReq<=p->nNodeSize || !pTree->zTerm ){
+
+ if( nReq>p->nNodeSize ){
+ /* An unusual case: this is the first term to be added to the node
+ ** and the static node buffer (p->nNodeSize bytes) is not large
+ ** enough. Use a separately malloced buffer instead This wastes
+ ** p->nNodeSize bytes, but since this scenario only comes about when
+ ** the database contain two terms that share a prefix of almost 2KB,
+ ** this is not expected to be a serious problem.
+ */
+ assert( pTree->aData==(char *)&pTree[1] );
+ pTree->aData = (char *)sqlite3_malloc(nReq);
+ if( !pTree->aData ){
+ return SQLITE_NOMEM;
+ }
+ }
+
+ if( pTree->zTerm ){
+ /* There is no prefix-length field for first term in a node */
+ nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nPrefix);
+ }
+
+ nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nSuffix);
+ memcpy(&pTree->aData[nData], &zTerm[nPrefix], nSuffix);
+ pTree->nData = nData + nSuffix;
+ pTree->nEntry++;
+
+ if( isCopyTerm ){
+ if( pTree->nMalloc<nTerm ){
+ char *zNew = sqlite3_realloc(pTree->zMalloc, nTerm*2);
+ if( !zNew ){
+ return SQLITE_NOMEM;
+ }
+ pTree->nMalloc = nTerm*2;
+ pTree->zMalloc = zNew;
+ }
+ pTree->zTerm = pTree->zMalloc;
+ memcpy(pTree->zTerm, zTerm, nTerm);
+ pTree->nTerm = nTerm;
+ }else{
+ pTree->zTerm = (char *)zTerm;
+ pTree->nTerm = nTerm;
+ }
+ return SQLITE_OK;
+ }
+ }
+
+ /* If control flows to here, it was not possible to append zTerm to the
+ ** current node. Create a new node (a right-sibling of the current node).
+ ** If this is the first node in the tree, the term is added to it.
+ **
+ ** Otherwise, the term is not added to the new node, it is left empty for
+ ** now. Instead, the term is inserted into the parent of pTree. If pTree
+ ** has no parent, one is created here.
+ */
+ pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
+ if( !pNew ){
+ return SQLITE_NOMEM;
+ }
+ memset(pNew, 0, sizeof(SegmentNode));
+ pNew->nData = 1 + FTS3_VARINT_MAX;
+ pNew->aData = (char *)&pNew[1];
+
+ if( pTree ){
+ SegmentNode *pParent = pTree->pParent;
+ rc = fts3NodeAddTerm(p, &pParent, isCopyTerm, zTerm, nTerm);
+ if( pTree->pParent==0 ){
+ pTree->pParent = pParent;
+ }
+ pTree->pRight = pNew;
+ pNew->pLeftmost = pTree->pLeftmost;
+ pNew->pParent = pParent;
+ pNew->zMalloc = pTree->zMalloc;
+ pNew->nMalloc = pTree->nMalloc;
+ pTree->zMalloc = 0;
+ }else{
+ pNew->pLeftmost = pNew;
+ rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
+ }
+
+ *ppTree = pNew;
+ return rc;
+}
+
+/*
+** Helper function for fts3NodeWrite().
+*/
+static int fts3TreeFinishNode(
+ SegmentNode *pTree,
+ int iHeight,
+ sqlite3_int64 iLeftChild
+){
+ int nStart;
+ assert( iHeight>=1 && iHeight<128 );
+ nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild);
+ pTree->aData[nStart] = (char)iHeight;
+ sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild);
+ return nStart;
+}
+
+/*
+** Write the buffer for the segment node pTree and all of its peers to the
+** database. Then call this function recursively to write the parent of
+** pTree and its peers to the database.
+**
+** Except, if pTree is a root node, do not write it to the database. Instead,
+** set output variables *paRoot and *pnRoot to contain the root node.
+**
+** If successful, SQLITE_OK is returned and output variable *piLast is
+** set to the largest blockid written to the database (or zero if no
+** blocks were written to the db). Otherwise, an SQLite error code is
+** returned.
+*/
+static int fts3NodeWrite(
+ Fts3Table *p, /* Virtual table handle */
+ SegmentNode *pTree, /* SegmentNode handle */
+ int iHeight, /* Height of this node in tree */
+ sqlite3_int64 iLeaf, /* Block id of first leaf node */
+ sqlite3_int64 iFree, /* Block id of next free slot in %_segments */
+ sqlite3_int64 *piLast, /* OUT: Block id of last entry written */
+ char **paRoot, /* OUT: Data for root node */
+ int *pnRoot /* OUT: Size of root node in bytes */
+){
+ int rc = SQLITE_OK;
+
+ if( !pTree->pParent ){
+ /* Root node of the tree. */
+ int nStart = fts3TreeFinishNode(pTree, iHeight, iLeaf);
+ *piLast = iFree-1;
+ *pnRoot = pTree->nData - nStart;
+ *paRoot = &pTree->aData[nStart];
+ }else{
+ SegmentNode *pIter;
+ sqlite3_int64 iNextFree = iFree;
+ sqlite3_int64 iNextLeaf = iLeaf;
+ for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){
+ int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf);
+ int nWrite = pIter->nData - nStart;
+
+ rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite);
+ iNextFree++;
+ iNextLeaf += (pIter->nEntry+1);
+ }
+ if( rc==SQLITE_OK ){
+ assert( iNextLeaf==iFree );
+ rc = fts3NodeWrite(
+ p, pTree->pParent, iHeight+1, iFree, iNextFree, piLast, paRoot, pnRoot
+ );
+ }
+ }
+
+ return rc;
+}
+
+/*
+** Free all memory allocations associated with the tree pTree.
+*/
+static void fts3NodeFree(SegmentNode *pTree){
+ if( pTree ){
+ SegmentNode *p = pTree->pLeftmost;
+ fts3NodeFree(p->pParent);
+ while( p ){
+ SegmentNode *pRight = p->pRight;
+ if( p->aData!=(char *)&p[1] ){
+ sqlite3_free(p->aData);
+ }
+ assert( pRight==0 || p->zMalloc==0 );
+ sqlite3_free(p->zMalloc);
+ sqlite3_free(p);
+ p = pRight;
+ }
+ }
+}
+
+/*
+** Add a term to the segment being constructed by the SegmentWriter object
+** *ppWriter. When adding the first term to a segment, *ppWriter should
+** be passed NULL. This function will allocate a new SegmentWriter object
+** and return it via the input/output variable *ppWriter in this case.
+**
+** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
+*/
+static int fts3SegWriterAdd(
+ Fts3Table *p, /* Virtual table handle */
+ SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
+ int isCopyTerm, /* True if buffer zTerm must be copied */
+ const char *zTerm, /* Pointer to buffer containing term */
+ int nTerm, /* Size of term in bytes */
+ const char *aDoclist, /* Pointer to buffer containing doclist */
+ int nDoclist /* Size of doclist in bytes */
+){
+ int nPrefix; /* Size of term prefix in bytes */
+ int nSuffix; /* Size of term suffix in bytes */
+ int nReq; /* Number of bytes required on leaf page */
+ int nData;
+ SegmentWriter *pWriter = *ppWriter;
+
+ if( !pWriter ){
+ int rc;
+ sqlite3_stmt *pStmt;
+
+ /* Allocate the SegmentWriter structure */
+ pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter));
+ if( !pWriter ) return SQLITE_NOMEM;
+ memset(pWriter, 0, sizeof(SegmentWriter));
+ *ppWriter = pWriter;
+
+ /* Allocate a buffer in which to accumulate data */
+ pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize);
+ if( !pWriter->aData ) return SQLITE_NOMEM;
+ pWriter->nSize = p->nNodeSize;
+
+ /* Find the next free blockid in the %_segments table */
+ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0);
+ if( rc!=SQLITE_OK ) return rc;
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ pWriter->iFree = sqlite3_column_int64(pStmt, 0);
+ pWriter->iFirst = pWriter->iFree;
+ }
+ rc = sqlite3_reset(pStmt);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ nData = pWriter->nData;
+
+ nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
+ nSuffix = nTerm-nPrefix;
+
+ /* Figure out how many bytes are required by this new entry */
+ nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
+ sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
+ nSuffix + /* Term suffix */
+ sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */
+ nDoclist; /* Doclist data */
+
+ if( nData>0 && nData+nReq>p->nNodeSize ){
+ int rc;
+
+ /* The current leaf node is full. Write it out to the database. */
+ rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
+ if( rc!=SQLITE_OK ) return rc;
+ p->nLeafAdd++;
+
+ /* Add the current term to the interior node tree. The term added to
+ ** the interior tree must:
+ **
+ ** a) be greater than the largest term on the leaf node just written
+ ** to the database (still available in pWriter->zTerm), and
+ **
+ ** b) be less than or equal to the term about to be added to the new
+ ** leaf node (zTerm/nTerm).
+ **
+ ** In other words, it must be the prefix of zTerm 1 byte longer than
+ ** the common prefix (if any) of zTerm and pWriter->zTerm.
+ */
+ assert( nPrefix<nTerm );
+ rc = fts3NodeAddTerm(p, &pWriter->pTree, isCopyTerm, zTerm, nPrefix+1);
+ if( rc!=SQLITE_OK ) return rc;
+
+ nData = 0;
+ pWriter->nTerm = 0;
+
+ nPrefix = 0;
+ nSuffix = nTerm;
+ nReq = 1 + /* varint containing prefix size */
+ sqlite3Fts3VarintLen(nTerm) + /* varint containing suffix size */
+ nTerm + /* Term suffix */
+ sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */
+ nDoclist; /* Doclist data */
+ }
+
+ /* If the buffer currently allocated is too small for this entry, realloc
+ ** the buffer to make it large enough.
+ */
+ if( nReq>pWriter->nSize ){
+ char *aNew = sqlite3_realloc(pWriter->aData, nReq);
+ if( !aNew ) return SQLITE_NOMEM;
+ pWriter->aData = aNew;
+ pWriter->nSize = nReq;
+ }
+ assert( nData+nReq<=pWriter->nSize );
+
+ /* Append the prefix-compressed term and doclist to the buffer. */
+ nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
+ nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
+ memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
+ nData += nSuffix;
+ nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
+ memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
+ pWriter->nData = nData + nDoclist;
+
+ /* Save the current term so that it can be used to prefix-compress the next.
+ ** If the isCopyTerm parameter is true, then the buffer pointed to by
+ ** zTerm is transient, so take a copy of the term data. Otherwise, just
+ ** store a copy of the pointer.
+ */
+ if( isCopyTerm ){
+ if( nTerm>pWriter->nMalloc ){
+ char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2);
+ if( !zNew ){
+ return SQLITE_NOMEM;
+ }
+ pWriter->nMalloc = nTerm*2;
+ pWriter->zMalloc = zNew;
+ pWriter->zTerm = zNew;
+ }
+ assert( pWriter->zTerm==pWriter->zMalloc );
+ memcpy(pWriter->zTerm, zTerm, nTerm);
+ }else{
+ pWriter->zTerm = (char *)zTerm;
+ }
+ pWriter->nTerm = nTerm;
+
+ return SQLITE_OK;
+}
+
+/*
+** Flush all data associated with the SegmentWriter object pWriter to the
+** database. This function must be called after all terms have been added
+** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is
+** returned. Otherwise, an SQLite error code.
+*/
+static int fts3SegWriterFlush(
+ Fts3Table *p, /* Virtual table handle */
+ SegmentWriter *pWriter, /* SegmentWriter to flush to the db */
+ sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */
+ int iIdx /* Value for 'idx' column of %_segdir */
+){
+ int rc; /* Return code */
+ if( pWriter->pTree ){
+ sqlite3_int64 iLast = 0; /* Largest block id written to database */
+ sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */
+ char *zRoot = NULL; /* Pointer to buffer containing root node */
+ int nRoot = 0; /* Size of buffer zRoot */
+
+ iLastLeaf = pWriter->iFree;
+ rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData);
+ if( rc==SQLITE_OK ){
+ rc = fts3NodeWrite(p, pWriter->pTree, 1,
+ pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
+ }
+ if( rc==SQLITE_OK ){
+ rc = fts3WriteSegdir(
+ p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot);
+ }
+ }else{
+ /* The entire tree fits on the root node. Write it to the segdir table. */
+ rc = fts3WriteSegdir(
+ p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
+ }
+ p->nLeafAdd++;
+ return rc;
+}
+
+/*
+** Release all memory held by the SegmentWriter object passed as the
+** first argument.
+*/
+static void fts3SegWriterFree(SegmentWriter *pWriter){
+ if( pWriter ){
+ sqlite3_free(pWriter->aData);
+ sqlite3_free(pWriter->zMalloc);
+ fts3NodeFree(pWriter->pTree);
+ sqlite3_free(pWriter);
+ }
+}
+
+/*
+** The first value in the apVal[] array is assumed to contain an integer.
+** This function tests if there exist any documents with docid values that
+** are different from that integer. i.e. if deleting the document with docid
+** pRowid would mean the FTS3 table were empty.
+**
+** If successful, *pisEmpty is set to true if the table is empty except for
+** document pRowid, or false otherwise, and SQLITE_OK is returned. If an
+** error occurs, an SQLite error code is returned.
+*/
+static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){
+ sqlite3_stmt *pStmt;
+ int rc;
+ if( p->zContentTbl ){
+ /* If using the content=xxx option, assume the table is never empty */
+ *pisEmpty = 0;
+ rc = SQLITE_OK;
+ }else{
+ rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid);
+ if( rc==SQLITE_OK ){
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ *pisEmpty = sqlite3_column_int(pStmt, 0);
+ }
+ rc = sqlite3_reset(pStmt);
+ }
+ }
+ return rc;
+}
+
+/*
+** Set *pnMax to the largest segment level in the database for the index
+** iIndex.
+**
+** Segment levels are stored in the 'level' column of the %_segdir table.
+**
+** Return SQLITE_OK if successful, or an SQLite error code if not.
+*/
+static int fts3SegmentMaxLevel(
+ Fts3Table *p,
+ int iLangid,
+ int iIndex,
+ sqlite3_int64 *pnMax
+){
+ sqlite3_stmt *pStmt;
+ int rc;
+ assert( iIndex>=0 && iIndex<p->nIndex );
+
+ /* Set pStmt to the compiled version of:
+ **
+ ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
+ **
+ ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
+ */
+ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
+ if( rc!=SQLITE_OK ) return rc;
+ sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
+ sqlite3_bind_int64(pStmt, 2,
+ getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
+ );
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ *pnMax = sqlite3_column_int64(pStmt, 0);
+ }
+ return sqlite3_reset(pStmt);
+}
+
+/*
+** Delete all entries in the %_segments table associated with the segment
+** opened with seg-reader pSeg. This function does not affect the contents
+** of the %_segdir table.
+*/
+static int fts3DeleteSegment(
+ Fts3Table *p, /* FTS table handle */
+ Fts3SegReader *pSeg /* Segment to delete */
+){
+ int rc = SQLITE_OK; /* Return code */
+ if( pSeg->iStartBlock ){
+ sqlite3_stmt *pDelete; /* SQL statement to delete rows */
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock);
+ sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock);
+ sqlite3_step(pDelete);
+ rc = sqlite3_reset(pDelete);
+ }
+ }
+ return rc;
+}
+
+/*
+** This function is used after merging multiple segments into a single large
+** segment to delete the old, now redundant, segment b-trees. Specifically,
+** it:
+**
+** 1) Deletes all %_segments entries for the segments associated with
+** each of the SegReader objects in the array passed as the third
+** argument, and
+**
+** 2) deletes all %_segdir entries with level iLevel, or all %_segdir
+** entries regardless of level if (iLevel<0).
+**
+** SQLITE_OK is returned if successful, otherwise an SQLite error code.
+*/
+static int fts3DeleteSegdir(
+ Fts3Table *p, /* Virtual table handle */
+ int iLangid, /* Language id */
+ int iIndex, /* Index for p->aIndex */
+ int iLevel, /* Level of %_segdir entries to delete */
+ Fts3SegReader **apSegment, /* Array of SegReader objects */
+ int nReader /* Size of array apSegment */
+){
+ int rc = SQLITE_OK; /* Return Code */
+ int i; /* Iterator variable */
+ sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */
+
+ for(i=0; rc==SQLITE_OK && i<nReader; i++){
+ rc = fts3DeleteSegment(p, apSegment[i]);
+ }
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ assert( iLevel>=0 || iLevel==FTS3_SEGCURSOR_ALL );
+ if( iLevel==FTS3_SEGCURSOR_ALL ){
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
+ sqlite3_bind_int64(pDelete, 2,
+ getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
+ );
+ }
+ }else{
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(
+ pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel)
+ );
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ sqlite3_step(pDelete);
+ rc = sqlite3_reset(pDelete);
+ }
+
+ return rc;
+}
+
+/*
+** When this function is called, buffer *ppList (size *pnList bytes) contains
+** a position list that may (or may not) feature multiple columns. This
+** function adjusts the pointer *ppList and the length *pnList so that they
+** identify the subset of the position list that corresponds to column iCol.
+**
+** If there are no entries in the input position list for column iCol, then
+** *pnList is set to zero before returning.
+**
+** If parameter bZero is non-zero, then any part of the input list following
+** the end of the output list is zeroed before returning.
+*/
+static void fts3ColumnFilter(
+ int iCol, /* Column to filter on */
+ int bZero, /* Zero out anything following *ppList */
+ char **ppList, /* IN/OUT: Pointer to position list */
+ int *pnList /* IN/OUT: Size of buffer *ppList in bytes */
+){
+ char *pList = *ppList;
+ int nList = *pnList;
+ char *pEnd = &pList[nList];
+ int iCurrent = 0;
+ char *p = pList;
+
+ assert( iCol>=0 );
+ while( 1 ){
+ char c = 0;
+ while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80;
+
+ if( iCol==iCurrent ){
+ nList = (int)(p - pList);
+ break;
+ }
+
+ nList -= (int)(p - pList);
+ pList = p;
+ if( nList==0 ){
+ break;
+ }
+ p = &pList[1];
+ p += sqlite3Fts3GetVarint32(p, &iCurrent);
+ }
+
+ if( bZero && &pList[nList]!=pEnd ){
+ memset(&pList[nList], 0, pEnd - &pList[nList]);
+ }
+ *ppList = pList;
+ *pnList = nList;
+}
+
+/*
+** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
+** existing data). Grow the buffer if required.
+**
+** If successful, return SQLITE_OK. Otherwise, if an OOM error is encountered
+** trying to resize the buffer, return SQLITE_NOMEM.
+*/
+static int fts3MsrBufferData(
+ Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
+ char *pList,
+ int nList
+){
+ if( nList>pMsr->nBuffer ){
+ char *pNew;
+ pMsr->nBuffer = nList*2;
+ pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
+ if( !pNew ) return SQLITE_NOMEM;
+ pMsr->aBuffer = pNew;
+ }
+
+ memcpy(pMsr->aBuffer, pList, nList);
+ return SQLITE_OK;
+}
+
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
+ Fts3Table *p, /* Virtual table handle */
+ Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
+ sqlite3_int64 *piDocid, /* OUT: Docid value */
+ char **paPoslist, /* OUT: Pointer to position list */
+ int *pnPoslist /* OUT: Size of position list in bytes */
+){
+ int nMerge = pMsr->nAdvance;
+ Fts3SegReader **apSegment = pMsr->apSegment;
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
+ p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
+ );
+
+ if( nMerge==0 ){
+ *paPoslist = 0;
+ return SQLITE_OK;
+ }
+
+ while( 1 ){
+ Fts3SegReader *pSeg;
+ pSeg = pMsr->apSegment[0];
+
+ if( pSeg->pOffsetList==0 ){
+ *paPoslist = 0;
+ break;
+ }else{
+ int rc;
+ char *pList;
+ int nList;
+ int j;
+ sqlite3_int64 iDocid = apSegment[0]->iDocid;
+
+ rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
+ j = 1;
+ while( rc==SQLITE_OK
+ && j<nMerge
+ && apSegment[j]->pOffsetList
+ && apSegment[j]->iDocid==iDocid
+ ){
+ rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
+ j++;
+ }
+ if( rc!=SQLITE_OK ) return rc;
+ fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
+
+ if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
+ rc = fts3MsrBufferData(pMsr, pList, nList+1);
+ if( rc!=SQLITE_OK ) return rc;
+ assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
+ pList = pMsr->aBuffer;
+ }
+
+ if( pMsr->iColFilter>=0 ){
+ fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
+ }
+
+ if( nList>0 ){
+ *paPoslist = pList;
+ *piDocid = iDocid;
+ *pnPoslist = nList;
+ break;
+ }
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+static int fts3SegReaderStart(
+ Fts3Table *p, /* Virtual table handle */
+ Fts3MultiSegReader *pCsr, /* Cursor object */
+ const char *zTerm, /* Term searched for (or NULL) */
+ int nTerm /* Length of zTerm in bytes */
+){
+ int i;
+ int nSeg = pCsr->nSegment;
+
+ /* If the Fts3SegFilter defines a specific term (or term prefix) to search
+ ** for, then advance each segment iterator until it points to a term of
+ ** equal or greater value than the specified term. This prevents many
+ ** unnecessary merge/sort operations for the case where single segment
+ ** b-tree leaf nodes contain more than one term.
+ */
+ for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
+ int res = 0;
+ Fts3SegReader *pSeg = pCsr->apSegment[i];
+ do {
+ int rc = fts3SegReaderNext(p, pSeg, 0);
+ if( rc!=SQLITE_OK ) return rc;
+ }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 );
+
+ if( pSeg->bLookup && res!=0 ){
+ fts3SegReaderSetEof(pSeg);
+ }
+ }
+ fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
+
+ return SQLITE_OK;
+}
+
+SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(
+ Fts3Table *p, /* Virtual table handle */
+ Fts3MultiSegReader *pCsr, /* Cursor object */
+ Fts3SegFilter *pFilter /* Restrictions on range of iteration */
+){
+ pCsr->pFilter = pFilter;
+ return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm);
+}
+
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
+ Fts3Table *p, /* Virtual table handle */
+ Fts3MultiSegReader *pCsr, /* Cursor object */
+ int iCol, /* Column to match on. */
+ const char *zTerm, /* Term to iterate through a doclist for */
+ int nTerm /* Number of bytes in zTerm */
+){
+ int i;
+ int rc;
+ int nSegment = pCsr->nSegment;
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
+ p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
+ );
+
+ assert( pCsr->pFilter==0 );
+ assert( zTerm && nTerm>0 );
+
+ /* Advance each segment iterator until it points to the term zTerm/nTerm. */
+ rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm);
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* Determine how many of the segments actually point to zTerm/nTerm. */
+ for(i=0; i<nSegment; i++){
+ Fts3SegReader *pSeg = pCsr->apSegment[i];
+ if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){
+ break;
+ }
+ }
+ pCsr->nAdvance = i;
+
+ /* Advance each of the segments to point to the first docid. */
+ for(i=0; i<pCsr->nAdvance; i++){
+ rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ fts3SegReaderSort(pCsr->apSegment, i, i, xCmp);
+
+ assert( iCol<0 || iCol<p->nColumn );
+ pCsr->iColFilter = iCol;
+
+ return SQLITE_OK;
+}
+
+/*
+** This function is called on a MultiSegReader that has been started using
+** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also
+** have been made. Calling this function puts the MultiSegReader in such
+** a state that if the next two calls are:
+**
+** sqlite3Fts3SegReaderStart()
+** sqlite3Fts3SegReaderStep()
+**
+** then the entire doclist for the term is available in
+** MultiSegReader.aDoclist/nDoclist.
+*/
+SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
+ int i; /* Used to iterate through segment-readers */
+
+ assert( pCsr->zTerm==0 );
+ assert( pCsr->nTerm==0 );
+ assert( pCsr->aDoclist==0 );
+ assert( pCsr->nDoclist==0 );
+
+ pCsr->nAdvance = 0;
+ pCsr->bRestart = 1;
+ for(i=0; i<pCsr->nSegment; i++){
+ pCsr->apSegment[i]->pOffsetList = 0;
+ pCsr->apSegment[i]->nOffsetList = 0;
+ pCsr->apSegment[i]->iDocid = 0;
+ }
+
+ return SQLITE_OK;
+}
+
+
+SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
+ Fts3Table *p, /* Virtual table handle */
+ Fts3MultiSegReader *pCsr /* Cursor object */
+){
+ int rc = SQLITE_OK;
+
+ int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY);
+ int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS);
+ int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER);
+ int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX);
+ int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN);
+ int isFirst = (pCsr->pFilter->flags & FTS3_SEGMENT_FIRST);
+
+ Fts3SegReader **apSegment = pCsr->apSegment;
+ int nSegment = pCsr->nSegment;
+ Fts3SegFilter *pFilter = pCsr->pFilter;
+ int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = (
+ p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp
+ );
+
+ if( pCsr->nSegment==0 ) return SQLITE_OK;
+
+ do {
+ int nMerge;
+ int i;
+
+ /* Advance the first pCsr->nAdvance entries in the apSegment[] array
+ ** forward. Then sort the list in order of current term again.
+ */
+ for(i=0; i<pCsr->nAdvance; i++){
+ Fts3SegReader *pSeg = apSegment[i];
+ if( pSeg->bLookup ){
+ fts3SegReaderSetEof(pSeg);
+ }else{
+ rc = fts3SegReaderNext(p, pSeg, 0);
+ }
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
+ pCsr->nAdvance = 0;
+
+ /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */
+ assert( rc==SQLITE_OK );
+ if( apSegment[0]->aNode==0 ) break;
+
+ pCsr->nTerm = apSegment[0]->nTerm;
+ pCsr->zTerm = apSegment[0]->zTerm;
+
+ /* If this is a prefix-search, and if the term that apSegment[0] points
+ ** to does not share a suffix with pFilter->zTerm/nTerm, then all
+ ** required callbacks have been made. In this case exit early.
+ **
+ ** Similarly, if this is a search for an exact match, and the first term
+ ** of segment apSegment[0] is not a match, exit early.
+ */
+ if( pFilter->zTerm && !isScan ){
+ if( pCsr->nTerm<pFilter->nTerm
+ || (!isPrefix && pCsr->nTerm>pFilter->nTerm)
+ || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm)
+ ){
+ break;
+ }
+ }
+
+ nMerge = 1;
+ while( nMerge<nSegment
+ && apSegment[nMerge]->aNode
+ && apSegment[nMerge]->nTerm==pCsr->nTerm
+ && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm)
+ ){
+ nMerge++;
+ }
+
+ assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
+ if( nMerge==1
+ && !isIgnoreEmpty
+ && !isFirst
+ && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
+ ){
+ pCsr->nDoclist = apSegment[0]->nDoclist;
+ if( fts3SegReaderIsPending(apSegment[0]) ){
+ rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
+ pCsr->aDoclist = pCsr->aBuffer;
+ }else{
+ pCsr->aDoclist = apSegment[0]->aDoclist;
+ }
+ if( rc==SQLITE_OK ) rc = SQLITE_ROW;
+ }else{
+ int nDoclist = 0; /* Size of doclist */
+ sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */
+
+ /* The current term of the first nMerge entries in the array
+ ** of Fts3SegReader objects is the same. The doclists must be merged
+ ** and a single term returned with the merged doclist.
+ */
+ for(i=0; i<nMerge; i++){
+ fts3SegReaderFirstDocid(p, apSegment[i]);
+ }
+ fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
+ while( apSegment[0]->pOffsetList ){
+ int j; /* Number of segments that share a docid */
+ char *pList;
+ int nList;
+ int nByte;
+ sqlite3_int64 iDocid = apSegment[0]->iDocid;
+ fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
+ j = 1;
+ while( j<nMerge
+ && apSegment[j]->pOffsetList
+ && apSegment[j]->iDocid==iDocid
+ ){
+ fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
+ j++;
+ }
+
+ if( isColFilter ){
+ fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
+ }
+
+ if( !isIgnoreEmpty || nList>0 ){
+
+ /* Calculate the 'docid' delta value to write into the merged
+ ** doclist. */
+ sqlite3_int64 iDelta;
+ if( p->bDescIdx && nDoclist>0 ){
+ iDelta = iPrev - iDocid;
+ }else{
+ iDelta = iDocid - iPrev;
+ }
+ assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
+ assert( nDoclist>0 || iDelta==iDocid );
+
+ nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
+ if( nDoclist+nByte>pCsr->nBuffer ){
+ char *aNew;
+ pCsr->nBuffer = (nDoclist+nByte)*2;
+ aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
+ if( !aNew ){
+ return SQLITE_NOMEM;
+ }
+ pCsr->aBuffer = aNew;
+ }
+
+ if( isFirst ){
+ char *a = &pCsr->aBuffer[nDoclist];
+ int nWrite;
+
+ nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a);
+ if( nWrite ){
+ iPrev = iDocid;
+ nDoclist += nWrite;
+ }
+ }else{
+ nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta);
+ iPrev = iDocid;
+ if( isRequirePos ){
+ memcpy(&pCsr->aBuffer[nDoclist], pList, nList);
+ nDoclist += nList;
+ pCsr->aBuffer[nDoclist++] = '\0';
+ }
+ }
+ }
+
+ fts3SegReaderSort(apSegment, nMerge, j, xCmp);
+ }
+ if( nDoclist>0 ){
+ pCsr->aDoclist = pCsr->aBuffer;
+ pCsr->nDoclist = nDoclist;
+ rc = SQLITE_ROW;
+ }
+ }
+ pCsr->nAdvance = nMerge;
+ }while( rc==SQLITE_OK );
+
+ return rc;
+}
+
+
+SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(
+ Fts3MultiSegReader *pCsr /* Cursor object */
+){
+ if( pCsr ){
+ int i;
+ for(i=0; i<pCsr->nSegment; i++){
+ sqlite3Fts3SegReaderFree(pCsr->apSegment[i]);
+ }
+ sqlite3_free(pCsr->apSegment);
+ sqlite3_free(pCsr->aBuffer);
+
+ pCsr->nSegment = 0;
+ pCsr->apSegment = 0;
+ pCsr->aBuffer = 0;
+ }
+}
+
+/*
+** Merge all level iLevel segments in the database into a single
+** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
+** single segment with a level equal to the numerically largest level
+** currently present in the database.
+**
+** If this function is called with iLevel<0, but there is only one
+** segment in the database, SQLITE_DONE is returned immediately.
+** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
+** an SQLite error code is returned.
+*/
+static int fts3SegmentMerge(
+ Fts3Table *p,
+ int iLangid, /* Language id to merge */
+ int iIndex, /* Index in p->aIndex[] to merge */
+ int iLevel /* Level to merge */
+){
+ int rc; /* Return code */
+ int iIdx = 0; /* Index of new segment */
+ sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */
+ SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */
+ Fts3SegFilter filter; /* Segment term filter condition */
+ Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
+ int bIgnoreEmpty = 0; /* True to ignore empty segments */
+
+ assert( iLevel==FTS3_SEGCURSOR_ALL
+ || iLevel==FTS3_SEGCURSOR_PENDING
+ || iLevel>=0
+ );
+ assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
+ assert( iIndex>=0 && iIndex<p->nIndex );
+
+ rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
+ if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
+
+ if( iLevel==FTS3_SEGCURSOR_ALL ){
+ /* This call is to merge all segments in the database to a single
+ ** segment. The level of the new segment is equal to the numerically
+ ** greatest segment level currently present in the database for this
+ ** index. The idx of the new segment is always 0. */
+ if( csr.nSegment==1 ){
+ rc = SQLITE_DONE;
+ goto finished;
+ }
+ rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel);
+ bIgnoreEmpty = 1;
+
+ }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
+ iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0);
+ rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx);
+ }else{
+ /* This call is to merge all segments at level iLevel. find the next
+ ** available segment index at level iLevel+1. The call to
+ ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
+ ** a single iLevel+2 segment if necessary. */
+ rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
+ iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
+ }
+ if( rc!=SQLITE_OK ) goto finished;
+ assert( csr.nSegment>0 );
+ assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
+ assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
+
+ memset(&filter, 0, sizeof(Fts3SegFilter));
+ filter.flags = FTS3_SEGMENT_REQUIRE_POS;
+ filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);
+
+ rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
+ while( SQLITE_OK==rc ){
+ rc = sqlite3Fts3SegReaderStep(p, &csr);
+ if( rc!=SQLITE_ROW ) break;
+ rc = fts3SegWriterAdd(p, &pWriter, 1,
+ csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
+ }
+ if( rc!=SQLITE_OK ) goto finished;
+ assert( pWriter );
+
+ if( iLevel!=FTS3_SEGCURSOR_PENDING ){
+ rc = fts3DeleteSegdir(
+ p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment
+ );
+ if( rc!=SQLITE_OK ) goto finished;
+ }
+ rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
+
+ finished:
+ fts3SegWriterFree(pWriter);
+ sqlite3Fts3SegReaderFinish(&csr);
+ return rc;
+}
+
+
+/*
+** Flush the contents of pendingTerms to level 0 segments.
+*/
+SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
+ int rc = SQLITE_OK;
+ int i;
+
+ for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
+ rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING);
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+ }
+ sqlite3Fts3PendingTermsClear(p);
+
+ /* Determine the auto-incr-merge setting if unknown. If enabled,
+ ** estimate the number of leaf blocks of content to be written
+ */
+ if( rc==SQLITE_OK && p->bHasStat
+ && p->bAutoincrmerge==0xff && p->nLeafAdd>0
+ ){
+ sqlite3_stmt *pStmt = 0;
+ rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
+ rc = sqlite3_step(pStmt);
+ p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0));
+ rc = sqlite3_reset(pStmt);
+ }
+ }
+ return rc;
+}
+
+/*
+** Encode N integers as varints into a blob.
+*/
+static void fts3EncodeIntArray(
+ int N, /* The number of integers to encode */
+ u32 *a, /* The integer values */
+ char *zBuf, /* Write the BLOB here */
+ int *pNBuf /* Write number of bytes if zBuf[] used here */
+){
+ int i, j;
+ for(i=j=0; i<N; i++){
+ j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]);
+ }
+ *pNBuf = j;
+}
+
+/*
+** Decode a blob of varints into N integers
+*/
+static void fts3DecodeIntArray(
+ int N, /* The number of integers to decode */
+ u32 *a, /* Write the integer values */
+ const char *zBuf, /* The BLOB containing the varints */
+ int nBuf /* size of the BLOB */
+){
+ int i, j;
+ UNUSED_PARAMETER(nBuf);
+ for(i=j=0; i<N; i++){
+ sqlite3_int64 x;
+ j += sqlite3Fts3GetVarint(&zBuf[j], &x);
+ assert(j<=nBuf);
+ a[i] = (u32)(x & 0xffffffff);
+ }
+}
+
+/*
+** Insert the sizes (in tokens) for each column of the document
+** with docid equal to p->iPrevDocid. The sizes are encoded as
+** a blob of varints.
+*/
+static void fts3InsertDocsize(
+ int *pRC, /* Result code */
+ Fts3Table *p, /* Table into which to insert */
+ u32 *aSz /* Sizes of each column, in tokens */
+){
+ char *pBlob; /* The BLOB encoding of the document size */
+ int nBlob; /* Number of bytes in the BLOB */
+ sqlite3_stmt *pStmt; /* Statement used to insert the encoding */
+ int rc; /* Result code from subfunctions */
+
+ if( *pRC ) return;
+ pBlob = sqlite3_malloc( 10*p->nColumn );
+ if( pBlob==0 ){
+ *pRC = SQLITE_NOMEM;
+ return;
+ }
+ fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob);
+ rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0);
+ if( rc ){
+ sqlite3_free(pBlob);
+ *pRC = rc;
+ return;
+ }
+ sqlite3_bind_int64(pStmt, 1, p->iPrevDocid);
+ sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free);
+ sqlite3_step(pStmt);
+ *pRC = sqlite3_reset(pStmt);
+}
+
+/*
+** Record 0 of the %_stat table contains a blob consisting of N varints,
+** where N is the number of user defined columns in the fts3 table plus
+** two. If nCol is the number of user defined columns, then values of the
+** varints are set as follows:
+**
+** Varint 0: Total number of rows in the table.
+**
+** Varint 1..nCol: For each column, the total number of tokens stored in
+** the column for all rows of the table.
+**
+** Varint 1+nCol: The total size, in bytes, of all text values in all
+** columns of all rows of the table.
+**
+*/
+static void fts3UpdateDocTotals(
+ int *pRC, /* The result code */
+ Fts3Table *p, /* Table being updated */
+ u32 *aSzIns, /* Size increases */
+ u32 *aSzDel, /* Size decreases */
+ int nChng /* Change in the number of documents */
+){
+ char *pBlob; /* Storage for BLOB written into %_stat */
+ int nBlob; /* Size of BLOB written into %_stat */
+ u32 *a; /* Array of integers that becomes the BLOB */
+ sqlite3_stmt *pStmt; /* Statement for reading and writing */
+ int i; /* Loop counter */
+ int rc; /* Result code from subfunctions */
+
+ const int nStat = p->nColumn+2;
+
+ if( *pRC ) return;
+ a = sqlite3_malloc( (sizeof(u32)+10)*nStat );
+ if( a==0 ){
+ *pRC = SQLITE_NOMEM;
+ return;
+ }
+ pBlob = (char*)&a[nStat];
+ rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
+ if( rc ){
+ sqlite3_free(a);
+ *pRC = rc;
+ return;
+ }
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
+ if( sqlite3_step(pStmt)==SQLITE_ROW ){
+ fts3DecodeIntArray(nStat, a,
+ sqlite3_column_blob(pStmt, 0),
+ sqlite3_column_bytes(pStmt, 0));
+ }else{
+ memset(a, 0, sizeof(u32)*(nStat) );
+ }
+ rc = sqlite3_reset(pStmt);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(a);
+ *pRC = rc;
+ return;
+ }
+ if( nChng<0 && a[0]<(u32)(-nChng) ){
+ a[0] = 0;
+ }else{
+ a[0] += nChng;
+ }
+ for(i=0; i<p->nColumn+1; i++){
+ u32 x = a[i+1];
+ if( x+aSzIns[i] < aSzDel[i] ){
+ x = 0;
+ }else{
+ x = x + aSzIns[i] - aSzDel[i];
+ }
+ a[i+1] = x;
+ }
+ fts3EncodeIntArray(nStat, a, pBlob, &nBlob);
+ rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
+ if( rc ){
+ sqlite3_free(a);
+ *pRC = rc;
+ return;
+ }
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
+ sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
+ sqlite3_step(pStmt);
+ *pRC = sqlite3_reset(pStmt);
+ sqlite3_free(a);
+}
+
+/*
+** Merge the entire database so that there is one segment for each
+** iIndex/iLangid combination.
+*/
+static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
+ int bSeenDone = 0;
+ int rc;
+ sqlite3_stmt *pAllLangid = 0;
+
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ sqlite3_bind_int(pAllLangid, 1, p->nIndex);
+ while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
+ int i;
+ int iLangid = sqlite3_column_int(pAllLangid, 0);
+ for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
+ rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL);
+ if( rc==SQLITE_DONE ){
+ bSeenDone = 1;
+ rc = SQLITE_OK;
+ }
+ }
+ }
+ rc2 = sqlite3_reset(pAllLangid);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ sqlite3Fts3SegmentsClose(p);
+ sqlite3Fts3PendingTermsClear(p);
+
+ return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
+}
+
+/*
+** This function is called when the user executes the following statement:
+**
+** INSERT INTO <tbl>(<tbl>) VALUES('rebuild');
+**
+** The entire FTS index is discarded and rebuilt. If the table is one
+** created using the content=xxx option, then the new index is based on
+** the current contents of the xxx table. Otherwise, it is rebuilt based
+** on the contents of the %_content table.
+*/
+static int fts3DoRebuild(Fts3Table *p){
+ int rc; /* Return Code */
+
+ rc = fts3DeleteAll(p, 0);
+ if( rc==SQLITE_OK ){
+ u32 *aSz = 0;
+ u32 *aSzIns = 0;
+ u32 *aSzDel = 0;
+ sqlite3_stmt *pStmt = 0;
+ int nEntry = 0;
+
+ /* Compose and prepare an SQL statement to loop through the content table */
+ char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+ sqlite3_free(zSql);
+ }
+
+ if( rc==SQLITE_OK ){
+ int nByte = sizeof(u32) * (p->nColumn+1)*3;
+ aSz = (u32 *)sqlite3_malloc(nByte);
+ if( aSz==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(aSz, 0, nByte);
+ aSzIns = &aSz[p->nColumn+1];
+ aSzDel = &aSzIns[p->nColumn+1];
+ }
+ }
+
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
+ int iCol;
+ int iLangid = langidFromSelect(p, pStmt);
+ rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
+ memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
+ for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
+ const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
+ rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
+ aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+ }
+ if( p->bHasDocsize ){
+ fts3InsertDocsize(&rc, p, aSz);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3_finalize(pStmt);
+ pStmt = 0;
+ }else{
+ nEntry++;
+ for(iCol=0; iCol<=p->nColumn; iCol++){
+ aSzIns[iCol] += aSz[iCol];
+ }
+ }
+ }
+ if( p->bFts4 ){
+ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
+ }
+ sqlite3_free(aSz);
+
+ if( pStmt ){
+ int rc2 = sqlite3_finalize(pStmt);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+** This function opens a cursor used to read the input data for an
+** incremental merge operation. Specifically, it opens a cursor to scan
+** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
+** level iAbsLevel.
+*/
+static int fts3IncrmergeCsr(
+ Fts3Table *p, /* FTS3 table handle */
+ sqlite3_int64 iAbsLevel, /* Absolute level to open */
+ int nSeg, /* Number of segments to merge */
+ Fts3MultiSegReader *pCsr /* Cursor object to populate */
+){
+ int rc; /* Return Code */
+ sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
+ int nByte; /* Bytes allocated at pCsr->apSegment[] */
+
+ /* Allocate space for the Fts3MultiSegReader.aCsr[] array */
+ memset(pCsr, 0, sizeof(*pCsr));
+ nByte = sizeof(Fts3SegReader *) * nSeg;
+ pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte);
+
+ if( pCsr->apSegment==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(pCsr->apSegment, 0, nByte);
+ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
+ }
+ if( rc==SQLITE_OK ){
+ int i;
+ int rc2;
+ sqlite3_bind_int64(pStmt, 1, iAbsLevel);
+ assert( pCsr->nSegment==0 );
+ for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && i<nSeg; i++){
+ rc = sqlite3Fts3SegReaderNew(i, 0,
+ sqlite3_column_int64(pStmt, 1), /* segdir.start_block */
+ sqlite3_column_int64(pStmt, 2), /* segdir.leaves_end_block */
+ sqlite3_column_int64(pStmt, 3), /* segdir.end_block */
+ sqlite3_column_blob(pStmt, 4), /* segdir.root */
+ sqlite3_column_bytes(pStmt, 4), /* segdir.root */
+ &pCsr->apSegment[i]
+ );
+ pCsr->nSegment++;
+ }
+ rc2 = sqlite3_reset(pStmt);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ return rc;
+}
+
+typedef struct IncrmergeWriter IncrmergeWriter;
+typedef struct NodeWriter NodeWriter;
+typedef struct Blob Blob;
+typedef struct NodeReader NodeReader;
+
+/*
+** An instance of the following structure is used as a dynamic buffer
+** to build up nodes or other blobs of data in.
+**
+** The function blobGrowBuffer() is used to extend the allocation.
+*/
+struct Blob {
+ char *a; /* Pointer to allocation */
+ int n; /* Number of valid bytes of data in a[] */
+ int nAlloc; /* Allocated size of a[] (nAlloc>=n) */
+};
+
+/*
+** This structure is used to build up buffers containing segment b-tree
+** nodes (blocks).
+*/
+struct NodeWriter {
+ sqlite3_int64 iBlock; /* Current block id */
+ Blob key; /* Last key written to the current block */
+ Blob block; /* Current block image */
+};
+
+/*
+** An object of this type contains the state required to create or append
+** to an appendable b-tree segment.
+*/
+struct IncrmergeWriter {
+ int nLeafEst; /* Space allocated for leaf blocks */
+ int nWork; /* Number of leaf pages flushed */
+ sqlite3_int64 iAbsLevel; /* Absolute level of input segments */
+ int iIdx; /* Index of *output* segment in iAbsLevel+1 */
+ sqlite3_int64 iStart; /* Block number of first allocated block */
+ sqlite3_int64 iEnd; /* Block number of last allocated block */
+ NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
+};
+
+/*
+** An object of the following type is used to read data from a single
+** FTS segment node. See the following functions:
+**
+** nodeReaderInit()
+** nodeReaderNext()
+** nodeReaderRelease()
+*/
+struct NodeReader {
+ const char *aNode;
+ int nNode;
+ int iOff; /* Current offset within aNode[] */
+
+ /* Output variables. Containing the current node entry. */
+ sqlite3_int64 iChild; /* Pointer to child node */
+ Blob term; /* Current term */
+ const char *aDoclist; /* Pointer to doclist */
+ int nDoclist; /* Size of doclist in bytes */
+};
+
+/*
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** Otherwise, if the allocation at pBlob->a is not already at least nMin
+** bytes in size, extend (realloc) it to be so.
+**
+** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a
+** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc
+** to reflect the new size of the pBlob->a[] buffer.
+*/
+static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
+ if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
+ int nAlloc = nMin;
+ char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc);
+ if( a ){
+ pBlob->nAlloc = nAlloc;
+ pBlob->a = a;
+ }else{
+ *pRc = SQLITE_NOMEM;
+ }
+ }
+}
+
+/*
+** Attempt to advance the node-reader object passed as the first argument to
+** the next entry on the node.
+**
+** Return an error code if an error occurs (SQLITE_NOMEM is possible).
+** Otherwise return SQLITE_OK. If there is no next entry on the node
+** (e.g. because the current entry is the last) set NodeReader->aNode to
+** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
+** variables for the new entry.
+*/
+static int nodeReaderNext(NodeReader *p){
+ int bFirst = (p->term.n==0); /* True for first term on the node */
+ int nPrefix = 0; /* Bytes to copy from previous term */
+ int nSuffix = 0; /* Bytes to append to the prefix */
+ int rc = SQLITE_OK; /* Return code */
+
+ assert( p->aNode );
+ if( p->iChild && bFirst==0 ) p->iChild++;
+ if( p->iOff>=p->nNode ){
+ /* EOF */
+ p->aNode = 0;
+ }else{
+ if( bFirst==0 ){
+ p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
+ }
+ p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
+
+ blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
+ if( rc==SQLITE_OK ){
+ memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
+ p->term.n = nPrefix+nSuffix;
+ p->iOff += nSuffix;
+ if( p->iChild==0 ){
+ p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
+ p->aDoclist = &p->aNode[p->iOff];
+ p->iOff += p->nDoclist;
+ }
+ }
+ }
+
+ assert( p->iOff<=p->nNode );
+
+ return rc;
+}
+
+/*
+** Release all dynamic resources held by node-reader object *p.
+*/
+static void nodeReaderRelease(NodeReader *p){
+ sqlite3_free(p->term.a);
+}
+
+/*
+** Initialize a node-reader object to read the node in buffer aNode/nNode.
+**
+** If successful, SQLITE_OK is returned and the NodeReader object set to
+** point to the first entry on the node (if any). Otherwise, an SQLite
+** error code is returned.
+*/
+static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
+ memset(p, 0, sizeof(NodeReader));
+ p->aNode = aNode;
+ p->nNode = nNode;
+
+ /* Figure out if this is a leaf or an internal node. */
+ if( p->aNode[0] ){
+ /* An internal node. */
+ p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
+ }else{
+ p->iOff = 1;
+ }
+
+ return nodeReaderNext(p);
+}
+
+/*
+** This function is called while writing an FTS segment each time a leaf o
+** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed
+** to be greater than the largest key on the node just written, but smaller
+** than or equal to the first key that will be written to the next leaf
+** node.
+**
+** The block id of the leaf node just written to disk may be found in
+** (pWriter->aNodeWriter[0].iBlock) when this function is called.
+*/
+static int fts3IncrmergePush(
+ Fts3Table *p, /* Fts3 table handle */
+ IncrmergeWriter *pWriter, /* Writer object */
+ const char *zTerm, /* Term to write to internal node */
+ int nTerm /* Bytes at zTerm */
+){
+ sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock;
+ int iLayer;
+
+ assert( nTerm>0 );
+ for(iLayer=1; ALWAYS(iLayer<FTS_MAX_APPENDABLE_HEIGHT); iLayer++){
+ sqlite3_int64 iNextPtr = 0;
+ NodeWriter *pNode = &pWriter->aNodeWriter[iLayer];
+ int rc = SQLITE_OK;
+ int nPrefix;
+ int nSuffix;
+ int nSpace;
+
+ /* Figure out how much space the key will consume if it is written to
+ ** the current node of layer iLayer. Due to the prefix compression,
+ ** the space required changes depending on which node the key is to
+ ** be added to. */
+ nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
+ nSuffix = nTerm - nPrefix;
+ nSpace = sqlite3Fts3VarintLen(nPrefix);
+ nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
+
+ if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
+ /* If the current node of layer iLayer contains zero keys, or if adding
+ ** the key to it will not cause it to grow to larger than nNodeSize
+ ** bytes in size, write the key here. */
+
+ Blob *pBlk = &pNode->block;
+ if( pBlk->n==0 ){
+ blobGrowBuffer(pBlk, p->nNodeSize, &rc);
+ if( rc==SQLITE_OK ){
+ pBlk->a[0] = (char)iLayer;
+ pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr);
+ }
+ }
+ blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc);
+ blobGrowBuffer(&pNode->key, nTerm, &rc);
+
+ if( rc==SQLITE_OK ){
+ if( pNode->key.n ){
+ pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
+ }
+ pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
+ memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
+ pBlk->n += nSuffix;
+
+ memcpy(pNode->key.a, zTerm, nTerm);
+ pNode->key.n = nTerm;
+ }
+ }else{
+ /* Otherwise, flush the current node of layer iLayer to disk.
+ ** Then allocate a new, empty sibling node. The key will be written
+ ** into the parent of this node. */
+ rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
+
+ assert( pNode->block.nAlloc>=p->nNodeSize );
+ pNode->block.a[0] = (char)iLayer;
+ pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1);
+
+ iNextPtr = pNode->iBlock;
+ pNode->iBlock++;
+ pNode->key.n = 0;
+ }
+
+ if( rc!=SQLITE_OK || iNextPtr==0 ) return rc;
+ iPtr = iNextPtr;
+ }
+
+ assert( 0 );
+ return 0;
+}
+
+/*
+** Append a term and (optionally) doclist to the FTS segment node currently
+** stored in blob *pNode. The node need not contain any terms, but the
+** header must be written before this function is called.
+**
+** A node header is a single 0x00 byte for a leaf node, or a height varint
+** followed by the left-hand-child varint for an internal node.
+**
+** The term to be appended is passed via arguments zTerm/nTerm. For a
+** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal
+** node, both aDoclist and nDoclist must be passed 0.
+**
+** If the size of the value in blob pPrev is zero, then this is the first
+** term written to the node. Otherwise, pPrev contains a copy of the
+** previous term. Before this function returns, it is updated to contain a
+** copy of zTerm/nTerm.
+**
+** It is assumed that the buffer associated with pNode is already large
+** enough to accommodate the new entry. The buffer associated with pPrev
+** is extended by this function if requrired.
+**
+** If an error (i.e. OOM condition) occurs, an SQLite error code is
+** returned. Otherwise, SQLITE_OK.
+*/
+static int fts3AppendToNode(
+ Blob *pNode, /* Current node image to append to */
+ Blob *pPrev, /* Buffer containing previous term written */
+ const char *zTerm, /* New term to write */
+ int nTerm, /* Size of zTerm in bytes */
+ const char *aDoclist, /* Doclist (or NULL) to write */
+ int nDoclist /* Size of aDoclist in bytes */
+){
+ int rc = SQLITE_OK; /* Return code */
+ int bFirst = (pPrev->n==0); /* True if this is the first term written */
+ int nPrefix; /* Size of term prefix in bytes */
+ int nSuffix; /* Size of term suffix in bytes */
+
+ /* Node must have already been started. There must be a doclist for a
+ ** leaf node, and there must not be a doclist for an internal node. */
+ assert( pNode->n>0 );
+ assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
+
+ blobGrowBuffer(pPrev, nTerm, &rc);
+ if( rc!=SQLITE_OK ) return rc;
+
+ nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
+ nSuffix = nTerm - nPrefix;
+ memcpy(pPrev->a, zTerm, nTerm);
+ pPrev->n = nTerm;
+
+ if( bFirst==0 ){
+ pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix);
+ }
+ pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix);
+ memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix);
+ pNode->n += nSuffix;
+
+ if( aDoclist ){
+ pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist);
+ memcpy(&pNode->a[pNode->n], aDoclist, nDoclist);
+ pNode->n += nDoclist;
+ }
+
+ assert( pNode->n<=pNode->nAlloc );
+
+ return SQLITE_OK;
+}
+
+/*
+** Append the current term and doclist pointed to by cursor pCsr to the
+** appendable b-tree segment opened for writing by pWriter.
+**
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
+*/
+static int fts3IncrmergeAppend(
+ Fts3Table *p, /* Fts3 table handle */
+ IncrmergeWriter *pWriter, /* Writer object */
+ Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */
+){
+ const char *zTerm = pCsr->zTerm;
+ int nTerm = pCsr->nTerm;
+ const char *aDoclist = pCsr->aDoclist;
+ int nDoclist = pCsr->nDoclist;
+ int rc = SQLITE_OK; /* Return code */
+ int nSpace; /* Total space in bytes required on leaf */
+ int nPrefix; /* Size of prefix shared with previous term */
+ int nSuffix; /* Size of suffix (nTerm - nPrefix) */
+ NodeWriter *pLeaf; /* Object used to write leaf nodes */
+
+ pLeaf = &pWriter->aNodeWriter[0];
+ nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
+ nSuffix = nTerm - nPrefix;
+
+ nSpace = sqlite3Fts3VarintLen(nPrefix);
+ nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
+ nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
+
+ /* If the current block is not empty, and if adding this term/doclist
+ ** to the current block would make it larger than Fts3Table.nNodeSize
+ ** bytes, write this block out to the database. */
+ if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){
+ rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
+ pWriter->nWork++;
+
+ /* Add the current term to the parent node. The term added to the
+ ** parent must:
+ **
+ ** a) be greater than the largest term on the leaf node just written
+ ** to the database (still available in pLeaf->key), and
+ **
+ ** b) be less than or equal to the term about to be added to the new
+ ** leaf node (zTerm/nTerm).
+ **
+ ** In other words, it must be the prefix of zTerm 1 byte longer than
+ ** the common prefix (if any) of zTerm and pWriter->zTerm.
+ */
+ if( rc==SQLITE_OK ){
+ rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1);
+ }
+
+ /* Advance to the next output block */
+ pLeaf->iBlock++;
+ pLeaf->key.n = 0;
+ pLeaf->block.n = 0;
+
+ nSuffix = nTerm;
+ nSpace = 1;
+ nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
+ nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
+ }
+
+ blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
+
+ if( rc==SQLITE_OK ){
+ if( pLeaf->block.n==0 ){
+ pLeaf->block.n = 1;
+ pLeaf->block.a[0] = '\0';
+ }
+ rc = fts3AppendToNode(
+ &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist
+ );
+ }
+
+ return rc;
+}
+
+/*
+** This function is called to release all dynamic resources held by the
+** merge-writer object pWriter, and if no error has occurred, to flush
+** all outstanding node buffers held by pWriter to disk.
+**
+** If *pRc is not SQLITE_OK when this function is called, then no attempt
+** is made to write any data to disk. Instead, this function serves only
+** to release outstanding resources.
+**
+** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while
+** flushing buffers to disk, *pRc is set to an SQLite error code before
+** returning.
+*/
+static void fts3IncrmergeRelease(
+ Fts3Table *p, /* FTS3 table handle */
+ IncrmergeWriter *pWriter, /* Merge-writer object */
+ int *pRc /* IN/OUT: Error code */
+){
+ int i; /* Used to iterate through non-root layers */
+ int iRoot; /* Index of root in pWriter->aNodeWriter */
+ NodeWriter *pRoot; /* NodeWriter for root node */
+ int rc = *pRc; /* Error code */
+
+ /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
+ ** root node. If the segment fits entirely on a single leaf node, iRoot
+ ** will be set to 0. If the root node is the parent of the leaves, iRoot
+ ** will be 1. And so on. */
+ for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){
+ NodeWriter *pNode = &pWriter->aNodeWriter[iRoot];
+ if( pNode->block.n>0 ) break;
+ assert( *pRc || pNode->block.nAlloc==0 );
+ assert( *pRc || pNode->key.nAlloc==0 );
+ sqlite3_free(pNode->block.a);
+ sqlite3_free(pNode->key.a);
+ }
+
+ /* Empty output segment. This is a no-op. */
+ if( iRoot<0 ) return;
+
+ /* The entire output segment fits on a single node. Normally, this means
+ ** the node would be stored as a blob in the "root" column of the %_segdir
+ ** table. However, this is not permitted in this case. The problem is that
+ ** space has already been reserved in the %_segments table, and so the
+ ** start_block and end_block fields of the %_segdir table must be populated.
+ ** And, by design or by accident, released versions of FTS cannot handle
+ ** segments that fit entirely on the root node with start_block!=0.
+ **
+ ** Instead, create a synthetic root node that contains nothing but a
+ ** pointer to the single content node. So that the segment consists of a
+ ** single leaf and a single interior (root) node.
+ **
+ ** Todo: Better might be to defer allocating space in the %_segments
+ ** table until we are sure it is needed.
+ */
+ if( iRoot==0 ){
+ Blob *pBlock = &pWriter->aNodeWriter[1].block;
+ blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc);
+ if( rc==SQLITE_OK ){
+ pBlock->a[0] = 0x01;
+ pBlock->n = 1 + sqlite3Fts3PutVarint(
+ &pBlock->a[1], pWriter->aNodeWriter[0].iBlock
+ );
+ }
+ iRoot = 1;
+ }
+ pRoot = &pWriter->aNodeWriter[iRoot];
+
+ /* Flush all currently outstanding nodes to disk. */
+ for(i=0; i<iRoot; i++){
+ NodeWriter *pNode = &pWriter->aNodeWriter[i];
+ if( pNode->block.n>0 && rc==SQLITE_OK ){
+ rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n);
+ }
+ sqlite3_free(pNode->block.a);
+ sqlite3_free(pNode->key.a);
+ }
+
+ /* Write the %_segdir record. */
+ if( rc==SQLITE_OK ){
+ rc = fts3WriteSegdir(p,
+ pWriter->iAbsLevel+1, /* level */
+ pWriter->iIdx, /* idx */
+ pWriter->iStart, /* start_block */
+ pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */
+ pWriter->iEnd, /* end_block */
+ pRoot->block.a, pRoot->block.n /* root */
+ );
+ }
+ sqlite3_free(pRoot->block.a);
+ sqlite3_free(pRoot->key.a);
+
+ *pRc = rc;
+}
+
+/*
+** Compare the term in buffer zLhs (size in bytes nLhs) with that in
+** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of
+** the other, it is considered to be smaller than the other.
+**
+** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve
+** if it is greater.
+*/
+static int fts3TermCmp(
+ const char *zLhs, int nLhs, /* LHS of comparison */
+ const char *zRhs, int nRhs /* RHS of comparison */
+){
+ int nCmp = MIN(nLhs, nRhs);
+ int res;
+
+ res = memcmp(zLhs, zRhs, nCmp);
+ if( res==0 ) res = nLhs - nRhs;
+
+ return res;
+}
+
+
+/*
+** Query to see if the entry in the %_segments table with blockid iEnd is
+** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before
+** returning. Otherwise, set *pbRes to 0.
+**
+** Or, if an error occurs while querying the database, return an SQLite
+** error code. The final value of *pbRes is undefined in this case.
+**
+** This is used to test if a segment is an "appendable" segment. If it
+** is, then a NULL entry has been inserted into the %_segments table
+** with blockid %_segdir.end_block.
+*/
+static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){
+ int bRes = 0; /* Result to set *pbRes to */
+ sqlite3_stmt *pCheck = 0; /* Statement to query database with */
+ int rc; /* Return code */
+
+ rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pCheck, 1, iEnd);
+ if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1;
+ rc = sqlite3_reset(pCheck);
+ }
+
+ *pbRes = bRes;
+ return rc;
+}
+
+/*
+** This function is called when initializing an incremental-merge operation.
+** It checks if the existing segment with index value iIdx at absolute level
+** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the
+** merge-writer object *pWriter is initialized to write to it.
+**
+** An existing segment can be appended to by an incremental merge if:
+**
+** * It was initially created as an appendable segment (with all required
+** space pre-allocated), and
+**
+** * The first key read from the input (arguments zKey and nKey) is
+** greater than the largest key currently stored in the potential
+** output segment.
+*/
+static int fts3IncrmergeLoad(
+ Fts3Table *p, /* Fts3 table handle */
+ sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
+ int iIdx, /* Index of candidate output segment */
+ const char *zKey, /* First key to write */
+ int nKey, /* Number of bytes in nKey */
+ IncrmergeWriter *pWriter /* Populate this object */
+){
+ int rc; /* Return code */
+ sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */
+
+ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */
+ sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */
+ sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */
+ const char *aRoot = 0; /* Pointer to %_segdir.root buffer */
+ int nRoot = 0; /* Size of aRoot[] in bytes */
+ int rc2; /* Return code from sqlite3_reset() */
+ int bAppendable = 0; /* Set to true if segment is appendable */
+
+ /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */
+ sqlite3_bind_int64(pSelect, 1, iAbsLevel+1);
+ sqlite3_bind_int(pSelect, 2, iIdx);
+ if( sqlite3_step(pSelect)==SQLITE_ROW ){
+ iStart = sqlite3_column_int64(pSelect, 1);
+ iLeafEnd = sqlite3_column_int64(pSelect, 2);
+ iEnd = sqlite3_column_int64(pSelect, 3);
+ nRoot = sqlite3_column_bytes(pSelect, 4);
+ aRoot = sqlite3_column_blob(pSelect, 4);
+ }else{
+ return sqlite3_reset(pSelect);
+ }
+
+ /* Check for the zero-length marker in the %_segments table */
+ rc = fts3IsAppendable(p, iEnd, &bAppendable);
+
+ /* Check that zKey/nKey is larger than the largest key the candidate */
+ if( rc==SQLITE_OK && bAppendable ){
+ char *aLeaf = 0;
+ int nLeaf = 0;
+
+ rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0);
+ if( rc==SQLITE_OK ){
+ NodeReader reader;
+ for(rc = nodeReaderInit(&reader, aLeaf, nLeaf);
+ rc==SQLITE_OK && reader.aNode;
+ rc = nodeReaderNext(&reader)
+ ){
+ assert( reader.aNode );
+ }
+ if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){
+ bAppendable = 0;
+ }
+ nodeReaderRelease(&reader);
+ }
+ sqlite3_free(aLeaf);
+ }
+
+ if( rc==SQLITE_OK && bAppendable ){
+ /* It is possible to append to this segment. Set up the IncrmergeWriter
+ ** object to do so. */
+ int i;
+ int nHeight = (int)aRoot[0];
+ NodeWriter *pNode;
+
+ pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
+ pWriter->iStart = iStart;
+ pWriter->iEnd = iEnd;
+ pWriter->iAbsLevel = iAbsLevel;
+ pWriter->iIdx = iIdx;
+
+ for(i=nHeight+1; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
+ pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
+ }
+
+ pNode = &pWriter->aNodeWriter[nHeight];
+ pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
+ blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
+ if( rc==SQLITE_OK ){
+ memcpy(pNode->block.a, aRoot, nRoot);
+ pNode->block.n = nRoot;
+ }
+
+ for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
+ NodeReader reader;
+ pNode = &pWriter->aNodeWriter[i];
+
+ rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
+ while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
+ blobGrowBuffer(&pNode->key, reader.term.n, &rc);
+ if( rc==SQLITE_OK ){
+ memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ pNode->key.n = reader.term.n;
+ if( i>0 ){
+ char *aBlock = 0;
+ int nBlock = 0;
+ pNode = &pWriter->aNodeWriter[i-1];
+ pNode->iBlock = reader.iChild;
+ rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
+ blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
+ if( rc==SQLITE_OK ){
+ memcpy(pNode->block.a, aBlock, nBlock);
+ pNode->block.n = nBlock;
+ }
+ sqlite3_free(aBlock);
+ }
+ }
+ nodeReaderRelease(&reader);
+ }
+ }
+
+ rc2 = sqlite3_reset(pSelect);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ return rc;
+}
+
+/*
+** Determine the largest segment index value that exists within absolute
+** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus
+** one before returning SQLITE_OK. Or, if there are no segments at all
+** within level iAbsLevel, set *piIdx to zero.
+**
+** If an error occurs, return an SQLite error code. The final value of
+** *piIdx is undefined in this case.
+*/
+static int fts3IncrmergeOutputIdx(
+ Fts3Table *p, /* FTS Table handle */
+ sqlite3_int64 iAbsLevel, /* Absolute index of input segments */
+ int *piIdx /* OUT: Next free index at iAbsLevel+1 */
+){
+ int rc;
+ sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */
+
+ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1);
+ sqlite3_step(pOutputIdx);
+ *piIdx = sqlite3_column_int(pOutputIdx, 0);
+ rc = sqlite3_reset(pOutputIdx);
+ }
+
+ return rc;
+}
+
+/*
+** Allocate an appendable output segment on absolute level iAbsLevel+1
+** with idx value iIdx.
+**
+** In the %_segdir table, a segment is defined by the values in three
+** columns:
+**
+** start_block
+** leaves_end_block
+** end_block
+**
+** When an appendable segment is allocated, it is estimated that the
+** maximum number of leaf blocks that may be required is the sum of the
+** number of leaf blocks consumed by the input segments, plus the number
+** of input segments, multiplied by two. This value is stored in stack
+** variable nLeafEst.
+**
+** A total of 16*nLeafEst blocks are allocated when an appendable segment
+** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous
+** array of leaf nodes starts at the first block allocated. The array
+** of interior nodes that are parents of the leaf nodes start at block
+** (start_block + (1 + end_block - start_block) / 16). And so on.
+**
+** In the actual code below, the value "16" is replaced with the
+** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT.
+*/
+static int fts3IncrmergeWriter(
+ Fts3Table *p, /* Fts3 table handle */
+ sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
+ int iIdx, /* Index of new output segment */
+ Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */
+ IncrmergeWriter *pWriter /* Populate this object */
+){
+ int rc; /* Return Code */
+ int i; /* Iterator variable */
+ int nLeafEst = 0; /* Blocks allocated for leaf nodes */
+ sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */
+ sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */
+
+ /* Calculate nLeafEst. */
+ rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pLeafEst, 1, iAbsLevel);
+ sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment);
+ if( SQLITE_ROW==sqlite3_step(pLeafEst) ){
+ nLeafEst = sqlite3_column_int(pLeafEst, 0);
+ }
+ rc = sqlite3_reset(pLeafEst);
+ }
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* Calculate the first block to use in the output segment */
+ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0);
+ if( rc==SQLITE_OK ){
+ if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){
+ pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0);
+ pWriter->iEnd = pWriter->iStart - 1;
+ pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT;
+ }
+ rc = sqlite3_reset(pFirstBlock);
+ }
+ if( rc!=SQLITE_OK ) return rc;
+
+ /* Insert the marker in the %_segments table to make sure nobody tries
+ ** to steal the space just allocated. This is also used to identify
+ ** appendable segments. */
+ rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0);
+ if( rc!=SQLITE_OK ) return rc;
+
+ pWriter->iAbsLevel = iAbsLevel;
+ pWriter->nLeafEst = nLeafEst;
+ pWriter->iIdx = iIdx;
+
+ /* Set up the array of NodeWriter objects */
+ for(i=0; i<FTS_MAX_APPENDABLE_HEIGHT; i++){
+ pWriter->aNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Remove an entry from the %_segdir table. This involves running the
+** following two statements:
+**
+** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx
+** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx
+**
+** The DELETE statement removes the specific %_segdir level. The UPDATE
+** statement ensures that the remaining segments have contiguously allocated
+** idx values.
+*/
+static int fts3RemoveSegdirEntry(
+ Fts3Table *p, /* FTS3 table handle */
+ sqlite3_int64 iAbsLevel, /* Absolute level to delete from */
+ int iIdx /* Index of %_segdir entry to delete */
+){
+ int rc; /* Return code */
+ sqlite3_stmt *pDelete = 0; /* DELETE statement */
+
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pDelete, 1, iAbsLevel);
+ sqlite3_bind_int(pDelete, 2, iIdx);
+ sqlite3_step(pDelete);
+ rc = sqlite3_reset(pDelete);
+ }
+
+ return rc;
+}
+
+/*
+** One or more segments have just been removed from absolute level iAbsLevel.
+** Update the 'idx' values of the remaining segments in the level so that
+** the idx values are a contiguous sequence starting from 0.
+*/
+static int fts3RepackSegdirLevel(
+ Fts3Table *p, /* FTS3 table handle */
+ sqlite3_int64 iAbsLevel /* Absolute level to repack */
+){
+ int rc; /* Return code */
+ int *aIdx = 0; /* Array of remaining idx values */
+ int nIdx = 0; /* Valid entries in aIdx[] */
+ int nAlloc = 0; /* Allocated size of aIdx[] */
+ int i; /* Iterator variable */
+ sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */
+ sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */
+
+ rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ sqlite3_bind_int64(pSelect, 1, iAbsLevel);
+ while( SQLITE_ROW==sqlite3_step(pSelect) ){
+ if( nIdx>=nAlloc ){
+ int *aNew;
+ nAlloc += 16;
+ aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int));
+ if( !aNew ){
+ rc = SQLITE_NOMEM;
+ break;
+ }
+ aIdx = aNew;
+ }
+ aIdx[nIdx++] = sqlite3_column_int(pSelect, 0);
+ }
+ rc2 = sqlite3_reset(pSelect);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0);
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pUpdate, 2, iAbsLevel);
+ }
+
+ assert( p->bIgnoreSavepoint==0 );
+ p->bIgnoreSavepoint = 1;
+ for(i=0; rc==SQLITE_OK && i<nIdx; i++){
+ if( aIdx[i]!=i ){
+ sqlite3_bind_int(pUpdate, 3, aIdx[i]);
+ sqlite3_bind_int(pUpdate, 1, i);
+ sqlite3_step(pUpdate);
+ rc = sqlite3_reset(pUpdate);
+ }
+ }
+ p->bIgnoreSavepoint = 0;
+
+ sqlite3_free(aIdx);
+ return rc;
+}
+
+static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){
+ pNode->a[0] = (char)iHeight;
+ if( iChild ){
+ assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) );
+ pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild);
+ }else{
+ assert( pNode->nAlloc>=1 );
+ pNode->n = 1;
+ }
+}
+
+/*
+** The first two arguments are a pointer to and the size of a segment b-tree
+** node. The node may be a leaf or an internal node.
+**
+** This function creates a new node image in blob object *pNew by copying
+** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes)
+** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode.
+*/
+static int fts3TruncateNode(
+ const char *aNode, /* Current node image */
+ int nNode, /* Size of aNode in bytes */
+ Blob *pNew, /* OUT: Write new node image here */
+ const char *zTerm, /* Omit all terms smaller than this */
+ int nTerm, /* Size of zTerm in bytes */
+ sqlite3_int64 *piBlock /* OUT: Block number in next layer down */
+){
+ NodeReader reader; /* Reader object */
+ Blob prev = {0, 0, 0}; /* Previous term written to new node */
+ int rc = SQLITE_OK; /* Return code */
+ int bLeaf = aNode[0]=='\0'; /* True for a leaf node */
+
+ /* Allocate required output space */
+ blobGrowBuffer(pNew, nNode, &rc);
+ if( rc!=SQLITE_OK ) return rc;
+ pNew->n = 0;
+
+ /* Populate new node buffer */
+ for(rc = nodeReaderInit(&reader, aNode, nNode);
+ rc==SQLITE_OK && reader.aNode;
+ rc = nodeReaderNext(&reader)
+ ){
+ if( pNew->n==0 ){
+ int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm);
+ if( res<0 || (bLeaf==0 && res==0) ) continue;
+ fts3StartNode(pNew, (int)aNode[0], reader.iChild);
+ *piBlock = reader.iChild;
+ }
+ rc = fts3AppendToNode(
+ pNew, &prev, reader.term.a, reader.term.n,
+ reader.aDoclist, reader.nDoclist
+ );
+ if( rc!=SQLITE_OK ) break;
+ }
+ if( pNew->n==0 ){
+ fts3StartNode(pNew, (int)aNode[0], reader.iChild);
+ *piBlock = reader.iChild;
+ }
+ assert( pNew->n<=pNew->nAlloc );
+
+ nodeReaderRelease(&reader);
+ sqlite3_free(prev.a);
+ return rc;
+}
+
+/*
+** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
+** level iAbsLevel. This may involve deleting entries from the %_segments
+** table, and modifying existing entries in both the %_segments and %_segdir
+** tables.
+**
+** SQLITE_OK is returned if the segment is updated successfully. Or an
+** SQLite error code otherwise.
+*/
+static int fts3TruncateSegment(
+ Fts3Table *p, /* FTS3 table handle */
+ sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */
+ int iIdx, /* Index within level of segment to modify */
+ const char *zTerm, /* Remove terms smaller than this */
+ int nTerm /* Number of bytes in buffer zTerm */
+){
+ int rc = SQLITE_OK; /* Return code */
+ Blob root = {0,0,0}; /* New root page image */
+ Blob block = {0,0,0}; /* Buffer used for any other block */
+ sqlite3_int64 iBlock = 0; /* Block id */
+ sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */
+ sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */
+ sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */
+
+ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0);
+ if( rc==SQLITE_OK ){
+ int rc2; /* sqlite3_reset() return code */
+ sqlite3_bind_int64(pFetch, 1, iAbsLevel);
+ sqlite3_bind_int(pFetch, 2, iIdx);
+ if( SQLITE_ROW==sqlite3_step(pFetch) ){
+ const char *aRoot = sqlite3_column_blob(pFetch, 4);
+ int nRoot = sqlite3_column_bytes(pFetch, 4);
+ iOldStart = sqlite3_column_int64(pFetch, 1);
+ rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock);
+ }
+ rc2 = sqlite3_reset(pFetch);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ while( rc==SQLITE_OK && iBlock ){
+ char *aBlock = 0;
+ int nBlock = 0;
+ iNewStart = iBlock;
+
+ rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0);
+ if( rc==SQLITE_OK ){
+ rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock);
+ }
+ if( rc==SQLITE_OK ){
+ rc = fts3WriteSegment(p, iNewStart, block.a, block.n);
+ }
+ sqlite3_free(aBlock);
+ }
+
+ /* Variable iNewStart now contains the first valid leaf node. */
+ if( rc==SQLITE_OK && iNewStart ){
+ sqlite3_stmt *pDel = 0;
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pDel, 1, iOldStart);
+ sqlite3_bind_int64(pDel, 2, iNewStart-1);
+ sqlite3_step(pDel);
+ rc = sqlite3_reset(pDel);
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ sqlite3_stmt *pChomp = 0;
+ rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pChomp, 1, iNewStart);
+ sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC);
+ sqlite3_bind_int64(pChomp, 3, iAbsLevel);
+ sqlite3_bind_int(pChomp, 4, iIdx);
+ sqlite3_step(pChomp);
+ rc = sqlite3_reset(pChomp);
+ }
+ }
+
+ sqlite3_free(root.a);
+ sqlite3_free(block.a);
+ return rc;
+}
+
+/*
+** This function is called after an incrmental-merge operation has run to
+** merge (or partially merge) two or more segments from absolute level
+** iAbsLevel.
+**
+** Each input segment is either removed from the db completely (if all of
+** its data was copied to the output segment by the incrmerge operation)
+** or modified in place so that it no longer contains those entries that
+** have been duplicated in the output segment.
+*/
+static int fts3IncrmergeChomp(
+ Fts3Table *p, /* FTS table handle */
+ sqlite3_int64 iAbsLevel, /* Absolute level containing segments */
+ Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */
+ int *pnRem /* Number of segments not deleted */
+){
+ int i;
+ int nRem = 0;
+ int rc = SQLITE_OK;
+
+ for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){
+ Fts3SegReader *pSeg = 0;
+ int j;
+
+ /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding
+ ** somewhere in the pCsr->apSegment[] array. */
+ for(j=0; ALWAYS(j<pCsr->nSegment); j++){
+ pSeg = pCsr->apSegment[j];
+ if( pSeg->iIdx==i ) break;
+ }
+ assert( j<pCsr->nSegment && pSeg->iIdx==i );
+
+ if( pSeg->aNode==0 ){
+ /* Seg-reader is at EOF. Remove the entire input segment. */
+ rc = fts3DeleteSegment(p, pSeg);
+ if( rc==SQLITE_OK ){
+ rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx);
+ }
+ *pnRem = 0;
+ }else{
+ /* The incremental merge did not copy all the data from this
+ ** segment to the upper level. The segment is modified in place
+ ** so that it contains no keys smaller than zTerm/nTerm. */
+ const char *zTerm = pSeg->zTerm;
+ int nTerm = pSeg->nTerm;
+ rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm);
+ nRem++;
+ }
+ }
+
+ if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){
+ rc = fts3RepackSegdirLevel(p, iAbsLevel);
+ }
+
+ *pnRem = nRem;
+ return rc;
+}
+
+/*
+** Store an incr-merge hint in the database.
+*/
+static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
+ sqlite3_stmt *pReplace = 0;
+ int rc; /* Return code */
+
+ rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT);
+ sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
+ sqlite3_step(pReplace);
+ rc = sqlite3_reset(pReplace);
+ }
+
+ return rc;
+}
+
+/*
+** Load an incr-merge hint from the database. The incr-merge hint, if one
+** exists, is stored in the rowid==1 row of the %_stat table.
+**
+** If successful, populate blob *pHint with the value read from the %_stat
+** table and return SQLITE_OK. Otherwise, if an error occurs, return an
+** SQLite error code.
+*/
+static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
+ sqlite3_stmt *pSelect = 0;
+ int rc;
+
+ pHint->n = 0;
+ rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT);
+ if( SQLITE_ROW==sqlite3_step(pSelect) ){
+ const char *aHint = sqlite3_column_blob(pSelect, 0);
+ int nHint = sqlite3_column_bytes(pSelect, 0);
+ if( aHint ){
+ blobGrowBuffer(pHint, nHint, &rc);
+ if( rc==SQLITE_OK ){
+ memcpy(pHint->a, aHint, nHint);
+ pHint->n = nHint;
+ }
+ }
+ }
+ rc2 = sqlite3_reset(pSelect);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ return rc;
+}
+
+/*
+** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
+** Otherwise, append an entry to the hint stored in blob *pHint. Each entry
+** consists of two varints, the absolute level number of the input segments
+** and the number of input segments.
+**
+** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs,
+** set *pRc to an SQLite error code before returning.
+*/
+static void fts3IncrmergeHintPush(
+ Blob *pHint, /* Hint blob to append to */
+ i64 iAbsLevel, /* First varint to store in hint */
+ int nInput, /* Second varint to store in hint */
+ int *pRc /* IN/OUT: Error code */
+){
+ blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc);
+ if( *pRc==SQLITE_OK ){
+ pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel);
+ pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput);
+ }
+}
+
+/*
+** Read the last entry (most recently pushed) from the hint blob *pHint
+** and then remove the entry. Write the two values read to *piAbsLevel and
+** *pnInput before returning.
+**
+** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
+** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB.
+*/
+static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
+ const int nHint = pHint->n;
+ int i;
+
+ i = pHint->n-2;
+ while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
+ while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
+
+ pHint->n = i;
+ i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
+ i += sqlite3Fts3GetVarint32(&pHint->a[i], pnInput);
+ if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
+
+ return SQLITE_OK;
+}
+
+
+/*
+** Attempt an incremental merge that writes nMerge leaf blocks.
+**
+** Incremental merges happen nMin segments at a time. The two
+** segments to be merged are the nMin oldest segments (the ones with
+** the smallest indexes) in the highest level that contains at least
+** nMin segments. Multiple merges might occur in an attempt to write the
+** quota of nMerge leaf blocks.
+*/
+SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
+ int rc; /* Return code */
+ int nRem = nMerge; /* Number of leaf pages yet to be written */
+ Fts3MultiSegReader *pCsr; /* Cursor used to read input data */
+ Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */
+ IncrmergeWriter *pWriter; /* Writer object */
+ int nSeg = 0; /* Number of input segments */
+ sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */
+ Blob hint = {0, 0, 0}; /* Hint read from %_stat table */
+ int bDirtyHint = 0; /* True if blob 'hint' has been modified */
+
+ /* Allocate space for the cursor, filter and writer objects */
+ const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
+ pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc);
+ if( !pWriter ) return SQLITE_NOMEM;
+ pFilter = (Fts3SegFilter *)&pWriter[1];
+ pCsr = (Fts3MultiSegReader *)&pFilter[1];
+
+ rc = fts3IncrmergeHintLoad(p, &hint);
+ while( rc==SQLITE_OK && nRem>0 ){
+ const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
+ sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
+ int bUseHint = 0; /* True if attempting to append */
+
+ /* Search the %_segdir table for the absolute level with the smallest
+ ** relative level number that contains at least nMin segments, if any.
+ ** If one is found, set iAbsLevel to the absolute level number and
+ ** nSeg to nMin. If no level with at least nMin segments can be found,
+ ** set nSeg to -1.
+ */
+ rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
+ sqlite3_bind_int(pFindLevel, 1, nMin);
+ if( sqlite3_step(pFindLevel)==SQLITE_ROW ){
+ iAbsLevel = sqlite3_column_int64(pFindLevel, 0);
+ nSeg = nMin;
+ }else{
+ nSeg = -1;
+ }
+ rc = sqlite3_reset(pFindLevel);
+
+ /* If the hint read from the %_stat table is not empty, check if the
+ ** last entry in it specifies a relative level smaller than or equal
+ ** to the level identified by the block above (if any). If so, this
+ ** iteration of the loop will work on merging at the hinted level.
+ */
+ if( rc==SQLITE_OK && hint.n ){
+ int nHint = hint.n;
+ sqlite3_int64 iHintAbsLevel = 0; /* Hint level */
+ int nHintSeg = 0; /* Hint number of segments */
+
+ rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
+ if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
+ iAbsLevel = iHintAbsLevel;
+ nSeg = nHintSeg;
+ bUseHint = 1;
+ bDirtyHint = 1;
+ }else{
+ /* This undoes the effect of the HintPop() above - so that no entry
+ ** is removed from the hint blob. */
+ hint.n = nHint;
+ }
+ }
+
+ /* If nSeg is less that zero, then there is no level with at least
+ ** nMin segments and no hint in the %_stat table. No work to do.
+ ** Exit early in this case. */
+ if( nSeg<0 ) break;
+
+ /* Open a cursor to iterate through the contents of the oldest nSeg
+ ** indexes of absolute level iAbsLevel. If this cursor is opened using
+ ** the 'hint' parameters, it is possible that there are less than nSeg
+ ** segments available in level iAbsLevel. In this case, no work is
+ ** done on iAbsLevel - fall through to the next iteration of the loop
+ ** to start work on some other level. */
+ memset(pWriter, 0, nAlloc);
+ pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
+ if( rc==SQLITE_OK ){
+ rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
+ }
+ if( SQLITE_OK==rc && pCsr->nSegment==nSeg
+ && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
+ && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
+ ){
+ int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
+ rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
+ if( rc==SQLITE_OK ){
+ if( bUseHint && iIdx>0 ){
+ const char *zKey = pCsr->zTerm;
+ int nKey = pCsr->nTerm;
+ rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
+ }else{
+ rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
+ }
+ }
+
+ if( rc==SQLITE_OK && pWriter->nLeafEst ){
+ fts3LogMerge(nSeg, iAbsLevel);
+ do {
+ rc = fts3IncrmergeAppend(p, pWriter, pCsr);
+ if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
+ if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
+ }while( rc==SQLITE_ROW );
+
+ /* Update or delete the input segments */
+ if( rc==SQLITE_OK ){
+ nRem -= (1 + pWriter->nWork);
+ rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg);
+ if( nSeg!=0 ){
+ bDirtyHint = 1;
+ fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc);
+ }
+ }
+ }
+
+ fts3IncrmergeRelease(p, pWriter, &rc);
+ }
+
+ sqlite3Fts3SegReaderFinish(pCsr);
+ }
+
+ /* Write the hint values into the %_stat table for the next incr-merger */
+ if( bDirtyHint && rc==SQLITE_OK ){
+ rc = fts3IncrmergeHintStore(p, &hint);
+ }
+
+ sqlite3_free(pWriter);
+ sqlite3_free(hint.a);
+ return rc;
+}
+
+/*
+** Convert the text beginning at *pz into an integer and return
+** its value. Advance *pz to point to the first character past
+** the integer.
+*/
+static int fts3Getint(const char **pz){
+ const char *z = *pz;
+ int i = 0;
+ while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
+ *pz = z;
+ return i;
+}
+
+/*
+** Process statements of the form:
+**
+** INSERT INTO table(table) VALUES('merge=A,B');
+**
+** A and B are integers that decode to be the number of leaf pages
+** written for the merge, and the minimum number of segments on a level
+** before it will be selected for a merge, respectively.
+*/
+static int fts3DoIncrmerge(
+ Fts3Table *p, /* FTS3 table handle */
+ const char *zParam /* Nul-terminated string containing "A,B" */
+){
+ int rc;
+ int nMin = (FTS3_MERGE_COUNT / 2);
+ int nMerge = 0;
+ const char *z = zParam;
+
+ /* Read the first integer value */
+ nMerge = fts3Getint(&z);
+
+ /* If the first integer value is followed by a ',', read the second
+ ** integer value. */
+ if( z[0]==',' && z[1]!='\0' ){
+ z++;
+ nMin = fts3Getint(&z);
+ }
+
+ if( z[0]!='\0' || nMin<2 ){
+ rc = SQLITE_ERROR;
+ }else{
+ rc = SQLITE_OK;
+ if( !p->bHasStat ){
+ assert( p->bFts4==0 );
+ sqlite3Fts3CreateStatTable(&rc, p);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3Incrmerge(p, nMerge, nMin);
+ }
+ sqlite3Fts3SegmentsClose(p);
+ }
+ return rc;
+}
+
+/*
+** Process statements of the form:
+**
+** INSERT INTO table(table) VALUES('automerge=X');
+**
+** where X is an integer. X==0 means to turn automerge off. X!=0 means
+** turn it on. The setting is persistent.
+*/
+static int fts3DoAutoincrmerge(
+ Fts3Table *p, /* FTS3 table handle */
+ const char *zParam /* Nul-terminated string containing boolean */
+){
+ int rc = SQLITE_OK;
+ sqlite3_stmt *pStmt = 0;
+ p->bAutoincrmerge = fts3Getint(&zParam)!=0;
+ if( !p->bHasStat ){
+ assert( p->bFts4==0 );
+ sqlite3Fts3CreateStatTable(&rc, p);
+ if( rc ) return rc;
+ }
+ rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
+ if( rc ) return rc;;
+ sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
+ sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ return rc;
+}
+
+/*
+** Return a 64-bit checksum for the FTS index entry specified by the
+** arguments to this function.
+*/
+static u64 fts3ChecksumEntry(
+ const char *zTerm, /* Pointer to buffer containing term */
+ int nTerm, /* Size of zTerm in bytes */
+ int iLangid, /* Language id for current row */
+ int iIndex, /* Index (0..Fts3Table.nIndex-1) */
+ i64 iDocid, /* Docid for current row. */
+ int iCol, /* Column number */
+ int iPos /* Position */
+){
+ int i;
+ u64 ret = (u64)iDocid;
+
+ ret += (ret<<3) + iLangid;
+ ret += (ret<<3) + iIndex;
+ ret += (ret<<3) + iCol;
+ ret += (ret<<3) + iPos;
+ for(i=0; i<nTerm; i++) ret += (ret<<3) + zTerm[i];
+
+ return ret;
+}
+
+/*
+** Return a checksum of all entries in the FTS index that correspond to
+** language id iLangid. The checksum is calculated by XORing the checksums
+** of each individual entry (see fts3ChecksumEntry()) together.
+**
+** If successful, the checksum value is returned and *pRc set to SQLITE_OK.
+** Otherwise, if an error occurs, *pRc is set to an SQLite error code. The
+** return value is undefined in this case.
+*/
+static u64 fts3ChecksumIndex(
+ Fts3Table *p, /* FTS3 table handle */
+ int iLangid, /* Language id to return cksum for */
+ int iIndex, /* Index to cksum (0..p->nIndex-1) */
+ int *pRc /* OUT: Return code */
+){
+ Fts3SegFilter filter;
+ Fts3MultiSegReader csr;
+ int rc;
+ u64 cksum = 0;
+
+ assert( *pRc==SQLITE_OK );
+
+ memset(&filter, 0, sizeof(filter));
+ memset(&csr, 0, sizeof(csr));
+ filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
+ filter.flags |= FTS3_SEGMENT_SCAN;
+
+ rc = sqlite3Fts3SegReaderCursor(
+ p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr
+ );
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
+ }
+
+ if( rc==SQLITE_OK ){
+ while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){
+ char *pCsr = csr.aDoclist;
+ char *pEnd = &pCsr[csr.nDoclist];
+
+ i64 iDocid = 0;
+ i64 iCol = 0;
+ i64 iPos = 0;
+
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
+ while( pCsr<pEnd ){
+ i64 iVal = 0;
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
+ if( pCsr<pEnd ){
+ if( iVal==0 || iVal==1 ){
+ iCol = 0;
+ iPos = 0;
+ if( iVal ){
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
+ }else{
+ pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
+ iDocid += iVal;
+ }
+ }else{
+ iPos += (iVal - 2);
+ cksum = cksum ^ fts3ChecksumEntry(
+ csr.zTerm, csr.nTerm, iLangid, iIndex, iDocid,
+ (int)iCol, (int)iPos
+ );
+ }
+ }
+ }
+ }
+ }
+ sqlite3Fts3SegReaderFinish(&csr);
+
+ *pRc = rc;
+ return cksum;
+}
+
+/*
+** Check if the contents of the FTS index match the current contents of the
+** content table. If no error occurs and the contents do match, set *pbOk
+** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk
+** to false before returning.
+**
+** If an error occurs (e.g. an OOM or IO error), return an SQLite error
+** code. The final value of *pbOk is undefined in this case.
+*/
+static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
+ int rc = SQLITE_OK; /* Return code */
+ u64 cksum1 = 0; /* Checksum based on FTS index contents */
+ u64 cksum2 = 0; /* Checksum based on %_content contents */
+ sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */
+
+ /* This block calculates the checksum according to the FTS index. */
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ sqlite3_bind_int(pAllLangid, 1, p->nIndex);
+ while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
+ int iLangid = sqlite3_column_int(pAllLangid, 0);
+ int i;
+ for(i=0; i<p->nIndex; i++){
+ cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc);
+ }
+ }
+ rc2 = sqlite3_reset(pAllLangid);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ /* This block calculates the checksum according to the %_content table */
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
+ sqlite3_stmt *pStmt = 0;
+ char *zSql;
+
+ zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+ sqlite3_free(zSql);
+ }
+
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
+ i64 iDocid = sqlite3_column_int64(pStmt, 0);
+ int iLang = langidFromSelect(p, pStmt);
+ int iCol;
+
+ for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
+ const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
+ int nText = sqlite3_column_bytes(pStmt, iCol+1);
+ sqlite3_tokenizer_cursor *pT = 0;
+
+ rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
+ while( rc==SQLITE_OK ){
+ char const *zToken; /* Buffer containing token */
+ int nToken = 0; /* Number of bytes in token */
+ int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+ int iPos = 0; /* Position of token in zText */
+
+ rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
+ if( rc==SQLITE_OK ){
+ int i;
+ cksum2 = cksum2 ^ fts3ChecksumEntry(
+ zToken, nToken, iLang, 0, iDocid, iCol, iPos
+ );
+ for(i=1; i<p->nIndex; i++){
+ if( p->aIndex[i].nPrefix<=nToken ){
+ cksum2 = cksum2 ^ fts3ChecksumEntry(
+ zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
+ );
+ }
+ }
+ }
+ }
+ if( pT ) pModule->xClose(pT);
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+ }
+ }
+
+ sqlite3_finalize(pStmt);
+ }
+
+ *pbOk = (cksum1==cksum2);
+ return rc;
+}
+
+/*
+** Run the integrity-check. If no error occurs and the current contents of
+** the FTS index are correct, return SQLITE_OK. Or, if the contents of the
+** FTS index are incorrect, return SQLITE_CORRUPT_VTAB.
+**
+** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
+** error code.
+**
+** The integrity-check works as follows. For each token and indexed token
+** prefix in the document set, a 64-bit checksum is calculated (by code
+** in fts3ChecksumEntry()) based on the following:
+**
+** + The index number (0 for the main index, 1 for the first prefix
+** index etc.),
+** + The token (or token prefix) text itself,
+** + The language-id of the row it appears in,
+** + The docid of the row it appears in,
+** + The column it appears in, and
+** + The tokens position within that column.
+**
+** The checksums for all entries in the index are XORed together to create
+** a single checksum for the entire index.
+**
+** The integrity-check code calculates the same checksum in two ways:
+**
+** 1. By scanning the contents of the FTS index, and
+** 2. By scanning and tokenizing the content table.
+**
+** If the two checksums are identical, the integrity-check is deemed to have
+** passed.
+*/
+static int fts3DoIntegrityCheck(
+ Fts3Table *p /* FTS3 table handle */
+){
+ int rc;
+ int bOk = 0;
+ rc = fts3IntegrityCheck(p, &bOk);
+ if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
+ return rc;
+}
+
+/*
+** Handle a 'special' INSERT of the form:
+**
+** "INSERT INTO tbl(tbl) VALUES(<expr>)"
+**
+** Argument pVal contains the result of <expr>. Currently the only
+** meaningful value to insert is the text 'optimize'.
+*/
+static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
+ int rc; /* Return Code */
+ const char *zVal = (const char *)sqlite3_value_text(pVal);
+ int nVal = sqlite3_value_bytes(pVal);
+
+ if( !zVal ){
+ return SQLITE_NOMEM;
+ }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){
+ rc = fts3DoOptimize(p, 0);
+ }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){
+ rc = fts3DoRebuild(p);
+ }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){
+ rc = fts3DoIntegrityCheck(p);
+ }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){
+ rc = fts3DoIncrmerge(p, &zVal[6]);
+ }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
+ rc = fts3DoAutoincrmerge(p, &zVal[10]);
+#ifdef SQLITE_TEST
+ }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
+ p->nNodeSize = atoi(&zVal[9]);
+ rc = SQLITE_OK;
+ }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
+ p->nMaxPendingData = atoi(&zVal[11]);
+ rc = SQLITE_OK;
+#endif
+ }else{
+ rc = SQLITE_ERROR;
+ }
+
+ return rc;
+}
+
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
+/*
+** Delete all cached deferred doclists. Deferred doclists are cached
+** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
+*/
+SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
+ Fts3DeferredToken *pDef;
+ for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
+ fts3PendingListDelete(pDef->pList);
+ pDef->pList = 0;
+ }
+}
+
+/*
+** Free all entries in the pCsr->pDeffered list. Entries are added to
+** this list using sqlite3Fts3DeferToken().
+*/
+SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
+ Fts3DeferredToken *pDef;
+ Fts3DeferredToken *pNext;
+ for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
+ pNext = pDef->pNext;
+ fts3PendingListDelete(pDef->pList);
+ sqlite3_free(pDef);
+ }
+ pCsr->pDeferred = 0;
+}
+
+/*
+** Generate deferred-doclists for all tokens in the pCsr->pDeferred list
+** based on the row that pCsr currently points to.
+**
+** A deferred-doclist is like any other doclist with position information
+** included, except that it only contains entries for a single row of the
+** table, not for all rows.
+*/
+SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
+ int rc = SQLITE_OK; /* Return code */
+ if( pCsr->pDeferred ){
+ int i; /* Used to iterate through table columns */
+ sqlite3_int64 iDocid; /* Docid of the row pCsr points to */
+ Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */
+
+ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
+ sqlite3_tokenizer *pT = p->pTokenizer;
+ sqlite3_tokenizer_module const *pModule = pT->pModule;
+
+ assert( pCsr->isRequireSeek==0 );
+ iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
+
+ for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
+ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
+ sqlite3_tokenizer_cursor *pTC = 0;
+
+ rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
+ while( rc==SQLITE_OK ){
+ char const *zToken; /* Buffer containing token */
+ int nToken = 0; /* Number of bytes in token */
+ int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+ int iPos = 0; /* Position of token in zText */
+
+ rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
+ for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
+ Fts3PhraseToken *pPT = pDef->pToken;
+ if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
+ && (pPT->bFirst==0 || iPos==0)
+ && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
+ && (0==memcmp(zToken, pPT->z, pPT->n))
+ ){
+ fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
+ }
+ }
+ }
+ if( pTC ) pModule->xClose(pTC);
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+ }
+
+ for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
+ if( pDef->pList ){
+ rc = fts3PendingListAppendVarint(&pDef->pList, 0);
+ }
+ }
+ }
+
+ return rc;
+}
+
+SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(
+ Fts3DeferredToken *p,
+ char **ppData,
+ int *pnData
+){
+ char *pRet;
+ int nSkip;
+ sqlite3_int64 dummy;
+
+ *ppData = 0;
+ *pnData = 0;
+
+ if( p->pList==0 ){
+ return SQLITE_OK;
+ }
+
+ pRet = (char *)sqlite3_malloc(p->pList->nData);
+ if( !pRet ) return SQLITE_NOMEM;
+
+ nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
+ *pnData = p->pList->nData - nSkip;
+ *ppData = pRet;
+
+ memcpy(pRet, &p->pList->aData[nSkip], *pnData);
+ return SQLITE_OK;
+}
+
+/*
+** Add an entry for token pToken to the pCsr->pDeferred list.
+*/
+SQLITE_PRIVATE int sqlite3Fts3DeferToken(
+ Fts3Cursor *pCsr, /* Fts3 table cursor */
+ Fts3PhraseToken *pToken, /* Token to defer */
+ int iCol /* Column that token must appear in (or -1) */
+){
+ Fts3DeferredToken *pDeferred;
+ pDeferred = sqlite3_malloc(sizeof(*pDeferred));
+ if( !pDeferred ){
+ return SQLITE_NOMEM;
+ }
+ memset(pDeferred, 0, sizeof(*pDeferred));
+ pDeferred->pToken = pToken;
+ pDeferred->pNext = pCsr->pDeferred;
+ pDeferred->iCol = iCol;
+ pCsr->pDeferred = pDeferred;
+
+ assert( pToken->pDeferred==0 );
+ pToken->pDeferred = pDeferred;
+
+ return SQLITE_OK;
+}
+#endif
+
+/*
+** SQLite value pRowid contains the rowid of a row that may or may not be
+** present in the FTS3 table. If it is, delete it and adjust the contents
+** of subsiduary data structures accordingly.
+*/
+static int fts3DeleteByRowid(
+ Fts3Table *p,
+ sqlite3_value *pRowid,
+ int *pnChng, /* IN/OUT: Decrement if row is deleted */
+ u32 *aSzDel
+){
+ int rc = SQLITE_OK; /* Return code */
+ int bFound = 0; /* True if *pRowid really is in the table */
+
+ fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound);
+ if( bFound && rc==SQLITE_OK ){
+ int isEmpty = 0; /* Deleting *pRowid leaves the table empty */
+ rc = fts3IsEmpty(p, pRowid, &isEmpty);
+ if( rc==SQLITE_OK ){
+ if( isEmpty ){
+ /* Deleting this row means the whole table is empty. In this case
+ ** delete the contents of all three tables and throw away any
+ ** data in the pendingTerms hash table. */
+ rc = fts3DeleteAll(p, 1);
+ *pnChng = 0;
+ memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2);
+ }else{
+ *pnChng = *pnChng - 1;
+ if( p->zContentTbl==0 ){
+ fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
+ }
+ if( p->bHasDocsize ){
+ fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+** This function does the work for the xUpdate method of FTS3 virtual
+** tables. The schema of the virtual table being:
+**
+** CREATE TABLE <table name>(
+** <user columns>,
+** <table name> HIDDEN,
+** docid HIDDEN,
+** <langid> HIDDEN
+** );
+**
+**
+*/
+SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
+ sqlite3_vtab *pVtab, /* FTS3 vtab object */
+ int nArg, /* Size of argument array */
+ sqlite3_value **apVal, /* Array of arguments */
+ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
+){
+ Fts3Table *p = (Fts3Table *)pVtab;
+ int rc = SQLITE_OK; /* Return Code */
+ int isRemove = 0; /* True for an UPDATE or DELETE */
+ u32 *aSzIns = 0; /* Sizes of inserted documents */
+ u32 *aSzDel = 0; /* Sizes of deleted documents */
+ int nChng = 0; /* Net change in number of documents */
+ int bInsertDone = 0;
+
+ assert( p->pSegments==0 );
+ assert(
+ nArg==1 /* DELETE operations */
+ || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */
+ );
+
+ /* Check for a "special" INSERT operation. One of the form:
+ **
+ ** INSERT INTO xyz(xyz) VALUES('command');
+ */
+ if( nArg>1
+ && sqlite3_value_type(apVal[0])==SQLITE_NULL
+ && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
+ ){
+ rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
+ goto update_out;
+ }
+
+ if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){
+ rc = SQLITE_CONSTRAINT;
+ goto update_out;
+ }
+
+ /* Allocate space to hold the change in document sizes */
+ aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
+ if( aSzDel==0 ){
+ rc = SQLITE_NOMEM;
+ goto update_out;
+ }
+ aSzIns = &aSzDel[p->nColumn+1];
+ memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
+
+ /* If this is an INSERT operation, or an UPDATE that modifies the rowid
+ ** value, then this operation requires constraint handling.
+ **
+ ** If the on-conflict mode is REPLACE, this means that the existing row
+ ** should be deleted from the database before inserting the new row. Or,
+ ** if the on-conflict mode is other than REPLACE, then this method must
+ ** detect the conflict and return SQLITE_CONSTRAINT before beginning to
+ ** modify the database file.
+ */
+ if( nArg>1 && p->zContentTbl==0 ){
+ /* Find the value object that holds the new rowid value. */
+ sqlite3_value *pNewRowid = apVal[3+p->nColumn];
+ if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){
+ pNewRowid = apVal[1];
+ }
+
+ if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
+ sqlite3_value_type(apVal[0])==SQLITE_NULL
+ || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
+ )){
+ /* The new rowid is not NULL (in this case the rowid will be
+ ** automatically assigned and there is no chance of a conflict), and
+ ** the statement is either an INSERT or an UPDATE that modifies the
+ ** rowid column. So if the conflict mode is REPLACE, then delete any
+ ** existing row with rowid=pNewRowid.
+ **
+ ** Or, if the conflict mode is not REPLACE, insert the new record into
+ ** the %_content table. If we hit the duplicate rowid constraint (or any
+ ** other error) while doing so, return immediately.
+ **
+ ** This branch may also run if pNewRowid contains a value that cannot
+ ** be losslessly converted to an integer. In this case, the eventual
+ ** call to fts3InsertData() (either just below or further on in this
+ ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
+ ** invoked, it will delete zero rows (since no row will have
+ ** docid=$pNewRowid if $pNewRowid is not an integer value).
+ */
+ if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){
+ rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel);
+ }else{
+ rc = fts3InsertData(p, apVal, pRowid);
+ bInsertDone = 1;
+ }
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ goto update_out;
+ }
+
+ /* If this is a DELETE or UPDATE operation, remove the old record. */
+ if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
+ assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
+ rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
+ isRemove = 1;
+ }
+
+ /* If this is an INSERT or UPDATE operation, insert the new record. */
+ if( nArg>1 && rc==SQLITE_OK ){
+ int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]);
+ if( bInsertDone==0 ){
+ rc = fts3InsertData(p, apVal, pRowid);
+ if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
+ rc = FTS_CORRUPT_VTAB;
+ }
+ }
+ if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
+ rc = fts3PendingTermsDocid(p, iLangid, *pRowid);
+ }
+ if( rc==SQLITE_OK ){
+ assert( p->iPrevDocid==*pRowid );
+ rc = fts3InsertTerms(p, iLangid, apVal, aSzIns);
+ }
+ if( p->bHasDocsize ){
+ fts3InsertDocsize(&rc, p, aSzIns);
+ }
+ nChng++;
+ }
+
+ if( p->bFts4 ){
+ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
+ }
+
+ update_out:
+ sqlite3_free(aSzDel);
+ sqlite3Fts3SegmentsClose(p);
+ return rc;
+}
+
+/*
+** Flush any data in the pending-terms hash table to disk. If successful,
+** merge all segments in the database (including the new segment, if
+** there was any data to flush) into a single segment.
+*/
+SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
+ int rc;
+ rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = fts3DoOptimize(p, 1);
+ if( rc==SQLITE_OK || rc==SQLITE_DONE ){
+ int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
+ if( rc2!=SQLITE_OK ) rc = rc2;
+ }else{
+ sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0);
+ sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0);
+ }
+ }
+ sqlite3Fts3SegmentsClose(p);
+ return rc;
+}
+
+#endif
+
+/************** End of fts3_write.c ******************************************/
+/************** Begin file fts3_snippet.c ************************************/
+/*
+** 2009 Oct 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+*/
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <string.h> */
+/* #include <assert.h> */
+
+/*
+** Characters that may appear in the second argument to matchinfo().
+*/
+#define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */
+#define FTS3_MATCHINFO_NCOL 'c' /* 1 value */
+#define FTS3_MATCHINFO_NDOC 'n' /* 1 value */
+#define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */
+#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */
+#define FTS3_MATCHINFO_LCS 's' /* nCol values */
+#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */
+
+/*
+** The default value for the second argument to matchinfo().
+*/
+#define FTS3_MATCHINFO_DEFAULT "pcx"
+
+
+/*
+** Used as an fts3ExprIterate() context when loading phrase doclists to
+** Fts3Expr.aDoclist[]/nDoclist.
+*/
+typedef struct LoadDoclistCtx LoadDoclistCtx;
+struct LoadDoclistCtx {
+ Fts3Cursor *pCsr; /* FTS3 Cursor */
+ int nPhrase; /* Number of phrases seen so far */
+ int nToken; /* Number of tokens seen so far */
+};
+
+/*
+** The following types are used as part of the implementation of the
+** fts3BestSnippet() routine.
+*/
+typedef struct SnippetIter SnippetIter;
+typedef struct SnippetPhrase SnippetPhrase;
+typedef struct SnippetFragment SnippetFragment;
+
+struct SnippetIter {
+ Fts3Cursor *pCsr; /* Cursor snippet is being generated from */
+ int iCol; /* Extract snippet from this column */
+ int nSnippet; /* Requested snippet length (in tokens) */
+ int nPhrase; /* Number of phrases in query */
+ SnippetPhrase *aPhrase; /* Array of size nPhrase */
+ int iCurrent; /* First token of current snippet */
+};
+
+struct SnippetPhrase {
+ int nToken; /* Number of tokens in phrase */
+ char *pList; /* Pointer to start of phrase position list */
+ int iHead; /* Next value in position list */
+ char *pHead; /* Position list data following iHead */
+ int iTail; /* Next value in trailing position list */
+ char *pTail; /* Position list data following iTail */
+};
+
+struct SnippetFragment {
+ int iCol; /* Column snippet is extracted from */
+ int iPos; /* Index of first token in snippet */
+ u64 covered; /* Mask of query phrases covered */
+ u64 hlmask; /* Mask of snippet terms to highlight */
+};
+
+/*
+** This type is used as an fts3ExprIterate() context object while
+** accumulating the data returned by the matchinfo() function.
+*/
+typedef struct MatchInfo MatchInfo;
+struct MatchInfo {
+ Fts3Cursor *pCursor; /* FTS3 Cursor */
+ int nCol; /* Number of columns in table */
+ int nPhrase; /* Number of matchable phrases in query */
+ sqlite3_int64 nDoc; /* Number of docs in database */
+ u32 *aMatchinfo; /* Pre-allocated buffer */
+};
+
+
+
+/*
+** The snippet() and offsets() functions both return text values. An instance
+** of the following structure is used to accumulate those values while the
+** functions are running. See fts3StringAppend() for details.
+*/
+typedef struct StrBuffer StrBuffer;
+struct StrBuffer {
+ char *z; /* Pointer to buffer containing string */
+ int n; /* Length of z in bytes (excl. nul-term) */
+ int nAlloc; /* Allocated size of buffer z in bytes */
+};
+
+
+/*
+** This function is used to help iterate through a position-list. A position
+** list is a list of unique integers, sorted from smallest to largest. Each
+** element of the list is represented by an FTS3 varint that takes the value
+** of the difference between the current element and the previous one plus
+** two. For example, to store the position-list:
+**
+** 4 9 113
+**
+** the three varints:
+**
+** 6 7 106
+**
+** are encoded.
+**
+** When this function is called, *pp points to the start of an element of
+** the list. *piPos contains the value of the previous entry in the list.
+** After it returns, *piPos contains the value of the next element of the
+** list and *pp is advanced to the following varint.
+*/
+static void fts3GetDeltaPosition(char **pp, int *piPos){
+ int iVal;
+ *pp += sqlite3Fts3GetVarint32(*pp, &iVal);
+ *piPos += (iVal-2);
+}
+
+/*
+** Helper function for fts3ExprIterate() (see below).
+*/
+static int fts3ExprIterate2(
+ Fts3Expr *pExpr, /* Expression to iterate phrases of */
+ int *piPhrase, /* Pointer to phrase counter */
+ int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
+ void *pCtx /* Second argument to pass to callback */
+){
+ int rc; /* Return code */
+ int eType = pExpr->eType; /* Type of expression node pExpr */
+
+ if( eType!=FTSQUERY_PHRASE ){
+ assert( pExpr->pLeft && pExpr->pRight );
+ rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx);
+ if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){
+ rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx);
+ }
+ }else{
+ rc = x(pExpr, *piPhrase, pCtx);
+ (*piPhrase)++;
+ }
+ return rc;
+}
+
+/*
+** Iterate through all phrase nodes in an FTS3 query, except those that
+** are part of a sub-tree that is the right-hand-side of a NOT operator.
+** For each phrase node found, the supplied callback function is invoked.
+**
+** If the callback function returns anything other than SQLITE_OK,
+** the iteration is abandoned and the error code returned immediately.
+** Otherwise, SQLITE_OK is returned after a callback has been made for
+** all eligible phrase nodes.
+*/
+static int fts3ExprIterate(
+ Fts3Expr *pExpr, /* Expression to iterate phrases of */
+ int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
+ void *pCtx /* Second argument to pass to callback */
+){
+ int iPhrase = 0; /* Variable used as the phrase counter */
+ return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
+}
+
+/*
+** This is an fts3ExprIterate() callback used while loading the doclists
+** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
+** fts3ExprLoadDoclists().
+*/
+static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
+ int rc = SQLITE_OK;
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
+
+ UNUSED_PARAMETER(iPhrase);
+
+ p->nPhrase++;
+ p->nToken += pPhrase->nToken;
+
+ return rc;
+}
+
+/*
+** Load the doclists for each phrase in the query associated with FTS3 cursor
+** pCsr.
+**
+** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable
+** phrases in the expression (all phrases except those directly or
+** indirectly descended from the right-hand-side of a NOT operator). If
+** pnToken is not NULL, then it is set to the number of tokens in all
+** matchable phrases of the expression.
+*/
+static int fts3ExprLoadDoclists(
+ Fts3Cursor *pCsr, /* Fts3 cursor for current query */
+ int *pnPhrase, /* OUT: Number of phrases in query */
+ int *pnToken /* OUT: Number of tokens in query */
+){
+ int rc; /* Return Code */
+ LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */
+ sCtx.pCsr = pCsr;
+ rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx);
+ if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
+ if( pnToken ) *pnToken = sCtx.nToken;
+ return rc;
+}
+
+static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
+ (*(int *)ctx)++;
+ UNUSED_PARAMETER(pExpr);
+ UNUSED_PARAMETER(iPhrase);
+ return SQLITE_OK;
+}
+static int fts3ExprPhraseCount(Fts3Expr *pExpr){
+ int nPhrase = 0;
+ (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase);
+ return nPhrase;
+}
+
+/*
+** Advance the position list iterator specified by the first two
+** arguments so that it points to the first element with a value greater
+** than or equal to parameter iNext.
+*/
+static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
+ char *pIter = *ppIter;
+ if( pIter ){
+ int iIter = *piIter;
+
+ while( iIter<iNext ){
+ if( 0==(*pIter & 0xFE) ){
+ iIter = -1;
+ pIter = 0;
+ break;
+ }
+ fts3GetDeltaPosition(&pIter, &iIter);
+ }
+
+ *piIter = iIter;
+ *ppIter = pIter;
+ }
+}
+
+/*
+** Advance the snippet iterator to the next candidate snippet.
+*/
+static int fts3SnippetNextCandidate(SnippetIter *pIter){
+ int i; /* Loop counter */
+
+ if( pIter->iCurrent<0 ){
+ /* The SnippetIter object has just been initialized. The first snippet
+ ** candidate always starts at offset 0 (even if this candidate has a
+ ** score of 0.0).
+ */
+ pIter->iCurrent = 0;
+
+ /* Advance the 'head' iterator of each phrase to the first offset that
+ ** is greater than or equal to (iNext+nSnippet).
+ */
+ for(i=0; i<pIter->nPhrase; i++){
+ SnippetPhrase *pPhrase = &pIter->aPhrase[i];
+ fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet);
+ }
+ }else{
+ int iStart;
+ int iEnd = 0x7FFFFFFF;
+
+ for(i=0; i<pIter->nPhrase; i++){
+ SnippetPhrase *pPhrase = &pIter->aPhrase[i];
+ if( pPhrase->pHead && pPhrase->iHead<iEnd ){
+ iEnd = pPhrase->iHead;
+ }
+ }
+ if( iEnd==0x7FFFFFFF ){
+ return 1;
+ }
+
+ pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1;
+ for(i=0; i<pIter->nPhrase; i++){
+ SnippetPhrase *pPhrase = &pIter->aPhrase[i];
+ fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1);
+ fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart);
+ }
+ }
+
+ return 0;
+}
+
+/*
+** Retrieve information about the current candidate snippet of snippet
+** iterator pIter.
+*/
+static void fts3SnippetDetails(
+ SnippetIter *pIter, /* Snippet iterator */
+ u64 mCovered, /* Bitmask of phrases already covered */
+ int *piToken, /* OUT: First token of proposed snippet */
+ int *piScore, /* OUT: "Score" for this snippet */
+ u64 *pmCover, /* OUT: Bitmask of phrases covered */
+ u64 *pmHighlight /* OUT: Bitmask of terms to highlight */
+){
+ int iStart = pIter->iCurrent; /* First token of snippet */
+ int iScore = 0; /* Score of this snippet */
+ int i; /* Loop counter */
+ u64 mCover = 0; /* Mask of phrases covered by this snippet */
+ u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */
+
+ for(i=0; i<pIter->nPhrase; i++){
+ SnippetPhrase *pPhrase = &pIter->aPhrase[i];
+ if( pPhrase->pTail ){
+ char *pCsr = pPhrase->pTail;
+ int iCsr = pPhrase->iTail;
+
+ while( iCsr<(iStart+pIter->nSnippet) ){
+ int j;
+ u64 mPhrase = (u64)1 << i;
+ u64 mPos = (u64)1 << (iCsr - iStart);
+ assert( iCsr>=iStart );
+ if( (mCover|mCovered)&mPhrase ){
+ iScore++;
+ }else{
+ iScore += 1000;
+ }
+ mCover |= mPhrase;
+
+ for(j=0; j<pPhrase->nToken; j++){
+ mHighlight |= (mPos>>j);
+ }
+
+ if( 0==(*pCsr & 0x0FE) ) break;
+ fts3GetDeltaPosition(&pCsr, &iCsr);
+ }
+ }
+ }
+
+ /* Set the output variables before returning. */
+ *piToken = iStart;
+ *piScore = iScore;
+ *pmCover = mCover;
+ *pmHighlight = mHighlight;
+}
+
+/*
+** This function is an fts3ExprIterate() callback used by fts3BestSnippet().
+** Each invocation populates an element of the SnippetIter.aPhrase[] array.
+*/
+static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
+ SnippetIter *p = (SnippetIter *)ctx;
+ SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
+ char *pCsr;
+ int rc;
+
+ pPhrase->nToken = pExpr->pPhrase->nToken;
+ rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
+ assert( rc==SQLITE_OK || pCsr==0 );
+ if( pCsr ){
+ int iFirst = 0;
+ pPhrase->pList = pCsr;
+ fts3GetDeltaPosition(&pCsr, &iFirst);
+ assert( iFirst>=0 );
+ pPhrase->pHead = pCsr;
+ pPhrase->pTail = pCsr;
+ pPhrase->iHead = iFirst;
+ pPhrase->iTail = iFirst;
+ }else{
+ assert( rc!=SQLITE_OK || (
+ pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
+ ));
+ }
+
+ return rc;
+}
+
+/*
+** Select the fragment of text consisting of nFragment contiguous tokens
+** from column iCol that represent the "best" snippet. The best snippet
+** is the snippet with the highest score, where scores are calculated
+** by adding:
+**
+** (a) +1 point for each occurrence of a matchable phrase in the snippet.
+**
+** (b) +1000 points for the first occurrence of each matchable phrase in
+** the snippet for which the corresponding mCovered bit is not set.
+**
+** The selected snippet parameters are stored in structure *pFragment before
+** returning. The score of the selected snippet is stored in *piScore
+** before returning.
+*/
+static int fts3BestSnippet(
+ int nSnippet, /* Desired snippet length */
+ Fts3Cursor *pCsr, /* Cursor to create snippet for */
+ int iCol, /* Index of column to create snippet from */
+ u64 mCovered, /* Mask of phrases already covered */
+ u64 *pmSeen, /* IN/OUT: Mask of phrases seen */
+ SnippetFragment *pFragment, /* OUT: Best snippet found */
+ int *piScore /* OUT: Score of snippet pFragment */
+){
+ int rc; /* Return Code */
+ int nList; /* Number of phrases in expression */
+ SnippetIter sIter; /* Iterates through snippet candidates */
+ int nByte; /* Number of bytes of space to allocate */
+ int iBestScore = -1; /* Best snippet score found so far */
+ int i; /* Loop counter */
+
+ memset(&sIter, 0, sizeof(sIter));
+
+ /* Iterate through the phrases in the expression to count them. The same
+ ** callback makes sure the doclists are loaded for each phrase.
+ */
+ rc = fts3ExprLoadDoclists(pCsr, &nList, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* Now that it is known how many phrases there are, allocate and zero
+ ** the required space using malloc().
+ */
+ nByte = sizeof(SnippetPhrase) * nList;
+ sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
+ if( !sIter.aPhrase ){
+ return SQLITE_NOMEM;
+ }
+ memset(sIter.aPhrase, 0, nByte);
+
+ /* Initialize the contents of the SnippetIter object. Then iterate through
+ ** the set of phrases in the expression to populate the aPhrase[] array.
+ */
+ sIter.pCsr = pCsr;
+ sIter.iCol = iCol;
+ sIter.nSnippet = nSnippet;
+ sIter.nPhrase = nList;
+ sIter.iCurrent = -1;
+ (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter);
+
+ /* Set the *pmSeen output variable. */
+ for(i=0; i<nList; i++){
+ if( sIter.aPhrase[i].pHead ){
+ *pmSeen |= (u64)1 << i;
+ }
+ }
+
+ /* Loop through all candidate snippets. Store the best snippet in
+ ** *pFragment. Store its associated 'score' in iBestScore.
+ */
+ pFragment->iCol = iCol;
+ while( !fts3SnippetNextCandidate(&sIter) ){
+ int iPos;
+ int iScore;
+ u64 mCover;
+ u64 mHighlight;
+ fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight);
+ assert( iScore>=0 );
+ if( iScore>iBestScore ){
+ pFragment->iPos = iPos;
+ pFragment->hlmask = mHighlight;
+ pFragment->covered = mCover;
+ iBestScore = iScore;
+ }
+ }
+
+ sqlite3_free(sIter.aPhrase);
+ *piScore = iBestScore;
+ return SQLITE_OK;
+}
+
+
+/*
+** Append a string to the string-buffer passed as the first argument.
+**
+** If nAppend is negative, then the length of the string zAppend is
+** determined using strlen().
+*/
+static int fts3StringAppend(
+ StrBuffer *pStr, /* Buffer to append to */
+ const char *zAppend, /* Pointer to data to append to buffer */
+ int nAppend /* Size of zAppend in bytes (or -1) */
+){
+ if( nAppend<0 ){
+ nAppend = (int)strlen(zAppend);
+ }
+
+ /* If there is insufficient space allocated at StrBuffer.z, use realloc()
+ ** to grow the buffer until so that it is big enough to accomadate the
+ ** appended data.
+ */
+ if( pStr->n+nAppend+1>=pStr->nAlloc ){
+ int nAlloc = pStr->nAlloc+nAppend+100;
+ char *zNew = sqlite3_realloc(pStr->z, nAlloc);
+ if( !zNew ){
+ return SQLITE_NOMEM;
+ }
+ pStr->z = zNew;
+ pStr->nAlloc = nAlloc;
+ }
+
+ /* Append the data to the string buffer. */
+ memcpy(&pStr->z[pStr->n], zAppend, nAppend);
+ pStr->n += nAppend;
+ pStr->z[pStr->n] = '\0';
+
+ return SQLITE_OK;
+}
+
+/*
+** The fts3BestSnippet() function often selects snippets that end with a
+** query term. That is, the final term of the snippet is always a term
+** that requires highlighting. For example, if 'X' is a highlighted term
+** and '.' is a non-highlighted term, BestSnippet() may select:
+**
+** ........X.....X
+**
+** This function "shifts" the beginning of the snippet forward in the
+** document so that there are approximately the same number of
+** non-highlighted terms to the right of the final highlighted term as there
+** are to the left of the first highlighted term. For example, to this:
+**
+** ....X.....X....
+**
+** This is done as part of extracting the snippet text, not when selecting
+** the snippet. Snippet selection is done based on doclists only, so there
+** is no way for fts3BestSnippet() to know whether or not the document
+** actually contains terms that follow the final highlighted term.
+*/
+static int fts3SnippetShift(
+ Fts3Table *pTab, /* FTS3 table snippet comes from */
+ int iLangid, /* Language id to use in tokenizing */
+ int nSnippet, /* Number of tokens desired for snippet */
+ const char *zDoc, /* Document text to extract snippet from */
+ int nDoc, /* Size of buffer zDoc in bytes */
+ int *piPos, /* IN/OUT: First token of snippet */
+ u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
+){
+ u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */
+
+ if( hlmask ){
+ int nLeft; /* Tokens to the left of first highlight */
+ int nRight; /* Tokens to the right of last highlight */
+ int nDesired; /* Ideal number of tokens to shift forward */
+
+ for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
+ for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
+ nDesired = (nLeft-nRight)/2;
+
+ /* Ideally, the start of the snippet should be pushed forward in the
+ ** document nDesired tokens. This block checks if there are actually
+ ** nDesired tokens to the right of the snippet. If so, *piPos and
+ ** *pHlMask are updated to shift the snippet nDesired tokens to the
+ ** right. Otherwise, the snippet is shifted by the number of tokens
+ ** available.
+ */
+ if( nDesired>0 ){
+ int nShift; /* Number of tokens to shift snippet by */
+ int iCurrent = 0; /* Token counter */
+ int rc; /* Return Code */
+ sqlite3_tokenizer_module *pMod;
+ sqlite3_tokenizer_cursor *pC;
+ pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
+
+ /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
+ ** or more tokens in zDoc/nDoc.
+ */
+ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
+ const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0;
+ rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
+ }
+ pMod->xClose(pC);
+ if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; }
+
+ nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet;
+ assert( nShift<=nDesired );
+ if( nShift>0 ){
+ *piPos += nShift;
+ *pHlmask = hlmask >> nShift;
+ }
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Extract the snippet text for fragment pFragment from cursor pCsr and
+** append it to string buffer pOut.
+*/
+static int fts3SnippetText(
+ Fts3Cursor *pCsr, /* FTS3 Cursor */
+ SnippetFragment *pFragment, /* Snippet to extract */
+ int iFragment, /* Fragment number */
+ int isLast, /* True for final fragment in snippet */
+ int nSnippet, /* Number of tokens in extracted snippet */
+ const char *zOpen, /* String inserted before highlighted term */
+ const char *zClose, /* String inserted after highlighted term */
+ const char *zEllipsis, /* String inserted between snippets */
+ StrBuffer *pOut /* Write output here */
+){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int rc; /* Return code */
+ const char *zDoc; /* Document text to extract snippet from */
+ int nDoc; /* Size of zDoc in bytes */
+ int iCurrent = 0; /* Current token number of document */
+ int iEnd = 0; /* Byte offset of end of current token */
+ int isShiftDone = 0; /* True after snippet is shifted */
+ int iPos = pFragment->iPos; /* First token of snippet */
+ u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */
+ int iCol = pFragment->iCol+1; /* Query column to extract text from */
+ sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
+ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */
+
+ zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
+ if( zDoc==0 ){
+ if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){
+ return SQLITE_NOMEM;
+ }
+ return SQLITE_OK;
+ }
+ nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
+
+ /* Open a token cursor on the document. */
+ pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
+ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ while( rc==SQLITE_OK ){
+ const char *ZDUMMY; /* Dummy argument used with tokenizer */
+ int DUMMY1 = -1; /* Dummy argument used with tokenizer */
+ int iBegin = 0; /* Offset in zDoc of start of token */
+ int iFin = 0; /* Offset in zDoc of end of token */
+ int isHighlight = 0; /* True for highlighted terms */
+
+ /* Variable DUMMY1 is initialized to a negative value above. Elsewhere
+ ** in the FTS code the variable that the third argument to xNext points to
+ ** is initialized to zero before the first (*but not necessarily
+ ** subsequent*) call to xNext(). This is done for a particular application
+ ** that needs to know whether or not the tokenizer is being used for
+ ** snippet generation or for some other purpose.
+ **
+ ** Extreme care is required when writing code to depend on this
+ ** initialization. It is not a documented part of the tokenizer interface.
+ ** If a tokenizer is used directly by any code outside of FTS, this
+ ** convention might not be respected. */
+ rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_DONE ){
+ /* Special case - the last token of the snippet is also the last token
+ ** of the column. Append any punctuation that occurred between the end
+ ** of the previous token and the end of the document to the output.
+ ** Then break out of the loop. */
+ rc = fts3StringAppend(pOut, &zDoc[iEnd], -1);
+ }
+ break;
+ }
+ if( iCurrent<iPos ){ continue; }
+
+ if( !isShiftDone ){
+ int n = nDoc - iBegin;
+ rc = fts3SnippetShift(
+ pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask
+ );
+ isShiftDone = 1;
+
+ /* Now that the shift has been done, check if the initial "..." are
+ ** required. They are required if (a) this is not the first fragment,
+ ** or (b) this fragment does not begin at position 0 of its column.
+ */
+ if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){
+ rc = fts3StringAppend(pOut, zEllipsis, -1);
+ }
+ if( rc!=SQLITE_OK || iCurrent<iPos ) continue;
+ }
+
+ if( iCurrent>=(iPos+nSnippet) ){
+ if( isLast ){
+ rc = fts3StringAppend(pOut, zEllipsis, -1);
+ }
+ break;
+ }
+
+ /* Set isHighlight to true if this term should be highlighted. */
+ isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0;
+
+ if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd);
+ if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1);
+ if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin);
+ if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1);
+
+ iEnd = iFin;
+ }
+
+ pMod->xClose(pC);
+ return rc;
+}
+
+
+/*
+** This function is used to count the entries in a column-list (a
+** delta-encoded list of term offsets within a single column of a single
+** row). When this function is called, *ppCollist should point to the
+** beginning of the first varint in the column-list (the varint that
+** contains the position of the first matching term in the column data).
+** Before returning, *ppCollist is set to point to the first byte after
+** the last varint in the column-list (either the 0x00 signifying the end
+** of the position-list, or the 0x01 that precedes the column number of
+** the next column in the position-list).
+**
+** The number of elements in the column-list is returned.
+*/
+static int fts3ColumnlistCount(char **ppCollist){
+ char *pEnd = *ppCollist;
+ char c = 0;
+ int nEntry = 0;
+
+ /* A column-list is terminated by either a 0x01 or 0x00. */
+ while( 0xFE & (*pEnd | c) ){
+ c = *pEnd++ & 0x80;
+ if( !c ) nEntry++;
+ }
+
+ *ppCollist = pEnd;
+ return nEntry;
+}
+
+/*
+** fts3ExprIterate() callback used to collect the "global" matchinfo stats
+** for a single query.
+**
+** fts3ExprIterate() callback to load the 'global' elements of a
+** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements
+** of the matchinfo array that are constant for all rows returned by the
+** current query.
+**
+** Argument pCtx is actually a pointer to a struct of type MatchInfo. This
+** function populates Matchinfo.aMatchinfo[] as follows:
+**
+** for(iCol=0; iCol<nCol; iCol++){
+** aMatchinfo[3*iPhrase*nCol + 3*iCol + 1] = X;
+** aMatchinfo[3*iPhrase*nCol + 3*iCol + 2] = Y;
+** }
+**
+** where X is the number of matches for phrase iPhrase is column iCol of all
+** rows of the table. Y is the number of rows for which column iCol contains
+** at least one instance of phrase iPhrase.
+**
+** If the phrase pExpr consists entirely of deferred tokens, then all X and
+** Y values are set to nDoc, where nDoc is the number of documents in the
+** file system. This is done because the full-text index doclist is required
+** to calculate these values properly, and the full-text index doclist is
+** not available for deferred tokens.
+*/
+static int fts3ExprGlobalHitsCb(
+ Fts3Expr *pExpr, /* Phrase expression node */
+ int iPhrase, /* Phrase number (numbered from zero) */
+ void *pCtx /* Pointer to MatchInfo structure */
+){
+ MatchInfo *p = (MatchInfo *)pCtx;
+ return sqlite3Fts3EvalPhraseStats(
+ p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol]
+ );
+}
+
+/*
+** fts3ExprIterate() callback used to collect the "local" part of the
+** FTS3_MATCHINFO_HITS array. The local stats are those elements of the
+** array that are different for each row returned by the query.
+*/
+static int fts3ExprLocalHitsCb(
+ Fts3Expr *pExpr, /* Phrase expression node */
+ int iPhrase, /* Phrase number */
+ void *pCtx /* Pointer to MatchInfo structure */
+){
+ int rc = SQLITE_OK;
+ MatchInfo *p = (MatchInfo *)pCtx;
+ int iStart = iPhrase * p->nCol * 3;
+ int i;
+
+ for(i=0; i<p->nCol && rc==SQLITE_OK; i++){
+ char *pCsr;
+ rc = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i, &pCsr);
+ if( pCsr ){
+ p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr);
+ }else{
+ p->aMatchinfo[iStart+i*3] = 0;
+ }
+ }
+
+ return rc;
+}
+
+static int fts3MatchinfoCheck(
+ Fts3Table *pTab,
+ char cArg,
+ char **pzErr
+){
+ if( (cArg==FTS3_MATCHINFO_NPHRASE)
+ || (cArg==FTS3_MATCHINFO_NCOL)
+ || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4)
+ || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4)
+ || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
+ || (cArg==FTS3_MATCHINFO_LCS)
+ || (cArg==FTS3_MATCHINFO_HITS)
+ ){
+ return SQLITE_OK;
+ }
+ *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg);
+ return SQLITE_ERROR;
+}
+
+static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
+ int nVal; /* Number of integers output by cArg */
+
+ switch( cArg ){
+ case FTS3_MATCHINFO_NDOC:
+ case FTS3_MATCHINFO_NPHRASE:
+ case FTS3_MATCHINFO_NCOL:
+ nVal = 1;
+ break;
+
+ case FTS3_MATCHINFO_AVGLENGTH:
+ case FTS3_MATCHINFO_LENGTH:
+ case FTS3_MATCHINFO_LCS:
+ nVal = pInfo->nCol;
+ break;
+
+ default:
+ assert( cArg==FTS3_MATCHINFO_HITS );
+ nVal = pInfo->nCol * pInfo->nPhrase * 3;
+ break;
+ }
+
+ return nVal;
+}
+
+static int fts3MatchinfoSelectDoctotal(
+ Fts3Table *pTab,
+ sqlite3_stmt **ppStmt,
+ sqlite3_int64 *pnDoc,
+ const char **paLen
+){
+ sqlite3_stmt *pStmt;
+ const char *a;
+ sqlite3_int64 nDoc;
+
+ if( !*ppStmt ){
+ int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ pStmt = *ppStmt;
+ assert( sqlite3_data_count(pStmt)==1 );
+
+ a = sqlite3_column_blob(pStmt, 0);
+ a += sqlite3Fts3GetVarint(a, &nDoc);
+ if( nDoc==0 ) return FTS_CORRUPT_VTAB;
+ *pnDoc = (u32)nDoc;
+
+ if( paLen ) *paLen = a;
+ return SQLITE_OK;
+}
+
+/*
+** An instance of the following structure is used to store state while
+** iterating through a multi-column position-list corresponding to the
+** hits for a single phrase on a single row in order to calculate the
+** values for a matchinfo() FTS3_MATCHINFO_LCS request.
+*/
+typedef struct LcsIterator LcsIterator;
+struct LcsIterator {
+ Fts3Expr *pExpr; /* Pointer to phrase expression */
+ int iPosOffset; /* Tokens count up to end of this phrase */
+ char *pRead; /* Cursor used to iterate through aDoclist */
+ int iPos; /* Current position */
+};
+
+/*
+** If LcsIterator.iCol is set to the following value, the iterator has
+** finished iterating through all offsets for all columns.
+*/
+#define LCS_ITERATOR_FINISHED 0x7FFFFFFF;
+
+static int fts3MatchinfoLcsCb(
+ Fts3Expr *pExpr, /* Phrase expression node */
+ int iPhrase, /* Phrase number (numbered from zero) */
+ void *pCtx /* Pointer to MatchInfo structure */
+){
+ LcsIterator *aIter = (LcsIterator *)pCtx;
+ aIter[iPhrase].pExpr = pExpr;
+ return SQLITE_OK;
+}
+
+/*
+** Advance the iterator passed as an argument to the next position. Return
+** 1 if the iterator is at EOF or if it now points to the start of the
+** position list for the next column.
+*/
+static int fts3LcsIteratorAdvance(LcsIterator *pIter){
+ char *pRead = pIter->pRead;
+ sqlite3_int64 iRead;
+ int rc = 0;
+
+ pRead += sqlite3Fts3GetVarint(pRead, &iRead);
+ if( iRead==0 || iRead==1 ){
+ pRead = 0;
+ rc = 1;
+ }else{
+ pIter->iPos += (int)(iRead-2);
+ }
+
+ pIter->pRead = pRead;
+ return rc;
+}
+
+/*
+** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag.
+**
+** If the call is successful, the longest-common-substring lengths for each
+** column are written into the first nCol elements of the pInfo->aMatchinfo[]
+** array before returning. SQLITE_OK is returned in this case.
+**
+** Otherwise, if an error occurs, an SQLite error code is returned and the
+** data written to the first nCol elements of pInfo->aMatchinfo[] is
+** undefined.
+*/
+static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
+ LcsIterator *aIter;
+ int i;
+ int iCol;
+ int nToken = 0;
+
+ /* Allocate and populate the array of LcsIterator objects. The array
+ ** contains one element for each matchable phrase in the query.
+ **/
+ aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
+ if( !aIter ) return SQLITE_NOMEM;
+ memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
+ (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
+
+ for(i=0; i<pInfo->nPhrase; i++){
+ LcsIterator *pIter = &aIter[i];
+ nToken -= pIter->pExpr->pPhrase->nToken;
+ pIter->iPosOffset = nToken;
+ }
+
+ for(iCol=0; iCol<pInfo->nCol; iCol++){
+ int nLcs = 0; /* LCS value for this column */
+ int nLive = 0; /* Number of iterators in aIter not at EOF */
+
+ for(i=0; i<pInfo->nPhrase; i++){
+ int rc;
+ LcsIterator *pIt = &aIter[i];
+ rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead);
+ if( rc!=SQLITE_OK ) return rc;
+ if( pIt->pRead ){
+ pIt->iPos = pIt->iPosOffset;
+ fts3LcsIteratorAdvance(&aIter[i]);
+ nLive++;
+ }
+ }
+
+ while( nLive>0 ){
+ LcsIterator *pAdv = 0; /* The iterator to advance by one position */
+ int nThisLcs = 0; /* LCS for the current iterator positions */
+
+ for(i=0; i<pInfo->nPhrase; i++){
+ LcsIterator *pIter = &aIter[i];
+ if( pIter->pRead==0 ){
+ /* This iterator is already at EOF for this column. */
+ nThisLcs = 0;
+ }else{
+ if( pAdv==0 || pIter->iPos<pAdv->iPos ){
+ pAdv = pIter;
+ }
+ if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){
+ nThisLcs++;
+ }else{
+ nThisLcs = 1;
+ }
+ if( nThisLcs>nLcs ) nLcs = nThisLcs;
+ }
+ }
+ if( fts3LcsIteratorAdvance(pAdv) ) nLive--;
+ }
+
+ pInfo->aMatchinfo[iCol] = nLcs;
+ }
+
+ sqlite3_free(aIter);
+ return SQLITE_OK;
+}
+
+/*
+** Populate the buffer pInfo->aMatchinfo[] with an array of integers to
+** be returned by the matchinfo() function. Argument zArg contains the
+** format string passed as the second argument to matchinfo (or the
+** default value "pcx" if no second argument was specified). The format
+** string has already been validated and the pInfo->aMatchinfo[] array
+** is guaranteed to be large enough for the output.
+**
+** If bGlobal is true, then populate all fields of the matchinfo() output.
+** If it is false, then assume that those fields that do not change between
+** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS)
+** have already been populated.
+**
+** Return SQLITE_OK if successful, or an SQLite error code if an error
+** occurs. If a value other than SQLITE_OK is returned, the state the
+** pInfo->aMatchinfo[] buffer is left in is undefined.
+*/
+static int fts3MatchinfoValues(
+ Fts3Cursor *pCsr, /* FTS3 cursor object */
+ int bGlobal, /* True to grab the global stats */
+ MatchInfo *pInfo, /* Matchinfo context object */
+ const char *zArg /* Matchinfo format string */
+){
+ int rc = SQLITE_OK;
+ int i;
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ sqlite3_stmt *pSelect = 0;
+
+ for(i=0; rc==SQLITE_OK && zArg[i]; i++){
+
+ switch( zArg[i] ){
+ case FTS3_MATCHINFO_NPHRASE:
+ if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase;
+ break;
+
+ case FTS3_MATCHINFO_NCOL:
+ if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
+ break;
+
+ case FTS3_MATCHINFO_NDOC:
+ if( bGlobal ){
+ sqlite3_int64 nDoc = 0;
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
+ pInfo->aMatchinfo[0] = (u32)nDoc;
+ }
+ break;
+
+ case FTS3_MATCHINFO_AVGLENGTH:
+ if( bGlobal ){
+ sqlite3_int64 nDoc; /* Number of rows in table */
+ const char *a; /* Aggregate column length array */
+
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
+ if( rc==SQLITE_OK ){
+ int iCol;
+ for(iCol=0; iCol<pInfo->nCol; iCol++){
+ u32 iVal;
+ sqlite3_int64 nToken;
+ a += sqlite3Fts3GetVarint(a, &nToken);
+ iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
+ pInfo->aMatchinfo[iCol] = iVal;
+ }
+ }
+ }
+ break;
+
+ case FTS3_MATCHINFO_LENGTH: {
+ sqlite3_stmt *pSelectDocsize = 0;
+ rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize);
+ if( rc==SQLITE_OK ){
+ int iCol;
+ const char *a = sqlite3_column_blob(pSelectDocsize, 0);
+ for(iCol=0; iCol<pInfo->nCol; iCol++){
+ sqlite3_int64 nToken;
+ a += sqlite3Fts3GetVarint(a, &nToken);
+ pInfo->aMatchinfo[iCol] = (u32)nToken;
+ }
+ }
+ sqlite3_reset(pSelectDocsize);
+ break;
+ }
+
+ case FTS3_MATCHINFO_LCS:
+ rc = fts3ExprLoadDoclists(pCsr, 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = fts3MatchinfoLcs(pCsr, pInfo);
+ }
+ break;
+
+ default: {
+ Fts3Expr *pExpr;
+ assert( zArg[i]==FTS3_MATCHINFO_HITS );
+ pExpr = pCsr->pExpr;
+ rc = fts3ExprLoadDoclists(pCsr, 0, 0);
+ if( rc!=SQLITE_OK ) break;
+ if( bGlobal ){
+ if( pCsr->pDeferred ){
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
+ if( rc!=SQLITE_OK ) break;
+ }
+ rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
+ if( rc!=SQLITE_OK ) break;
+ }
+ (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo);
+ break;
+ }
+ }
+
+ pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]);
+ }
+
+ sqlite3_reset(pSelect);
+ return rc;
+}
+
+
+/*
+** Populate pCsr->aMatchinfo[] with data for the current row. The
+** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32).
+*/
+static int fts3GetMatchinfo(
+ Fts3Cursor *pCsr, /* FTS3 Cursor object */
+ const char *zArg /* Second argument to matchinfo() function */
+){
+ MatchInfo sInfo;
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int rc = SQLITE_OK;
+ int bGlobal = 0; /* Collect 'global' stats as well as local */
+
+ memset(&sInfo, 0, sizeof(MatchInfo));
+ sInfo.pCursor = pCsr;
+ sInfo.nCol = pTab->nColumn;
+
+ /* If there is cached matchinfo() data, but the format string for the
+ ** cache does not match the format string for this request, discard
+ ** the cached data. */
+ if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){
+ assert( pCsr->aMatchinfo );
+ sqlite3_free(pCsr->aMatchinfo);
+ pCsr->zMatchinfo = 0;
+ pCsr->aMatchinfo = 0;
+ }
+
+ /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the
+ ** matchinfo function has been called for this query. In this case
+ ** allocate the array used to accumulate the matchinfo data and
+ ** initialize those elements that are constant for every row.
+ */
+ if( pCsr->aMatchinfo==0 ){
+ int nMatchinfo = 0; /* Number of u32 elements in match-info */
+ int nArg; /* Bytes in zArg */
+ int i; /* Used to iterate through zArg */
+
+ /* Determine the number of phrases in the query */
+ pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr);
+ sInfo.nPhrase = pCsr->nPhrase;
+
+ /* Determine the number of integers in the buffer returned by this call. */
+ for(i=0; zArg[i]; i++){
+ nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]);
+ }
+
+ /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */
+ nArg = (int)strlen(zArg);
+ pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1);
+ if( !pCsr->aMatchinfo ) return SQLITE_NOMEM;
+
+ pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo];
+ pCsr->nMatchinfo = nMatchinfo;
+ memcpy(pCsr->zMatchinfo, zArg, nArg+1);
+ memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo);
+ pCsr->isMatchinfoNeeded = 1;
+ bGlobal = 1;
+ }
+
+ sInfo.aMatchinfo = pCsr->aMatchinfo;
+ sInfo.nPhrase = pCsr->nPhrase;
+ if( pCsr->isMatchinfoNeeded ){
+ rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg);
+ pCsr->isMatchinfoNeeded = 0;
+ }
+
+ return rc;
+}
+
+/*
+** Implementation of snippet() function.
+*/
+SQLITE_PRIVATE void sqlite3Fts3Snippet(
+ sqlite3_context *pCtx, /* SQLite function call context */
+ Fts3Cursor *pCsr, /* Cursor object */
+ const char *zStart, /* Snippet start text - "<b>" */
+ const char *zEnd, /* Snippet end text - "</b>" */
+ const char *zEllipsis, /* Snippet ellipsis text - "<b>...</b>" */
+ int iCol, /* Extract snippet from this column */
+ int nToken /* Approximate number of tokens in snippet */
+){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int rc = SQLITE_OK;
+ int i;
+ StrBuffer res = {0, 0, 0};
+
+ /* The returned text includes up to four fragments of text extracted from
+ ** the data in the current row. The first iteration of the for(...) loop
+ ** below attempts to locate a single fragment of text nToken tokens in
+ ** size that contains at least one instance of all phrases in the query
+ ** expression that appear in the current row. If such a fragment of text
+ ** cannot be found, the second iteration of the loop attempts to locate
+ ** a pair of fragments, and so on.
+ */
+ int nSnippet = 0; /* Number of fragments in this snippet */
+ SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */
+ int nFToken = -1; /* Number of tokens in each fragment */
+
+ if( !pCsr->pExpr ){
+ sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+ return;
+ }
+
+ for(nSnippet=1; 1; nSnippet++){
+
+ int iSnip; /* Loop counter 0..nSnippet-1 */
+ u64 mCovered = 0; /* Bitmask of phrases covered by snippet */
+ u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */
+
+ if( nToken>=0 ){
+ nFToken = (nToken+nSnippet-1) / nSnippet;
+ }else{
+ nFToken = -1 * nToken;
+ }
+
+ for(iSnip=0; iSnip<nSnippet; iSnip++){
+ int iBestScore = -1; /* Best score of columns checked so far */
+ int iRead; /* Used to iterate through columns */
+ SnippetFragment *pFragment = &aSnippet[iSnip];
+
+ memset(pFragment, 0, sizeof(*pFragment));
+
+ /* Loop through all columns of the table being considered for snippets.
+ ** If the iCol argument to this function was negative, this means all
+ ** columns of the FTS3 table. Otherwise, only column iCol is considered.
+ */
+ for(iRead=0; iRead<pTab->nColumn; iRead++){
+ SnippetFragment sF = {0, 0, 0, 0};
+ int iS;
+ if( iCol>=0 && iRead!=iCol ) continue;
+
+ /* Find the best snippet of nFToken tokens in column iRead. */
+ rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS);
+ if( rc!=SQLITE_OK ){
+ goto snippet_out;
+ }
+ if( iS>iBestScore ){
+ *pFragment = sF;
+ iBestScore = iS;
+ }
+ }
+
+ mCovered |= pFragment->covered;
+ }
+
+ /* If all query phrases seen by fts3BestSnippet() are present in at least
+ ** one of the nSnippet snippet fragments, break out of the loop.
+ */
+ assert( (mCovered&mSeen)==mCovered );
+ if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break;
+ }
+
+ assert( nFToken>0 );
+
+ for(i=0; i<nSnippet && rc==SQLITE_OK; i++){
+ rc = fts3SnippetText(pCsr, &aSnippet[i],
+ i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res
+ );
+ }
+
+ snippet_out:
+ sqlite3Fts3SegmentsClose(pTab);
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(pCtx, rc);
+ sqlite3_free(res.z);
+ }else{
+ sqlite3_result_text(pCtx, res.z, -1, sqlite3_free);
+ }
+}
+
+
+typedef struct TermOffset TermOffset;
+typedef struct TermOffsetCtx TermOffsetCtx;
+
+struct TermOffset {
+ char *pList; /* Position-list */
+ int iPos; /* Position just read from pList */
+ int iOff; /* Offset of this term from read positions */
+};
+
+struct TermOffsetCtx {
+ Fts3Cursor *pCsr;
+ int iCol; /* Column of table to populate aTerm for */
+ int iTerm;
+ sqlite3_int64 iDocid;
+ TermOffset *aTerm;
+};
+
+/*
+** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets().
+*/
+static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
+ TermOffsetCtx *p = (TermOffsetCtx *)ctx;
+ int nTerm; /* Number of tokens in phrase */
+ int iTerm; /* For looping through nTerm phrase terms */
+ char *pList; /* Pointer to position list for phrase */
+ int iPos = 0; /* First position in position-list */
+ int rc;
+
+ UNUSED_PARAMETER(iPhrase);
+ rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList);
+ nTerm = pExpr->pPhrase->nToken;
+ if( pList ){
+ fts3GetDeltaPosition(&pList, &iPos);
+ assert( iPos>=0 );
+ }
+
+ for(iTerm=0; iTerm<nTerm; iTerm++){
+ TermOffset *pT = &p->aTerm[p->iTerm++];
+ pT->iOff = nTerm-iTerm-1;
+ pT->pList = pList;
+ pT->iPos = iPos;
+ }
+
+ return rc;
+}
+
+/*
+** Implementation of offsets() function.
+*/
+SQLITE_PRIVATE void sqlite3Fts3Offsets(
+ sqlite3_context *pCtx, /* SQLite function call context */
+ Fts3Cursor *pCsr /* Cursor object */
+){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
+ int rc; /* Return Code */
+ int nToken; /* Number of tokens in query */
+ int iCol; /* Column currently being processed */
+ StrBuffer res = {0, 0, 0}; /* Result string */
+ TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */
+
+ if( !pCsr->pExpr ){
+ sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+ return;
+ }
+
+ memset(&sCtx, 0, sizeof(sCtx));
+ assert( pCsr->isRequireSeek==0 );
+
+ /* Count the number of terms in the query */
+ rc = fts3ExprLoadDoclists(pCsr, 0, &nToken);
+ if( rc!=SQLITE_OK ) goto offsets_out;
+
+ /* Allocate the array of TermOffset iterators. */
+ sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
+ if( 0==sCtx.aTerm ){
+ rc = SQLITE_NOMEM;
+ goto offsets_out;
+ }
+ sCtx.iDocid = pCsr->iPrevId;
+ sCtx.pCsr = pCsr;
+
+ /* Loop through the table columns, appending offset information to
+ ** string-buffer res for each column.
+ */
+ for(iCol=0; iCol<pTab->nColumn; iCol++){
+ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
+ const char *ZDUMMY; /* Dummy argument used with xNext() */
+ int NDUMMY = 0; /* Dummy argument used with xNext() */
+ int iStart = 0;
+ int iEnd = 0;
+ int iCurrent = 0;
+ const char *zDoc;
+ int nDoc;
+
+ /* Initialize the contents of sCtx.aTerm[] for column iCol. There is
+ ** no way that this operation can fail, so the return code from
+ ** fts3ExprIterate() can be discarded.
+ */
+ sCtx.iCol = iCol;
+ sCtx.iTerm = 0;
+ (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx);
+
+ /* Retreive the text stored in column iCol. If an SQL NULL is stored
+ ** in column iCol, jump immediately to the next iteration of the loop.
+ ** If an OOM occurs while retrieving the data (this can happen if SQLite
+ ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
+ ** to the caller.
+ */
+ zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1);
+ nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
+ if( zDoc==0 ){
+ if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){
+ continue;
+ }
+ rc = SQLITE_NOMEM;
+ goto offsets_out;
+ }
+
+ /* Initialize a tokenizer iterator to iterate through column iCol. */
+ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid,
+ zDoc, nDoc, &pC
+ );
+ if( rc!=SQLITE_OK ) goto offsets_out;
+
+ rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
+ while( rc==SQLITE_OK ){
+ int i; /* Used to loop through terms */
+ int iMinPos = 0x7FFFFFFF; /* Position of next token */
+ TermOffset *pTerm = 0; /* TermOffset associated with next token */
+
+ for(i=0; i<nToken; i++){
+ TermOffset *pT = &sCtx.aTerm[i];
+ if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){
+ iMinPos = pT->iPos-pT->iOff;
+ pTerm = pT;
+ }
+ }
+
+ if( !pTerm ){
+ /* All offsets for this column have been gathered. */
+ rc = SQLITE_DONE;
+ }else{
+ assert( iCurrent<=iMinPos );
+ if( 0==(0xFE&*pTerm->pList) ){
+ pTerm->pList = 0;
+ }else{
+ fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
+ }
+ while( rc==SQLITE_OK && iCurrent<iMinPos ){
+ rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
+ }
+ if( rc==SQLITE_OK ){
+ char aBuffer[64];
+ sqlite3_snprintf(sizeof(aBuffer), aBuffer,
+ "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
+ );
+ rc = fts3StringAppend(&res, aBuffer, -1);
+ }else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){
+ rc = FTS_CORRUPT_VTAB;
+ }
+ }
+ }
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ }
+
+ pMod->xClose(pC);
+ if( rc!=SQLITE_OK ) goto offsets_out;
+ }
+
+ offsets_out:
+ sqlite3_free(sCtx.aTerm);
+ assert( rc!=SQLITE_DONE );
+ sqlite3Fts3SegmentsClose(pTab);
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(pCtx, rc);
+ sqlite3_free(res.z);
+ }else{
+ sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free);
+ }
+ return;
+}
+
+/*
+** Implementation of matchinfo() function.
+*/
+SQLITE_PRIVATE void sqlite3Fts3Matchinfo(
+ sqlite3_context *pContext, /* Function call context */
+ Fts3Cursor *pCsr, /* FTS3 table cursor */
+ const char *zArg /* Second arg to matchinfo() function */
+){
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int rc;
+ int i;
+ const char *zFormat;
+
+ if( zArg ){
+ for(i=0; zArg[i]; i++){
+ char *zErr = 0;
+ if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){
+ sqlite3_result_error(pContext, zErr, -1);
+ sqlite3_free(zErr);
+ return;
+ }
+ }
+ zFormat = zArg;
+ }else{
+ zFormat = FTS3_MATCHINFO_DEFAULT;
+ }
+
+ if( !pCsr->pExpr ){
+ sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
+ return;
+ }
+
+ /* Retrieve matchinfo() data. */
+ rc = fts3GetMatchinfo(pCsr, zFormat);
+ sqlite3Fts3SegmentsClose(pTab);
+
+ if( rc!=SQLITE_OK ){
+ sqlite3_result_error_code(pContext, rc);
+ }else{
+ int n = pCsr->nMatchinfo * sizeof(u32);
+ sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT);
+ }
+}
+
+#endif
+
+/************** End of fts3_snippet.c ****************************************/
+/************** Begin file fts3_unicode.c ************************************/
+/*
+** 2012 May 24
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** Implementation of the "unicode" full-text-search tokenizer.
+*/
+
+#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+
+/* #include <assert.h> */
+/* #include <stdlib.h> */
+/* #include <stdio.h> */
+/* #include <string.h> */
+
+
+/*
+** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
+** from the sqlite3 source file utf.c. If this file is compiled as part
+** of the amalgamation, they are not required.
+*/
+#ifndef SQLITE_AMALGAMATION
+
+static const unsigned char sqlite3Utf8Trans1[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
+};
+
+#define READ_UTF8(zIn, zTerm, c) \
+ c = *(zIn++); \
+ if( c>=0xc0 ){ \
+ c = sqlite3Utf8Trans1[c-0xc0]; \
+ while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ c = (c<<6) + (0x3f & *(zIn++)); \
+ } \
+ if( c<0x80 \
+ || (c&0xFFFFF800)==0xD800 \
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
+ }
+
+#define WRITE_UTF8(zOut, c) { \
+ if( c<0x00080 ){ \
+ *zOut++ = (u8)(c&0xFF); \
+ } \
+ else if( c<0x00800 ){ \
+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ } \
+ else if( c<0x10000 ){ \
+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ }else{ \
+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
+ } \
+}
+
+#endif /* ifndef SQLITE_AMALGAMATION */
+
+typedef struct unicode_tokenizer unicode_tokenizer;
+typedef struct unicode_cursor unicode_cursor;
+
+struct unicode_tokenizer {
+ sqlite3_tokenizer base;
+ int bRemoveDiacritic;
+ int nException;
+ int *aiException;
+};
+
+struct unicode_cursor {
+ sqlite3_tokenizer_cursor base;
+ const unsigned char *aInput; /* Input text being tokenized */
+ int nInput; /* Size of aInput[] in bytes */
+ int iOff; /* Current offset within aInput[] */
+ int iToken; /* Index of next token to be returned */
+ char *zToken; /* storage for current token */
+ int nAlloc; /* space allocated at zToken */
+};
+
+
+/*
+** Destroy a tokenizer allocated by unicodeCreate().
+*/
+static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
+ if( pTokenizer ){
+ unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer;
+ sqlite3_free(p->aiException);
+ sqlite3_free(p);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE
+** statement has specified that the tokenizer for this table shall consider
+** all characters in string zIn/nIn to be separators (if bAlnum==0) or
+** token characters (if bAlnum==1).
+**
+** For each codepoint in the zIn/nIn string, this function checks if the
+** sqlite3FtsUnicodeIsalnum() function already returns the desired result.
+** If so, no action is taken. Otherwise, the codepoint is added to the
+** unicode_tokenizer.aiException[] array. For the purposes of tokenization,
+** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all
+** codepoints in the aiException[] array.
+**
+** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
+** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
+** It is not possible to change the behavior of the tokenizer with respect
+** to these codepoints.
+*/
+static int unicodeAddExceptions(
+ unicode_tokenizer *p, /* Tokenizer to add exceptions to */
+ int bAlnum, /* Replace Isalnum() return value with this */
+ const char *zIn, /* Array of characters to make exceptions */
+ int nIn /* Length of z in bytes */
+){
+ const unsigned char *z = (const unsigned char *)zIn;
+ const unsigned char *zTerm = &z[nIn];
+ int iCode;
+ int nEntry = 0;
+
+ assert( bAlnum==0 || bAlnum==1 );
+
+ while( z<zTerm ){
+ READ_UTF8(z, zTerm, iCode);
+ assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
+ if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
+ && sqlite3FtsUnicodeIsdiacritic(iCode)==0
+ ){
+ nEntry++;
+ }
+ }
+
+ if( nEntry ){
+ int *aNew; /* New aiException[] array */
+ int nNew; /* Number of valid entries in array aNew[] */
+
+ aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
+ if( aNew==0 ) return SQLITE_NOMEM;
+ nNew = p->nException;
+
+ z = (const unsigned char *)zIn;
+ while( z<zTerm ){
+ READ_UTF8(z, zTerm, iCode);
+ if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
+ && sqlite3FtsUnicodeIsdiacritic(iCode)==0
+ ){
+ int i, j;
+ for(i=0; i<nNew && aNew[i]<iCode; i++);
+ for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
+ aNew[i] = iCode;
+ nNew++;
+ }
+ }
+ p->aiException = aNew;
+ p->nException = nNew;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Return true if the p->aiException[] array contains the value iCode.
+*/
+static int unicodeIsException(unicode_tokenizer *p, int iCode){
+ if( p->nException>0 ){
+ int *a = p->aiException;
+ int iLo = 0;
+ int iHi = p->nException-1;
+
+ while( iHi>=iLo ){
+ int iTest = (iHi + iLo) / 2;
+ if( iCode==a[iTest] ){
+ return 1;
+ }else if( iCode>a[iTest] ){
+ iLo = iTest+1;
+ }else{
+ iHi = iTest-1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+** Return true if, for the purposes of tokenization, codepoint iCode is
+** considered a token character (not a separator).
+*/
+static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){
+ assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
+ return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode);
+}
+
+/*
+** Create a new tokenizer instance.
+*/
+static int unicodeCreate(
+ int nArg, /* Size of array argv[] */
+ const char * const *azArg, /* Tokenizer creation arguments */
+ sqlite3_tokenizer **pp /* OUT: New tokenizer handle */
+){
+ unicode_tokenizer *pNew; /* New tokenizer object */
+ int i;
+ int rc = SQLITE_OK;
+
+ pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
+ if( pNew==NULL ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(unicode_tokenizer));
+ pNew->bRemoveDiacritic = 1;
+
+ for(i=0; rc==SQLITE_OK && i<nArg; i++){
+ const char *z = azArg[i];
+ int n = strlen(z);
+
+ if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
+ pNew->bRemoveDiacritic = 1;
+ }
+ else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
+ pNew->bRemoveDiacritic = 0;
+ }
+ else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
+ rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
+ }
+ else if( n>=11 && memcmp("separators=", z, 11)==0 ){
+ rc = unicodeAddExceptions(pNew, 0, &z[11], n-11);
+ }
+ else{
+ /* Unrecognized argument */
+ rc = SQLITE_ERROR;
+ }
+ }
+
+ if( rc!=SQLITE_OK ){
+ unicodeDestroy((sqlite3_tokenizer *)pNew);
+ pNew = 0;
+ }
+ *pp = (sqlite3_tokenizer *)pNew;
+ return rc;
+}
+
+/*
+** Prepare to begin tokenizing a particular string. The input
+** string to be tokenized is pInput[0..nBytes-1]. A cursor
+** used to incrementally tokenize this string is returned in
+** *ppCursor.
+*/
+static int unicodeOpen(
+ sqlite3_tokenizer *p, /* The tokenizer */
+ const char *aInput, /* Input string */
+ int nInput, /* Size of string aInput in bytes */
+ sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */
+){
+ unicode_cursor *pCsr;
+
+ pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor));
+ if( pCsr==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(pCsr, 0, sizeof(unicode_cursor));
+
+ pCsr->aInput = (const unsigned char *)aInput;
+ if( aInput==0 ){
+ pCsr->nInput = 0;
+ }else if( nInput<0 ){
+ pCsr->nInput = (int)strlen(aInput);
+ }else{
+ pCsr->nInput = nInput;
+ }
+
+ *pp = &pCsr->base;
+ UNUSED_PARAMETER(p);
+ return SQLITE_OK;
+}
+
+/*
+** Close a tokenization cursor previously opened by a call to
+** simpleOpen() above.
+*/
+static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){
+ unicode_cursor *pCsr = (unicode_cursor *) pCursor;
+ sqlite3_free(pCsr->zToken);
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+/*
+** Extract the next token from a tokenization cursor. The cursor must
+** have been opened by a prior call to simpleOpen().
+*/
+static int unicodeNext(
+ sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */
+ const char **paToken, /* OUT: Token text */
+ int *pnToken, /* OUT: Number of bytes at *paToken */
+ int *piStart, /* OUT: Starting offset of token */
+ int *piEnd, /* OUT: Ending offset of token */
+ int *piPos /* OUT: Position integer of token */
+){
+ unicode_cursor *pCsr = (unicode_cursor *)pC;
+ unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
+ int iCode;
+ char *zOut;
+ const unsigned char *z = &pCsr->aInput[pCsr->iOff];
+ const unsigned char *zStart = z;
+ const unsigned char *zEnd;
+ const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
+
+ /* Scan past any delimiter characters before the start of the next token.
+ ** Return SQLITE_DONE early if this takes us all the way to the end of
+ ** the input. */
+ while( z<zTerm ){
+ READ_UTF8(z, zTerm, iCode);
+ if( unicodeIsAlnum(p, iCode) ) break;
+ zStart = z;
+ }
+ if( zStart>=zTerm ) return SQLITE_DONE;
+
+ zOut = pCsr->zToken;
+ do {
+ int iOut;
+
+ /* Grow the output buffer if required. */
+ if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
+ char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
+ if( !zNew ) return SQLITE_NOMEM;
+ zOut = &zNew[zOut - pCsr->zToken];
+ pCsr->zToken = zNew;
+ pCsr->nAlloc += 64;
+ }
+
+ /* Write the folded case of the last character read to the output */
+ zEnd = z;
+ iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
+ if( iOut ){
+ WRITE_UTF8(zOut, iOut);
+ }
+
+ /* If the cursor is not at EOF, read the next character */
+ if( z>=zTerm ) break;
+ READ_UTF8(z, zTerm, iCode);
+ }while( unicodeIsAlnum(p, iCode)
+ || sqlite3FtsUnicodeIsdiacritic(iCode)
+ );
+
+ /* Set the output variables and return. */
+ pCsr->iOff = (z - pCsr->aInput);
+ *paToken = pCsr->zToken;
+ *pnToken = zOut - pCsr->zToken;
+ *piStart = (zStart - pCsr->aInput);
+ *piEnd = (zEnd - pCsr->aInput);
+ *piPos = pCsr->iToken++;
+ return SQLITE_OK;
+}
+
+/*
+** Set *ppModule to a pointer to the sqlite3_tokenizer_module
+** structure for the unicode tokenizer.
+*/
+SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){
+ static const sqlite3_tokenizer_module module = {
+ 0,
+ unicodeCreate,
+ unicodeDestroy,
+ unicodeOpen,
+ unicodeClose,
+ unicodeNext,
+ 0,
+ };
+ *ppModule = &module;
+}
+
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */
+
+/************** End of fts3_unicode.c ****************************************/
+/************** Begin file fts3_unicode2.c ***********************************/
+/*
+** 2012 May 25
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+*/
+
+/*
+** DO NOT EDIT THIS MACHINE GENERATED FILE.
+*/
+
+#if defined(SQLITE_ENABLE_FTS4_UNICODE61)
+#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
+
+/* #include <assert.h> */
+
+/*
+** Return true if the argument corresponds to a unicode codepoint
+** classified as either a letter or a number. Otherwise false.
+**
+** The results are undefined if the value passed to this function
+** is less than zero.
+*/
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
+ /* Each unsigned integer in the following array corresponds to a contiguous
+ ** range of unicode codepoints that are not either letters or numbers (i.e.
+ ** codepoints for which this function should return 0).
+ **
+ ** The most significant 22 bits in each 32-bit value contain the first
+ ** codepoint in the range. The least significant 10 bits are used to store
+ ** the size of the range (always at least 1). In other words, the value
+ ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
+ ** C. It is not possible to represent a range larger than 1023 codepoints
+ ** using this format.
+ */
+ const static unsigned int aEntry[] = {
+ 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
+ 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
+ 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
+ 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
+ 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
+ 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
+ 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
+ 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
+ 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
+ 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
+ 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
+ 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
+ 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
+ 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
+ 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
+ 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
+ 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
+ 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
+ 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
+ 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
+ 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
+ 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
+ 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
+ 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
+ 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
+ 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
+ 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
+ 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
+ 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
+ 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
+ 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
+ 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
+ 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
+ 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
+ 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
+ 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
+ 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
+ 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
+ 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
+ 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
+ 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
+ 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
+ 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
+ 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
+ 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
+ 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
+ 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
+ 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
+ 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
+ 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
+ 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
+ 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
+ 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
+ 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
+ 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
+ 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
+ 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
+ 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
+ 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
+ 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
+ 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
+ 0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
+ 0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
+ 0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
+ 0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
+ 0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
+ 0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,
+ 0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,
+ 0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
+ 0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
+ 0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,
+ 0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
+ 0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
+ 0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
+ 0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
+ 0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
+ 0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
+ 0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
+ 0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
+ 0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
+ 0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
+ 0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
+ 0x43FFF401,
+ };
+ static const unsigned int aAscii[4] = {
+ 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
+ };
+
+ if( c<128 ){
+ return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
+ }else if( c<(1<<22) ){
+ unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
+ int iRes;
+ int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
+ int iLo = 0;
+ while( iHi>=iLo ){
+ int iTest = (iHi + iLo) / 2;
+ if( key >= aEntry[iTest] ){
+ iRes = iTest;
+ iLo = iTest+1;
+ }else{
+ iHi = iTest-1;
+ }
+ }
+ assert( aEntry[0]<key );
+ assert( key>=aEntry[iRes] );
+ return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
+ }
+ return 1;
+}
+
+
+/*
+** If the argument is a codepoint corresponding to a lowercase letter
+** in the ASCII range with a diacritic added, return the codepoint
+** of the ASCII letter only. For example, if passed 235 - "LATIN
+** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
+** E"). The resuls of passing a codepoint that corresponds to an
+** uppercase letter are undefined.
+*/
+static int remove_diacritic(int c){
+ unsigned short aDia[] = {
+ 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
+ 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
+ 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
+ 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
+ 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
+ 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
+ 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
+ 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
+ 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
+ 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
+ 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
+ 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
+ 62924, 63050, 63082, 63274, 63390,
+ };
+ char aChar[] = {
+ '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
+ 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
+ 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
+ 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
+ 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
+ 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
+ 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
+ 'e', 'i', 'o', 'u', 'y',
+ };
+
+ unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
+ int iRes = 0;
+ int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
+ int iLo = 0;
+ while( iHi>=iLo ){
+ int iTest = (iHi + iLo) / 2;
+ if( key >= aDia[iTest] ){
+ iRes = iTest;
+ iLo = iTest+1;
+ }else{
+ iHi = iTest-1;
+ }
+ }
+ assert( key>=aDia[iRes] );
+ return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
+};
+
+
+/*
+** Return true if the argument interpreted as a unicode codepoint
+** is a diacritical modifier character.
+*/
+SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){
+ unsigned int mask0 = 0x08029FDF;
+ unsigned int mask1 = 0x000361F8;
+ if( c<768 || c>817 ) return 0;
+ return (c < 768+32) ?
+ (mask0 & (1 << (c-768))) :
+ (mask1 & (1 << (c-768-32)));
+}
+
+
+/*
+** Interpret the argument as a unicode codepoint. If the codepoint
+** is an upper case character that has a lower case equivalent,
+** return the codepoint corresponding to the lower case version.
+** Otherwise, return a copy of the argument.
+**
+** The results are undefined if the value passed to this function
+** is less than zero.
+*/
+SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
+ /* Each entry in the following array defines a rule for folding a range
+ ** of codepoints to lower case. The rule applies to a range of nRange
+ ** codepoints starting at codepoint iCode.
+ **
+ ** If the least significant bit in flags is clear, then the rule applies
+ ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
+ ** need to be folded). Or, if it is set, then the rule only applies to
+ ** every second codepoint in the range, starting with codepoint C.
+ **
+ ** The 7 most significant bits in flags are an index into the aiOff[]
+ ** array. If a specific codepoint C does require folding, then its lower
+ ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
+ **
+ ** The contents of this array are generated by parsing the CaseFolding.txt
+ ** file distributed as part of the "Unicode Character Database". See
+ ** http://www.unicode.org for details.
+ */
+ static const struct TableEntry {
+ unsigned short iCode;
+ unsigned char flags;
+ unsigned char nRange;
+ } aEntry[] = {
+ {65, 14, 26}, {181, 64, 1}, {192, 14, 23},
+ {216, 14, 7}, {256, 1, 48}, {306, 1, 6},
+ {313, 1, 16}, {330, 1, 46}, {376, 116, 1},
+ {377, 1, 6}, {383, 104, 1}, {385, 50, 1},
+ {386, 1, 4}, {390, 44, 1}, {391, 0, 1},
+ {393, 42, 2}, {395, 0, 1}, {398, 32, 1},
+ {399, 38, 1}, {400, 40, 1}, {401, 0, 1},
+ {403, 42, 1}, {404, 46, 1}, {406, 52, 1},
+ {407, 48, 1}, {408, 0, 1}, {412, 52, 1},
+ {413, 54, 1}, {415, 56, 1}, {416, 1, 6},
+ {422, 60, 1}, {423, 0, 1}, {425, 60, 1},
+ {428, 0, 1}, {430, 60, 1}, {431, 0, 1},
+ {433, 58, 2}, {435, 1, 4}, {439, 62, 1},
+ {440, 0, 1}, {444, 0, 1}, {452, 2, 1},
+ {453, 0, 1}, {455, 2, 1}, {456, 0, 1},
+ {458, 2, 1}, {459, 1, 18}, {478, 1, 18},
+ {497, 2, 1}, {498, 1, 4}, {502, 122, 1},
+ {503, 134, 1}, {504, 1, 40}, {544, 110, 1},
+ {546, 1, 18}, {570, 70, 1}, {571, 0, 1},
+ {573, 108, 1}, {574, 68, 1}, {577, 0, 1},
+ {579, 106, 1}, {580, 28, 1}, {581, 30, 1},
+ {582, 1, 10}, {837, 36, 1}, {880, 1, 4},
+ {886, 0, 1}, {902, 18, 1}, {904, 16, 3},
+ {908, 26, 1}, {910, 24, 2}, {913, 14, 17},
+ {931, 14, 9}, {962, 0, 1}, {975, 4, 1},
+ {976, 140, 1}, {977, 142, 1}, {981, 146, 1},
+ {982, 144, 1}, {984, 1, 24}, {1008, 136, 1},
+ {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1},
+ {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1},
+ {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32},
+ {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1},
+ {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38},
+ {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1},
+ {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1},
+ {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6},
+ {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6},
+ {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8},
+ {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2},
+ {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1},
+ {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2},
+ {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2},
+ {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2},
+ {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1},
+ {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16},
+ {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47},
+ {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1},
+ {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1},
+ {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1},
+ {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2},
+ {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1},
+ {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14},
+ {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1},
+ {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1},
+ {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1},
+ {65313, 14, 26},
+ };
+ static const unsigned short aiOff[] = {
+ 1, 2, 8, 15, 16, 26, 28, 32,
+ 37, 38, 40, 48, 63, 64, 69, 71,
+ 79, 80, 116, 202, 203, 205, 206, 207,
+ 209, 210, 211, 213, 214, 217, 218, 219,
+ 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721,
+ 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274,
+ 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406,
+ 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462,
+ 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511,
+ 65514, 65521, 65527, 65528, 65529,
+ };
+
+ int ret = c;
+
+ assert( c>=0 );
+ assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
+
+ if( c<128 ){
+ if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
+ }else if( c<65536 ){
+ int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
+ int iLo = 0;
+ int iRes = -1;
+
+ while( iHi>=iLo ){
+ int iTest = (iHi + iLo) / 2;
+ int cmp = (c - aEntry[iTest].iCode);
+ if( cmp>=0 ){
+ iRes = iTest;
+ iLo = iTest+1;
+ }else{
+ iHi = iTest-1;
+ }
+ }
+ assert( iRes<0 || c>=aEntry[iRes].iCode );
+
+ if( iRes>=0 ){
+ const struct TableEntry *p = &aEntry[iRes];
+ if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
+ ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
+ assert( ret>0 );
+ }
+ }
+
+ if( bRemoveDiacritic ) ret = remove_diacritic(ret);
+ }
+
+ else if( c>=66560 && c<66600 ){
+ ret = c + 40;
+ }
+
+ return ret;
+}
+#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
+#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */
+
+/************** End of fts3_unicode2.c ***************************************/
+/************** Begin file rtree.c *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code for implementations of the r-tree and r*-tree
+** algorithms packaged as an SQLite virtual table module.
+*/
+
+/*
+** Database Format of R-Tree Tables
+** --------------------------------
+**
+** The data structure for a single virtual r-tree table is stored in three
+** native SQLite tables declared as follows. In each case, the '%' character
+** in the table name is replaced with the user-supplied name of the r-tree
+** table.
+**
+** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB)
+** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
+** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
+**
+** The data for each node of the r-tree structure is stored in the %_node
+** table. For each node that is not the root node of the r-tree, there is
+** an entry in the %_parent table associating the node with its parent.
+** And for each row of data in the table, there is an entry in the %_rowid
+** table that maps from the entries rowid to the id of the node that it
+** is stored on.
+**
+** The root node of an r-tree always exists, even if the r-tree table is
+** empty. The nodeno of the root node is always 1. All other nodes in the
+** table must be the same size as the root node. The content of each node
+** is formatted as follows:
+**
+** 1. If the node is the root node (node 1), then the first 2 bytes
+** of the node contain the tree depth as a big-endian integer.
+** For non-root nodes, the first 2 bytes are left unused.
+**
+** 2. The next 2 bytes contain the number of entries currently
+** stored in the node.
+**
+** 3. The remainder of the node contains the node entries. Each entry
+** consists of a single 8-byte integer followed by an even number
+** of 4-byte coordinates. For leaf nodes the integer is the rowid
+** of a record. For internal nodes it is the node number of a
+** child page.
+*/
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
+
+/*
+** This file contains an implementation of a couple of different variants
+** of the r-tree algorithm. See the README file for further details. The
+** same data-structure is used for all, but the algorithms for insert and
+** delete operations vary. The variants used are selected at compile time
+** by defining the following symbols:
+*/
+
+/* Either, both or none of the following may be set to activate
+** r*tree variant algorithms.
+*/
+#define VARIANT_RSTARTREE_CHOOSESUBTREE 0
+#define VARIANT_RSTARTREE_REINSERT 1
+
+/*
+** Exactly one of the following must be set to 1.
+*/
+#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0
+#define VARIANT_GUTTMAN_LINEAR_SPLIT 0
+#define VARIANT_RSTARTREE_SPLIT 1
+
+#define VARIANT_GUTTMAN_SPLIT \
+ (VARIANT_GUTTMAN_LINEAR_SPLIT||VARIANT_GUTTMAN_QUADRATIC_SPLIT)
+
+#if VARIANT_GUTTMAN_QUADRATIC_SPLIT
+ #define PickNext QuadraticPickNext
+ #define PickSeeds QuadraticPickSeeds
+ #define AssignCells splitNodeGuttman
+#endif
+#if VARIANT_GUTTMAN_LINEAR_SPLIT
+ #define PickNext LinearPickNext
+ #define PickSeeds LinearPickSeeds
+ #define AssignCells splitNodeGuttman
+#endif
+#if VARIANT_RSTARTREE_SPLIT
+ #define AssignCells splitNodeStartree
+#endif
+
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+# define NDEBUG 1
+#endif
+
+#ifndef SQLITE_CORE
+ SQLITE_EXTENSION_INIT1
+#else
+#endif
+
+/* #include <string.h> */
+/* #include <assert.h> */
+
+#ifndef SQLITE_AMALGAMATION
+#include "sqlite3rtree.h"
+typedef sqlite3_int64 i64;
+typedef unsigned char u8;
+typedef unsigned int u32;
+#endif
+
+/* The following macro is used to suppress compiler warnings.
+*/
+#ifndef UNUSED_PARAMETER
+# define UNUSED_PARAMETER(x) (void)(x)
+#endif
+
+typedef struct Rtree Rtree;
+typedef struct RtreeCursor RtreeCursor;
+typedef struct RtreeNode RtreeNode;
+typedef struct RtreeCell RtreeCell;
+typedef struct RtreeConstraint RtreeConstraint;
+typedef struct RtreeMatchArg RtreeMatchArg;
+typedef struct RtreeGeomCallback RtreeGeomCallback;
+typedef union RtreeCoord RtreeCoord;
+
+/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
+#define RTREE_MAX_DIMENSIONS 5
+
+/* Size of hash table Rtree.aHash. This hash table is not expected to
+** ever contain very many entries, so a fixed number of buckets is
+** used.
+*/
+#define HASHSIZE 128
+
+/*
+** An rtree virtual-table object.
+*/
+struct Rtree {
+ sqlite3_vtab base;
+ sqlite3 *db; /* Host database connection */
+ int iNodeSize; /* Size in bytes of each node in the node table */
+ int nDim; /* Number of dimensions */
+ int nBytesPerCell; /* Bytes consumed per cell */
+ int iDepth; /* Current depth of the r-tree structure */
+ char *zDb; /* Name of database containing r-tree table */
+ char *zName; /* Name of r-tree table */
+ RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
+ int nBusy; /* Current number of users of this structure */
+
+ /* List of nodes removed during a CondenseTree operation. List is
+ ** linked together via the pointer normally used for hash chains -
+ ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
+ ** headed by the node (leaf nodes have RtreeNode.iNode==0).
+ */
+ RtreeNode *pDeleted;
+ int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */
+
+ /* Statements to read/write/delete a record from xxx_node */
+ sqlite3_stmt *pReadNode;
+ sqlite3_stmt *pWriteNode;
+ sqlite3_stmt *pDeleteNode;
+
+ /* Statements to read/write/delete a record from xxx_rowid */
+ sqlite3_stmt *pReadRowid;
+ sqlite3_stmt *pWriteRowid;
+ sqlite3_stmt *pDeleteRowid;
+
+ /* Statements to read/write/delete a record from xxx_parent */
+ sqlite3_stmt *pReadParent;
+ sqlite3_stmt *pWriteParent;
+ sqlite3_stmt *pDeleteParent;
+
+ int eCoordType;
+};
+
+/* Possible values for eCoordType: */
+#define RTREE_COORD_REAL32 0
+#define RTREE_COORD_INT32 1
+
+/*
+** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will
+** only deal with integer coordinates. No floating point operations
+** will be done.
+*/
+#ifdef SQLITE_RTREE_INT_ONLY
+ typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */
+ typedef int RtreeValue; /* Low accuracy coordinate */
+#else
+ typedef double RtreeDValue; /* High accuracy coordinate */
+ typedef float RtreeValue; /* Low accuracy coordinate */
+#endif
+
+/*
+** The minimum number of cells allowed for a node is a third of the
+** maximum. In Gutman's notation:
+**
+** m = M/3
+**
+** If an R*-tree "Reinsert" operation is required, the same number of
+** cells are removed from the overfull node and reinserted into the tree.
+*/
+#define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3)
+#define RTREE_REINSERT(p) RTREE_MINCELLS(p)
+#define RTREE_MAXCELLS 51
+
+/*
+** The smallest possible node-size is (512-64)==448 bytes. And the largest
+** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates).
+** Therefore all non-root nodes must contain at least 3 entries. Since
+** 2^40 is greater than 2^64, an r-tree structure always has a depth of
+** 40 or less.
+*/
+#define RTREE_MAX_DEPTH 40
+
+/*
+** An rtree cursor object.
+*/
+struct RtreeCursor {
+ sqlite3_vtab_cursor base;
+ RtreeNode *pNode; /* Node cursor is currently pointing at */
+ int iCell; /* Index of current cell in pNode */
+ int iStrategy; /* Copy of idxNum search parameter */
+ int nConstraint; /* Number of entries in aConstraint */
+ RtreeConstraint *aConstraint; /* Search constraints. */
+};
+
+union RtreeCoord {
+ RtreeValue f;
+ int i;
+};
+
+/*
+** The argument is an RtreeCoord. Return the value stored within the RtreeCoord
+** formatted as a RtreeDValue (double or int64). This macro assumes that local
+** variable pRtree points to the Rtree structure associated with the
+** RtreeCoord.
+*/
+#ifdef SQLITE_RTREE_INT_ONLY
+# define DCOORD(coord) ((RtreeDValue)coord.i)
+#else
+# define DCOORD(coord) ( \
+ (pRtree->eCoordType==RTREE_COORD_REAL32) ? \
+ ((double)coord.f) : \
+ ((double)coord.i) \
+ )
+#endif
+
+/*
+** A search constraint.
+*/
+struct RtreeConstraint {
+ int iCoord; /* Index of constrained coordinate */
+ int op; /* Constraining operation */
+ RtreeDValue rValue; /* Constraint value. */
+ int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
+ sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */
+};
+
+/* Possible values for RtreeConstraint.op */
+#define RTREE_EQ 0x41
+#define RTREE_LE 0x42
+#define RTREE_LT 0x43
+#define RTREE_GE 0x44
+#define RTREE_GT 0x45
+#define RTREE_MATCH 0x46
+
+/*
+** An rtree structure node.
+*/
+struct RtreeNode {
+ RtreeNode *pParent; /* Parent node */
+ i64 iNode;
+ int nRef;
+ int isDirty;
+ u8 *zData;
+ RtreeNode *pNext; /* Next node in this hash chain */
+};
+#define NCELL(pNode) readInt16(&(pNode)->zData[2])
+
+/*
+** Structure to store a deserialized rtree record.
+*/
+struct RtreeCell {
+ i64 iRowid;
+ RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2];
+};
+
+
+/*
+** Value for the first field of every RtreeMatchArg object. The MATCH
+** operator tests that the first field of a blob operand matches this
+** value to avoid operating on invalid blobs (which could cause a segfault).
+*/
+#define RTREE_GEOMETRY_MAGIC 0x891245AB
+
+/*
+** An instance of this structure must be supplied as a blob argument to
+** the right-hand-side of an SQL MATCH operator used to constrain an
+** r-tree query.
+*/
+struct RtreeMatchArg {
+ u32 magic; /* Always RTREE_GEOMETRY_MAGIC */
+ int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *);
+ void *pContext;
+ int nParam;
+ RtreeDValue aParam[1];
+};
+
+/*
+** When a geometry callback is created (see sqlite3_rtree_geometry_callback),
+** a single instance of the following structure is allocated. It is used
+** as the context for the user-function created by by s_r_g_c(). The object
+** is eventually deleted by the destructor mechanism provided by
+** sqlite3_create_function_v2() (which is called by s_r_g_c() to create
+** the geometry callback function).
+*/
+struct RtreeGeomCallback {
+ int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
+ void *pContext;
+};
+
+#ifndef MAX
+# define MAX(x,y) ((x) < (y) ? (y) : (x))
+#endif
+#ifndef MIN
+# define MIN(x,y) ((x) > (y) ? (y) : (x))
+#endif
+
+/*
+** Functions to deserialize a 16 bit integer, 32 bit real number and
+** 64 bit integer. The deserialized value is returned.
+*/
+static int readInt16(u8 *p){
+ return (p[0]<<8) + p[1];
+}
+static void readCoord(u8 *p, RtreeCoord *pCoord){
+ u32 i = (
+ (((u32)p[0]) << 24) +
+ (((u32)p[1]) << 16) +
+ (((u32)p[2]) << 8) +
+ (((u32)p[3]) << 0)
+ );
+ *(u32 *)pCoord = i;
+}
+static i64 readInt64(u8 *p){
+ return (
+ (((i64)p[0]) << 56) +
+ (((i64)p[1]) << 48) +
+ (((i64)p[2]) << 40) +
+ (((i64)p[3]) << 32) +
+ (((i64)p[4]) << 24) +
+ (((i64)p[5]) << 16) +
+ (((i64)p[6]) << 8) +
+ (((i64)p[7]) << 0)
+ );
+}
+
+/*
+** Functions to serialize a 16 bit integer, 32 bit real number and
+** 64 bit integer. The value returned is the number of bytes written
+** to the argument buffer (always 2, 4 and 8 respectively).
+*/
+static int writeInt16(u8 *p, int i){
+ p[0] = (i>> 8)&0xFF;
+ p[1] = (i>> 0)&0xFF;
+ return 2;
+}
+static int writeCoord(u8 *p, RtreeCoord *pCoord){
+ u32 i;
+ assert( sizeof(RtreeCoord)==4 );
+ assert( sizeof(u32)==4 );
+ i = *(u32 *)pCoord;
+ p[0] = (i>>24)&0xFF;
+ p[1] = (i>>16)&0xFF;
+ p[2] = (i>> 8)&0xFF;
+ p[3] = (i>> 0)&0xFF;
+ return 4;
+}
+static int writeInt64(u8 *p, i64 i){
+ p[0] = (i>>56)&0xFF;
+ p[1] = (i>>48)&0xFF;
+ p[2] = (i>>40)&0xFF;
+ p[3] = (i>>32)&0xFF;
+ p[4] = (i>>24)&0xFF;
+ p[5] = (i>>16)&0xFF;
+ p[6] = (i>> 8)&0xFF;
+ p[7] = (i>> 0)&0xFF;
+ return 8;
+}
+
+/*
+** Increment the reference count of node p.
+*/
+static void nodeReference(RtreeNode *p){
+ if( p ){
+ p->nRef++;
+ }
+}
+
+/*
+** Clear the content of node p (set all bytes to 0x00).
+*/
+static void nodeZero(Rtree *pRtree, RtreeNode *p){
+ memset(&p->zData[2], 0, pRtree->iNodeSize-2);
+ p->isDirty = 1;
+}
+
+/*
+** Given a node number iNode, return the corresponding key to use
+** in the Rtree.aHash table.
+*/
+static int nodeHash(i64 iNode){
+ return (
+ (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^
+ (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0)
+ ) % HASHSIZE;
+}
+
+/*
+** Search the node hash table for node iNode. If found, return a pointer
+** to it. Otherwise, return 0.
+*/
+static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){
+ RtreeNode *p;
+ for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext);
+ return p;
+}
+
+/*
+** Add node pNode to the node hash table.
+*/
+static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){
+ int iHash;
+ assert( pNode->pNext==0 );
+ iHash = nodeHash(pNode->iNode);
+ pNode->pNext = pRtree->aHash[iHash];
+ pRtree->aHash[iHash] = pNode;
+}
+
+/*
+** Remove node pNode from the node hash table.
+*/
+static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
+ RtreeNode **pp;
+ if( pNode->iNode!=0 ){
+ pp = &pRtree->aHash[nodeHash(pNode->iNode)];
+ for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); }
+ *pp = pNode->pNext;
+ pNode->pNext = 0;
+ }
+}
+
+/*
+** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0),
+** indicating that node has not yet been assigned a node number. It is
+** assigned a node number when nodeWrite() is called to write the
+** node contents out to the database.
+*/
+static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
+ RtreeNode *pNode;
+ pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize);
+ if( pNode ){
+ memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
+ pNode->zData = (u8 *)&pNode[1];
+ pNode->nRef = 1;
+ pNode->pParent = pParent;
+ pNode->isDirty = 1;
+ nodeReference(pParent);
+ }
+ return pNode;
+}
+
+/*
+** Obtain a reference to an r-tree node.
+*/
+static int
+nodeAcquire(
+ Rtree *pRtree, /* R-tree structure */
+ i64 iNode, /* Node number to load */
+ RtreeNode *pParent, /* Either the parent node or NULL */
+ RtreeNode **ppNode /* OUT: Acquired node */
+){
+ int rc;
+ int rc2 = SQLITE_OK;
+ RtreeNode *pNode;
+
+ /* Check if the requested node is already in the hash table. If so,
+ ** increase its reference count and return it.
+ */
+ if( (pNode = nodeHashLookup(pRtree, iNode)) ){
+ assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
+ if( pParent && !pNode->pParent ){
+ nodeReference(pParent);
+ pNode->pParent = pParent;
+ }
+ pNode->nRef++;
+ *ppNode = pNode;
+ return SQLITE_OK;
+ }
+
+ sqlite3_bind_int64(pRtree->pReadNode, 1, iNode);
+ rc = sqlite3_step(pRtree->pReadNode);
+ if( rc==SQLITE_ROW ){
+ const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
+ if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){
+ pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
+ if( !pNode ){
+ rc2 = SQLITE_NOMEM;
+ }else{
+ pNode->pParent = pParent;
+ pNode->zData = (u8 *)&pNode[1];
+ pNode->nRef = 1;
+ pNode->iNode = iNode;
+ pNode->isDirty = 0;
+ pNode->pNext = 0;
+ memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
+ nodeReference(pParent);
+ }
+ }
+ }
+ rc = sqlite3_reset(pRtree->pReadNode);
+ if( rc==SQLITE_OK ) rc = rc2;
+
+ /* If the root node was just loaded, set pRtree->iDepth to the height
+ ** of the r-tree structure. A height of zero means all data is stored on
+ ** the root node. A height of one means the children of the root node
+ ** are the leaves, and so on. If the depth as specified on the root node
+ ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
+ */
+ if( pNode && iNode==1 ){
+ pRtree->iDepth = readInt16(pNode->zData);
+ if( pRtree->iDepth>RTREE_MAX_DEPTH ){
+ rc = SQLITE_CORRUPT_VTAB;
+ }
+ }
+
+ /* If no error has occurred so far, check if the "number of entries"
+ ** field on the node is too large. If so, set the return code to
+ ** SQLITE_CORRUPT_VTAB.
+ */
+ if( pNode && rc==SQLITE_OK ){
+ if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
+ rc = SQLITE_CORRUPT_VTAB;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ if( pNode!=0 ){
+ nodeHashInsert(pRtree, pNode);
+ }else{
+ rc = SQLITE_CORRUPT_VTAB;
+ }
+ *ppNode = pNode;
+ }else{
+ sqlite3_free(pNode);
+ *ppNode = 0;
+ }
+
+ return rc;
+}
+
+/*
+** Overwrite cell iCell of node pNode with the contents of pCell.
+*/
+static void nodeOverwriteCell(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
+ int iCell
+){
+ int ii;
+ u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
+ p += writeInt64(p, pCell->iRowid);
+ for(ii=0; ii<(pRtree->nDim*2); ii++){
+ p += writeCoord(p, &pCell->aCoord[ii]);
+ }
+ pNode->isDirty = 1;
+}
+
+/*
+** Remove cell the cell with index iCell from node pNode.
+*/
+static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){
+ u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
+ u8 *pSrc = &pDst[pRtree->nBytesPerCell];
+ int nByte = (NCELL(pNode) - iCell - 1) * pRtree->nBytesPerCell;
+ memmove(pDst, pSrc, nByte);
+ writeInt16(&pNode->zData[2], NCELL(pNode)-1);
+ pNode->isDirty = 1;
+}
+
+/*
+** Insert the contents of cell pCell into node pNode. If the insert
+** is successful, return SQLITE_OK.
+**
+** If there is not enough free space in pNode, return SQLITE_FULL.
+*/
+static int
+nodeInsertCell(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell
+){
+ int nCell; /* Current number of cells in pNode */
+ int nMaxCell; /* Maximum number of cells for pNode */
+
+ nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell;
+ nCell = NCELL(pNode);
+
+ assert( nCell<=nMaxCell );
+ if( nCell<nMaxCell ){
+ nodeOverwriteCell(pRtree, pNode, pCell, nCell);
+ writeInt16(&pNode->zData[2], nCell+1);
+ pNode->isDirty = 1;
+ }
+
+ return (nCell==nMaxCell);
+}
+
+/*
+** If the node is dirty, write it out to the database.
+*/
+static int
+nodeWrite(Rtree *pRtree, RtreeNode *pNode){
+ int rc = SQLITE_OK;
+ if( pNode->isDirty ){
+ sqlite3_stmt *p = pRtree->pWriteNode;
+ if( pNode->iNode ){
+ sqlite3_bind_int64(p, 1, pNode->iNode);
+ }else{
+ sqlite3_bind_null(p, 1);
+ }
+ sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC);
+ sqlite3_step(p);
+ pNode->isDirty = 0;
+ rc = sqlite3_reset(p);
+ if( pNode->iNode==0 && rc==SQLITE_OK ){
+ pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
+ nodeHashInsert(pRtree, pNode);
+ }
+ }
+ return rc;
+}
+
+/*
+** Release a reference to a node. If the node is dirty and the reference
+** count drops to zero, the node data is written to the database.
+*/
+static int
+nodeRelease(Rtree *pRtree, RtreeNode *pNode){
+ int rc = SQLITE_OK;
+ if( pNode ){
+ assert( pNode->nRef>0 );
+ pNode->nRef--;
+ if( pNode->nRef==0 ){
+ if( pNode->iNode==1 ){
+ pRtree->iDepth = -1;
+ }
+ if( pNode->pParent ){
+ rc = nodeRelease(pRtree, pNode->pParent);
+ }
+ if( rc==SQLITE_OK ){
+ rc = nodeWrite(pRtree, pNode);
+ }
+ nodeHashDelete(pRtree, pNode);
+ sqlite3_free(pNode);
+ }
+ }
+ return rc;
+}
+
+/*
+** Return the 64-bit integer value associated with cell iCell of
+** node pNode. If pNode is a leaf node, this is a rowid. If it is
+** an internal node, then the 64-bit integer is a child page number.
+*/
+static i64 nodeGetRowid(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ int iCell
+){
+ assert( iCell<NCELL(pNode) );
+ return readInt64(&pNode->zData[4 + pRtree->nBytesPerCell*iCell]);
+}
+
+/*
+** Return coordinate iCoord from cell iCell in node pNode.
+*/
+static void nodeGetCoord(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ int iCell,
+ int iCoord,
+ RtreeCoord *pCoord /* Space to write result to */
+){
+ readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
+}
+
+/*
+** Deserialize cell iCell of node pNode. Populate the structure pointed
+** to by pCell with the results.
+*/
+static void nodeGetCell(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ int iCell,
+ RtreeCell *pCell
+){
+ int ii;
+ pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
+ for(ii=0; ii<pRtree->nDim*2; ii++){
+ nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]);
+ }
+}
+
+
+/* Forward declaration for the function that does the work of
+** the virtual table module xCreate() and xConnect() methods.
+*/
+static int rtreeInit(
+ sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int
+);
+
+/*
+** Rtree virtual table module xCreate method.
+*/
+static int rtreeCreate(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
+}
+
+/*
+** Rtree virtual table module xConnect method.
+*/
+static int rtreeConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0);
+}
+
+/*
+** Increment the r-tree reference count.
+*/
+static void rtreeReference(Rtree *pRtree){
+ pRtree->nBusy++;
+}
+
+/*
+** Decrement the r-tree reference count. When the reference count reaches
+** zero the structure is deleted.
+*/
+static void rtreeRelease(Rtree *pRtree){
+ pRtree->nBusy--;
+ if( pRtree->nBusy==0 ){
+ sqlite3_finalize(pRtree->pReadNode);
+ sqlite3_finalize(pRtree->pWriteNode);
+ sqlite3_finalize(pRtree->pDeleteNode);
+ sqlite3_finalize(pRtree->pReadRowid);
+ sqlite3_finalize(pRtree->pWriteRowid);
+ sqlite3_finalize(pRtree->pDeleteRowid);
+ sqlite3_finalize(pRtree->pReadParent);
+ sqlite3_finalize(pRtree->pWriteParent);
+ sqlite3_finalize(pRtree->pDeleteParent);
+ sqlite3_free(pRtree);
+ }
+}
+
+/*
+** Rtree virtual table module xDisconnect method.
+*/
+static int rtreeDisconnect(sqlite3_vtab *pVtab){
+ rtreeRelease((Rtree *)pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** Rtree virtual table module xDestroy method.
+*/
+static int rtreeDestroy(sqlite3_vtab *pVtab){
+ Rtree *pRtree = (Rtree *)pVtab;
+ int rc;
+ char *zCreate = sqlite3_mprintf(
+ "DROP TABLE '%q'.'%q_node';"
+ "DROP TABLE '%q'.'%q_rowid';"
+ "DROP TABLE '%q'.'%q_parent';",
+ pRtree->zDb, pRtree->zName,
+ pRtree->zDb, pRtree->zName,
+ pRtree->zDb, pRtree->zName
+ );
+ if( !zCreate ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);
+ sqlite3_free(zCreate);
+ }
+ if( rc==SQLITE_OK ){
+ rtreeRelease(pRtree);
+ }
+
+ return rc;
+}
+
+/*
+** Rtree virtual table module xOpen method.
+*/
+static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
+ int rc = SQLITE_NOMEM;
+ RtreeCursor *pCsr;
+
+ pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
+ if( pCsr ){
+ memset(pCsr, 0, sizeof(RtreeCursor));
+ pCsr->base.pVtab = pVTab;
+ rc = SQLITE_OK;
+ }
+ *ppCursor = (sqlite3_vtab_cursor *)pCsr;
+
+ return rc;
+}
+
+
+/*
+** Free the RtreeCursor.aConstraint[] array and its contents.
+*/
+static void freeCursorConstraints(RtreeCursor *pCsr){
+ if( pCsr->aConstraint ){
+ int i; /* Used to iterate through constraint array */
+ for(i=0; i<pCsr->nConstraint; i++){
+ sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom;
+ if( pGeom ){
+ if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser);
+ sqlite3_free(pGeom);
+ }
+ }
+ sqlite3_free(pCsr->aConstraint);
+ pCsr->aConstraint = 0;
+ }
+}
+
+/*
+** Rtree virtual table module xClose method.
+*/
+static int rtreeClose(sqlite3_vtab_cursor *cur){
+ Rtree *pRtree = (Rtree *)(cur->pVtab);
+ int rc;
+ RtreeCursor *pCsr = (RtreeCursor *)cur;
+ freeCursorConstraints(pCsr);
+ rc = nodeRelease(pRtree, pCsr->pNode);
+ sqlite3_free(pCsr);
+ return rc;
+}
+
+/*
+** Rtree virtual table module xEof method.
+**
+** Return non-zero if the cursor does not currently point to a valid
+** record (i.e if the scan has finished), or zero otherwise.
+*/
+static int rtreeEof(sqlite3_vtab_cursor *cur){
+ RtreeCursor *pCsr = (RtreeCursor *)cur;
+ return (pCsr->pNode==0);
+}
+
+/*
+** The r-tree constraint passed as the second argument to this function is
+** guaranteed to be a MATCH constraint.
+*/
+static int testRtreeGeom(
+ Rtree *pRtree, /* R-Tree object */
+ RtreeConstraint *pConstraint, /* MATCH constraint to test */
+ RtreeCell *pCell, /* Cell to test */
+ int *pbRes /* OUT: Test result */
+){
+ int i;
+ RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2];
+ int nCoord = pRtree->nDim*2;
+
+ assert( pConstraint->op==RTREE_MATCH );
+ assert( pConstraint->pGeom );
+
+ for(i=0; i<nCoord; i++){
+ aCoord[i] = DCOORD(pCell->aCoord[i]);
+ }
+ return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes);
+}
+
+/*
+** Cursor pCursor currently points to a cell in a non-leaf page.
+** Set *pbEof to true if the sub-tree headed by the cell is filtered
+** (excluded) by the constraints in the pCursor->aConstraint[]
+** array, or false otherwise.
+**
+** Return SQLITE_OK if successful or an SQLite error code if an error
+** occurs within a geometry callback.
+*/
+static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){
+ RtreeCell cell;
+ int ii;
+ int bRes = 0;
+ int rc = SQLITE_OK;
+
+ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
+ for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){
+ RtreeConstraint *p = &pCursor->aConstraint[ii];
+ RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]);
+ RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]);
+
+ assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
+ || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
+ );
+
+ switch( p->op ){
+ case RTREE_LE: case RTREE_LT:
+ bRes = p->rValue<cell_min;
+ break;
+
+ case RTREE_GE: case RTREE_GT:
+ bRes = p->rValue>cell_max;
+ break;
+
+ case RTREE_EQ:
+ bRes = (p->rValue>cell_max || p->rValue<cell_min);
+ break;
+
+ default: {
+ assert( p->op==RTREE_MATCH );
+ rc = testRtreeGeom(pRtree, p, &cell, &bRes);
+ bRes = !bRes;
+ break;
+ }
+ }
+ }
+
+ *pbEof = bRes;
+ return rc;
+}
+
+/*
+** Test if the cell that cursor pCursor currently points to
+** would be filtered (excluded) by the constraints in the
+** pCursor->aConstraint[] array. If so, set *pbEof to true before
+** returning. If the cell is not filtered (excluded) by the constraints,
+** set pbEof to zero.
+**
+** Return SQLITE_OK if successful or an SQLite error code if an error
+** occurs within a geometry callback.
+**
+** This function assumes that the cell is part of a leaf node.
+*/
+static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){
+ RtreeCell cell;
+ int ii;
+ *pbEof = 0;
+
+ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
+ for(ii=0; ii<pCursor->nConstraint; ii++){
+ RtreeConstraint *p = &pCursor->aConstraint[ii];
+ RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]);
+ int res;
+ assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
+ || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
+ );
+ switch( p->op ){
+ case RTREE_LE: res = (coord<=p->rValue); break;
+ case RTREE_LT: res = (coord<p->rValue); break;
+ case RTREE_GE: res = (coord>=p->rValue); break;
+ case RTREE_GT: res = (coord>p->rValue); break;
+ case RTREE_EQ: res = (coord==p->rValue); break;
+ default: {
+ int rc;
+ assert( p->op==RTREE_MATCH );
+ rc = testRtreeGeom(pRtree, p, &cell, &res);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ break;
+ }
+ }
+
+ if( !res ){
+ *pbEof = 1;
+ return SQLITE_OK;
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Cursor pCursor currently points at a node that heads a sub-tree of
+** height iHeight (if iHeight==0, then the node is a leaf). Descend
+** to point to the left-most cell of the sub-tree that matches the
+** configured constraints.
+*/
+static int descendToCell(
+ Rtree *pRtree,
+ RtreeCursor *pCursor,
+ int iHeight,
+ int *pEof /* OUT: Set to true if cannot descend */
+){
+ int isEof;
+ int rc;
+ int ii;
+ RtreeNode *pChild;
+ sqlite3_int64 iRowid;
+
+ RtreeNode *pSavedNode = pCursor->pNode;
+ int iSavedCell = pCursor->iCell;
+
+ assert( iHeight>=0 );
+
+ if( iHeight==0 ){
+ rc = testRtreeEntry(pRtree, pCursor, &isEof);
+ }else{
+ rc = testRtreeCell(pRtree, pCursor, &isEof);
+ }
+ if( rc!=SQLITE_OK || isEof || iHeight==0 ){
+ goto descend_to_cell_out;
+ }
+
+ iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell);
+ rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild);
+ if( rc!=SQLITE_OK ){
+ goto descend_to_cell_out;
+ }
+
+ nodeRelease(pRtree, pCursor->pNode);
+ pCursor->pNode = pChild;
+ isEof = 1;
+ for(ii=0; isEof && ii<NCELL(pChild); ii++){
+ pCursor->iCell = ii;
+ rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof);
+ if( rc!=SQLITE_OK ){
+ goto descend_to_cell_out;
+ }
+ }
+
+ if( isEof ){
+ assert( pCursor->pNode==pChild );
+ nodeReference(pSavedNode);
+ nodeRelease(pRtree, pChild);
+ pCursor->pNode = pSavedNode;
+ pCursor->iCell = iSavedCell;
+ }
+
+descend_to_cell_out:
+ *pEof = isEof;
+ return rc;
+}
+
+/*
+** One of the cells in node pNode is guaranteed to have a 64-bit
+** integer value equal to iRowid. Return the index of this cell.
+*/
+static int nodeRowidIndex(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ i64 iRowid,
+ int *piIndex
+){
+ int ii;
+ int nCell = NCELL(pNode);
+ for(ii=0; ii<nCell; ii++){
+ if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
+ *piIndex = ii;
+ return SQLITE_OK;
+ }
+ }
+ return SQLITE_CORRUPT_VTAB;
+}
+
+/*
+** Return the index of the cell containing a pointer to node pNode
+** in its parent. If pNode is the root node, return -1.
+*/
+static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
+ RtreeNode *pParent = pNode->pParent;
+ if( pParent ){
+ return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
+ }
+ *piIndex = -1;
+ return SQLITE_OK;
+}
+
+/*
+** Rtree virtual table module xNext method.
+*/
+static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
+ Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab);
+ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
+ int rc = SQLITE_OK;
+
+ /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is
+ ** already at EOF. It is against the rules to call the xNext() method of
+ ** a cursor that has already reached EOF.
+ */
+ assert( pCsr->pNode );
+
+ if( pCsr->iStrategy==1 ){
+ /* This "scan" is a direct lookup by rowid. There is no next entry. */
+ nodeRelease(pRtree, pCsr->pNode);
+ pCsr->pNode = 0;
+ }else{
+ /* Move to the next entry that matches the configured constraints. */
+ int iHeight = 0;
+ while( pCsr->pNode ){
+ RtreeNode *pNode = pCsr->pNode;
+ int nCell = NCELL(pNode);
+ for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){
+ int isEof;
+ rc = descendToCell(pRtree, pCsr, iHeight, &isEof);
+ if( rc!=SQLITE_OK || !isEof ){
+ return rc;
+ }
+ }
+ pCsr->pNode = pNode->pParent;
+ rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ nodeReference(pCsr->pNode);
+ nodeRelease(pRtree, pNode);
+ iHeight++;
+ }
+ }
+
+ return rc;
+}
+
+/*
+** Rtree virtual table module xRowid method.
+*/
+static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
+ Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
+ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
+
+ assert(pCsr->pNode);
+ *pRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);
+
+ return SQLITE_OK;
+}
+
+/*
+** Rtree virtual table module xColumn method.
+*/
+static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
+ Rtree *pRtree = (Rtree *)cur->pVtab;
+ RtreeCursor *pCsr = (RtreeCursor *)cur;
+
+ if( i==0 ){
+ i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);
+ sqlite3_result_int64(ctx, iRowid);
+ }else{
+ RtreeCoord c;
+ nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c);
+#ifndef SQLITE_RTREE_INT_ONLY
+ if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
+ sqlite3_result_double(ctx, c.f);
+ }else
+#endif
+ {
+ assert( pRtree->eCoordType==RTREE_COORD_INT32 );
+ sqlite3_result_int(ctx, c.i);
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Use nodeAcquire() to obtain the leaf node containing the record with
+** rowid iRowid. If successful, set *ppLeaf to point to the node and
+** return SQLITE_OK. If there is no such record in the table, set
+** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf
+** to zero and return an SQLite error code.
+*/
+static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){
+ int rc;
+ *ppLeaf = 0;
+ sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid);
+ if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){
+ i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0);
+ rc = nodeAcquire(pRtree, iNode, 0, ppLeaf);
+ sqlite3_reset(pRtree->pReadRowid);
+ }else{
+ rc = sqlite3_reset(pRtree->pReadRowid);
+ }
+ return rc;
+}
+
+/*
+** This function is called to configure the RtreeConstraint object passed
+** as the second argument for a MATCH constraint. The value passed as the
+** first argument to this function is the right-hand operand to the MATCH
+** operator.
+*/
+static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
+ RtreeMatchArg *p;
+ sqlite3_rtree_geometry *pGeom;
+ int nBlob;
+
+ /* Check that value is actually a blob. */
+ if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR;
+
+ /* Check that the blob is roughly the right size. */
+ nBlob = sqlite3_value_bytes(pValue);
+ if( nBlob<(int)sizeof(RtreeMatchArg)
+ || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0
+ ){
+ return SQLITE_ERROR;
+ }
+
+ pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc(
+ sizeof(sqlite3_rtree_geometry) + nBlob
+ );
+ if( !pGeom ) return SQLITE_NOMEM;
+ memset(pGeom, 0, sizeof(sqlite3_rtree_geometry));
+ p = (RtreeMatchArg *)&pGeom[1];
+
+ memcpy(p, sqlite3_value_blob(pValue), nBlob);
+ if( p->magic!=RTREE_GEOMETRY_MAGIC
+ || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue))
+ ){
+ sqlite3_free(pGeom);
+ return SQLITE_ERROR;
+ }
+
+ pGeom->pContext = p->pContext;
+ pGeom->nParam = p->nParam;
+ pGeom->aParam = p->aParam;
+
+ pCons->xGeom = p->xGeom;
+ pCons->pGeom = pGeom;
+ return SQLITE_OK;
+}
+
+/*
+** Rtree virtual table module xFilter method.
+*/
+static int rtreeFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
+ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
+
+ RtreeNode *pRoot = 0;
+ int ii;
+ int rc = SQLITE_OK;
+
+ rtreeReference(pRtree);
+
+ freeCursorConstraints(pCsr);
+ pCsr->iStrategy = idxNum;
+
+ if( idxNum==1 ){
+ /* Special case - lookup by rowid. */
+ RtreeNode *pLeaf; /* Leaf on which the required cell resides */
+ i64 iRowid = sqlite3_value_int64(argv[0]);
+ rc = findLeafNode(pRtree, iRowid, &pLeaf);
+ pCsr->pNode = pLeaf;
+ if( pLeaf ){
+ assert( rc==SQLITE_OK );
+ rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell);
+ }
+ }else{
+ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
+ ** with the configured constraints.
+ */
+ if( argc>0 ){
+ pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
+ pCsr->nConstraint = argc;
+ if( !pCsr->aConstraint ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc);
+ assert( (idxStr==0 && argc==0)
+ || (idxStr && (int)strlen(idxStr)==argc*2) );
+ for(ii=0; ii<argc; ii++){
+ RtreeConstraint *p = &pCsr->aConstraint[ii];
+ p->op = idxStr[ii*2];
+ p->iCoord = idxStr[ii*2+1]-'a';
+ if( p->op==RTREE_MATCH ){
+ /* A MATCH operator. The right-hand-side must be a blob that
+ ** can be cast into an RtreeMatchArg object. One created using
+ ** an sqlite3_rtree_geometry_callback() SQL user function.
+ */
+ rc = deserializeGeometry(argv[ii], p);
+ if( rc!=SQLITE_OK ){
+ break;
+ }
+ }else{
+#ifdef SQLITE_RTREE_INT_ONLY
+ p->rValue = sqlite3_value_int64(argv[ii]);
+#else
+ p->rValue = sqlite3_value_double(argv[ii]);
+#endif
+ }
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ pCsr->pNode = 0;
+ rc = nodeAcquire(pRtree, 1, 0, &pRoot);
+ }
+ if( rc==SQLITE_OK ){
+ int isEof = 1;
+ int nCell = NCELL(pRoot);
+ pCsr->pNode = pRoot;
+ for(pCsr->iCell=0; rc==SQLITE_OK && pCsr->iCell<nCell; pCsr->iCell++){
+ assert( pCsr->pNode==pRoot );
+ rc = descendToCell(pRtree, pCsr, pRtree->iDepth, &isEof);
+ if( !isEof ){
+ break;
+ }
+ }
+ if( rc==SQLITE_OK && isEof ){
+ assert( pCsr->pNode==pRoot );
+ nodeRelease(pRtree, pRoot);
+ pCsr->pNode = 0;
+ }
+ assert( rc!=SQLITE_OK || !pCsr->pNode || pCsr->iCell<NCELL(pCsr->pNode) );
+ }
+ }
+
+ rtreeRelease(pRtree);
+ return rc;
+}
+
+/*
+** Rtree virtual table module xBestIndex method. There are three
+** table scan strategies to choose from (in order from most to
+** least desirable):
+**
+** idxNum idxStr Strategy
+** ------------------------------------------------
+** 1 Unused Direct lookup by rowid.
+** 2 See below R-tree query or full-table scan.
+** ------------------------------------------------
+**
+** If strategy 1 is used, then idxStr is not meaningful. If strategy
+** 2 is used, idxStr is formatted to contain 2 bytes for each
+** constraint used. The first two bytes of idxStr correspond to
+** the constraint in sqlite3_index_info.aConstraintUsage[] with
+** (argvIndex==1) etc.
+**
+** The first of each pair of bytes in idxStr identifies the constraint
+** operator as follows:
+**
+** Operator Byte Value
+** ----------------------
+** = 0x41 ('A')
+** <= 0x42 ('B')
+** < 0x43 ('C')
+** >= 0x44 ('D')
+** > 0x45 ('E')
+** MATCH 0x46 ('F')
+** ----------------------
+**
+** The second of each pair of bytes identifies the coordinate column
+** to which the constraint applies. The leftmost coordinate column
+** is 'a', the second from the left 'b' etc.
+*/
+static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+ int rc = SQLITE_OK;
+ int ii;
+
+ int iIdx = 0;
+ char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
+ memset(zIdxStr, 0, sizeof(zIdxStr));
+ UNUSED_PARAMETER(tab);
+
+ assert( pIdxInfo->idxStr==0 );
+ for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
+ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
+
+ if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ /* We have an equality constraint on the rowid. Use strategy 1. */
+ int jj;
+ for(jj=0; jj<ii; jj++){
+ pIdxInfo->aConstraintUsage[jj].argvIndex = 0;
+ pIdxInfo->aConstraintUsage[jj].omit = 0;
+ }
+ pIdxInfo->idxNum = 1;
+ pIdxInfo->aConstraintUsage[ii].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[jj].omit = 1;
+
+ /* This strategy involves a two rowid lookups on an B-Tree structures
+ ** and then a linear search of an R-Tree node. This should be
+ ** considered almost as quick as a direct rowid lookup (for which
+ ** sqlite uses an internal cost of 0.0).
+ */
+ pIdxInfo->estimatedCost = 10.0;
+ return SQLITE_OK;
+ }
+
+ if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){
+ u8 op;
+ switch( p->op ){
+ case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
+ case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
+ case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
+ case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
+ case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
+ default:
+ assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
+ op = RTREE_MATCH;
+ break;
+ }
+ zIdxStr[iIdx++] = op;
+ zIdxStr[iIdx++] = p->iColumn - 1 + 'a';
+ pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
+ pIdxInfo->aConstraintUsage[ii].omit = 1;
+ }
+ }
+
+ pIdxInfo->idxNum = 2;
+ pIdxInfo->needToFreeIdxStr = 1;
+ if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
+ return SQLITE_NOMEM;
+ }
+ assert( iIdx>=0 );
+ pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1));
+ return rc;
+}
+
+/*
+** Return the N-dimensional volumn of the cell stored in *p.
+*/
+static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
+ RtreeDValue area = (RtreeDValue)1;
+ int ii;
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])));
+ }
+ return area;
+}
+
+/*
+** Return the margin length of cell p. The margin length is the sum
+** of the objects size in each dimension.
+*/
+static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){
+ RtreeDValue margin = (RtreeDValue)0;
+ int ii;
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
+ }
+ return margin;
+}
+
+/*
+** Store the union of cells p1 and p2 in p1.
+*/
+static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
+ int ii;
+ if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);
+ p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);
+ }
+ }else{
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
+ p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
+ }
+ }
+}
+
+/*
+** Return true if the area covered by p2 is a subset of the area covered
+** by p1. False otherwise.
+*/
+static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
+ int ii;
+ int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ RtreeCoord *a1 = &p1->aCoord[ii];
+ RtreeCoord *a2 = &p2->aCoord[ii];
+ if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
+ || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
+ ){
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+** Return the amount cell p would grow by if it were unioned with pCell.
+*/
+static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){
+ RtreeDValue area;
+ RtreeCell cell;
+ memcpy(&cell, p, sizeof(RtreeCell));
+ area = cellArea(pRtree, &cell);
+ cellUnion(pRtree, &cell, pCell);
+ return (cellArea(pRtree, &cell)-area);
+}
+
+#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT
+static RtreeDValue cellOverlap(
+ Rtree *pRtree,
+ RtreeCell *p,
+ RtreeCell *aCell,
+ int nCell,
+ int iExclude
+){
+ int ii;
+ RtreeDValue overlap = 0.0;
+ for(ii=0; ii<nCell; ii++){
+#if VARIANT_RSTARTREE_CHOOSESUBTREE
+ if( ii!=iExclude )
+#else
+ assert( iExclude==-1 );
+ UNUSED_PARAMETER(iExclude);
+#endif
+ {
+ int jj;
+ RtreeDValue o = (RtreeDValue)1;
+ for(jj=0; jj<(pRtree->nDim*2); jj+=2){
+ RtreeDValue x1, x2;
+
+ x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
+ x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
+
+ if( x2<x1 ){
+ o = 0.0;
+ break;
+ }else{
+ o = o * (x2-x1);
+ }
+ }
+ overlap += o;
+ }
+ }
+ return overlap;
+}
+#endif
+
+#if VARIANT_RSTARTREE_CHOOSESUBTREE
+static RtreeDValue cellOverlapEnlargement(
+ Rtree *pRtree,
+ RtreeCell *p,
+ RtreeCell *pInsert,
+ RtreeCell *aCell,
+ int nCell,
+ int iExclude
+){
+ RtreeDValue before, after;
+ before = cellOverlap(pRtree, p, aCell, nCell, iExclude);
+ cellUnion(pRtree, p, pInsert);
+ after = cellOverlap(pRtree, p, aCell, nCell, iExclude);
+ return (after-before);
+}
+#endif
+
+
+/*
+** This function implements the ChooseLeaf algorithm from Gutman[84].
+** ChooseSubTree in r*tree terminology.
+*/
+static int ChooseLeaf(
+ Rtree *pRtree, /* Rtree table */
+ RtreeCell *pCell, /* Cell to insert into rtree */
+ int iHeight, /* Height of sub-tree rooted at pCell */
+ RtreeNode **ppLeaf /* OUT: Selected leaf page */
+){
+ int rc;
+ int ii;
+ RtreeNode *pNode;
+ rc = nodeAcquire(pRtree, 1, 0, &pNode);
+
+ for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
+ int iCell;
+ sqlite3_int64 iBest = 0;
+
+ RtreeDValue fMinGrowth = 0.0;
+ RtreeDValue fMinArea = 0.0;
+#if VARIANT_RSTARTREE_CHOOSESUBTREE
+ RtreeDValue fMinOverlap = 0.0;
+ RtreeDValue overlap;
+#endif
+
+ int nCell = NCELL(pNode);
+ RtreeCell cell;
+ RtreeNode *pChild;
+
+ RtreeCell *aCell = 0;
+
+#if VARIANT_RSTARTREE_CHOOSESUBTREE
+ if( ii==(pRtree->iDepth-1) ){
+ int jj;
+ aCell = sqlite3_malloc(sizeof(RtreeCell)*nCell);
+ if( !aCell ){
+ rc = SQLITE_NOMEM;
+ nodeRelease(pRtree, pNode);
+ pNode = 0;
+ continue;
+ }
+ for(jj=0; jj<nCell; jj++){
+ nodeGetCell(pRtree, pNode, jj, &aCell[jj]);
+ }
+ }
+#endif
+
+ /* Select the child node which will be enlarged the least if pCell
+ ** is inserted into it. Resolve ties by choosing the entry with
+ ** the smallest area.
+ */
+ for(iCell=0; iCell<nCell; iCell++){
+ int bBest = 0;
+ RtreeDValue growth;
+ RtreeDValue area;
+ nodeGetCell(pRtree, pNode, iCell, &cell);
+ growth = cellGrowth(pRtree, &cell, pCell);
+ area = cellArea(pRtree, &cell);
+
+#if VARIANT_RSTARTREE_CHOOSESUBTREE
+ if( ii==(pRtree->iDepth-1) ){
+ overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell);
+ }else{
+ overlap = 0.0;
+ }
+ if( (iCell==0)
+ || (overlap<fMinOverlap)
+ || (overlap==fMinOverlap && growth<fMinGrowth)
+ || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea)
+ ){
+ bBest = 1;
+ fMinOverlap = overlap;
+ }
+#else
+ if( iCell==0||growth<fMinGrowth||(growth==fMinGrowth && area<fMinArea) ){
+ bBest = 1;
+ }
+#endif
+ if( bBest ){
+ fMinGrowth = growth;
+ fMinArea = area;
+ iBest = cell.iRowid;
+ }
+ }
+
+ sqlite3_free(aCell);
+ rc = nodeAcquire(pRtree, iBest, pNode, &pChild);
+ nodeRelease(pRtree, pNode);
+ pNode = pChild;
+ }
+
+ *ppLeaf = pNode;
+ return rc;
+}
+
+/*
+** A cell with the same content as pCell has just been inserted into
+** the node pNode. This function updates the bounding box cells in
+** all ancestor elements.
+*/
+static int AdjustTree(
+ Rtree *pRtree, /* Rtree table */
+ RtreeNode *pNode, /* Adjust ancestry of this node. */
+ RtreeCell *pCell /* This cell was just inserted */
+){
+ RtreeNode *p = pNode;
+ while( p->pParent ){
+ RtreeNode *pParent = p->pParent;
+ RtreeCell cell;
+ int iCell;
+
+ if( nodeParentIndex(pRtree, p, &iCell) ){
+ return SQLITE_CORRUPT_VTAB;
+ }
+
+ nodeGetCell(pRtree, pParent, iCell, &cell);
+ if( !cellContains(pRtree, &cell, pCell) ){
+ cellUnion(pRtree, &cell, pCell);
+ nodeOverwriteCell(pRtree, pParent, &cell, iCell);
+ }
+
+ p = pParent;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Write mapping (iRowid->iNode) to the <rtree>_rowid table.
+*/
+static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){
+ sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid);
+ sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode);
+ sqlite3_step(pRtree->pWriteRowid);
+ return sqlite3_reset(pRtree->pWriteRowid);
+}
+
+/*
+** Write mapping (iNode->iPar) to the <rtree>_parent table.
+*/
+static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){
+ sqlite3_bind_int64(pRtree->pWriteParent, 1, iNode);
+ sqlite3_bind_int64(pRtree->pWriteParent, 2, iPar);
+ sqlite3_step(pRtree->pWriteParent);
+ return sqlite3_reset(pRtree->pWriteParent);
+}
+
+static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int);
+
+#if VARIANT_GUTTMAN_LINEAR_SPLIT
+/*
+** Implementation of the linear variant of the PickNext() function from
+** Guttman[84].
+*/
+static RtreeCell *LinearPickNext(
+ Rtree *pRtree,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeCell *pLeftBox,
+ RtreeCell *pRightBox,
+ int *aiUsed
+){
+ int ii;
+ for(ii=0; aiUsed[ii]; ii++);
+ aiUsed[ii] = 1;
+ return &aCell[ii];
+}
+
+/*
+** Implementation of the linear variant of the PickSeeds() function from
+** Guttman[84].
+*/
+static void LinearPickSeeds(
+ Rtree *pRtree,
+ RtreeCell *aCell,
+ int nCell,
+ int *piLeftSeed,
+ int *piRightSeed
+){
+ int i;
+ int iLeftSeed = 0;
+ int iRightSeed = 1;
+ RtreeDValue maxNormalInnerWidth = (RtreeDValue)0;
+
+ /* Pick two "seed" cells from the array of cells. The algorithm used
+ ** here is the LinearPickSeeds algorithm from Gutman[1984]. The
+ ** indices of the two seed cells in the array are stored in local
+ ** variables iLeftSeek and iRightSeed.
+ */
+ for(i=0; i<pRtree->nDim; i++){
+ RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]);
+ RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]);
+ RtreeDValue x3 = x1;
+ RtreeDValue x4 = x2;
+ int jj;
+
+ int iCellLeft = 0;
+ int iCellRight = 0;
+
+ for(jj=1; jj<nCell; jj++){
+ RtreeDValue left = DCOORD(aCell[jj].aCoord[i*2]);
+ RtreeDValue right = DCOORD(aCell[jj].aCoord[i*2+1]);
+
+ if( left<x1 ) x1 = left;
+ if( right>x4 ) x4 = right;
+ if( left>x3 ){
+ x3 = left;
+ iCellRight = jj;
+ }
+ if( right<x2 ){
+ x2 = right;
+ iCellLeft = jj;
+ }
+ }
+
+ if( x4!=x1 ){
+ RtreeDValue normalwidth = (x3 - x2) / (x4 - x1);
+ if( normalwidth>maxNormalInnerWidth ){
+ iLeftSeed = iCellLeft;
+ iRightSeed = iCellRight;
+ }
+ }
+ }
+
+ *piLeftSeed = iLeftSeed;
+ *piRightSeed = iRightSeed;
+}
+#endif /* VARIANT_GUTTMAN_LINEAR_SPLIT */
+
+#if VARIANT_GUTTMAN_QUADRATIC_SPLIT
+/*
+** Implementation of the quadratic variant of the PickNext() function from
+** Guttman[84].
+*/
+static RtreeCell *QuadraticPickNext(
+ Rtree *pRtree,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeCell *pLeftBox,
+ RtreeCell *pRightBox,
+ int *aiUsed
+){
+ #define FABS(a) ((a)<0.0?-1.0*(a):(a))
+
+ int iSelect = -1;
+ RtreeDValue fDiff;
+ int ii;
+ for(ii=0; ii<nCell; ii++){
+ if( aiUsed[ii]==0 ){
+ RtreeDValue left = cellGrowth(pRtree, pLeftBox, &aCell[ii]);
+ RtreeDValue right = cellGrowth(pRtree, pLeftBox, &aCell[ii]);
+ RtreeDValue diff = FABS(right-left);
+ if( iSelect<0 || diff>fDiff ){
+ fDiff = diff;
+ iSelect = ii;
+ }
+ }
+ }
+ aiUsed[iSelect] = 1;
+ return &aCell[iSelect];
+}
+
+/*
+** Implementation of the quadratic variant of the PickSeeds() function from
+** Guttman[84].
+*/
+static void QuadraticPickSeeds(
+ Rtree *pRtree,
+ RtreeCell *aCell,
+ int nCell,
+ int *piLeftSeed,
+ int *piRightSeed
+){
+ int ii;
+ int jj;
+
+ int iLeftSeed = 0;
+ int iRightSeed = 1;
+ RtreeDValue fWaste = 0.0;
+
+ for(ii=0; ii<nCell; ii++){
+ for(jj=ii+1; jj<nCell; jj++){
+ RtreeDValue right = cellArea(pRtree, &aCell[jj]);
+ RtreeDValue growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]);
+ RtreeDValue waste = growth - right;
+
+ if( waste>fWaste ){
+ iLeftSeed = ii;
+ iRightSeed = jj;
+ fWaste = waste;
+ }
+ }
+ }
+
+ *piLeftSeed = iLeftSeed;
+ *piRightSeed = iRightSeed;
+}
+#endif /* VARIANT_GUTTMAN_QUADRATIC_SPLIT */
+
+/*
+** Arguments aIdx, aDistance and aSpare all point to arrays of size
+** nIdx. The aIdx array contains the set of integers from 0 to
+** (nIdx-1) in no particular order. This function sorts the values
+** in aIdx according to the indexed values in aDistance. For
+** example, assuming the inputs:
+**
+** aIdx = { 0, 1, 2, 3 }
+** aDistance = { 5.0, 2.0, 7.0, 6.0 }
+**
+** this function sets the aIdx array to contain:
+**
+** aIdx = { 0, 1, 2, 3 }
+**
+** The aSpare array is used as temporary working space by the
+** sorting algorithm.
+*/
+static void SortByDistance(
+ int *aIdx,
+ int nIdx,
+ RtreeDValue *aDistance,
+ int *aSpare
+){
+ if( nIdx>1 ){
+ int iLeft = 0;
+ int iRight = 0;
+
+ int nLeft = nIdx/2;
+ int nRight = nIdx-nLeft;
+ int *aLeft = aIdx;
+ int *aRight = &aIdx[nLeft];
+
+ SortByDistance(aLeft, nLeft, aDistance, aSpare);
+ SortByDistance(aRight, nRight, aDistance, aSpare);
+
+ memcpy(aSpare, aLeft, sizeof(int)*nLeft);
+ aLeft = aSpare;
+
+ while( iLeft<nLeft || iRight<nRight ){
+ if( iLeft==nLeft ){
+ aIdx[iLeft+iRight] = aRight[iRight];
+ iRight++;
+ }else if( iRight==nRight ){
+ aIdx[iLeft+iRight] = aLeft[iLeft];
+ iLeft++;
+ }else{
+ RtreeDValue fLeft = aDistance[aLeft[iLeft]];
+ RtreeDValue fRight = aDistance[aRight[iRight]];
+ if( fLeft<fRight ){
+ aIdx[iLeft+iRight] = aLeft[iLeft];
+ iLeft++;
+ }else{
+ aIdx[iLeft+iRight] = aRight[iRight];
+ iRight++;
+ }
+ }
+ }
+
+#if 0
+ /* Check that the sort worked */
+ {
+ int jj;
+ for(jj=1; jj<nIdx; jj++){
+ RtreeDValue left = aDistance[aIdx[jj-1]];
+ RtreeDValue right = aDistance[aIdx[jj]];
+ assert( left<=right );
+ }
+ }
+#endif
+ }
+}
+
+/*
+** Arguments aIdx, aCell and aSpare all point to arrays of size
+** nIdx. The aIdx array contains the set of integers from 0 to
+** (nIdx-1) in no particular order. This function sorts the values
+** in aIdx according to dimension iDim of the cells in aCell. The
+** minimum value of dimension iDim is considered first, the
+** maximum used to break ties.
+**
+** The aSpare array is used as temporary working space by the
+** sorting algorithm.
+*/
+static void SortByDimension(
+ Rtree *pRtree,
+ int *aIdx,
+ int nIdx,
+ int iDim,
+ RtreeCell *aCell,
+ int *aSpare
+){
+ if( nIdx>1 ){
+
+ int iLeft = 0;
+ int iRight = 0;
+
+ int nLeft = nIdx/2;
+ int nRight = nIdx-nLeft;
+ int *aLeft = aIdx;
+ int *aRight = &aIdx[nLeft];
+
+ SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare);
+ SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare);
+
+ memcpy(aSpare, aLeft, sizeof(int)*nLeft);
+ aLeft = aSpare;
+ while( iLeft<nLeft || iRight<nRight ){
+ RtreeDValue xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]);
+ RtreeDValue xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]);
+ RtreeDValue xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]);
+ RtreeDValue xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]);
+ if( (iLeft!=nLeft) && ((iRight==nRight)
+ || (xleft1<xright1)
+ || (xleft1==xright1 && xleft2<xright2)
+ )){
+ aIdx[iLeft+iRight] = aLeft[iLeft];
+ iLeft++;
+ }else{
+ aIdx[iLeft+iRight] = aRight[iRight];
+ iRight++;
+ }
+ }
+
+#if 0
+ /* Check that the sort worked */
+ {
+ int jj;
+ for(jj=1; jj<nIdx; jj++){
+ RtreeDValue xleft1 = aCell[aIdx[jj-1]].aCoord[iDim*2];
+ RtreeDValue xleft2 = aCell[aIdx[jj-1]].aCoord[iDim*2+1];
+ RtreeDValue xright1 = aCell[aIdx[jj]].aCoord[iDim*2];
+ RtreeDValue xright2 = aCell[aIdx[jj]].aCoord[iDim*2+1];
+ assert( xleft1<=xright1 && (xleft1<xright1 || xleft2<=xright2) );
+ }
+ }
+#endif
+ }
+}
+
+#if VARIANT_RSTARTREE_SPLIT
+/*
+** Implementation of the R*-tree variant of SplitNode from Beckman[1990].
+*/
+static int splitNodeStartree(
+ Rtree *pRtree,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeNode *pLeft,
+ RtreeNode *pRight,
+ RtreeCell *pBboxLeft,
+ RtreeCell *pBboxRight
+){
+ int **aaSorted;
+ int *aSpare;
+ int ii;
+
+ int iBestDim = 0;
+ int iBestSplit = 0;
+ RtreeDValue fBestMargin = 0.0;
+
+ int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
+
+ aaSorted = (int **)sqlite3_malloc(nByte);
+ if( !aaSorted ){
+ return SQLITE_NOMEM;
+ }
+
+ aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell];
+ memset(aaSorted, 0, nByte);
+ for(ii=0; ii<pRtree->nDim; ii++){
+ int jj;
+ aaSorted[ii] = &((int *)&aaSorted[pRtree->nDim])[ii*nCell];
+ for(jj=0; jj<nCell; jj++){
+ aaSorted[ii][jj] = jj;
+ }
+ SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);
+ }
+
+ for(ii=0; ii<pRtree->nDim; ii++){
+ RtreeDValue margin = 0.0;
+ RtreeDValue fBestOverlap = 0.0;
+ RtreeDValue fBestArea = 0.0;
+ int iBestLeft = 0;
+ int nLeft;
+
+ for(
+ nLeft=RTREE_MINCELLS(pRtree);
+ nLeft<=(nCell-RTREE_MINCELLS(pRtree));
+ nLeft++
+ ){
+ RtreeCell left;
+ RtreeCell right;
+ int kk;
+ RtreeDValue overlap;
+ RtreeDValue area;
+
+ memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell));
+ memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell));
+ for(kk=1; kk<(nCell-1); kk++){
+ if( kk<nLeft ){
+ cellUnion(pRtree, &left, &aCell[aaSorted[ii][kk]]);
+ }else{
+ cellUnion(pRtree, &right, &aCell[aaSorted[ii][kk]]);
+ }
+ }
+ margin += cellMargin(pRtree, &left);
+ margin += cellMargin(pRtree, &right);
+ overlap = cellOverlap(pRtree, &left, &right, 1, -1);
+ area = cellArea(pRtree, &left) + cellArea(pRtree, &right);
+ if( (nLeft==RTREE_MINCELLS(pRtree))
+ || (overlap<fBestOverlap)
+ || (overlap==fBestOverlap && area<fBestArea)
+ ){
+ iBestLeft = nLeft;
+ fBestOverlap = overlap;
+ fBestArea = area;
+ }
+ }
+
+ if( ii==0 || margin<fBestMargin ){
+ iBestDim = ii;
+ fBestMargin = margin;
+ iBestSplit = iBestLeft;
+ }
+ }
+
+ memcpy(pBboxLeft, &aCell[aaSorted[iBestDim][0]], sizeof(RtreeCell));
+ memcpy(pBboxRight, &aCell[aaSorted[iBestDim][iBestSplit]], sizeof(RtreeCell));
+ for(ii=0; ii<nCell; ii++){
+ RtreeNode *pTarget = (ii<iBestSplit)?pLeft:pRight;
+ RtreeCell *pBbox = (ii<iBestSplit)?pBboxLeft:pBboxRight;
+ RtreeCell *pCell = &aCell[aaSorted[iBestDim][ii]];
+ nodeInsertCell(pRtree, pTarget, pCell);
+ cellUnion(pRtree, pBbox, pCell);
+ }
+
+ sqlite3_free(aaSorted);
+ return SQLITE_OK;
+}
+#endif
+
+#if VARIANT_GUTTMAN_SPLIT
+/*
+** Implementation of the regular R-tree SplitNode from Guttman[1984].
+*/
+static int splitNodeGuttman(
+ Rtree *pRtree,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeNode *pLeft,
+ RtreeNode *pRight,
+ RtreeCell *pBboxLeft,
+ RtreeCell *pBboxRight
+){
+ int iLeftSeed = 0;
+ int iRightSeed = 1;
+ int *aiUsed;
+ int i;
+
+ aiUsed = sqlite3_malloc(sizeof(int)*nCell);
+ if( !aiUsed ){
+ return SQLITE_NOMEM;
+ }
+ memset(aiUsed, 0, sizeof(int)*nCell);
+
+ PickSeeds(pRtree, aCell, nCell, &iLeftSeed, &iRightSeed);
+
+ memcpy(pBboxLeft, &aCell[iLeftSeed], sizeof(RtreeCell));
+ memcpy(pBboxRight, &aCell[iRightSeed], sizeof(RtreeCell));
+ nodeInsertCell(pRtree, pLeft, &aCell[iLeftSeed]);
+ nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]);
+ aiUsed[iLeftSeed] = 1;
+ aiUsed[iRightSeed] = 1;
+
+ for(i=nCell-2; i>0; i--){
+ RtreeCell *pNext;
+ pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed);
+ RtreeDValue diff =
+ cellGrowth(pRtree, pBboxLeft, pNext) -
+ cellGrowth(pRtree, pBboxRight, pNext)
+ ;
+ if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i)
+ || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i))
+ ){
+ nodeInsertCell(pRtree, pRight, pNext);
+ cellUnion(pRtree, pBboxRight, pNext);
+ }else{
+ nodeInsertCell(pRtree, pLeft, pNext);
+ cellUnion(pRtree, pBboxLeft, pNext);
+ }
+ }
+
+ sqlite3_free(aiUsed);
+ return SQLITE_OK;
+}
+#endif
+
+static int updateMapping(
+ Rtree *pRtree,
+ i64 iRowid,
+ RtreeNode *pNode,
+ int iHeight
+){
+ int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64);
+ xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);
+ if( iHeight>0 ){
+ RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);
+ if( pChild ){
+ nodeRelease(pRtree, pChild->pParent);
+ nodeReference(pNode);
+ pChild->pParent = pNode;
+ }
+ }
+ return xSetMapping(pRtree, iRowid, pNode->iNode);
+}
+
+static int SplitNode(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
+ int iHeight
+){
+ int i;
+ int newCellIsRight = 0;
+
+ int rc = SQLITE_OK;
+ int nCell = NCELL(pNode);
+ RtreeCell *aCell;
+ int *aiUsed;
+
+ RtreeNode *pLeft = 0;
+ RtreeNode *pRight = 0;
+
+ RtreeCell leftbbox;
+ RtreeCell rightbbox;
+
+ /* Allocate an array and populate it with a copy of pCell and
+ ** all cells from node pLeft. Then zero the original node.
+ */
+ aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
+ if( !aCell ){
+ rc = SQLITE_NOMEM;
+ goto splitnode_out;
+ }
+ aiUsed = (int *)&aCell[nCell+1];
+ memset(aiUsed, 0, sizeof(int)*(nCell+1));
+ for(i=0; i<nCell; i++){
+ nodeGetCell(pRtree, pNode, i, &aCell[i]);
+ }
+ nodeZero(pRtree, pNode);
+ memcpy(&aCell[nCell], pCell, sizeof(RtreeCell));
+ nCell++;
+
+ if( pNode->iNode==1 ){
+ pRight = nodeNew(pRtree, pNode);
+ pLeft = nodeNew(pRtree, pNode);
+ pRtree->iDepth++;
+ pNode->isDirty = 1;
+ writeInt16(pNode->zData, pRtree->iDepth);
+ }else{
+ pLeft = pNode;
+ pRight = nodeNew(pRtree, pLeft->pParent);
+ nodeReference(pLeft);
+ }
+
+ if( !pLeft || !pRight ){
+ rc = SQLITE_NOMEM;
+ goto splitnode_out;
+ }
+
+ memset(pLeft->zData, 0, pRtree->iNodeSize);
+ memset(pRight->zData, 0, pRtree->iNodeSize);
+
+ rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox);
+ if( rc!=SQLITE_OK ){
+ goto splitnode_out;
+ }
+
+ /* Ensure both child nodes have node numbers assigned to them by calling
+ ** nodeWrite(). Node pRight always needs a node number, as it was created
+ ** by nodeNew() above. But node pLeft sometimes already has a node number.
+ ** In this case avoid the all to nodeWrite().
+ */
+ if( SQLITE_OK!=(rc = nodeWrite(pRtree, pRight))
+ || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft)))
+ ){
+ goto splitnode_out;
+ }
+
+ rightbbox.iRowid = pRight->iNode;
+ leftbbox.iRowid = pLeft->iNode;
+
+ if( pNode->iNode==1 ){
+ rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1);
+ if( rc!=SQLITE_OK ){
+ goto splitnode_out;
+ }
+ }else{
+ RtreeNode *pParent = pLeft->pParent;
+ int iCell;
+ rc = nodeParentIndex(pRtree, pLeft, &iCell);
+ if( rc==SQLITE_OK ){
+ nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
+ rc = AdjustTree(pRtree, pParent, &leftbbox);
+ }
+ if( rc!=SQLITE_OK ){
+ goto splitnode_out;
+ }
+ }
+ if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){
+ goto splitnode_out;
+ }
+
+ for(i=0; i<NCELL(pRight); i++){
+ i64 iRowid = nodeGetRowid(pRtree, pRight, i);
+ rc = updateMapping(pRtree, iRowid, pRight, iHeight);
+ if( iRowid==pCell->iRowid ){
+ newCellIsRight = 1;
+ }
+ if( rc!=SQLITE_OK ){
+ goto splitnode_out;
+ }
+ }
+ if( pNode->iNode==1 ){
+ for(i=0; i<NCELL(pLeft); i++){
+ i64 iRowid = nodeGetRowid(pRtree, pLeft, i);
+ rc = updateMapping(pRtree, iRowid, pLeft, iHeight);
+ if( rc!=SQLITE_OK ){
+ goto splitnode_out;
+ }
+ }
+ }else if( newCellIsRight==0 ){
+ rc = updateMapping(pRtree, pCell->iRowid, pLeft, iHeight);
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = nodeRelease(pRtree, pRight);
+ pRight = 0;
+ }
+ if( rc==SQLITE_OK ){
+ rc = nodeRelease(pRtree, pLeft);
+ pLeft = 0;
+ }
+
+splitnode_out:
+ nodeRelease(pRtree, pRight);
+ nodeRelease(pRtree, pLeft);
+ sqlite3_free(aCell);
+ return rc;
+}
+
+/*
+** If node pLeaf is not the root of the r-tree and its pParent pointer is
+** still NULL, load all ancestor nodes of pLeaf into memory and populate
+** the pLeaf->pParent chain all the way up to the root node.
+**
+** This operation is required when a row is deleted (or updated - an update
+** is implemented as a delete followed by an insert). SQLite provides the
+** rowid of the row to delete, which can be used to find the leaf on which
+** the entry resides (argument pLeaf). Once the leaf is located, this
+** function is called to determine its ancestry.
+*/
+static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
+ int rc = SQLITE_OK;
+ RtreeNode *pChild = pLeaf;
+ while( rc==SQLITE_OK && pChild->iNode!=1 && pChild->pParent==0 ){
+ int rc2 = SQLITE_OK; /* sqlite3_reset() return code */
+ sqlite3_bind_int64(pRtree->pReadParent, 1, pChild->iNode);
+ rc = sqlite3_step(pRtree->pReadParent);
+ if( rc==SQLITE_ROW ){
+ RtreeNode *pTest; /* Used to test for reference loops */
+ i64 iNode; /* Node number of parent node */
+
+ /* Before setting pChild->pParent, test that we are not creating a
+ ** loop of references (as we would if, say, pChild==pParent). We don't
+ ** want to do this as it leads to a memory leak when trying to delete
+ ** the referenced counted node structures.
+ */
+ iNode = sqlite3_column_int64(pRtree->pReadParent, 0);
+ for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
+ if( !pTest ){
+ rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
+ }
+ }
+ rc = sqlite3_reset(pRtree->pReadParent);
+ if( rc==SQLITE_OK ) rc = rc2;
+ if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
+ pChild = pChild->pParent;
+ }
+ return rc;
+}
+
+static int deleteCell(Rtree *, RtreeNode *, int, int);
+
+static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
+ int rc;
+ int rc2;
+ RtreeNode *pParent = 0;
+ int iCell;
+
+ assert( pNode->nRef==1 );
+
+ /* Remove the entry in the parent cell. */
+ rc = nodeParentIndex(pRtree, pNode, &iCell);
+ if( rc==SQLITE_OK ){
+ pParent = pNode->pParent;
+ pNode->pParent = 0;
+ rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
+ }
+ rc2 = nodeRelease(pRtree, pParent);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* Remove the xxx_node entry. */
+ sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode);
+ sqlite3_step(pRtree->pDeleteNode);
+ if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){
+ return rc;
+ }
+
+ /* Remove the xxx_parent entry. */
+ sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode);
+ sqlite3_step(pRtree->pDeleteParent);
+ if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){
+ return rc;
+ }
+
+ /* Remove the node from the in-memory hash table and link it into
+ ** the Rtree.pDeleted list. Its contents will be re-inserted later on.
+ */
+ nodeHashDelete(pRtree, pNode);
+ pNode->iNode = iHeight;
+ pNode->pNext = pRtree->pDeleted;
+ pNode->nRef++;
+ pRtree->pDeleted = pNode;
+
+ return SQLITE_OK;
+}
+
+static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){
+ RtreeNode *pParent = pNode->pParent;
+ int rc = SQLITE_OK;
+ if( pParent ){
+ int ii;
+ int nCell = NCELL(pNode);
+ RtreeCell box; /* Bounding box for pNode */
+ nodeGetCell(pRtree, pNode, 0, &box);
+ for(ii=1; ii<nCell; ii++){
+ RtreeCell cell;
+ nodeGetCell(pRtree, pNode, ii, &cell);
+ cellUnion(pRtree, &box, &cell);
+ }
+ box.iRowid = pNode->iNode;
+ rc = nodeParentIndex(pRtree, pNode, &ii);
+ if( rc==SQLITE_OK ){
+ nodeOverwriteCell(pRtree, pParent, &box, ii);
+ rc = fixBoundingBox(pRtree, pParent);
+ }
+ }
+ return rc;
+}
+
+/*
+** Delete the cell at index iCell of node pNode. After removing the
+** cell, adjust the r-tree data structure if required.
+*/
+static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
+ RtreeNode *pParent;
+ int rc;
+
+ if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){
+ return rc;
+ }
+
+ /* Remove the cell from the node. This call just moves bytes around
+ ** the in-memory node image, so it cannot fail.
+ */
+ nodeDeleteCell(pRtree, pNode, iCell);
+
+ /* If the node is not the tree root and now has less than the minimum
+ ** number of cells, remove it from the tree. Otherwise, update the
+ ** cell in the parent node so that it tightly contains the updated
+ ** node.
+ */
+ pParent = pNode->pParent;
+ assert( pParent || pNode->iNode==1 );
+ if( pParent ){
+ if( NCELL(pNode)<RTREE_MINCELLS(pRtree) ){
+ rc = removeNode(pRtree, pNode, iHeight);
+ }else{
+ rc = fixBoundingBox(pRtree, pNode);
+ }
+ }
+
+ return rc;
+}
+
+static int Reinsert(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
+ int iHeight
+){
+ int *aOrder;
+ int *aSpare;
+ RtreeCell *aCell;
+ RtreeDValue *aDistance;
+ int nCell;
+ RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS];
+ int iDim;
+ int ii;
+ int rc = SQLITE_OK;
+ int n;
+
+ memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS);
+
+ nCell = NCELL(pNode)+1;
+ n = (nCell+1)&(~1);
+
+ /* Allocate the buffers used by this operation. The allocation is
+ ** relinquished before this function returns.
+ */
+ aCell = (RtreeCell *)sqlite3_malloc(n * (
+ sizeof(RtreeCell) + /* aCell array */
+ sizeof(int) + /* aOrder array */
+ sizeof(int) + /* aSpare array */
+ sizeof(RtreeDValue) /* aDistance array */
+ ));
+ if( !aCell ){
+ return SQLITE_NOMEM;
+ }
+ aOrder = (int *)&aCell[n];
+ aSpare = (int *)&aOrder[n];
+ aDistance = (RtreeDValue *)&aSpare[n];
+
+ for(ii=0; ii<nCell; ii++){
+ if( ii==(nCell-1) ){
+ memcpy(&aCell[ii], pCell, sizeof(RtreeCell));
+ }else{
+ nodeGetCell(pRtree, pNode, ii, &aCell[ii]);
+ }
+ aOrder[ii] = ii;
+ for(iDim=0; iDim<pRtree->nDim; iDim++){
+ aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);
+ aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);
+ }
+ }
+ for(iDim=0; iDim<pRtree->nDim; iDim++){
+ aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2));
+ }
+
+ for(ii=0; ii<nCell; ii++){
+ aDistance[ii] = 0.0;
+ for(iDim=0; iDim<pRtree->nDim; iDim++){
+ RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) -
+ DCOORD(aCell[ii].aCoord[iDim*2]));
+ aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
+ }
+ }
+
+ SortByDistance(aOrder, nCell, aDistance, aSpare);
+ nodeZero(pRtree, pNode);
+
+ for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){
+ RtreeCell *p = &aCell[aOrder[ii]];
+ nodeInsertCell(pRtree, pNode, p);
+ if( p->iRowid==pCell->iRowid ){
+ if( iHeight==0 ){
+ rc = rowidWrite(pRtree, p->iRowid, pNode->iNode);
+ }else{
+ rc = parentWrite(pRtree, p->iRowid, pNode->iNode);
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ rc = fixBoundingBox(pRtree, pNode);
+ }
+ for(; rc==SQLITE_OK && ii<nCell; ii++){
+ /* Find a node to store this cell in. pNode->iNode currently contains
+ ** the height of the sub-tree headed by the cell.
+ */
+ RtreeNode *pInsert;
+ RtreeCell *p = &aCell[aOrder[ii]];
+ rc = ChooseLeaf(pRtree, p, iHeight, &pInsert);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ rc = rtreeInsertCell(pRtree, pInsert, p, iHeight);
+ rc2 = nodeRelease(pRtree, pInsert);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+ }
+
+ sqlite3_free(aCell);
+ return rc;
+}
+
+/*
+** Insert cell pCell into node pNode. Node pNode is the head of a
+** subtree iHeight high (leaf nodes have iHeight==0).
+*/
+static int rtreeInsertCell(
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
+ int iHeight
+){
+ int rc = SQLITE_OK;
+ if( iHeight>0 ){
+ RtreeNode *pChild = nodeHashLookup(pRtree, pCell->iRowid);
+ if( pChild ){
+ nodeRelease(pRtree, pChild->pParent);
+ nodeReference(pNode);
+ pChild->pParent = pNode;
+ }
+ }
+ if( nodeInsertCell(pRtree, pNode, pCell) ){
+#if VARIANT_RSTARTREE_REINSERT
+ if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){
+ rc = SplitNode(pRtree, pNode, pCell, iHeight);
+ }else{
+ pRtree->iReinsertHeight = iHeight;
+ rc = Reinsert(pRtree, pNode, pCell, iHeight);
+ }
+#else
+ rc = SplitNode(pRtree, pNode, pCell, iHeight);
+#endif
+ }else{
+ rc = AdjustTree(pRtree, pNode, pCell);
+ if( rc==SQLITE_OK ){
+ if( iHeight==0 ){
+ rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
+ }else{
+ rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode);
+ }
+ }
+ }
+ return rc;
+}
+
+static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){
+ int ii;
+ int rc = SQLITE_OK;
+ int nCell = NCELL(pNode);
+
+ for(ii=0; rc==SQLITE_OK && ii<nCell; ii++){
+ RtreeNode *pInsert;
+ RtreeCell cell;
+ nodeGetCell(pRtree, pNode, ii, &cell);
+
+ /* Find a node to store this cell in. pNode->iNode currently contains
+ ** the height of the sub-tree headed by the cell.
+ */
+ rc = ChooseLeaf(pRtree, &cell, (int)pNode->iNode, &pInsert);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ rc = rtreeInsertCell(pRtree, pInsert, &cell, (int)pNode->iNode);
+ rc2 = nodeRelease(pRtree, pInsert);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Select a currently unused rowid for a new r-tree record.
+*/
+static int newRowid(Rtree *pRtree, i64 *piRowid){
+ int rc;
+ sqlite3_bind_null(pRtree->pWriteRowid, 1);
+ sqlite3_bind_null(pRtree->pWriteRowid, 2);
+ sqlite3_step(pRtree->pWriteRowid);
+ rc = sqlite3_reset(pRtree->pWriteRowid);
+ *piRowid = sqlite3_last_insert_rowid(pRtree->db);
+ return rc;
+}
+
+/*
+** Remove the entry with rowid=iDelete from the r-tree structure.
+*/
+static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
+ int rc; /* Return code */
+ RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */
+ int iCell; /* Index of iDelete cell in pLeaf */
+ RtreeNode *pRoot; /* Root node of rtree structure */
+
+
+ /* Obtain a reference to the root node to initialize Rtree.iDepth */
+ rc = nodeAcquire(pRtree, 1, 0, &pRoot);
+
+ /* Obtain a reference to the leaf node that contains the entry
+ ** about to be deleted.
+ */
+ if( rc==SQLITE_OK ){
+ rc = findLeafNode(pRtree, iDelete, &pLeaf);
+ }
+
+ /* Delete the cell in question from the leaf node. */
+ if( rc==SQLITE_OK ){
+ int rc2;
+ rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
+ if( rc==SQLITE_OK ){
+ rc = deleteCell(pRtree, pLeaf, iCell, 0);
+ }
+ rc2 = nodeRelease(pRtree, pLeaf);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+
+ /* Delete the corresponding entry in the <rtree>_rowid table. */
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
+ sqlite3_step(pRtree->pDeleteRowid);
+ rc = sqlite3_reset(pRtree->pDeleteRowid);
+ }
+
+ /* Check if the root node now has exactly one child. If so, remove
+ ** it, schedule the contents of the child for reinsertion and
+ ** reduce the tree height by one.
+ **
+ ** This is equivalent to copying the contents of the child into
+ ** the root node (the operation that Gutman's paper says to perform
+ ** in this scenario).
+ */
+ if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
+ int rc2;
+ RtreeNode *pChild;
+ i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
+ rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
+ if( rc==SQLITE_OK ){
+ rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
+ }
+ rc2 = nodeRelease(pRtree, pChild);
+ if( rc==SQLITE_OK ) rc = rc2;
+ if( rc==SQLITE_OK ){
+ pRtree->iDepth--;
+ writeInt16(pRoot->zData, pRtree->iDepth);
+ pRoot->isDirty = 1;
+ }
+ }
+
+ /* Re-insert the contents of any underfull nodes removed from the tree. */
+ for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
+ if( rc==SQLITE_OK ){
+ rc = reinsertNodeContent(pRtree, pLeaf);
+ }
+ pRtree->pDeleted = pLeaf->pNext;
+ sqlite3_free(pLeaf);
+ }
+
+ /* Release the reference to the root node. */
+ if( rc==SQLITE_OK ){
+ rc = nodeRelease(pRtree, pRoot);
+ }else{
+ nodeRelease(pRtree, pRoot);
+ }
+
+ return rc;
+}
+
+/*
+** Rounding constants for float->double conversion.
+*/
+#define RNDTOWARDS (1.0 - 1.0/8388608.0) /* Round towards zero */
+#define RNDAWAY (1.0 + 1.0/8388608.0) /* Round away from zero */
+
+#if !defined(SQLITE_RTREE_INT_ONLY)
+/*
+** Convert an sqlite3_value into an RtreeValue (presumably a float)
+** while taking care to round toward negative or positive, respectively.
+*/
+static RtreeValue rtreeValueDown(sqlite3_value *v){
+ double d = sqlite3_value_double(v);
+ float f = (float)d;
+ if( f>d ){
+ f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS));
+ }
+ return f;
+}
+static RtreeValue rtreeValueUp(sqlite3_value *v){
+ double d = sqlite3_value_double(v);
+ float f = (float)d;
+ if( f<d ){
+ f = (float)(d*(d<0 ? RNDTOWARDS : RNDAWAY));
+ }
+ return f;
+}
+#endif /* !defined(SQLITE_RTREE_INT_ONLY) */
+
+
+/*
+** The xUpdate method for rtree module virtual tables.
+*/
+static int rtreeUpdate(
+ sqlite3_vtab *pVtab,
+ int nData,
+ sqlite3_value **azData,
+ sqlite_int64 *pRowid
+){
+ Rtree *pRtree = (Rtree *)pVtab;
+ int rc = SQLITE_OK;
+ RtreeCell cell; /* New cell to insert if nData>1 */
+ int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
+
+ rtreeReference(pRtree);
+ assert(nData>=1);
+
+ /* Constraint handling. A write operation on an r-tree table may return
+ ** SQLITE_CONSTRAINT for two reasons:
+ **
+ ** 1. A duplicate rowid value, or
+ ** 2. The supplied data violates the "x2>=x1" constraint.
+ **
+ ** In the first case, if the conflict-handling mode is REPLACE, then
+ ** the conflicting row can be removed before proceeding. In the second
+ ** case, SQLITE_CONSTRAINT must be returned regardless of the
+ ** conflict-handling mode specified by the user.
+ */
+ if( nData>1 ){
+ int ii;
+
+ /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
+ assert( nData==(pRtree->nDim*2 + 3) );
+#ifndef SQLITE_RTREE_INT_ONLY
+ if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
+ cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
+ if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
+ rc = SQLITE_CONSTRAINT;
+ goto constraint;
+ }
+ }
+ }else
+#endif
+ {
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
+ cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
+ if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
+ rc = SQLITE_CONSTRAINT;
+ goto constraint;
+ }
+ }
+ }
+
+ /* If a rowid value was supplied, check if it is already present in
+ ** the table. If so, the constraint has failed. */
+ if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
+ cell.iRowid = sqlite3_value_int64(azData[2]);
+ if( sqlite3_value_type(azData[0])==SQLITE_NULL
+ || sqlite3_value_int64(azData[0])!=cell.iRowid
+ ){
+ int steprc;
+ sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
+ steprc = sqlite3_step(pRtree->pReadRowid);
+ rc = sqlite3_reset(pRtree->pReadRowid);
+ if( SQLITE_ROW==steprc ){
+ if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){
+ rc = rtreeDeleteRowid(pRtree, cell.iRowid);
+ }else{
+ rc = SQLITE_CONSTRAINT;
+ goto constraint;
+ }
+ }
+ }
+ bHaveRowid = 1;
+ }
+ }
+
+ /* If azData[0] is not an SQL NULL value, it is the rowid of a
+ ** record to delete from the r-tree table. The following block does
+ ** just that.
+ */
+ if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
+ rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0]));
+ }
+
+ /* If the azData[] array contains more than one element, elements
+ ** (azData[2]..azData[argc-1]) contain a new record to insert into
+ ** the r-tree structure.
+ */
+ if( rc==SQLITE_OK && nData>1 ){
+ /* Insert the new record into the r-tree */
+ RtreeNode *pLeaf = 0;
+
+ /* Figure out the rowid of the new row. */
+ if( bHaveRowid==0 ){
+ rc = newRowid(pRtree, &cell.iRowid);
+ }
+ *pRowid = cell.iRowid;
+
+ if( rc==SQLITE_OK ){
+ rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
+ }
+ if( rc==SQLITE_OK ){
+ int rc2;
+ pRtree->iReinsertHeight = -1;
+ rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0);
+ rc2 = nodeRelease(pRtree, pLeaf);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+ }
+
+constraint:
+ rtreeRelease(pRtree);
+ return rc;
+}
+
+/*
+** The xRename method for rtree module virtual tables.
+*/
+static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
+ Rtree *pRtree = (Rtree *)pVtab;
+ int rc = SQLITE_NOMEM;
+ char *zSql = sqlite3_mprintf(
+ "ALTER TABLE %Q.'%q_node' RENAME TO \"%w_node\";"
+ "ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";"
+ "ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";"
+ , pRtree->zDb, pRtree->zName, zNewName
+ , pRtree->zDb, pRtree->zName, zNewName
+ , pRtree->zDb, pRtree->zName, zNewName
+ );
+ if( zSql ){
+ rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0);
+ sqlite3_free(zSql);
+ }
+ return rc;
+}
+
+static sqlite3_module rtreeModule = {
+ 0, /* iVersion */
+ rtreeCreate, /* xCreate - create a table */
+ rtreeConnect, /* xConnect - connect to an existing table */
+ rtreeBestIndex, /* xBestIndex - Determine search strategy */
+ rtreeDisconnect, /* xDisconnect - Disconnect from a table */
+ rtreeDestroy, /* xDestroy - Drop a table */
+ rtreeOpen, /* xOpen - open a cursor */
+ rtreeClose, /* xClose - close a cursor */
+ rtreeFilter, /* xFilter - configure scan constraints */
+ rtreeNext, /* xNext - advance a cursor */
+ rtreeEof, /* xEof */
+ rtreeColumn, /* xColumn - read data */
+ rtreeRowid, /* xRowid - read data */
+ rtreeUpdate, /* xUpdate - write data */
+ 0, /* xBegin - begin transaction */
+ 0, /* xSync - sync transaction */
+ 0, /* xCommit - commit transaction */
+ 0, /* xRollback - rollback transaction */
+ 0, /* xFindFunction - function overloading */
+ rtreeRename, /* xRename - rename the table */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0 /* xRollbackTo */
+};
+
+static int rtreeSqlInit(
+ Rtree *pRtree,
+ sqlite3 *db,
+ const char *zDb,
+ const char *zPrefix,
+ int isCreate
+){
+ int rc = SQLITE_OK;
+
+ #define N_STATEMENT 9
+ static const char *azSql[N_STATEMENT] = {
+ /* Read and write the xxx_node table */
+ "SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1",
+ "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
+ "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
+
+ /* Read and write the xxx_rowid table */
+ "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1",
+ "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)",
+ "DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1",
+
+ /* Read and write the xxx_parent table */
+ "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1",
+ "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)",
+ "DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1"
+ };
+ sqlite3_stmt **appStmt[N_STATEMENT];
+ int i;
+
+ pRtree->db = db;
+
+ if( isCreate ){
+ char *zCreate = sqlite3_mprintf(
+"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);"
+"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);"
+"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY, parentnode INTEGER);"
+"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))",
+ zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize
+ );
+ if( !zCreate ){
+ return SQLITE_NOMEM;
+ }
+ rc = sqlite3_exec(db, zCreate, 0, 0, 0);
+ sqlite3_free(zCreate);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+
+ appStmt[0] = &pRtree->pReadNode;
+ appStmt[1] = &pRtree->pWriteNode;
+ appStmt[2] = &pRtree->pDeleteNode;
+ appStmt[3] = &pRtree->pReadRowid;
+ appStmt[4] = &pRtree->pWriteRowid;
+ appStmt[5] = &pRtree->pDeleteRowid;
+ appStmt[6] = &pRtree->pReadParent;
+ appStmt[7] = &pRtree->pWriteParent;
+ appStmt[8] = &pRtree->pDeleteParent;
+
+ for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
+ char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
+ if( zSql ){
+ rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0);
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ sqlite3_free(zSql);
+ }
+
+ return rc;
+}
+
+/*
+** The second argument to this function contains the text of an SQL statement
+** that returns a single integer value. The statement is compiled and executed
+** using database connection db. If successful, the integer value returned
+** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error
+** code is returned and the value of *piVal after returning is not defined.
+*/
+static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
+ int rc = SQLITE_NOMEM;
+ if( zSql ){
+ sqlite3_stmt *pStmt = 0;
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ if( rc==SQLITE_OK ){
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ *piVal = sqlite3_column_int(pStmt, 0);
+ }
+ rc = sqlite3_finalize(pStmt);
+ }
+ }
+ return rc;
+}
+
+/*
+** This function is called from within the xConnect() or xCreate() method to
+** determine the node-size used by the rtree table being created or connected
+** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned.
+** Otherwise, an SQLite error code is returned.
+**
+** If this function is being called as part of an xConnect(), then the rtree
+** table already exists. In this case the node-size is determined by inspecting
+** the root node of the tree.
+**
+** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
+** This ensures that each node is stored on a single database page. If the
+** database page-size is so large that more than RTREE_MAXCELLS entries
+** would fit in a single node, use a smaller node-size.
+*/
+static int getNodeSize(
+ sqlite3 *db, /* Database handle */
+ Rtree *pRtree, /* Rtree handle */
+ int isCreate, /* True for xCreate, false for xConnect */
+ char **pzErr /* OUT: Error message, if any */
+){
+ int rc;
+ char *zSql;
+ if( isCreate ){
+ int iPageSize = 0;
+ zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
+ rc = getIntFromStmt(db, zSql, &iPageSize);
+ if( rc==SQLITE_OK ){
+ pRtree->iNodeSize = iPageSize-64;
+ if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
+ pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
+ }
+ }else{
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
+ }else{
+ zSql = sqlite3_mprintf(
+ "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
+ pRtree->zDb, pRtree->zName
+ );
+ rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
+ if( rc!=SQLITE_OK ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
+ }
+
+ sqlite3_free(zSql);
+ return rc;
+}
+
+/*
+** This function is the implementation of both the xConnect and xCreate
+** methods of the r-tree virtual table.
+**
+** argv[0] -> module name
+** argv[1] -> database name
+** argv[2] -> table name
+** argv[...] -> column names...
+*/
+static int rtreeInit(
+ sqlite3 *db, /* Database connection */
+ void *pAux, /* One of the RTREE_COORD_* constants */
+ int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */
+ sqlite3_vtab **ppVtab, /* OUT: New virtual table */
+ char **pzErr, /* OUT: Error message, if any */
+ int isCreate /* True for xCreate, false for xConnect */
+){
+ int rc = SQLITE_OK;
+ Rtree *pRtree;
+ int nDb; /* Length of string argv[1] */
+ int nName; /* Length of string argv[2] */
+ int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32);
+
+ const char *aErrMsg[] = {
+ 0, /* 0 */
+ "Wrong number of columns for an rtree table", /* 1 */
+ "Too few columns for an rtree table", /* 2 */
+ "Too many columns for an rtree table" /* 3 */
+ };
+
+ int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
+ if( aErrMsg[iErr] ){
+ *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
+ return SQLITE_ERROR;
+ }
+
+ sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
+
+ /* Allocate the sqlite3_vtab structure */
+ nDb = (int)strlen(argv[1]);
+ nName = (int)strlen(argv[2]);
+ pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
+ if( !pRtree ){
+ return SQLITE_NOMEM;
+ }
+ memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
+ pRtree->nBusy = 1;
+ pRtree->base.pModule = &rtreeModule;
+ pRtree->zDb = (char *)&pRtree[1];
+ pRtree->zName = &pRtree->zDb[nDb+1];
+ pRtree->nDim = (argc-4)/2;
+ pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
+ pRtree->eCoordType = eCoordType;
+ memcpy(pRtree->zDb, argv[1], nDb);
+ memcpy(pRtree->zName, argv[2], nName);
+
+ /* Figure out the node size to use. */
+ rc = getNodeSize(db, pRtree, isCreate, pzErr);
+
+ /* Create/Connect to the underlying relational database schema. If
+ ** that is successful, call sqlite3_declare_vtab() to configure
+ ** the r-tree table schema.
+ */
+ if( rc==SQLITE_OK ){
+ if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }else{
+ char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
+ char *zTmp;
+ int ii;
+ for(ii=4; zSql && ii<argc; ii++){
+ zTmp = zSql;
+ zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
+ sqlite3_free(zTmp);
+ }
+ if( zSql ){
+ zTmp = zSql;
+ zSql = sqlite3_mprintf("%s);", zTmp);
+ sqlite3_free(zTmp);
+ }
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
+ sqlite3_free(zSql);
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ *ppVtab = (sqlite3_vtab *)pRtree;
+ }else{
+ rtreeRelease(pRtree);
+ }
+ return rc;
+}
+
+
+/*
+** Implementation of a scalar function that decodes r-tree nodes to
+** human readable strings. This can be used for debugging and analysis.
+**
+** The scalar function takes two arguments, a blob of data containing
+** an r-tree node, and the number of dimensions the r-tree indexes.
+** For a two-dimensional r-tree structure called "rt", to deserialize
+** all nodes, a statement like:
+**
+** SELECT rtreenode(2, data) FROM rt_node;
+**
+** The human readable string takes the form of a Tcl list with one
+** entry for each cell in the r-tree node. Each entry is itself a
+** list, containing the 8-byte rowid/pageno followed by the
+** <num-dimension>*2 coordinates.
+*/
+static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
+ char *zText = 0;
+ RtreeNode node;
+ Rtree tree;
+ int ii;
+
+ UNUSED_PARAMETER(nArg);
+ memset(&node, 0, sizeof(RtreeNode));
+ memset(&tree, 0, sizeof(Rtree));
+ tree.nDim = sqlite3_value_int(apArg[0]);
+ tree.nBytesPerCell = 8 + 8 * tree.nDim;
+ node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
+
+ for(ii=0; ii<NCELL(&node); ii++){
+ char zCell[512];
+ int nCell = 0;
+ RtreeCell cell;
+ int jj;
+
+ nodeGetCell(&tree, &node, ii, &cell);
+ sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
+ nCell = (int)strlen(zCell);
+ for(jj=0; jj<tree.nDim*2; jj++){
+#ifndef SQLITE_RTREE_INT_ONLY
+ sqlite3_snprintf(512-nCell,&zCell[nCell], " %f",
+ (double)cell.aCoord[jj].f);
+#else
+ sqlite3_snprintf(512-nCell,&zCell[nCell], " %d",
+ cell.aCoord[jj].i);
+#endif
+ nCell = (int)strlen(zCell);
+ }
+
+ if( zText ){
+ char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
+ sqlite3_free(zText);
+ zText = zTextNew;
+ }else{
+ zText = sqlite3_mprintf("{%s}", zCell);
+ }
+ }
+
+ sqlite3_result_text(ctx, zText, -1, sqlite3_free);
+}
+
+static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
+ UNUSED_PARAMETER(nArg);
+ if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
+ || sqlite3_value_bytes(apArg[0])<2
+ ){
+ sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
+ }else{
+ u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
+ sqlite3_result_int(ctx, readInt16(zBlob));
+ }
+}
+
+/*
+** Register the r-tree module with database handle db. This creates the
+** virtual table module "rtree" and the debugging/analysis scalar
+** function "rtreenode".
+*/
+SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){
+ const int utf8 = SQLITE_UTF8;
+ int rc;
+
+ rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
+ }
+ if( rc==SQLITE_OK ){
+#ifdef SQLITE_RTREE_INT_ONLY
+ void *c = (void *)RTREE_COORD_INT32;
+#else
+ void *c = (void *)RTREE_COORD_REAL32;
+#endif
+ rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0);
+ }
+ if( rc==SQLITE_OK ){
+ void *c = (void *)RTREE_COORD_INT32;
+ rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0);
+ }
+
+ return rc;
+}
+
+/*
+** A version of sqlite3_free() that can be used as a callback. This is used
+** in two places - as the destructor for the blob value returned by the
+** invocation of a geometry function, and as the destructor for the geometry
+** functions themselves.
+*/
+static void doSqlite3Free(void *p){
+ sqlite3_free(p);
+}
+
+/*
+** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite
+** scalar user function. This C function is the callback used for all such
+** registered SQL functions.
+**
+** The scalar user functions return a blob that is interpreted by r-tree
+** table MATCH operators.
+*/
+static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
+ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
+ RtreeMatchArg *pBlob;
+ int nBlob;
+
+ nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue);
+ pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
+ if( !pBlob ){
+ sqlite3_result_error_nomem(ctx);
+ }else{
+ int i;
+ pBlob->magic = RTREE_GEOMETRY_MAGIC;
+ pBlob->xGeom = pGeomCtx->xGeom;
+ pBlob->pContext = pGeomCtx->pContext;
+ pBlob->nParam = nArg;
+ for(i=0; i<nArg; i++){
+#ifdef SQLITE_RTREE_INT_ONLY
+ pBlob->aParam[i] = sqlite3_value_int64(aArg[i]);
+#else
+ pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
+#endif
+ }
+ sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free);
+ }
+}
+
+/*
+** Register a new geometry function for use with the r-tree MATCH operator.
+*/
+SQLITE_API int sqlite3_rtree_geometry_callback(
+ sqlite3 *db,
+ const char *zGeom,
+ int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *),
+ void *pContext
+){
+ RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */
+
+ /* Allocate and populate the context object. */
+ pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
+ if( !pGeomCtx ) return SQLITE_NOMEM;
+ pGeomCtx->xGeom = xGeom;
+ pGeomCtx->pContext = pContext;
+
+ /* Create the new user-function. Register a destructor function to delete
+ ** the context object when it is no longer required. */
+ return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY,
+ (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free
+ );
+}
+
+#if !SQLITE_CORE
+SQLITE_API int sqlite3_extension_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi)
+ return sqlite3RtreeInit(db);
+}
+#endif
+
+#endif
+
+/************** End of rtree.c ***********************************************/
+/************** Begin file icu.c *********************************************/
+/*
+** 2007 May 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
+**
+** This file implements an integration between the ICU library
+** ("International Components for Unicode", an open-source library
+** for handling unicode data) and SQLite. The integration uses
+** ICU to provide the following to SQLite:
+**
+** * An implementation of the SQL regexp() function (and hence REGEXP
+** operator) using the ICU uregex_XX() APIs.
+**
+** * Implementations of the SQL scalar upper() and lower() functions
+** for case mapping.
+**
+** * Integration of ICU and SQLite collation seqences.
+**
+** * An implementation of the LIKE operator that uses ICU to
+** provide case-independent matching.
+*/
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
+
+/* Include ICU headers */
+#include <unicode/utypes.h>
+#include <unicode/uregex.h>
+#include <unicode/ustring.h>
+#include <unicode/ucol.h>
+
+/* #include <assert.h> */
+
+#ifndef SQLITE_CORE
+ SQLITE_EXTENSION_INIT1
+#else
+#endif
+
+/*
+** Maximum length (in bytes) of the pattern in a LIKE or GLOB
+** operator.
+*/
+#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
+# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
+#endif
+
+/*
+** Version of sqlite3_free() that is always a function, never a macro.
+*/
+static void xFree(void *p){
+ sqlite3_free(p);
+}
+
+/*
+** Compare two UTF-8 strings for equality where the first string is
+** a "LIKE" expression. Return true (1) if they are the same and
+** false (0) if they are different.
+*/
+static int icuLikeCompare(
+ const uint8_t *zPattern, /* LIKE pattern */
+ const uint8_t *zString, /* The UTF-8 string to compare against */
+ const UChar32 uEsc /* The escape character */
+){
+ static const int MATCH_ONE = (UChar32)'_';
+ static const int MATCH_ALL = (UChar32)'%';
+
+ int iPattern = 0; /* Current byte index in zPattern */
+ int iString = 0; /* Current byte index in zString */
+
+ int prevEscape = 0; /* True if the previous character was uEsc */
+
+ while( zPattern[iPattern]!=0 ){
+
+ /* Read (and consume) the next character from the input pattern. */
+ UChar32 uPattern;
+ U8_NEXT_UNSAFE(zPattern, iPattern, uPattern);
+ assert(uPattern!=0);
+
+ /* There are now 4 possibilities:
+ **
+ ** 1. uPattern is an unescaped match-all character "%",
+ ** 2. uPattern is an unescaped match-one character "_",
+ ** 3. uPattern is an unescaped escape character, or
+ ** 4. uPattern is to be handled as an ordinary character
+ */
+ if( !prevEscape && uPattern==MATCH_ALL ){
+ /* Case 1. */
+ uint8_t c;
+
+ /* Skip any MATCH_ALL or MATCH_ONE characters that follow a
+ ** MATCH_ALL. For each MATCH_ONE, skip one character in the
+ ** test string.
+ */
+ while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){
+ if( c==MATCH_ONE ){
+ if( zString[iString]==0 ) return 0;
+ U8_FWD_1_UNSAFE(zString, iString);
+ }
+ iPattern++;
+ }
+
+ if( zPattern[iPattern]==0 ) return 1;
+
+ while( zString[iString] ){
+ if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){
+ return 1;
+ }
+ U8_FWD_1_UNSAFE(zString, iString);
+ }
+ return 0;
+
+ }else if( !prevEscape && uPattern==MATCH_ONE ){
+ /* Case 2. */
+ if( zString[iString]==0 ) return 0;
+ U8_FWD_1_UNSAFE(zString, iString);
+
+ }else if( !prevEscape && uPattern==uEsc){
+ /* Case 3. */
+ prevEscape = 1;
+
+ }else{
+ /* Case 4. */
+ UChar32 uString;
+ U8_NEXT_UNSAFE(zString, iString, uString);
+ uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT);
+ uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT);
+ if( uString!=uPattern ){
+ return 0;
+ }
+ prevEscape = 0;
+ }
+ }
+
+ return zString[iString]==0;
+}
+
+/*
+** Implementation of the like() SQL function. This function implements
+** the build-in LIKE operator. The first argument to the function is the
+** pattern and the second argument is the string. So, the SQL statements:
+**
+** A LIKE B
+**
+** is implemented as like(B, A). If there is an escape character E,
+**
+** A LIKE B ESCAPE E
+**
+** is mapped to like(B, A, E).
+*/
+static void icuLikeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *zA = sqlite3_value_text(argv[0]);
+ const unsigned char *zB = sqlite3_value_text(argv[1]);
+ UChar32 uEsc = 0;
+
+ /* Limit the length of the LIKE or GLOB pattern to avoid problems
+ ** of deep recursion and N*N behavior in patternCompare().
+ */
+ if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){
+ sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
+ return;
+ }
+
+
+ if( argc==3 ){
+ /* The escape character string must consist of a single UTF-8 character.
+ ** Otherwise, return an error.
+ */
+ int nE= sqlite3_value_bytes(argv[2]);
+ const unsigned char *zE = sqlite3_value_text(argv[2]);
+ int i = 0;
+ if( zE==0 ) return;
+ U8_NEXT(zE, i, nE, uEsc);
+ if( i!=nE){
+ sqlite3_result_error(context,
+ "ESCAPE expression must be a single character", -1);
+ return;
+ }
+ }
+
+ if( zA && zB ){
+ sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc));
+ }
+}
+
+/*
+** This function is called when an ICU function called from within
+** the implementation of an SQL scalar function returns an error.
+**
+** The scalar function context passed as the first argument is
+** loaded with an error message based on the following two args.
+*/
+static void icuFunctionError(
+ sqlite3_context *pCtx, /* SQLite scalar function context */
+ const char *zName, /* Name of ICU function that failed */
+ UErrorCode e /* Error code returned by ICU function */
+){
+ char zBuf[128];
+ sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e));
+ zBuf[127] = '\0';
+ sqlite3_result_error(pCtx, zBuf, -1);
+}
+
+/*
+** Function to delete compiled regexp objects. Registered as
+** a destructor function with sqlite3_set_auxdata().
+*/
+static void icuRegexpDelete(void *p){
+ URegularExpression *pExpr = (URegularExpression *)p;
+ uregex_close(pExpr);
+}
+
+/*
+** Implementation of SQLite REGEXP operator. This scalar function takes
+** two arguments. The first is a regular expression pattern to compile
+** the second is a string to match against that pattern. If either
+** argument is an SQL NULL, then NULL Is returned. Otherwise, the result
+** is 1 if the string matches the pattern, or 0 otherwise.
+**
+** SQLite maps the regexp() function to the regexp() operator such
+** that the following two are equivalent:
+**
+** zString REGEXP zPattern
+** regexp(zPattern, zString)
+**
+** Uses the following ICU regexp APIs:
+**
+** uregex_open()
+** uregex_matches()
+** uregex_close()
+*/
+static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
+ UErrorCode status = U_ZERO_ERROR;
+ URegularExpression *pExpr;
+ UBool res;
+ const UChar *zString = sqlite3_value_text16(apArg[1]);
+
+ (void)nArg; /* Unused parameter */
+
+ /* If the left hand side of the regexp operator is NULL,
+ ** then the result is also NULL.
+ */
+ if( !zString ){
+ return;
+ }
+
+ pExpr = sqlite3_get_auxdata(p, 0);
+ if( !pExpr ){
+ const UChar *zPattern = sqlite3_value_text16(apArg[0]);
+ if( !zPattern ){
+ return;
+ }
+ pExpr = uregex_open(zPattern, -1, 0, 0, &status);
+
+ if( U_SUCCESS(status) ){
+ sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
+ }else{
+ assert(!pExpr);
+ icuFunctionError(p, "uregex_open", status);
+ return;
+ }
+ }
+
+ /* Configure the text that the regular expression operates on. */
+ uregex_setText(pExpr, zString, -1, &status);
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "uregex_setText", status);
+ return;
+ }
+
+ /* Attempt the match */
+ res = uregex_matches(pExpr, 0, &status);
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "uregex_matches", status);
+ return;
+ }
+
+ /* Set the text that the regular expression operates on to a NULL
+ ** pointer. This is not really necessary, but it is tidier than
+ ** leaving the regular expression object configured with an invalid
+ ** pointer after this function returns.
+ */
+ uregex_setText(pExpr, 0, 0, &status);
+
+ /* Return 1 or 0. */
+ sqlite3_result_int(p, res ? 1 : 0);
+}
+
+/*
+** Implementations of scalar functions for case mapping - upper() and
+** lower(). Function upper() converts its input to upper-case (ABC).
+** Function lower() converts to lower-case (abc).
+**
+** ICU provides two types of case mapping, "general" case mapping and
+** "language specific". Refer to ICU documentation for the differences
+** between the two.
+**
+** To utilise "general" case mapping, the upper() or lower() scalar
+** functions are invoked with one argument:
+**
+** upper('ABC') -> 'abc'
+** lower('abc') -> 'ABC'
+**
+** To access ICU "language specific" case mapping, upper() or lower()
+** should be invoked with two arguments. The second argument is the name
+** of the locale to use. Passing an empty string ("") or SQL NULL value
+** as the second argument is the same as invoking the 1 argument version
+** of upper() or lower().
+**
+** lower('I', 'en_us') -> 'i'
+** lower('I', 'tr_tr') -> 'ı' (small dotless i)
+**
+** http://www.icu-project.org/userguide/posix.html#case_mappings
+*/
+static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
+ const UChar *zInput;
+ UChar *zOutput;
+ int nInput;
+ int nOutput;
+
+ UErrorCode status = U_ZERO_ERROR;
+ const char *zLocale = 0;
+
+ assert(nArg==1 || nArg==2);
+ if( nArg==2 ){
+ zLocale = (const char *)sqlite3_value_text(apArg[1]);
+ }
+
+ zInput = sqlite3_value_text16(apArg[0]);
+ if( !zInput ){
+ return;
+ }
+ nInput = sqlite3_value_bytes16(apArg[0]);
+
+ nOutput = nInput * 2 + 2;
+ zOutput = sqlite3_malloc(nOutput);
+ if( !zOutput ){
+ return;
+ }
+
+ if( sqlite3_user_data(p) ){
+ u_strToUpper(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status);
+ }else{
+ u_strToLower(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status);
+ }
+
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "u_strToLower()/u_strToUpper", status);
+ return;
+ }
+
+ sqlite3_result_text16(p, zOutput, -1, xFree);
+}
+
+/*
+** Collation sequence destructor function. The pCtx argument points to
+** a UCollator structure previously allocated using ucol_open().
+*/
+static void icuCollationDel(void *pCtx){
+ UCollator *p = (UCollator *)pCtx;
+ ucol_close(p);
+}
+
+/*
+** Collation sequence comparison function. The pCtx argument points to
+** a UCollator structure previously allocated using ucol_open().
+*/
+static int icuCollationColl(
+ void *pCtx,
+ int nLeft,
+ const void *zLeft,
+ int nRight,
+ const void *zRight
+){
+ UCollationResult res;
+ UCollator *p = (UCollator *)pCtx;
+ res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2);
+ switch( res ){
+ case UCOL_LESS: return -1;
+ case UCOL_GREATER: return +1;
+ case UCOL_EQUAL: return 0;
+ }
+ assert(!"Unexpected return value from ucol_strcoll()");
+ return 0;
+}
+
+/*
+** Implementation of the scalar function icu_load_collation().
+**
+** This scalar function is used to add ICU collation based collation
+** types to an SQLite database connection. It is intended to be called
+** as follows:
+**
+** SELECT icu_load_collation(<locale>, <collation-name>);
+**
+** Where <locale> is a string containing an ICU locale identifier (i.e.
+** "en_AU", "tr_TR" etc.) and <collation-name> is the name of the
+** collation sequence to create.
+*/
+static void icuLoadCollation(
+ sqlite3_context *p,
+ int nArg,
+ sqlite3_value **apArg
+){
+ sqlite3 *db = (sqlite3 *)sqlite3_user_data(p);
+ UErrorCode status = U_ZERO_ERROR;
+ const char *zLocale; /* Locale identifier - (eg. "jp_JP") */
+ const char *zName; /* SQL Collation sequence name (eg. "japanese") */
+ UCollator *pUCollator; /* ICU library collation object */
+ int rc; /* Return code from sqlite3_create_collation_x() */
+
+ assert(nArg==2);
+ zLocale = (const char *)sqlite3_value_text(apArg[0]);
+ zName = (const char *)sqlite3_value_text(apArg[1]);
+
+ if( !zLocale || !zName ){
+ return;
+ }
+
+ pUCollator = ucol_open(zLocale, &status);
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "ucol_open", status);
+ return;
+ }
+ assert(p);
+
+ rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
+ icuCollationColl, icuCollationDel
+ );
+ if( rc!=SQLITE_OK ){
+ ucol_close(pUCollator);
+ sqlite3_result_error(p, "Error registering collation function", -1);
+ }
+}
+
+/*
+** Register the ICU extension functions with database db.
+*/
+SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
+ struct IcuScalar {
+ const char *zName; /* Function name */
+ int nArg; /* Number of arguments */
+ int enc; /* Optimal text encoding */
+ void *pContext; /* sqlite3_user_data() context */
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+ } scalars[] = {
+ {"regexp", 2, SQLITE_ANY, 0, icuRegexpFunc},
+
+ {"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16},
+
+ {"lower", 1, SQLITE_UTF8, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF8, (void*)1, icuCaseFunc16},
+
+ {"like", 2, SQLITE_UTF8, 0, icuLikeFunc},
+ {"like", 3, SQLITE_UTF8, 0, icuLikeFunc},
+
+ {"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation},
+ };
+
+ int rc = SQLITE_OK;
+ int i;
+
+ for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
+ struct IcuScalar *p = &scalars[i];
+ rc = sqlite3_create_function(
+ db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0
+ );
+ }
+
+ return rc;
+}
+
+#if !SQLITE_CORE
+SQLITE_API int sqlite3_extension_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi)
+ return sqlite3IcuInit(db);
+}
+#endif
+
+#endif
+
+/************** End of icu.c *************************************************/
+/************** Begin file fts3_icu.c ****************************************/
+/*
+** 2007 June 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements a tokenizer for fts3 based on the ICU library.
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+#ifdef SQLITE_ENABLE_ICU
+
+/* #include <assert.h> */
+/* #include <string.h> */
+
+#include <unicode/ubrk.h>
+/* #include <unicode/ucol.h> */
+/* #include <unicode/ustring.h> */
+#include <unicode/utf16.h>
+
+typedef struct IcuTokenizer IcuTokenizer;
+typedef struct IcuCursor IcuCursor;
+
+struct IcuTokenizer {
+ sqlite3_tokenizer base;
+ char *zLocale;
+};
+
+struct IcuCursor {
+ sqlite3_tokenizer_cursor base;
+
+ UBreakIterator *pIter; /* ICU break-iterator object */
+ int nChar; /* Number of UChar elements in pInput */
+ UChar *aChar; /* Copy of input using utf-16 encoding */
+ int *aOffset; /* Offsets of each character in utf-8 input */
+
+ int nBuffer;
+ char *zBuffer;
+
+ int iToken;
+};
+
+/*
+** Create a new tokenizer instance.
+*/
+static int icuCreate(
+ int argc, /* Number of entries in argv[] */
+ const char * const *argv, /* Tokenizer creation arguments */
+ sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
+){
+ IcuTokenizer *p;
+ int n = 0;
+
+ if( argc>0 ){
+ n = strlen(argv[0])+1;
+ }
+ p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
+ if( !p ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, sizeof(IcuTokenizer));
+
+ if( n ){
+ p->zLocale = (char *)&p[1];
+ memcpy(p->zLocale, argv[0], n);
+ }
+
+ *ppTokenizer = (sqlite3_tokenizer *)p;
+
+ return SQLITE_OK;
+}
+
+/*
+** Destroy a tokenizer
+*/
+static int icuDestroy(sqlite3_tokenizer *pTokenizer){
+ IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
+ sqlite3_free(p);
+ return SQLITE_OK;
+}
+
+/*
+** Prepare to begin tokenizing a particular string. The input
+** string to be tokenized is pInput[0..nBytes-1]. A cursor
+** used to incrementally tokenize this string is returned in
+** *ppCursor.
+*/
+static int icuOpen(
+ sqlite3_tokenizer *pTokenizer, /* The tokenizer */
+ const char *zInput, /* Input string */
+ int nInput, /* Length of zInput in bytes */
+ sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
+){
+ IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
+ IcuCursor *pCsr;
+
+ const int32_t opt = U_FOLD_CASE_DEFAULT;
+ UErrorCode status = U_ZERO_ERROR;
+ int nChar;
+
+ UChar32 c;
+ int iInput = 0;
+ int iOut = 0;
+
+ *ppCursor = 0;
+
+ if( zInput==0 ){
+ nInput = 0;
+ zInput = "";
+ }else if( nInput<0 ){
+ nInput = strlen(zInput);
+ }
+ nChar = nInput+1;
+ pCsr = (IcuCursor *)sqlite3_malloc(
+ sizeof(IcuCursor) + /* IcuCursor */
+ ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
+ (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
+ );
+ if( !pCsr ){
+ return SQLITE_NOMEM;
+ }
+ memset(pCsr, 0, sizeof(IcuCursor));
+ pCsr->aChar = (UChar *)&pCsr[1];
+ pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
+
+ pCsr->aOffset[iOut] = iInput;
+ U8_NEXT(zInput, iInput, nInput, c);
+ while( c>0 ){
+ int isError = 0;
+ c = u_foldCase(c, opt);
+ U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
+ if( isError ){
+ sqlite3_free(pCsr);
+ return SQLITE_ERROR;
+ }
+ pCsr->aOffset[iOut] = iInput;
+
+ if( iInput<nInput ){
+ U8_NEXT(zInput, iInput, nInput, c);
+ }else{
+ c = 0;
+ }
+ }
+
+ pCsr->pIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status);
+ if( !U_SUCCESS(status) ){
+ sqlite3_free(pCsr);
+ return SQLITE_ERROR;
+ }
+ pCsr->nChar = iOut;
+
+ ubrk_first(pCsr->pIter);
+ *ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
+ return SQLITE_OK;
+}
+
+/*
+** Close a tokenization cursor previously opened by a call to icuOpen().
+*/
+static int icuClose(sqlite3_tokenizer_cursor *pCursor){
+ IcuCursor *pCsr = (IcuCursor *)pCursor;
+ ubrk_close(pCsr->pIter);
+ sqlite3_free(pCsr->zBuffer);
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+/*
+** Extract the next token from a tokenization cursor.
+*/
+static int icuNext(
+ sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
+ const char **ppToken, /* OUT: *ppToken is the token text */
+ int *pnBytes, /* OUT: Number of bytes in token */
+ int *piStartOffset, /* OUT: Starting offset of token */
+ int *piEndOffset, /* OUT: Ending offset of token */
+ int *piPosition /* OUT: Position integer of token */
+){
+ IcuCursor *pCsr = (IcuCursor *)pCursor;
+
+ int iStart = 0;
+ int iEnd = 0;
+ int nByte = 0;
+
+ while( iStart==iEnd ){
+ UChar32 c;
+
+ iStart = ubrk_current(pCsr->pIter);
+ iEnd = ubrk_next(pCsr->pIter);
+ if( iEnd==UBRK_DONE ){
+ return SQLITE_DONE;
+ }
+
+ while( iStart<iEnd ){
+ int iWhite = iStart;
+ U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
+ if( u_isspace(c) ){
+ iStart = iWhite;
+ }else{
+ break;
+ }
+ }
+ assert(iStart<=iEnd);
+ }
+
+ do {
+ UErrorCode status = U_ZERO_ERROR;
+ if( nByte ){
+ char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte);
+ if( !zNew ){
+ return SQLITE_NOMEM;
+ }
+ pCsr->zBuffer = zNew;
+ pCsr->nBuffer = nByte;
+ }
+
+ u_strToUTF8(
+ pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */
+ &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */
+ &status /* Output success/failure */
+ );
+ } while( nByte>pCsr->nBuffer );
+
+ *ppToken = pCsr->zBuffer;
+ *pnBytes = nByte;
+ *piStartOffset = pCsr->aOffset[iStart];
+ *piEndOffset = pCsr->aOffset[iEnd];
+ *piPosition = pCsr->iToken++;
+
+ return SQLITE_OK;
+}
+
+/*
+** The set of routines that implement the simple tokenizer
+*/
+static const sqlite3_tokenizer_module icuTokenizerModule = {
+ 0, /* iVersion */
+ icuCreate, /* xCreate */
+ icuDestroy, /* xCreate */
+ icuOpen, /* xOpen */
+ icuClose, /* xClose */
+ icuNext, /* xNext */
+};
+
+/*
+** Set *ppModule to point at the implementation of the ICU tokenizer.
+*/
+SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(
+ sqlite3_tokenizer_module const**ppModule
+){
+ *ppModule = &icuTokenizerModule;
+}
+
+#endif /* defined(SQLITE_ENABLE_ICU) */
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_icu.c ********************************************/
diff --git a/lib/sqlite/sqlite3.h b/lib/sqlite/sqlite3.h
new file mode 100644
index 000000000..1332eb162
--- /dev/null
+++ b/lib/sqlite/sqlite3.h
@@ -0,0 +1,7174 @@
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the SQLite library
+** presents to client programs. If a C-function, structure, datatype,
+** or constant definition does not appear in this file, then it is
+** not a published API of SQLite, is subject to change without
+** notice, and should not be referenced by programs that use SQLite.
+**
+** Some of the definitions that are in this file are marked as
+** "experimental". Experimental interfaces are normally new
+** features recently added to SQLite. We do not anticipate changes
+** to experimental interfaces but reserve the right to make minor changes
+** if experience from use "in the wild" suggest such changes are prudent.
+**
+** The official C-language API documentation for SQLite is derived
+** from comments in this file. This file is the authoritative source
+** on how SQLite interfaces are suppose to operate.
+**
+** The name of this file under configuration management is "sqlite.h.in".
+** The makefile makes some minor changes to this file (such as inserting
+** the version number) and changes its name to "sqlite3.h" as
+** part of the build process.
+*/
+#ifndef _SQLITE3_H_
+#define _SQLITE3_H_
+#include <stdarg.h> /* Needed for the definition of va_list */
+
+/*
+** Make sure we can call this stuff from C++.
+*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+** Add the ability to override 'extern'
+*/
+#ifndef SQLITE_EXTERN
+# define SQLITE_EXTERN extern
+#endif
+
+#ifndef SQLITE_API
+# define SQLITE_API
+#endif
+
+
+/*
+** These no-op macros are used in front of interfaces to mark those
+** interfaces as either deprecated or experimental. New applications
+** should not use deprecated interfaces - they are support for backwards
+** compatibility only. Application writers should be aware that
+** experimental interfaces are subject to change in point releases.
+**
+** These macros used to resolve to various kinds of compiler magic that
+** would generate warning messages when they were used. But that
+** compiler magic ended up generating such a flurry of bug reports
+** that we have taken it all out and gone back to using simple
+** noop macros.
+*/
+#define SQLITE_DEPRECATED
+#define SQLITE_EXPERIMENTAL
+
+/*
+** Ensure these symbols were not defined by some previous header file.
+*/
+#ifdef SQLITE_VERSION
+# undef SQLITE_VERSION
+#endif
+#ifdef SQLITE_VERSION_NUMBER
+# undef SQLITE_VERSION_NUMBER
+#endif
+
+/*
+** CAPI3REF: Compile-Time Library Version Numbers
+**
+** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header
+** evaluates to a string literal that is the SQLite version in the
+** format "X.Y.Z" where X is the major version number (always 3 for
+** SQLite3) and Y is the minor version number and Z is the release number.)^
+** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer
+** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
+** numbers used in [SQLITE_VERSION].)^
+** The SQLITE_VERSION_NUMBER for any given release of SQLite will also
+** be larger than the release from which it is derived. Either Y will
+** be held constant and Z will be incremented or else Y will be incremented
+** and Z will be reset to zero.
+**
+** Since version 3.6.18, SQLite source code has been stored in the
+** <a href="http://www.fossil-scm.org/">Fossil configuration management
+** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
+** a string which identifies a particular check-in of SQLite
+** within its configuration management system. ^The SQLITE_SOURCE_ID
+** string contains the date and time of the check-in (UTC) and an SHA1
+** hash of the entire source tree.
+**
+** See also: [sqlite3_libversion()],
+** [sqlite3_libversion_number()], [sqlite3_sourceid()],
+** [sqlite_version()] and [sqlite_source_id()].
+*/
+#define SQLITE_VERSION "3.7.16.1"
+#define SQLITE_VERSION_NUMBER 3007016
+#define SQLITE_SOURCE_ID "2013-03-29 13:44:34 527231bc67285f01fb18d4451b28f61da3c4e39d"
+
+/*
+** CAPI3REF: Run-Time Library Version Numbers
+** KEYWORDS: sqlite3_version, sqlite3_sourceid
+**
+** These interfaces provide the same information as the [SQLITE_VERSION],
+** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
+** but are associated with the library instead of the header file. ^(Cautious
+** programmers might include assert() statements in their application to
+** verify that values returned by these interfaces match the macros in
+** the header, and thus insure that the application is
+** compiled with matching library and header files.
+**
+** <blockquote><pre>
+** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
+** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
+** </pre></blockquote>)^
+**
+** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
+** macro. ^The sqlite3_libversion() function returns a pointer to the
+** to the sqlite3_version[] string constant. The sqlite3_libversion()
+** function is provided for use in DLLs since DLL users usually do not have
+** direct access to string constants within the DLL. ^The
+** sqlite3_libversion_number() function returns an integer equal to
+** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
+** a pointer to a string constant whose value is the same as the
+** [SQLITE_SOURCE_ID] C preprocessor macro.
+**
+** See also: [sqlite_version()] and [sqlite_source_id()].
+*/
+SQLITE_API SQLITE_EXTERN const char sqlite3_version[];
+SQLITE_API const char *sqlite3_libversion(void);
+SQLITE_API const char *sqlite3_sourceid(void);
+SQLITE_API int sqlite3_libversion_number(void);
+
+/*
+** CAPI3REF: Run-Time Library Compilation Options Diagnostics
+**
+** ^The sqlite3_compileoption_used() function returns 0 or 1
+** indicating whether the specified option was defined at
+** compile time. ^The SQLITE_ prefix may be omitted from the
+** option name passed to sqlite3_compileoption_used().
+**
+** ^The sqlite3_compileoption_get() function allows iterating
+** over the list of options that were defined at compile time by
+** returning the N-th compile time option string. ^If N is out of range,
+** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
+** prefix is omitted from any strings returned by
+** sqlite3_compileoption_get().
+**
+** ^Support for the diagnostic functions sqlite3_compileoption_used()
+** and sqlite3_compileoption_get() may be omitted by specifying the
+** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
+**
+** See also: SQL functions [sqlite_compileoption_used()] and
+** [sqlite_compileoption_get()] and the [compile_options pragma].
+*/
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
+SQLITE_API const char *sqlite3_compileoption_get(int N);
+#endif
+
+/*
+** CAPI3REF: Test To See If The Library Is Threadsafe
+**
+** ^The sqlite3_threadsafe() function returns zero if and only if
+** SQLite was compiled with mutexing code omitted due to the
+** [SQLITE_THREADSAFE] compile-time option being set to 0.
+**
+** SQLite can be compiled with or without mutexes. When
+** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
+** are enabled and SQLite is threadsafe. When the
+** [SQLITE_THREADSAFE] macro is 0,
+** the mutexes are omitted. Without the mutexes, it is not safe
+** to use SQLite concurrently from more than one thread.
+**
+** Enabling mutexes incurs a measurable performance penalty.
+** So if speed is of utmost importance, it makes sense to disable
+** the mutexes. But for maximum safety, mutexes should be enabled.
+** ^The default behavior is for mutexes to be enabled.
+**
+** This interface can be used by an application to make sure that the
+** version of SQLite that it is linking against was compiled with
+** the desired setting of the [SQLITE_THREADSAFE] macro.
+**
+** This interface only reports on the compile-time mutex setting
+** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
+** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
+** can be fully or partially disabled using a call to [sqlite3_config()]
+** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
+** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the
+** sqlite3_threadsafe() function shows only the compile-time setting of
+** thread safety, not any run-time changes to that setting made by
+** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
+** is unchanged by calls to sqlite3_config().)^
+**
+** See the [threading mode] documentation for additional information.
+*/
+SQLITE_API int sqlite3_threadsafe(void);
+
+/*
+** CAPI3REF: Database Connection Handle
+** KEYWORDS: {database connection} {database connections}
+**
+** Each open SQLite database is represented by a pointer to an instance of
+** the opaque structure named "sqlite3". It is useful to think of an sqlite3
+** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and
+** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
+** and [sqlite3_close_v2()] are its destructors. There are many other
+** interfaces (such as
+** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
+** [sqlite3_busy_timeout()] to name but three) that are methods on an
+** sqlite3 object.
+*/
+typedef struct sqlite3 sqlite3;
+
+/*
+** CAPI3REF: 64-Bit Integer Types
+** KEYWORDS: sqlite_int64 sqlite_uint64
+**
+** Because there is no cross-platform way to specify 64-bit integer types
+** SQLite includes typedefs for 64-bit signed and unsigned integers.
+**
+** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions.
+** The sqlite_int64 and sqlite_uint64 types are supported for backwards
+** compatibility only.
+**
+** ^The sqlite3_int64 and sqlite_int64 types can store integer values
+** between -9223372036854775808 and +9223372036854775807 inclusive. ^The
+** sqlite3_uint64 and sqlite_uint64 types can store integer values
+** between 0 and +18446744073709551615 inclusive.
+*/
+#ifdef SQLITE_INT64_TYPE
+ typedef SQLITE_INT64_TYPE sqlite_int64;
+ typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef __int64 sqlite_int64;
+ typedef unsigned __int64 sqlite_uint64;
+#else
+ typedef long long int sqlite_int64;
+ typedef unsigned long long int sqlite_uint64;
+#endif
+typedef sqlite_int64 sqlite3_int64;
+typedef sqlite_uint64 sqlite3_uint64;
+
+/*
+** If compiling for a processor that lacks floating point support,
+** substitute integer for floating-point.
+*/
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# define double sqlite3_int64
+#endif
+
+/*
+** CAPI3REF: Closing A Database Connection
+**
+** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
+** for the [sqlite3] object.
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
+** the [sqlite3] object is successfully destroyed and all associated
+** resources are deallocated.
+**
+** ^If the database connection is associated with unfinalized prepared
+** statements or unfinished sqlite3_backup objects then sqlite3_close()
+** will leave the database connection open and return [SQLITE_BUSY].
+** ^If sqlite3_close_v2() is called with unfinalized prepared statements
+** and unfinished sqlite3_backups, then the database connection becomes
+** an unusable "zombie" which will automatically be deallocated when the
+** last prepared statement is finalized or the last sqlite3_backup is
+** finished. The sqlite3_close_v2() interface is intended for use with
+** host languages that are garbage collected, and where the order in which
+** destructors are called is arbitrary.
+**
+** Applications should [sqlite3_finalize | finalize] all [prepared statements],
+** [sqlite3_blob_close | close] all [BLOB handles], and
+** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
+** with the [sqlite3] object prior to attempting to close the object. ^If
+** sqlite3_close_v2() is called on a [database connection] that still has
+** outstanding [prepared statements], [BLOB handles], and/or
+** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
+** of resources is deferred until all [prepared statements], [BLOB handles],
+** and [sqlite3_backup] objects are also destroyed.
+**
+** ^If an [sqlite3] object is destroyed while a transaction is open,
+** the transaction is automatically rolled back.
+**
+** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
+** must be either a NULL
+** pointer or an [sqlite3] object pointer obtained
+** from [sqlite3_open()], [sqlite3_open16()], or
+** [sqlite3_open_v2()], and not previously closed.
+** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
+** argument is a harmless no-op.
+*/
+SQLITE_API int sqlite3_close(sqlite3*);
+SQLITE_API int sqlite3_close_v2(sqlite3*);
+
+/*
+** The type for a callback function.
+** This is legacy and deprecated. It is included for historical
+** compatibility and is not documented.
+*/
+typedef int (*sqlite3_callback)(void*,int,char**, char**);
+
+/*
+** CAPI3REF: One-Step Query Execution Interface
+**
+** The sqlite3_exec() interface is a convenience wrapper around
+** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
+** that allows an application to run multiple statements of SQL
+** without having to use a lot of C code.
+**
+** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
+** semicolon-separate SQL statements passed into its 2nd argument,
+** in the context of the [database connection] passed in as its 1st
+** argument. ^If the callback function of the 3rd argument to
+** sqlite3_exec() is not NULL, then it is invoked for each result row
+** coming out of the evaluated SQL statements. ^The 4th argument to
+** sqlite3_exec() is relayed through to the 1st argument of each
+** callback invocation. ^If the callback pointer to sqlite3_exec()
+** is NULL, then no callback is ever invoked and result rows are
+** ignored.
+**
+** ^If an error occurs while evaluating the SQL statements passed into
+** sqlite3_exec(), then execution of the current statement stops and
+** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec()
+** is not NULL then any error message is written into memory obtained
+** from [sqlite3_malloc()] and passed back through the 5th parameter.
+** To avoid memory leaks, the application should invoke [sqlite3_free()]
+** on error message strings returned through the 5th parameter of
+** of sqlite3_exec() after the error message string is no longer needed.
+** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors
+** occur, then sqlite3_exec() sets the pointer in its 5th parameter to
+** NULL before returning.
+**
+** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec()
+** routine returns SQLITE_ABORT without invoking the callback again and
+** without running any subsequent SQL statements.
+**
+** ^The 2nd argument to the sqlite3_exec() callback function is the
+** number of columns in the result. ^The 3rd argument to the sqlite3_exec()
+** callback is an array of pointers to strings obtained as if from
+** [sqlite3_column_text()], one for each column. ^If an element of a
+** result row is NULL then the corresponding string pointer for the
+** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the
+** sqlite3_exec() callback is an array of pointers to strings where each
+** entry represents the name of corresponding result column as obtained
+** from [sqlite3_column_name()].
+**
+** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
+** to an empty string, or a pointer that contains only whitespace and/or
+** SQL comments, then no SQL statements are evaluated and the database
+** is not changed.
+**
+** Restrictions:
+**
+** <ul>
+** <li> The application must insure that the 1st parameter to sqlite3_exec()
+** is a valid and open [database connection].
+** <li> The application must not close [database connection] specified by
+** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
+** <li> The application must not modify the SQL statement text passed into
+** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+** </ul>
+*/
+SQLITE_API int sqlite3_exec(
+ sqlite3*, /* An open database */
+ const char *sql, /* SQL to be evaluated */
+ int (*callback)(void*,int,char**,char**), /* Callback function */
+ void *, /* 1st argument to callback */
+ char **errmsg /* Error msg written here */
+);
+
+/*
+** CAPI3REF: Result Codes
+** KEYWORDS: SQLITE_OK {error code} {error codes}
+** KEYWORDS: {result code} {result codes}
+**
+** Many SQLite functions return an integer result code from the set shown
+** here in order to indicate success or failure.
+**
+** New error codes may be added in future versions of SQLite.
+**
+** See also: [SQLITE_IOERR_READ | extended result codes],
+** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
+*/
+#define SQLITE_OK 0 /* Successful result */
+/* beginning-of-error-codes */
+#define SQLITE_ERROR 1 /* SQL error or missing database */
+#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
+#define SQLITE_PERM 3 /* Access permission denied */
+#define SQLITE_ABORT 4 /* Callback routine requested an abort */
+#define SQLITE_BUSY 5 /* The database file is locked */
+#define SQLITE_LOCKED 6 /* A table in the database is locked */
+#define SQLITE_NOMEM 7 /* A malloc() failed */
+#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
+#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
+#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
+#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
+#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */
+#define SQLITE_FULL 13 /* Insertion failed because database is full */
+#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
+#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
+#define SQLITE_EMPTY 16 /* Database is empty */
+#define SQLITE_SCHEMA 17 /* The database schema changed */
+#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
+#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
+#define SQLITE_MISMATCH 20 /* Data type mismatch */
+#define SQLITE_MISUSE 21 /* Library used incorrectly */
+#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
+#define SQLITE_AUTH 23 /* Authorization denied */
+#define SQLITE_FORMAT 24 /* Auxiliary database format error */
+#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
+#define SQLITE_NOTADB 26 /* File opened that is not a database file */
+#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
+#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
+/* end-of-error-codes */
+
+/*
+** CAPI3REF: Extended Result Codes
+** KEYWORDS: {extended error code} {extended error codes}
+** KEYWORDS: {extended result code} {extended result codes}
+**
+** In its default configuration, SQLite API routines return one of 26 integer
+** [SQLITE_OK | result codes]. However, experience has shown that many of
+** these result codes are too coarse-grained. They do not provide as
+** much information about problems as programmers might like. In an effort to
+** address this, newer versions of SQLite (version 3.3.8 and later) include
+** support for additional result codes that provide more detailed information
+** about errors. The extended result codes are enabled or disabled
+** on a per database connection basis using the
+** [sqlite3_extended_result_codes()] API.
+**
+** Some of the available extended result codes are listed here.
+** One may expect the number of extended result codes will be expand
+** over time. Software that uses extended result codes should expect
+** to see new result codes in future releases of SQLite.
+**
+** The SQLITE_OK result code will never be extended. It will always
+** be exactly zero.
+*/
+#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
+#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
+#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
+#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
+#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8))
+#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8))
+#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8))
+#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8))
+#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8))
+#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8))
+#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8))
+#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
+#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
+#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
+#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
+#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
+#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
+#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
+#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
+#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
+#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
+#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
+#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
+#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
+#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
+#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
+#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
+#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
+#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
+#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
+
+/*
+** CAPI3REF: Flags For File Open Operations
+**
+** These bit values are intended for use in the
+** 3rd parameter to the [sqlite3_open_v2()] interface and
+** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
+*/
+#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
+#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
+#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
+#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
+#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
+#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
+#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
+#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
+#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */
+#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
+#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
+
+/* Reserved: 0x00F00000 */
+
+/*
+** CAPI3REF: Device Characteristics
+**
+** The xDeviceCharacteristics method of the [sqlite3_io_methods]
+** object returns an integer which is a vector of these
+** bit values expressing I/O characteristics of the mass storage
+** device that holds the file that the [sqlite3_io_methods]
+** refers to.
+**
+** The SQLITE_IOCAP_ATOMIC property means that all writes of
+** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
+** mean that writes of blocks that are nnn bytes in size and
+** are aligned to an address which is an integer multiple of
+** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
+** that when data is appended to a file, the data is appended
+** first then the size of the file is extended, never the other
+** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
+** information is written to disk in the same order as calls
+** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that
+** after reboot following a crash or power loss, the only bytes in a
+** file that were written at the application level might have changed
+** and that adjacent bytes, even bytes within the same sector are
+** guaranteed to be unchanged.
+*/
+#define SQLITE_IOCAP_ATOMIC 0x00000001
+#define SQLITE_IOCAP_ATOMIC512 0x00000002
+#define SQLITE_IOCAP_ATOMIC1K 0x00000004
+#define SQLITE_IOCAP_ATOMIC2K 0x00000008
+#define SQLITE_IOCAP_ATOMIC4K 0x00000010
+#define SQLITE_IOCAP_ATOMIC8K 0x00000020
+#define SQLITE_IOCAP_ATOMIC16K 0x00000040
+#define SQLITE_IOCAP_ATOMIC32K 0x00000080
+#define SQLITE_IOCAP_ATOMIC64K 0x00000100
+#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
+#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
+#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
+#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
+
+/*
+** CAPI3REF: File Locking Levels
+**
+** SQLite uses one of these integer values as the second
+** argument to calls it makes to the xLock() and xUnlock() methods
+** of an [sqlite3_io_methods] object.
+*/
+#define SQLITE_LOCK_NONE 0
+#define SQLITE_LOCK_SHARED 1
+#define SQLITE_LOCK_RESERVED 2
+#define SQLITE_LOCK_PENDING 3
+#define SQLITE_LOCK_EXCLUSIVE 4
+
+/*
+** CAPI3REF: Synchronization Type Flags
+**
+** When SQLite invokes the xSync() method of an
+** [sqlite3_io_methods] object it uses a combination of
+** these integer values as the second argument.
+**
+** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
+** sync operation only needs to flush data to mass storage. Inode
+** information need not be flushed. If the lower four bits of the flag
+** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics.
+** If the lower four bits equal SQLITE_SYNC_FULL, that means
+** to use Mac OS X style fullsync instead of fsync().
+**
+** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags
+** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL
+** settings. The [synchronous pragma] determines when calls to the
+** xSync VFS method occur and applies uniformly across all platforms.
+** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how
+** energetic or rigorous or forceful the sync operations are and
+** only make a difference on Mac OSX for the default SQLite code.
+** (Third-party VFS implementations might also make the distinction
+** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the
+** operating systems natively supported by SQLite, only Mac OSX
+** cares about the difference.)
+*/
+#define SQLITE_SYNC_NORMAL 0x00002
+#define SQLITE_SYNC_FULL 0x00003
+#define SQLITE_SYNC_DATAONLY 0x00010
+
+/*
+** CAPI3REF: OS Interface Open File Handle
+**
+** An [sqlite3_file] object represents an open file in the
+** [sqlite3_vfs | OS interface layer]. Individual OS interface
+** implementations will
+** want to subclass this object by appending additional fields
+** for their own use. The pMethods entry is a pointer to an
+** [sqlite3_io_methods] object that defines methods for performing
+** I/O operations on the open file.
+*/
+typedef struct sqlite3_file sqlite3_file;
+struct sqlite3_file {
+ const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
+};
+
+/*
+** CAPI3REF: OS Interface File Virtual Methods Object
+**
+** Every file opened by the [sqlite3_vfs.xOpen] method populates an
+** [sqlite3_file] object (or, more commonly, a subclass of the
+** [sqlite3_file] object) with a pointer to an instance of this object.
+** This object defines the methods used to perform various operations
+** against the open file represented by the [sqlite3_file] object.
+**
+** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
+** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
+** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
+** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
+** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
+** to NULL.
+**
+** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
+** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
+** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
+** flag may be ORed in to indicate that only the data of the file
+** and not its inode needs to be synced.
+**
+** The integer values to xLock() and xUnlock() are one of
+** <ul>
+** <li> [SQLITE_LOCK_NONE],
+** <li> [SQLITE_LOCK_SHARED],
+** <li> [SQLITE_LOCK_RESERVED],
+** <li> [SQLITE_LOCK_PENDING], or
+** <li> [SQLITE_LOCK_EXCLUSIVE].
+** </ul>
+** xLock() increases the lock. xUnlock() decreases the lock.
+** The xCheckReservedLock() method checks whether any database connection,
+** either in this process or in some other process, is holding a RESERVED,
+** PENDING, or EXCLUSIVE lock on the file. It returns true
+** if such a lock exists and false otherwise.
+**
+** The xFileControl() method is a generic interface that allows custom
+** VFS implementations to directly control an open file using the
+** [sqlite3_file_control()] interface. The second "op" argument is an
+** integer opcode. The third argument is a generic pointer intended to
+** point to a structure that may contain arguments or space in which to
+** write return values. Potential uses for xFileControl() might be
+** functions to enable blocking locks with timeouts, to change the
+** locking strategy (for example to use dot-file locks), to inquire
+** about the status of a lock, or to break stale locks. The SQLite
+** core reserves all opcodes less than 100 for its own use.
+** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
+** Applications that define a custom xFileControl method should use opcodes
+** greater than 100 to avoid conflicts. VFS implementations should
+** return [SQLITE_NOTFOUND] for file control opcodes that they do not
+** recognize.
+**
+** The xSectorSize() method returns the sector size of the
+** device that underlies the file. The sector size is the
+** minimum write that can be performed without disturbing
+** other bytes in the file. The xDeviceCharacteristics()
+** method returns a bit vector describing behaviors of the
+** underlying device:
+**
+** <ul>
+** <li> [SQLITE_IOCAP_ATOMIC]
+** <li> [SQLITE_IOCAP_ATOMIC512]
+** <li> [SQLITE_IOCAP_ATOMIC1K]
+** <li> [SQLITE_IOCAP_ATOMIC2K]
+** <li> [SQLITE_IOCAP_ATOMIC4K]
+** <li> [SQLITE_IOCAP_ATOMIC8K]
+** <li> [SQLITE_IOCAP_ATOMIC16K]
+** <li> [SQLITE_IOCAP_ATOMIC32K]
+** <li> [SQLITE_IOCAP_ATOMIC64K]
+** <li> [SQLITE_IOCAP_SAFE_APPEND]
+** <li> [SQLITE_IOCAP_SEQUENTIAL]
+** </ul>
+**
+** The SQLITE_IOCAP_ATOMIC property means that all writes of
+** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
+** mean that writes of blocks that are nnn bytes in size and
+** are aligned to an address which is an integer multiple of
+** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
+** that when data is appended to a file, the data is appended
+** first then the size of the file is extended, never the other
+** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
+** information is written to disk in the same order as calls
+** to xWrite().
+**
+** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill
+** in the unread portions of the buffer with zeros. A VFS that
+** fails to zero-fill short reads might seem to work. However,
+** failure to zero-fill short reads will eventually lead to
+** database corruption.
+*/
+typedef struct sqlite3_io_methods sqlite3_io_methods;
+struct sqlite3_io_methods {
+ int iVersion;
+ int (*xClose)(sqlite3_file*);
+ int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+ int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
+ int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
+ int (*xSync)(sqlite3_file*, int flags);
+ int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
+ int (*xLock)(sqlite3_file*, int);
+ int (*xUnlock)(sqlite3_file*, int);
+ int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
+ int (*xFileControl)(sqlite3_file*, int op, void *pArg);
+ int (*xSectorSize)(sqlite3_file*);
+ int (*xDeviceCharacteristics)(sqlite3_file*);
+ /* Methods above are valid for version 1 */
+ int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
+ int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
+ void (*xShmBarrier)(sqlite3_file*);
+ int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
+ /* Methods above are valid for version 2 */
+ /* Additional methods may be added in future releases */
+};
+
+/*
+** CAPI3REF: Standard File Control Opcodes
+**
+** These integer constants are opcodes for the xFileControl method
+** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
+** interface.
+**
+** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
+** opcode causes the xFileControl method to write the current state of
+** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
+** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
+** into an integer that the pArg argument points to. This capability
+** is used during testing and only needs to be supported when SQLITE_TEST
+** is defined.
+** <ul>
+** <li>[[SQLITE_FCNTL_SIZE_HINT]]
+** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
+** layer a hint of how large the database file will grow to be during the
+** current transaction. This hint is not guaranteed to be accurate but it
+** is often close. The underlying VFS might choose to preallocate database
+** file space based on this hint in order to help writes to the database
+** file run faster.
+**
+** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
+** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
+** extends and truncates the database file in chunks of a size specified
+** by the user. The fourth argument to [sqlite3_file_control()] should
+** point to an integer (type int) containing the new chunk-size to use
+** for the nominated database. Allocating database file space in large
+** chunks (say 1MB at a time), may reduce file-system fragmentation and
+** improve performance on some systems.
+**
+** <li>[[SQLITE_FCNTL_FILE_POINTER]]
+** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
+** to the [sqlite3_file] object associated with a particular database
+** connection. See the [sqlite3_file_control()] documentation for
+** additional information.
+**
+** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
+** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
+** SQLite and sent to all VFSes in place of a call to the xSync method
+** when the database connection has [PRAGMA synchronous] set to OFF.)^
+** Some specialized VFSes need this signal in order to operate correctly
+** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
+** VFSes do not need this signal and should silently ignore this opcode.
+** Applications should not call [sqlite3_file_control()] with this
+** opcode as doing so may disrupt the operation of the specialized VFSes
+** that do require it.
+**
+** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
+** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
+** retry counts and intervals for certain disk I/O operations for the
+** windows [VFS] in order to provide robustness in the presence of
+** anti-virus programs. By default, the windows VFS will retry file read,
+** file write, and file delete operations up to 10 times, with a delay
+** of 25 milliseconds before the first retry and with the delay increasing
+** by an additional 25 milliseconds with each subsequent retry. This
+** opcode allows these two values (10 retries and 25 milliseconds of delay)
+** to be adjusted. The values are changed for all database connections
+** within the same process. The argument is a pointer to an array of two
+** integers where the first integer i the new retry count and the second
+** integer is the delay. If either integer is negative, then the setting
+** is not changed but instead the prior value of that setting is written
+** into the array entry, allowing the current retry settings to be
+** interrogated. The zDbName parameter is ignored.
+**
+** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
+** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
+** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
+** write ahead log and shared memory files used for transaction control
+** are automatically deleted when the latest connection to the database
+** closes. Setting persistent WAL mode causes those files to persist after
+** close. Persisting the files is useful when other processes that do not
+** have write permission on the directory containing the database file want
+** to read the database file, as the WAL and shared memory files must exist
+** in order for the database to be readable. The fourth parameter to
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
+** WAL mode. If the integer is -1, then it is overwritten with the current
+** WAL persistence setting.
+**
+** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
+** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
+** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
+** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
+** xDeviceCharacteristics methods. The fourth parameter to
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
+** mode. If the integer is -1, then it is overwritten with the current
+** zero-damage mode setting.
+**
+** <li>[[SQLITE_FCNTL_OVERWRITE]]
+** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
+** a write transaction to indicate that, unless it is rolled back for some
+** reason, the entire database file will be overwritten by the current
+** transaction. This is used by VACUUM operations.
+**
+** <li>[[SQLITE_FCNTL_VFSNAME]]
+** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
+** all [VFSes] in the VFS stack. The names are of all VFS shims and the
+** final bottom-level VFS are written into memory obtained from
+** [sqlite3_malloc()] and the result is stored in the char* variable
+** that the fourth parameter of [sqlite3_file_control()] points to.
+** The caller is responsible for freeing the memory when done. As with
+** all file-control actions, there is no guarantee that this will actually
+** do anything. Callers should initialize the char* variable to a NULL
+** pointer in case this file-control is not implemented. This file-control
+** is intended for diagnostic use only.
+**
+** <li>[[SQLITE_FCNTL_PRAGMA]]
+** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
+** file control is sent to the open [sqlite3_file] object corresponding
+** to the database file to which the pragma statement refers. ^The argument
+** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
+** pointers to strings (char**) in which the second element of the array
+** is the name of the pragma and the third element is the argument to the
+** pragma or NULL if the pragma has no argument. ^The handler for an
+** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
+** of the char** argument point to a string obtained from [sqlite3_mprintf()]
+** or the equivalent and that string will become the result of the pragma or
+** the error message if the pragma fails. ^If the
+** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
+** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
+** file control returns [SQLITE_OK], then the parser assumes that the
+** VFS has handled the PRAGMA itself and the parser generates a no-op
+** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
+** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
+** that the VFS encountered an error while handling the [PRAGMA] and the
+** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
+** file control occurs at the beginning of pragma statement analysis and so
+** it is able to override built-in [PRAGMA] statements.
+**
+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
+** ^This file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke this file-control to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses. The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()]. The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
+** </ul>
+*/
+#define SQLITE_FCNTL_LOCKSTATE 1
+#define SQLITE_GET_LOCKPROXYFILE 2
+#define SQLITE_SET_LOCKPROXYFILE 3
+#define SQLITE_LAST_ERRNO 4
+#define SQLITE_FCNTL_SIZE_HINT 5
+#define SQLITE_FCNTL_CHUNK_SIZE 6
+#define SQLITE_FCNTL_FILE_POINTER 7
+#define SQLITE_FCNTL_SYNC_OMITTED 8
+#define SQLITE_FCNTL_WIN32_AV_RETRY 9
+#define SQLITE_FCNTL_PERSIST_WAL 10
+#define SQLITE_FCNTL_OVERWRITE 11
+#define SQLITE_FCNTL_VFSNAME 12
+#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
+#define SQLITE_FCNTL_PRAGMA 14
+#define SQLITE_FCNTL_BUSYHANDLER 15
+#define SQLITE_FCNTL_TEMPFILENAME 16
+
+/*
+** CAPI3REF: Mutex Handle
+**
+** The mutex module within SQLite defines [sqlite3_mutex] to be an
+** abstract type for a mutex object. The SQLite core never looks
+** at the internal representation of an [sqlite3_mutex]. It only
+** deals with pointers to the [sqlite3_mutex] object.
+**
+** Mutexes are created using [sqlite3_mutex_alloc()].
+*/
+typedef struct sqlite3_mutex sqlite3_mutex;
+
+/*
+** CAPI3REF: OS Interface Object
+**
+** An instance of the sqlite3_vfs object defines the interface between
+** the SQLite core and the underlying operating system. The "vfs"
+** in the name of the object stands for "virtual file system". See
+** the [VFS | VFS documentation] for further information.
+**
+** The value of the iVersion field is initially 1 but may be larger in
+** future versions of SQLite. Additional fields may be appended to this
+** object when the iVersion value is increased. Note that the structure
+** of the sqlite3_vfs object changes in the transaction between
+** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not
+** modified.
+**
+** The szOsFile field is the size of the subclassed [sqlite3_file]
+** structure used by this VFS. mxPathname is the maximum length of
+** a pathname in this VFS.
+**
+** Registered sqlite3_vfs objects are kept on a linked list formed by
+** the pNext pointer. The [sqlite3_vfs_register()]
+** and [sqlite3_vfs_unregister()] interfaces manage this list
+** in a thread-safe way. The [sqlite3_vfs_find()] interface
+** searches the list. Neither the application code nor the VFS
+** implementation should use the pNext pointer.
+**
+** The pNext field is the only field in the sqlite3_vfs
+** structure that SQLite will ever modify. SQLite will only access
+** or modify this field while holding a particular static mutex.
+** The application should never modify anything within the sqlite3_vfs
+** object once the object has been registered.
+**
+** The zName field holds the name of the VFS module. The name must
+** be unique across all VFS modules.
+**
+** [[sqlite3_vfs.xOpen]]
+** ^SQLite guarantees that the zFilename parameter to xOpen
+** is either a NULL pointer or string obtained
+** from xFullPathname() with an optional suffix added.
+** ^If a suffix is added to the zFilename parameter, it will
+** consist of a single "-" character followed by no more than
+** 11 alphanumeric and/or "-" characters.
+** ^SQLite further guarantees that
+** the string will be valid and unchanged until xClose() is
+** called. Because of the previous sentence,
+** the [sqlite3_file] can safely store a pointer to the
+** filename if it needs to remember the filename for some reason.
+** If the zFilename parameter to xOpen is a NULL pointer then xOpen
+** must invent its own temporary name for the file. ^Whenever the
+** xFilename parameter is NULL it will also be the case that the
+** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
+**
+** The flags argument to xOpen() includes all bits set in
+** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
+** or [sqlite3_open16()] is used, then flags includes at least
+** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
+** If xOpen() opens a file read-only then it sets *pOutFlags to
+** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
+**
+** ^(SQLite will also add one of the following flags to the xOpen()
+** call, depending on the object being opened:
+**
+** <ul>
+** <li> [SQLITE_OPEN_MAIN_DB]
+** <li> [SQLITE_OPEN_MAIN_JOURNAL]
+** <li> [SQLITE_OPEN_TEMP_DB]
+** <li> [SQLITE_OPEN_TEMP_JOURNAL]
+** <li> [SQLITE_OPEN_TRANSIENT_DB]
+** <li> [SQLITE_OPEN_SUBJOURNAL]
+** <li> [SQLITE_OPEN_MASTER_JOURNAL]
+** <li> [SQLITE_OPEN_WAL]
+** </ul>)^
+**
+** The file I/O implementation can use the object type flags to
+** change the way it deals with files. For example, an application
+** that does not care about crash recovery or rollback might make
+** the open of a journal file a no-op. Writes to this journal would
+** also be no-ops, and any attempt to read the journal would return
+** SQLITE_IOERR. Or the implementation might recognize that a database
+** file will be doing page-aligned sector reads and writes in a random
+** order and set up its I/O subsystem accordingly.
+**
+** SQLite might also add one of the following flags to the xOpen method:
+**
+** <ul>
+** <li> [SQLITE_OPEN_DELETEONCLOSE]
+** <li> [SQLITE_OPEN_EXCLUSIVE]
+** </ul>
+**
+** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
+** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE]
+** will be set for TEMP databases and their journals, transient
+** databases, and subjournals.
+**
+** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
+** with the [SQLITE_OPEN_CREATE] flag, which are both directly
+** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
+** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
+** SQLITE_OPEN_CREATE, is used to indicate that file should always
+** be created, and that it is an error if it already exists.
+** It is <i>not</i> used to indicate the file should be opened
+** for exclusive access.
+**
+** ^At least szOsFile bytes of memory are allocated by SQLite
+** to hold the [sqlite3_file] structure passed as the third
+** argument to xOpen. The xOpen method does not have to
+** allocate the structure; it should just fill it in. Note that
+** the xOpen method must set the sqlite3_file.pMethods to either
+** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
+** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
+** element will be valid after xOpen returns regardless of the success
+** or failure of the xOpen call.
+**
+** [[sqlite3_vfs.xAccess]]
+** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
+** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
+** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
+** to test whether a file is at least readable. The file can be a
+** directory.
+**
+** ^SQLite will always allocate at least mxPathname+1 bytes for the
+** output buffer xFullPathname. The exact size of the output buffer
+** is also passed as a parameter to both methods. If the output buffer
+** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
+** handled as a fatal error by SQLite, vfs implementations should endeavor
+** to prevent this by setting mxPathname to a sufficiently large value.
+**
+** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
+** interfaces are not strictly a part of the filesystem, but they are
+** included in the VFS structure for completeness.
+** The xRandomness() function attempts to return nBytes bytes
+** of good-quality randomness into zOut. The return value is
+** the actual number of bytes of randomness obtained.
+** The xSleep() method causes the calling thread to sleep for at
+** least the number of microseconds given. ^The xCurrentTime()
+** method returns a Julian Day Number for the current date and time as
+** a floating point value.
+** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
+** Day Number multiplied by 86400000 (the number of milliseconds in
+** a 24-hour day).
+** ^SQLite will use the xCurrentTimeInt64() method to get the current
+** date and time if that method is available (if iVersion is 2 or
+** greater and the function pointer is not NULL) and will fall back
+** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
+**
+** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
+** are not used by the SQLite core. These optional interfaces are provided
+** by some VFSes to facilitate testing of the VFS code. By overriding
+** system calls with functions under its control, a test program can
+** simulate faults and error conditions that would otherwise be difficult
+** or impossible to induce. The set of system calls that can be overridden
+** varies from one VFS to another, and from one version of the same VFS to the
+** next. Applications that use these interfaces must be prepared for any
+** or all of these interfaces to be NULL or for their behavior to change
+** from one release to the next. Applications must not attempt to access
+** any of these methods if the iVersion of the VFS is less than 3.
+*/
+typedef struct sqlite3_vfs sqlite3_vfs;
+typedef void (*sqlite3_syscall_ptr)(void);
+struct sqlite3_vfs {
+ int iVersion; /* Structure version number (currently 3) */
+ int szOsFile; /* Size of subclassed sqlite3_file */
+ int mxPathname; /* Maximum file pathname length */
+ sqlite3_vfs *pNext; /* Next registered VFS */
+ const char *zName; /* Name of this virtual file system */
+ void *pAppData; /* Pointer to application-specific data */
+ int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
+ int flags, int *pOutFlags);
+ int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
+ int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
+ int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
+ void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
+ void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
+ void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
+ void (*xDlClose)(sqlite3_vfs*, void*);
+ int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
+ int (*xSleep)(sqlite3_vfs*, int microseconds);
+ int (*xCurrentTime)(sqlite3_vfs*, double*);
+ int (*xGetLastError)(sqlite3_vfs*, int, char *);
+ /*
+ ** The methods above are in version 1 of the sqlite_vfs object
+ ** definition. Those that follow are added in version 2 or later
+ */
+ int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
+ /*
+ ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
+ ** Those below are for version 3 and greater.
+ */
+ int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
+ sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
+ const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
+ /*
+ ** The methods above are in versions 1 through 3 of the sqlite_vfs object.
+ ** New fields may be appended in figure versions. The iVersion
+ ** value will increment whenever this happens.
+ */
+};
+
+/*
+** CAPI3REF: Flags for the xAccess VFS method
+**
+** These integer constants can be used as the third parameter to
+** the xAccess method of an [sqlite3_vfs] object. They determine
+** what kind of permissions the xAccess method is looking for.
+** With SQLITE_ACCESS_EXISTS, the xAccess method
+** simply checks whether the file exists.
+** With SQLITE_ACCESS_READWRITE, the xAccess method
+** checks whether the named directory is both readable and writable
+** (in other words, if files can be added, removed, and renamed within
+** the directory).
+** The SQLITE_ACCESS_READWRITE constant is currently used only by the
+** [temp_store_directory pragma], though this could change in a future
+** release of SQLite.
+** With SQLITE_ACCESS_READ, the xAccess method
+** checks whether the file is readable. The SQLITE_ACCESS_READ constant is
+** currently unused, though it might be used in a future release of
+** SQLite.
+*/
+#define SQLITE_ACCESS_EXISTS 0
+#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */
+#define SQLITE_ACCESS_READ 2 /* Unused */
+
+/*
+** CAPI3REF: Flags for the xShmLock VFS method
+**
+** These integer constants define the various locking operations
+** allowed by the xShmLock method of [sqlite3_io_methods]. The
+** following are the only legal combinations of flags to the
+** xShmLock method:
+**
+** <ul>
+** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
+** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
+** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
+** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
+** </ul>
+**
+** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
+** was given no the corresponding lock.
+**
+** The xShmLock method can transition between unlocked and SHARED or
+** between unlocked and EXCLUSIVE. It cannot transition between SHARED
+** and EXCLUSIVE.
+*/
+#define SQLITE_SHM_UNLOCK 1
+#define SQLITE_SHM_LOCK 2
+#define SQLITE_SHM_SHARED 4
+#define SQLITE_SHM_EXCLUSIVE 8
+
+/*
+** CAPI3REF: Maximum xShmLock index
+**
+** The xShmLock method on [sqlite3_io_methods] may use values
+** between 0 and this upper bound as its "offset" argument.
+** The SQLite core will never attempt to acquire or release a
+** lock outside of this range
+*/
+#define SQLITE_SHM_NLOCK 8
+
+
+/*
+** CAPI3REF: Initialize The SQLite Library
+**
+** ^The sqlite3_initialize() routine initializes the
+** SQLite library. ^The sqlite3_shutdown() routine
+** deallocates any resources that were allocated by sqlite3_initialize().
+** These routines are designed to aid in process initialization and
+** shutdown on embedded systems. Workstation applications using
+** SQLite normally do not need to invoke either of these routines.
+**
+** A call to sqlite3_initialize() is an "effective" call if it is
+** the first time sqlite3_initialize() is invoked during the lifetime of
+** the process, or if it is the first time sqlite3_initialize() is invoked
+** following a call to sqlite3_shutdown(). ^(Only an effective call
+** of sqlite3_initialize() does any initialization. All other calls
+** are harmless no-ops.)^
+**
+** A call to sqlite3_shutdown() is an "effective" call if it is the first
+** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only
+** an effective call to sqlite3_shutdown() does any deinitialization.
+** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^
+**
+** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown()
+** is not. The sqlite3_shutdown() interface must only be called from a
+** single thread. All open [database connections] must be closed and all
+** other SQLite resources must be deallocated prior to invoking
+** sqlite3_shutdown().
+**
+** Among other things, ^sqlite3_initialize() will invoke
+** sqlite3_os_init(). Similarly, ^sqlite3_shutdown()
+** will invoke sqlite3_os_end().
+**
+** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success.
+** ^If for some reason, sqlite3_initialize() is unable to initialize
+** the library (perhaps it is unable to allocate a needed resource such
+** as a mutex) it returns an [error code] other than [SQLITE_OK].
+**
+** ^The sqlite3_initialize() routine is called internally by many other
+** SQLite interfaces so that an application usually does not need to
+** invoke sqlite3_initialize() directly. For example, [sqlite3_open()]
+** calls sqlite3_initialize() so the SQLite library will be automatically
+** initialized when [sqlite3_open()] is called if it has not be initialized
+** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT]
+** compile-time option, then the automatic calls to sqlite3_initialize()
+** are omitted and the application must call sqlite3_initialize() directly
+** prior to using any other SQLite interface. For maximum portability,
+** it is recommended that applications always invoke sqlite3_initialize()
+** directly prior to using any other SQLite interface. Future releases
+** of SQLite may require this. In other words, the behavior exhibited
+** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the
+** default behavior in some future release of SQLite.
+**
+** The sqlite3_os_init() routine does operating-system specific
+** initialization of the SQLite library. The sqlite3_os_end()
+** routine undoes the effect of sqlite3_os_init(). Typical tasks
+** performed by these routines include allocation or deallocation
+** of static resources, initialization of global variables,
+** setting up a default [sqlite3_vfs] module, or setting up
+** a default configuration using [sqlite3_config()].
+**
+** The application should never invoke either sqlite3_os_init()
+** or sqlite3_os_end() directly. The application should only invoke
+** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init()
+** interface is called automatically by sqlite3_initialize() and
+** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate
+** implementations for sqlite3_os_init() and sqlite3_os_end()
+** are built into SQLite when it is compiled for Unix, Windows, or OS/2.
+** When [custom builds | built for other platforms]
+** (using the [SQLITE_OS_OTHER=1] compile-time
+** option) the application must supply a suitable implementation for
+** sqlite3_os_init() and sqlite3_os_end(). An application-supplied
+** implementation of sqlite3_os_init() or sqlite3_os_end()
+** must return [SQLITE_OK] on success and some other [error code] upon
+** failure.
+*/
+SQLITE_API int sqlite3_initialize(void);
+SQLITE_API int sqlite3_shutdown(void);
+SQLITE_API int sqlite3_os_init(void);
+SQLITE_API int sqlite3_os_end(void);
+
+/*
+** CAPI3REF: Configuring The SQLite Library
+**
+** The sqlite3_config() interface is used to make global configuration
+** changes to SQLite in order to tune SQLite to the specific needs of
+** the application. The default configuration is recommended for most
+** applications and so this routine is usually not necessary. It is
+** provided to support rare applications with unusual needs.
+**
+** The sqlite3_config() interface is not threadsafe. The application
+** must insure that no other SQLite interfaces are invoked by other
+** threads while sqlite3_config() is running. Furthermore, sqlite3_config()
+** may only be invoked prior to library initialization using
+** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
+** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
+** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
+** Note, however, that ^sqlite3_config() can be called as part of the
+** implementation of an application-defined [sqlite3_os_init()].
+**
+** The first argument to sqlite3_config() is an integer
+** [configuration option] that determines
+** what property of SQLite is to be configured. Subsequent arguments
+** vary depending on the [configuration option]
+** in the first argument.
+**
+** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
+** ^If the option is unknown or SQLite is unable to set the option
+** then this routine returns a non-zero [error code].
+*/
+SQLITE_API int sqlite3_config(int, ...);
+
+/*
+** CAPI3REF: Configure database connections
+**
+** The sqlite3_db_config() interface is used to make configuration
+** changes to a [database connection]. The interface is similar to
+** [sqlite3_config()] except that the changes apply to a single
+** [database connection] (specified in the first argument).
+**
+** The second argument to sqlite3_db_config(D,V,...) is the
+** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code
+** that indicates what aspect of the [database connection] is being configured.
+** Subsequent arguments vary depending on the configuration verb.
+**
+** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
+** the call is considered successful.
+*/
+SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+
+/*
+** CAPI3REF: Memory Allocation Routines
+**
+** An instance of this object defines the interface between SQLite
+** and low-level memory allocation routines.
+**
+** This object is used in only one place in the SQLite interface.
+** A pointer to an instance of this object is the argument to
+** [sqlite3_config()] when the configuration option is
+** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
+** By creating an instance of this object
+** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
+** during configuration, an application can specify an alternative
+** memory allocation subsystem for SQLite to use for all of its
+** dynamic memory needs.
+**
+** Note that SQLite comes with several [built-in memory allocators]
+** that are perfectly adequate for the overwhelming majority of applications
+** and that this object is only useful to a tiny minority of applications
+** with specialized memory allocation requirements. This object is
+** also used during testing of SQLite in order to specify an alternative
+** memory allocator that simulates memory out-of-memory conditions in
+** order to verify that SQLite recovers gracefully from such
+** conditions.
+**
+** The xMalloc, xRealloc, and xFree methods must work like the
+** malloc(), realloc() and free() functions from the standard C library.
+** ^SQLite guarantees that the second argument to
+** xRealloc is always a value returned by a prior call to xRoundup.
+**
+** xSize should return the allocated size of a memory allocation
+** previously obtained from xMalloc or xRealloc. The allocated size
+** is always at least as big as the requested size but may be larger.
+**
+** The xRoundup method returns what would be the allocated size of
+** a memory allocation given a particular requested size. Most memory
+** allocators round up memory allocations at least to the next multiple
+** of 8. Some allocators round up to a larger multiple or to a power of 2.
+** Every memory allocation request coming in through [sqlite3_malloc()]
+** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
+** that causes the corresponding memory allocation to fail.
+**
+** The xInit method initializes the memory allocator. (For example,
+** it might allocate any require mutexes or initialize internal data
+** structures. The xShutdown method is invoked (indirectly) by
+** [sqlite3_shutdown()] and should deallocate any resources acquired
+** by xInit. The pAppData pointer is used as the only parameter to
+** xInit and xShutdown.
+**
+** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes
+** the xInit method, so the xInit method need not be threadsafe. The
+** xShutdown method is only called from [sqlite3_shutdown()] so it does
+** not need to be threadsafe either. For all other methods, SQLite
+** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the
+** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which
+** it is by default) and so the methods are automatically serialized.
+** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other
+** methods must be threadsafe or else make their own arrangements for
+** serialization.
+**
+** SQLite will never invoke xInit() more than once without an intervening
+** call to xShutdown().
+*/
+typedef struct sqlite3_mem_methods sqlite3_mem_methods;
+struct sqlite3_mem_methods {
+ void *(*xMalloc)(int); /* Memory allocation function */
+ void (*xFree)(void*); /* Free a prior allocation */
+ void *(*xRealloc)(void*,int); /* Resize an allocation */
+ int (*xSize)(void*); /* Return the size of an allocation */
+ int (*xRoundup)(int); /* Round up request size to allocation size */
+ int (*xInit)(void*); /* Initialize the memory allocator */
+ void (*xShutdown)(void*); /* Deinitialize the memory allocator */
+ void *pAppData; /* Argument to xInit() and xShutdown() */
+};
+
+/*
+** CAPI3REF: Configuration Options
+** KEYWORDS: {configuration option}
+**
+** These constants are the available integer configuration options that
+** can be passed as the first argument to the [sqlite3_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_config()] to make sure that
+** the call worked. The [sqlite3_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
+**
+** <dl>
+** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
+** <dd>There are no arguments to this option. ^This option sets the
+** [threading mode] to Single-thread. In other words, it disables
+** all mutexing and puts SQLite into a mode where it can only be used
+** by a single thread. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** it is not possible to change the [threading mode] from its default
+** value of Single-thread and so [sqlite3_config()] will return
+** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
+** configuration option.</dd>
+**
+** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
+** <dd>There are no arguments to this option. ^This option sets the
+** [threading mode] to Multi-thread. In other words, it disables
+** mutexing on [database connection] and [prepared statement] objects.
+** The application is responsible for serializing access to
+** [database connections] and [prepared statements]. But other mutexes
+** are enabled so that SQLite will be safe to use in a multi-threaded
+** environment as long as no two threads attempt to use the same
+** [database connection] at the same time. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** it is not possible to set the Multi-thread [threading mode] and
+** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
+** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
+**
+** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
+** <dd>There are no arguments to this option. ^This option sets the
+** [threading mode] to Serialized. In other words, this option enables
+** all mutexes including the recursive
+** mutexes on [database connection] and [prepared statement] objects.
+** In this mode (which is the default when SQLite is compiled with
+** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access
+** to [database connections] and [prepared statements] so that the
+** application is free to use the same [database connection] or the
+** same [prepared statement] in different threads at the same time.
+** ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** it is not possible to set the Serialized [threading mode] and
+** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
+** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
+**
+** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mem_methods] structure. The argument specifies
+** alternative low-level memory allocation routines to be used in place of
+** the memory allocation routines built into SQLite.)^ ^SQLite makes
+** its own private copy of the content of the [sqlite3_mem_methods] structure
+** before the [sqlite3_config()] call returns.</dd>
+**
+** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
+** structure is filled with the currently defined memory allocation routines.)^
+** This option can be used to overload the default memory allocation
+** routines with a wrapper that simulations memory allocation failure or
+** tracks memory usage, for example. </dd>
+**
+** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
+** <dd> ^This option takes single argument of type int, interpreted as a
+** boolean, which enables or disables the collection of memory allocation
+** statistics. ^(When memory allocation statistics are disabled, the
+** following SQLite interfaces become non-operational:
+** <ul>
+** <li> [sqlite3_memory_used()]
+** <li> [sqlite3_memory_highwater()]
+** <li> [sqlite3_soft_heap_limit64()]
+** <li> [sqlite3_status()]
+** </ul>)^
+** ^Memory allocation statistics are enabled by default unless SQLite is
+** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
+** allocation statistics are disabled by default.
+** </dd>
+**
+** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
+** <dd> ^This option specifies a static memory buffer that SQLite can use for
+** scratch memory. There are three arguments: A pointer an 8-byte
+** aligned memory buffer from which the scratch allocations will be
+** drawn, the size of each scratch allocation (sz),
+** and the maximum number of scratch allocations (N). The sz
+** argument must be a multiple of 16.
+** The first argument must be a pointer to an 8-byte aligned buffer
+** of at least sz*N bytes of memory.
+** ^SQLite will use no more than two scratch buffers per thread. So
+** N should be set to twice the expected maximum number of threads.
+** ^SQLite will never require a scratch buffer that is more than 6
+** times the database page size. ^If SQLite needs needs additional
+** scratch memory beyond what is provided by this configuration option, then
+** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
+**
+** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
+** <dd> ^This option specifies a static memory buffer that SQLite can use for
+** the database page cache with the default page cache implementation.
+** This configuration should not be used if an application-define page
+** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option.
+** There are three arguments to this option: A pointer to 8-byte aligned
+** memory, the size of each page buffer (sz), and the number of pages (N).
+** The sz argument should be the size of the largest database page
+** (a power of two between 512 and 32768) plus a little extra for each
+** page header. ^The page header size is 20 to 40 bytes depending on
+** the host architecture. ^It is harmless, apart from the wasted memory,
+** to make sz a little too large. The first
+** argument should point to an allocation of at least sz*N bytes of memory.
+** ^SQLite will use the memory provided by the first argument to satisfy its
+** memory needs for the first N pages that it adds to cache. ^If additional
+** page cache memory is needed beyond what is provided by this option, then
+** SQLite goes to [sqlite3_malloc()] for the additional storage space.
+** The pointer in the first argument must
+** be aligned to an 8-byte boundary or subsequent behavior of SQLite
+** will be undefined.</dd>
+**
+** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
+** <dd> ^This option specifies a static memory buffer that SQLite will use
+** for all of its dynamic memory allocation needs beyond those provided
+** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
+** There are three arguments: An 8-byte aligned pointer to the memory,
+** the number of bytes in the memory buffer, and the minimum allocation size.
+** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts
+** to using its default memory allocator (the system malloc() implementation),
+** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the
+** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or
+** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory
+** allocator is engaged to handle all of SQLites memory allocation needs.
+** The first pointer (the memory pointer) must be aligned to an 8-byte
+** boundary or subsequent behavior of SQLite will be undefined.
+** The minimum allocation size is capped at 2**12. Reasonable values
+** for the minimum allocation size are 2**5 through 2**8.</dd>
+**
+** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mutex_methods] structure. The argument specifies
+** alternative low-level mutex routines to be used in place
+** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
+** content of the [sqlite3_mutex_methods] structure before the call to
+** [sqlite3_config()] returns. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** the entire mutexing subsystem is omitted from the build and hence calls to
+** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
+** return [SQLITE_ERROR].</dd>
+**
+** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mutex_methods] structure. The
+** [sqlite3_mutex_methods]
+** structure is filled with the currently defined mutex routines.)^
+** This option can be used to overload the default mutex allocation
+** routines with a wrapper used to track mutex usage for performance
+** profiling or testing, for example. ^If SQLite is compiled with
+** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
+** the entire mutexing subsystem is omitted from the build and hence calls to
+** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
+** return [SQLITE_ERROR].</dd>
+**
+** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
+** <dd> ^(This option takes two arguments that determine the default
+** memory allocation for the lookaside memory allocator on each
+** [database connection]. The first argument is the
+** size of each lookaside buffer slot and the second is the number of
+** slots allocated to each database connection.)^ ^(This option sets the
+** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
+** verb to [sqlite3_db_config()] can be used to change the lookaside
+** configuration on individual connections.)^ </dd>
+**
+** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
+** <dd> ^(This option takes a single argument which is a pointer to
+** an [sqlite3_pcache_methods2] object. This object specifies the interface
+** to a custom page cache implementation.)^ ^SQLite makes a copy of the
+** object and uses it for page cache memory allocations.</dd>
+**
+** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
+** <dd> ^(This option takes a single argument which is a pointer to an
+** [sqlite3_pcache_methods2] object. SQLite copies of the current
+** page cache implementation into that object.)^ </dd>
+**
+** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
+** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
+** function with a call signature of void(*)(void*,int,const char*),
+** and a pointer to void. ^If the function pointer is not NULL, it is
+** invoked by [sqlite3_log()] to process each logging event. ^If the
+** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
+** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
+** passed through as the first parameter to the application-defined logger
+** function whenever that function is invoked. ^The second parameter to
+** the logger function is a copy of the first parameter to the corresponding
+** [sqlite3_log()] call and is intended to be a [result code] or an
+** [extended result code]. ^The third parameter passed to the logger is
+** log message after formatting via [sqlite3_snprintf()].
+** The SQLite logging interface is not reentrant; the logger function
+** supplied by the application must not invoke any SQLite interface.
+** In a multi-threaded application, the application-defined logger
+** function must be threadsafe. </dd>
+**
+** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
+** <dd> This option takes a single argument of type int. If non-zero, then
+** URI handling is globally enabled. If the parameter is zero, then URI handling
+** is globally disabled. If URI handling is globally enabled, all filenames
+** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
+** specified as part of [ATTACH] commands are interpreted as URIs, regardless
+** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
+** connection is opened. If it is globally disabled, filenames are
+** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
+** database connection is opened. By default, URI handling is globally
+** disabled. The default value may be changed by compiling with the
+** [SQLITE_USE_URI] symbol defined.
+**
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd> This option takes a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer. The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** malfunction when the optimization is enabled. Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
+** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
+** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
+** <dd> These options are obsolete and should not be used by new code.
+** They are retained for backwards compatibility but are now no-ops.
+** </dl>
+**
+** [[SQLITE_CONFIG_SQLLOG]]
+** <dt>SQLITE_CONFIG_SQLLOG
+** <dd>This option is only available if sqlite is compiled with the
+** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
+** The second should be of type (void*). The callback is invoked by the library
+** in three separate circumstances, identified by the value passed as the
+** fourth parameter. If the fourth parameter is 0, then the database connection
+** passed as the second argument has just been opened. The third argument
+** points to a buffer containing the name of the main database file. If the
+** fourth parameter is 1, then the SQL statement that the third parameter
+** points to has just been executed. Or, if the fourth parameter is 2, then
+** the connection being passed as the second parameter is being closed. The
+** third parameter is passed NULL In this case.
+** </dl>
+*/
+#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
+#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
+#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
+#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */
+#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
+#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
+#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
+#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
+#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
+/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
+#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
+#define SQLITE_CONFIG_PCACHE 14 /* no-op */
+#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */
+#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
+#define SQLITE_CONFIG_URI 17 /* int */
+#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
+#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
+
+/*
+** CAPI3REF: Database Connection Configuration Options
+**
+** These constants are the available integer configuration options that
+** can be passed as the second argument to the [sqlite3_db_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_db_config()] to make sure that
+** the call worked. ^The [sqlite3_db_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
+**
+** <dl>
+** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
+** <dd> ^This option takes three additional arguments that determine the
+** [lookaside memory allocator] configuration for the [database connection].
+** ^The first argument (the third parameter to [sqlite3_db_config()] is a
+** pointer to a memory buffer to use for lookaside memory.
+** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
+** may be NULL in which case SQLite will allocate the
+** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
+** size of each lookaside buffer slot. ^The third argument is the number of
+** slots. The size of the buffer in the first argument must be greater than
+** or equal to the product of the second and third arguments. The buffer
+** must be aligned to an 8-byte boundary. ^If the second argument to
+** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
+** rounded down to the next smaller multiple of 8. ^(The lookaside memory
+** configuration for a database connection can only be changed when that
+** connection is not currently using lookaside memory, or in other words
+** when the "current value" returned by
+** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero.
+** Any attempt to change the lookaside memory configuration when lookaside
+** memory is in use leaves the configuration unchanged and returns
+** [SQLITE_BUSY].)^</dd>
+**
+** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
+** <dd> ^This option is used to enable or disable the enforcement of
+** [foreign key constraints]. There should be two additional arguments.
+** The first argument is an integer which is 0 to disable FK enforcement,
+** positive to enable FK enforcement or negative to leave FK enforcement
+** unchanged. The second parameter is a pointer to an integer into which
+** is written 0 or 1 to indicate whether FK enforcement is off or on
+** following this call. The second parameter may be a NULL pointer, in
+** which case the FK enforcement setting is not reported back. </dd>
+**
+** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
+** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
+** There should be two additional arguments.
+** The first argument is an integer which is 0 to disable triggers,
+** positive to enable triggers or negative to leave the setting unchanged.
+** The second parameter is a pointer to an integer into which
+** is written 0 or 1 to indicate whether triggers are disabled or enabled
+** following this call. The second parameter may be a NULL pointer, in
+** which case the trigger setting is not reported back. </dd>
+**
+** </dl>
+*/
+#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
+#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
+
+
+/*
+** CAPI3REF: Enable Or Disable Extended Result Codes
+**
+** ^The sqlite3_extended_result_codes() routine enables or disables the
+** [extended result codes] feature of SQLite. ^The extended result
+** codes are disabled by default for historical compatibility.
+*/
+SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
+
+/*
+** CAPI3REF: Last Insert Rowid
+**
+** ^Each entry in an SQLite table has a unique 64-bit signed
+** integer key called the [ROWID | "rowid"]. ^The rowid is always available
+** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
+** names are not also used by explicitly declared columns. ^If
+** the table has a column of type [INTEGER PRIMARY KEY] then that column
+** is another alias for the rowid.
+**
+** ^This routine returns the [rowid] of the most recent
+** successful [INSERT] into the database from the [database connection]
+** in the first argument. ^As of SQLite version 3.7.7, this routines
+** records the last insert rowid of both ordinary tables and [virtual tables].
+** ^If no successful [INSERT]s
+** have ever occurred on that database connection, zero is returned.
+**
+** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
+** method, then this routine will return the [rowid] of the inserted
+** row as long as the trigger or virtual table method is running.
+** But once the trigger or virtual table method ends, the value returned
+** by this routine reverts to what it was before the trigger or virtual
+** table method began.)^
+**
+** ^An [INSERT] that fails due to a constraint violation is not a
+** successful [INSERT] and does not change the value returned by this
+** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
+** and INSERT OR ABORT make no changes to the return value of this
+** routine when their insertion fails. ^(When INSERT OR REPLACE
+** encounters a constraint violation, it does not fail. The
+** INSERT continues to completion after deleting rows that caused
+** the constraint problem so INSERT OR REPLACE will always change
+** the return value of this interface.)^
+**
+** ^For the purposes of this routine, an [INSERT] is considered to
+** be successful even if it is subsequently rolled back.
+**
+** This function is accessible to SQL statements via the
+** [last_insert_rowid() SQL function].
+**
+** If a separate thread performs a new [INSERT] on the same
+** database connection while the [sqlite3_last_insert_rowid()]
+** function is running and thus changes the last insert [rowid],
+** then the value returned by [sqlite3_last_insert_rowid()] is
+** unpredictable and might not equal either the old or the new
+** last insert [rowid].
+*/
+SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+
+/*
+** CAPI3REF: Count The Number Of Rows Modified
+**
+** ^This function returns the number of database rows that were changed
+** or inserted or deleted by the most recently completed SQL statement
+** on the [database connection] specified by the first parameter.
+** ^(Only changes that are directly specified by the [INSERT], [UPDATE],
+** or [DELETE] statement are counted. Auxiliary changes caused by
+** triggers or [foreign key actions] are not counted.)^ Use the
+** [sqlite3_total_changes()] function to find the total number of changes
+** including changes caused by triggers and foreign key actions.
+**
+** ^Changes to a view that are simulated by an [INSTEAD OF trigger]
+** are not counted. Only real table changes are counted.
+**
+** ^(A "row change" is a change to a single row of a single table
+** caused by an INSERT, DELETE, or UPDATE statement. Rows that
+** are changed as side effects of [REPLACE] constraint resolution,
+** rollback, ABORT processing, [DROP TABLE], or by any other
+** mechanisms do not count as direct row changes.)^
+**
+** A "trigger context" is a scope of execution that begins and
+** ends with the script of a [CREATE TRIGGER | trigger].
+** Most SQL statements are
+** evaluated outside of any trigger. This is the "top level"
+** trigger context. If a trigger fires from the top level, a
+** new trigger context is entered for the duration of that one
+** trigger. Subtriggers create subcontexts for their duration.
+**
+** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does
+** not create a new trigger context.
+**
+** ^This function returns the number of direct row changes in the
+** most recent INSERT, UPDATE, or DELETE statement within the same
+** trigger context.
+**
+** ^Thus, when called from the top level, this function returns the
+** number of changes in the most recent INSERT, UPDATE, or DELETE
+** that also occurred at the top level. ^(Within the body of a trigger,
+** the sqlite3_changes() interface can be called to find the number of
+** changes in the most recently completed INSERT, UPDATE, or DELETE
+** statement within the body of the same trigger.
+** However, the number returned does not include changes
+** caused by subtriggers since those have their own context.)^
+**
+** See also the [sqlite3_total_changes()] interface, the
+** [count_changes pragma], and the [changes() SQL function].
+**
+** If a separate thread makes changes on the same database connection
+** while [sqlite3_changes()] is running then the value returned
+** is unpredictable and not meaningful.
+*/
+SQLITE_API int sqlite3_changes(sqlite3*);
+
+/*
+** CAPI3REF: Total Number Of Rows Modified
+**
+** ^This function returns the number of row changes caused by [INSERT],
+** [UPDATE] or [DELETE] statements since the [database connection] was opened.
+** ^(The count returned by sqlite3_total_changes() includes all changes
+** from all [CREATE TRIGGER | trigger] contexts and changes made by
+** [foreign key actions]. However,
+** the count does not include changes used to implement [REPLACE] constraints,
+** do rollbacks or ABORT processing, or [DROP TABLE] processing. The
+** count does not include rows of views that fire an [INSTEAD OF trigger],
+** though if the INSTEAD OF trigger makes changes of its own, those changes
+** are counted.)^
+** ^The sqlite3_total_changes() function counts the changes as soon as
+** the statement that makes them is completed (when the statement handle
+** is passed to [sqlite3_reset()] or [sqlite3_finalize()]).
+**
+** See also the [sqlite3_changes()] interface, the
+** [count_changes pragma], and the [total_changes() SQL function].
+**
+** If a separate thread makes changes on the same database connection
+** while [sqlite3_total_changes()] is running then the value
+** returned is unpredictable and not meaningful.
+*/
+SQLITE_API int sqlite3_total_changes(sqlite3*);
+
+/*
+** CAPI3REF: Interrupt A Long-Running Query
+**
+** ^This function causes any pending database operation to abort and
+** return at its earliest opportunity. This routine is typically
+** called in response to a user action such as pressing "Cancel"
+** or Ctrl-C where the user wants a long query operation to halt
+** immediately.
+**
+** ^It is safe to call this routine from a thread different from the
+** thread that is currently running the database operation. But it
+** is not safe to call this routine with a [database connection] that
+** is closed or might close before sqlite3_interrupt() returns.
+**
+** ^If an SQL operation is very nearly finished at the time when
+** sqlite3_interrupt() is called, then it might not have an opportunity
+** to be interrupted and might continue to completion.
+**
+** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT].
+** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE
+** that is inside an explicit transaction, then the entire transaction
+** will be rolled back automatically.
+**
+** ^The sqlite3_interrupt(D) call is in effect until all currently running
+** SQL statements on [database connection] D complete. ^Any new SQL statements
+** that are started after the sqlite3_interrupt() call and before the
+** running statements reaches zero are interrupted as if they had been
+** running prior to the sqlite3_interrupt() call. ^New SQL statements
+** that are started after the running statement count reaches zero are
+** not effected by the sqlite3_interrupt().
+** ^A call to sqlite3_interrupt(D) that occurs when there are no running
+** SQL statements is a no-op and has no effect on SQL statements
+** that are started after the sqlite3_interrupt() call returns.
+**
+** If the database connection closes while [sqlite3_interrupt()]
+** is running then bad things will likely happen.
+*/
+SQLITE_API void sqlite3_interrupt(sqlite3*);
+
+/*
+** CAPI3REF: Determine If An SQL Statement Is Complete
+**
+** These routines are useful during command-line input to determine if the
+** currently entered text seems to form a complete SQL statement or
+** if additional input is needed before sending the text into
+** SQLite for parsing. ^These routines return 1 if the input string
+** appears to be a complete SQL statement. ^A statement is judged to be
+** complete if it ends with a semicolon token and is not a prefix of a
+** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within
+** string literals or quoted identifier names or comments are not
+** independent tokens (they are part of the token in which they are
+** embedded) and thus do not count as a statement terminator. ^Whitespace
+** and comments that follow the final semicolon are ignored.
+**
+** ^These routines return 0 if the statement is incomplete. ^If a
+** memory allocation fails, then SQLITE_NOMEM is returned.
+**
+** ^These routines do not parse the SQL statements thus
+** will not detect syntactically incorrect SQL.
+**
+** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
+** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
+** automatically by sqlite3_complete16(). If that initialization fails,
+** then the return value from sqlite3_complete16() will be non-zero
+** regardless of whether or not the input SQL is complete.)^
+**
+** The input to [sqlite3_complete()] must be a zero-terminated
+** UTF-8 string.
+**
+** The input to [sqlite3_complete16()] must be a zero-terminated
+** UTF-16 string in native byte order.
+*/
+SQLITE_API int sqlite3_complete(const char *sql);
+SQLITE_API int sqlite3_complete16(const void *sql);
+
+/*
+** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
+**
+** ^This routine sets a callback function that might be invoked whenever
+** an attempt is made to open a database table that another thread
+** or process has locked.
+**
+** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
+** is returned immediately upon encountering the lock. ^If the busy callback
+** is not NULL, then the callback might be invoked with two arguments.
+**
+** ^The first argument to the busy handler is a copy of the void* pointer which
+** is the third argument to sqlite3_busy_handler(). ^The second argument to
+** the busy handler callback is the number of times that the busy handler has
+** been invoked for this locking event. ^If the
+** busy callback returns 0, then no additional attempts are made to
+** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
+** ^If the callback returns non-zero, then another attempt
+** is made to open the database for reading and the cycle repeats.
+**
+** The presence of a busy handler does not guarantee that it will be invoked
+** when there is lock contention. ^If SQLite determines that invoking the busy
+** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
+** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
+** Consider a scenario where one process is holding a read lock that
+** it is trying to promote to a reserved lock and
+** a second process is holding a reserved lock that it is trying
+** to promote to an exclusive lock. The first process cannot proceed
+** because it is blocked by the second and the second process cannot
+** proceed because it is blocked by the first. If both processes
+** invoke the busy handlers, neither will make any progress. Therefore,
+** SQLite returns [SQLITE_BUSY] for the first process, hoping that this
+** will induce the first process to release its read lock and allow
+** the second process to proceed.
+**
+** ^The default busy callback is NULL.
+**
+** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
+** when SQLite is in the middle of a large transaction where all the
+** changes will not fit into the in-memory cache. SQLite will
+** already hold a RESERVED lock on the database file, but it needs
+** to promote this lock to EXCLUSIVE so that it can spill cache
+** pages into the database file without harm to concurrent
+** readers. ^If it is unable to promote the lock, then the in-memory
+** cache will be left in an inconsistent state and so the error
+** code is promoted from the relatively benign [SQLITE_BUSY] to
+** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
+** forces an automatic rollback of the changes. See the
+** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
+** CorruptionFollowingBusyError</a> wiki page for a discussion of why
+** this is important.
+**
+** ^(There can only be a single busy handler defined for each
+** [database connection]. Setting a new busy handler clears any
+** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
+** will also set or clear the busy handler.
+**
+** The busy callback should not take any actions which modify the
+** database connection that invoked the busy handler. Any such actions
+** result in undefined behavior.
+**
+** A busy handler must not close the database connection
+** or [prepared statement] that invoked the busy handler.
+*/
+SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
+
+/*
+** CAPI3REF: Set A Busy Timeout
+**
+** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
+** for a specified amount of time when a table is locked. ^The handler
+** will sleep multiple times until at least "ms" milliseconds of sleeping
+** have accumulated. ^After at least "ms" milliseconds of sleeping,
+** the handler returns 0 which causes [sqlite3_step()] to return
+** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
+**
+** ^Calling this routine with an argument less than or equal to zero
+** turns off all busy handlers.
+**
+** ^(There can only be a single busy handler for a particular
+** [database connection] any any given moment. If another busy handler
+** was defined (using [sqlite3_busy_handler()]) prior to calling
+** this routine, that other busy handler is cleared.)^
+*/
+SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
+
+/*
+** CAPI3REF: Convenience Routines For Running Queries
+**
+** This is a legacy interface that is preserved for backwards compatibility.
+** Use of this interface is not recommended.
+**
+** Definition: A <b>result table</b> is memory data structure created by the
+** [sqlite3_get_table()] interface. A result table records the
+** complete query results from one or more queries.
+**
+** The table conceptually has a number of rows and columns. But
+** these numbers are not part of the result table itself. These
+** numbers are obtained separately. Let N be the number of rows
+** and M be the number of columns.
+**
+** A result table is an array of pointers to zero-terminated UTF-8 strings.
+** There are (N+1)*M elements in the array. The first M pointers point
+** to zero-terminated strings that contain the names of the columns.
+** The remaining entries all point to query results. NULL values result
+** in NULL pointers. All other values are in their UTF-8 zero-terminated
+** string representation as returned by [sqlite3_column_text()].
+**
+** A result table might consist of one or more memory allocations.
+** It is not safe to pass a result table directly to [sqlite3_free()].
+** A result table should be deallocated using [sqlite3_free_table()].
+**
+** ^(As an example of the result table format, suppose a query result
+** is as follows:
+**
+** <blockquote><pre>
+** Name | Age
+** -----------------------
+** Alice | 43
+** Bob | 28
+** Cindy | 21
+** </pre></blockquote>
+**
+** There are two column (M==2) and three rows (N==3). Thus the
+** result table has 8 entries. Suppose the result table is stored
+** in an array names azResult. Then azResult holds this content:
+**
+** <blockquote><pre>
+** azResult&#91;0] = "Name";
+** azResult&#91;1] = "Age";
+** azResult&#91;2] = "Alice";
+** azResult&#91;3] = "43";
+** azResult&#91;4] = "Bob";
+** azResult&#91;5] = "28";
+** azResult&#91;6] = "Cindy";
+** azResult&#91;7] = "21";
+** </pre></blockquote>)^
+**
+** ^The sqlite3_get_table() function evaluates one or more
+** semicolon-separated SQL statements in the zero-terminated UTF-8
+** string of its 2nd parameter and returns a result table to the
+** pointer given in its 3rd parameter.
+**
+** After the application has finished with the result from sqlite3_get_table(),
+** it must pass the result table pointer to sqlite3_free_table() in order to
+** release the memory that was malloced. Because of the way the
+** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling
+** function must not try to call [sqlite3_free()] directly. Only
+** [sqlite3_free_table()] is able to release the memory properly and safely.
+**
+** The sqlite3_get_table() interface is implemented as a wrapper around
+** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access
+** to any internal data structures of SQLite. It uses only the public
+** interface defined here. As a consequence, errors that occur in the
+** wrapper layer outside of the internal [sqlite3_exec()] call are not
+** reflected in subsequent calls to [sqlite3_errcode()] or
+** [sqlite3_errmsg()].
+*/
+SQLITE_API int sqlite3_get_table(
+ sqlite3 *db, /* An open database */
+ const char *zSql, /* SQL to be evaluated */
+ char ***pazResult, /* Results of the query */
+ int *pnRow, /* Number of result rows written here */
+ int *pnColumn, /* Number of result columns written here */
+ char **pzErrmsg /* Error msg written here */
+);
+SQLITE_API void sqlite3_free_table(char **result);
+
+/*
+** CAPI3REF: Formatted String Printing Functions
+**
+** These routines are work-alikes of the "printf()" family of functions
+** from the standard C library.
+**
+** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
+** results into memory obtained from [sqlite3_malloc()].
+** The strings returned by these two routines should be
+** released by [sqlite3_free()]. ^Both routines return a
+** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
+** memory to hold the resulting string.
+**
+** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from
+** the standard C library. The result is written into the
+** buffer supplied as the second parameter whose size is given by
+** the first parameter. Note that the order of the
+** first two parameters is reversed from snprintf().)^ This is an
+** historical accident that cannot be fixed without breaking
+** backwards compatibility. ^(Note also that sqlite3_snprintf()
+** returns a pointer to its buffer instead of the number of
+** characters actually written into the buffer.)^ We admit that
+** the number of characters written would be a more useful return
+** value but we cannot change the implementation of sqlite3_snprintf()
+** now without breaking compatibility.
+**
+** ^As long as the buffer size is greater than zero, sqlite3_snprintf()
+** guarantees that the buffer is always zero-terminated. ^The first
+** parameter "n" is the total size of the buffer, including space for
+** the zero terminator. So the longest string that can be completely
+** written will be n-1 characters.
+**
+** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
+**
+** These routines all implement some additional formatting
+** options that are useful for constructing SQL statements.
+** All of the usual printf() formatting options apply. In addition, there
+** is are "%q", "%Q", and "%z" options.
+**
+** ^(The %q option works like %s in that it substitutes a nul-terminated
+** string from the argument list. But %q also doubles every '\'' character.
+** %q is designed for use inside a string literal.)^ By doubling each '\''
+** character it escapes that character and allows it to be inserted into
+** the string.
+**
+** For example, assume the string variable zText contains text as follows:
+**
+** <blockquote><pre>
+** char *zText = "It's a happy day!";
+** </pre></blockquote>
+**
+** One can use this text in an SQL statement as follows:
+**
+** <blockquote><pre>
+** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+** sqlite3_exec(db, zSQL, 0, 0, 0);
+** sqlite3_free(zSQL);
+** </pre></blockquote>
+**
+** Because the %q format string is used, the '\'' character in zText
+** is escaped and the SQL generated is as follows:
+**
+** <blockquote><pre>
+** INSERT INTO table1 VALUES('It''s a happy day!')
+** </pre></blockquote>
+**
+** This is correct. Had we used %s instead of %q, the generated SQL
+** would have looked like this:
+**
+** <blockquote><pre>
+** INSERT INTO table1 VALUES('It's a happy day!');
+** </pre></blockquote>
+**
+** This second example is an SQL syntax error. As a general rule you should
+** always use %q instead of %s when inserting text into a string literal.
+**
+** ^(The %Q option works like %q except it also adds single quotes around
+** the outside of the total string. Additionally, if the parameter in the
+** argument list is a NULL pointer, %Q substitutes the text "NULL" (without
+** single quotes).)^ So, for example, one could say:
+**
+** <blockquote><pre>
+** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+** sqlite3_exec(db, zSQL, 0, 0, 0);
+** sqlite3_free(zSQL);
+** </pre></blockquote>
+**
+** The code above will render a correct SQL statement in the zSQL
+** variable even if the zText variable is a NULL pointer.
+**
+** ^(The "%z" formatting option works like "%s" but with the
+** addition that after the string has been read and copied into
+** the result, [sqlite3_free()] is called on the input string.)^
+*/
+SQLITE_API char *sqlite3_mprintf(const char*,...);
+SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
+SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
+SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
+
+/*
+** CAPI3REF: Memory Allocation Subsystem
+**
+** The SQLite core uses these three routines for all of its own
+** internal memory allocation needs. "Core" in the previous sentence
+** does not include operating-system specific VFS implementation. The
+** Windows VFS uses native malloc() and free() for some operations.
+**
+** ^The sqlite3_malloc() routine returns a pointer to a block
+** of memory at least N bytes in length, where N is the parameter.
+** ^If sqlite3_malloc() is unable to obtain sufficient free
+** memory, it returns a NULL pointer. ^If the parameter N to
+** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
+** a NULL pointer.
+**
+** ^Calling sqlite3_free() with a pointer previously returned
+** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
+** that it might be reused. ^The sqlite3_free() routine is
+** a no-op if is called with a NULL pointer. Passing a NULL pointer
+** to sqlite3_free() is harmless. After being freed, memory
+** should neither be read nor written. Even reading previously freed
+** memory might result in a segmentation fault or other severe error.
+** Memory corruption, a segmentation fault, or other severe error
+** might result if sqlite3_free() is called with a non-NULL pointer that
+** was not obtained from sqlite3_malloc() or sqlite3_realloc().
+**
+** ^(The sqlite3_realloc() interface attempts to resize a
+** prior memory allocation to be at least N bytes, where N is the
+** second parameter. The memory allocation to be resized is the first
+** parameter.)^ ^ If the first parameter to sqlite3_realloc()
+** is a NULL pointer then its behavior is identical to calling
+** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc().
+** ^If the second parameter to sqlite3_realloc() is zero or
+** negative then the behavior is exactly the same as calling
+** sqlite3_free(P) where P is the first parameter to sqlite3_realloc().
+** ^sqlite3_realloc() returns a pointer to a memory allocation
+** of at least N bytes in size or NULL if sufficient memory is unavailable.
+** ^If M is the size of the prior allocation, then min(N,M) bytes
+** of the prior allocation are copied into the beginning of buffer returned
+** by sqlite3_realloc() and the prior allocation is freed.
+** ^If sqlite3_realloc() returns NULL, then the prior allocation
+** is not freed.
+**
+** ^The memory returned by sqlite3_malloc() and sqlite3_realloc()
+** is always aligned to at least an 8 byte boundary, or to a
+** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
+** option is used.
+**
+** In SQLite version 3.5.0 and 3.5.1, it was possible to define
+** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
+** implementation of these routines to be omitted. That capability
+** is no longer provided. Only built-in memory allocators can be used.
+**
+** Prior to SQLite version 3.7.10, the Windows OS interface layer called
+** the system malloc() and free() directly when converting
+** filenames between the UTF-8 encoding used by SQLite
+** and whatever filename encoding is used by the particular Windows
+** installation. Memory allocation errors were detected, but
+** they were reported back as [SQLITE_CANTOPEN] or
+** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
+**
+** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
+** must be either NULL or else pointers obtained from a prior
+** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
+** not yet been released.
+**
+** The application must not read or write any part of
+** a block of memory after it has been released using
+** [sqlite3_free()] or [sqlite3_realloc()].
+*/
+SQLITE_API void *sqlite3_malloc(int);
+SQLITE_API void *sqlite3_realloc(void*, int);
+SQLITE_API void sqlite3_free(void*);
+
+/*
+** CAPI3REF: Memory Allocator Statistics
+**
+** SQLite provides these two interfaces for reporting on the status
+** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
+** routines, which form the built-in memory allocation subsystem.
+**
+** ^The [sqlite3_memory_used()] routine returns the number of bytes
+** of memory currently outstanding (malloced but not freed).
+** ^The [sqlite3_memory_highwater()] routine returns the maximum
+** value of [sqlite3_memory_used()] since the high-water mark
+** was last reset. ^The values returned by [sqlite3_memory_used()] and
+** [sqlite3_memory_highwater()] include any overhead
+** added by SQLite in its implementation of [sqlite3_malloc()],
+** but not overhead added by the any underlying system library
+** routines that [sqlite3_malloc()] may call.
+**
+** ^The memory high-water mark is reset to the current value of
+** [sqlite3_memory_used()] if and only if the parameter to
+** [sqlite3_memory_highwater()] is true. ^The value returned
+** by [sqlite3_memory_highwater(1)] is the high-water mark
+** prior to the reset.
+*/
+SQLITE_API sqlite3_int64 sqlite3_memory_used(void);
+SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
+
+/*
+** CAPI3REF: Pseudo-Random Number Generator
+**
+** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
+** select random [ROWID | ROWIDs] when inserting new records into a table that
+** already uses the largest possible [ROWID]. The PRNG is also used for
+** the build-in random() and randomblob() SQL functions. This interface allows
+** applications to access the same PRNG for other purposes.
+**
+** ^A call to this routine stores N bytes of randomness into buffer P.
+**
+** ^The first time this routine is invoked (either internally or by
+** the application) the PRNG is seeded using randomness obtained
+** from the xRandomness method of the default [sqlite3_vfs] object.
+** ^On all subsequent invocations, the pseudo-randomness is generated
+** internally and without recourse to the [sqlite3_vfs] xRandomness
+** method.
+*/
+SQLITE_API void sqlite3_randomness(int N, void *P);
+
+/*
+** CAPI3REF: Compile-Time Authorization Callbacks
+**
+** ^This routine registers an authorizer callback with a particular
+** [database connection], supplied in the first argument.
+** ^The authorizer callback is invoked as SQL statements are being compiled
+** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
+** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various
+** points during the compilation process, as logic is being created
+** to perform various actions, the authorizer callback is invoked to
+** see if those actions are allowed. ^The authorizer callback should
+** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the
+** specific action but allow the SQL statement to continue to be
+** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be
+** rejected with an error. ^If the authorizer callback returns
+** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY]
+** then the [sqlite3_prepare_v2()] or equivalent call that triggered
+** the authorizer will fail with an error message.
+**
+** When the callback returns [SQLITE_OK], that means the operation
+** requested is ok. ^When the callback returns [SQLITE_DENY], the
+** [sqlite3_prepare_v2()] or equivalent call that triggered the
+** authorizer will fail with an error message explaining that
+** access is denied.
+**
+** ^The first parameter to the authorizer callback is a copy of the third
+** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
+** to the callback is an integer [SQLITE_COPY | action code] that specifies
+** the particular action to be authorized. ^The third through sixth parameters
+** to the callback are zero-terminated strings that contain additional
+** details about the action to be authorized.
+**
+** ^If the action code is [SQLITE_READ]
+** and the callback returns [SQLITE_IGNORE] then the
+** [prepared statement] statement is constructed to substitute
+** a NULL value in place of the table column that would have
+** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
+** return can be used to deny an untrusted user access to individual
+** columns of a table.
+** ^If the action code is [SQLITE_DELETE] and the callback returns
+** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
+** [truncate optimization] is disabled and all rows are deleted individually.
+**
+** An authorizer is used when [sqlite3_prepare | preparing]
+** SQL statements from an untrusted source, to ensure that the SQL statements
+** do not try to access data they are not allowed to see, or that they do not
+** try to execute malicious statements that damage the database. For
+** example, an application may allow a user to enter arbitrary
+** SQL queries for evaluation by a database. But the application does
+** not want the user to be able to make arbitrary changes to the
+** database. An authorizer could then be put in place while the
+** user-entered SQL is being [sqlite3_prepare | prepared] that
+** disallows everything except [SELECT] statements.
+**
+** Applications that need to process SQL from untrusted sources
+** might also consider lowering resource limits using [sqlite3_limit()]
+** and limiting database size using the [max_page_count] [PRAGMA]
+** in addition to using an authorizer.
+**
+** ^(Only a single authorizer can be in place on a database connection
+** at a time. Each call to sqlite3_set_authorizer overrides the
+** previous call.)^ ^Disable the authorizer by installing a NULL callback.
+** The authorizer is disabled by default.
+**
+** The authorizer callback must not do anything that will modify
+** the database connection that invoked the authorizer callback.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
+** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the
+** statement might be re-prepared during [sqlite3_step()] due to a
+** schema change. Hence, the application should ensure that the
+** correct authorizer callback remains in place during the [sqlite3_step()].
+**
+** ^Note that the authorizer callback is invoked only during
+** [sqlite3_prepare()] or its variants. Authorization is not
+** performed during statement evaluation in [sqlite3_step()], unless
+** as stated in the previous paragraph, sqlite3_step() invokes
+** sqlite3_prepare_v2() to reprepare a statement after a schema change.
+*/
+SQLITE_API int sqlite3_set_authorizer(
+ sqlite3*,
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
+ void *pUserData
+);
+
+/*
+** CAPI3REF: Authorizer Return Codes
+**
+** The [sqlite3_set_authorizer | authorizer callback function] must
+** return either [SQLITE_OK] or one of these two constants in order
+** to signal SQLite whether or not the action is permitted. See the
+** [sqlite3_set_authorizer | authorizer documentation] for additional
+** information.
+**
+** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
+** from the [sqlite3_vtab_on_conflict()] interface.
+*/
+#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
+#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
+
+/*
+** CAPI3REF: Authorizer Action Codes
+**
+** The [sqlite3_set_authorizer()] interface registers a callback function
+** that is invoked to authorize certain SQL statement actions. The
+** second parameter to the callback is an integer code that specifies
+** what action is being authorized. These are the integer action codes that
+** the authorizer callback may be passed.
+**
+** These action code values signify what kind of operation is to be
+** authorized. The 3rd and 4th parameters to the authorization
+** callback function will be parameters or NULL depending on which of these
+** codes is used as the second parameter. ^(The 5th parameter to the
+** authorizer callback is the name of the database ("main", "temp",
+** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback
+** is the name of the inner-most trigger or view that is responsible for
+** the access attempt or NULL if this access attempt is directly from
+** top-level SQL code.
+*/
+/******************************************* 3rd ************ 4th ***********/
+#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */
+#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */
+#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
+#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */
+#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
+#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */
+#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */
+#define SQLITE_CREATE_VIEW 8 /* View Name NULL */
+#define SQLITE_DELETE 9 /* Table Name NULL */
+#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */
+#define SQLITE_DROP_TABLE 11 /* Table Name NULL */
+#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */
+#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */
+#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
+#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */
+#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */
+#define SQLITE_DROP_VIEW 17 /* View Name NULL */
+#define SQLITE_INSERT 18 /* Table Name NULL */
+#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */
+#define SQLITE_READ 20 /* Table Name Column Name */
+#define SQLITE_SELECT 21 /* NULL NULL */
+#define SQLITE_TRANSACTION 22 /* Operation NULL */
+#define SQLITE_UPDATE 23 /* Table Name Column Name */
+#define SQLITE_ATTACH 24 /* Filename NULL */
+#define SQLITE_DETACH 25 /* Database Name NULL */
+#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
+#define SQLITE_REINDEX 27 /* Index Name NULL */
+#define SQLITE_ANALYZE 28 /* Table Name NULL */
+#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */
+#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
+#define SQLITE_FUNCTION 31 /* NULL Function Name */
+#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
+#define SQLITE_COPY 0 /* No longer used */
+
+/*
+** CAPI3REF: Tracing And Profiling Functions
+**
+** These routines register callback functions that can be used for
+** tracing and profiling the execution of SQL statements.
+**
+** ^The callback function registered by sqlite3_trace() is invoked at
+** various times when an SQL statement is being run by [sqlite3_step()].
+** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the
+** SQL statement text as the statement first begins executing.
+** ^(Additional sqlite3_trace() callbacks might occur
+** as each triggered subprogram is entered. The callbacks for triggers
+** contain a UTF-8 SQL comment that identifies the trigger.)^
+**
+** ^The callback function registered by sqlite3_profile() is invoked
+** as each SQL statement finishes. ^The profile callback contains
+** the original statement text and an estimate of wall-clock time
+** of how long that statement took to run. ^The profile callback
+** time is in units of nanoseconds, however the current implementation
+** is only capable of millisecond resolution so the six least significant
+** digits in the time are meaningless. Future versions of SQLite
+** might provide greater resolution on the profiler callback. The
+** sqlite3_profile() function is considered experimental and is
+** subject to change in future versions of SQLite.
+*/
+SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
+ void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
+
+/*
+** CAPI3REF: Query Progress Callbacks
+**
+** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
+** function X to be invoked periodically during long running calls to
+** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for
+** database connection D. An example use for this
+** interface is to keep a GUI updated during a large query.
+**
+** ^The parameter P is passed through as the only parameter to the
+** callback function X. ^The parameter N is the number of
+** [virtual machine instructions] that are evaluated between successive
+** invocations of the callback X.
+**
+** ^Only a single progress handler may be defined at one time per
+** [database connection]; setting a new progress handler cancels the
+** old one. ^Setting parameter X to NULL disables the progress handler.
+** ^The progress handler is also disabled by setting N to a value less
+** than 1.
+**
+** ^If the progress callback returns non-zero, the operation is
+** interrupted. This feature can be used to implement a
+** "Cancel" button on a GUI progress dialog box.
+**
+** The progress handler callback must not do anything that will modify
+** the database connection that invoked the progress handler.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
+*/
+SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+
+/*
+** CAPI3REF: Opening A New Database Connection
+**
+** ^These routines open an SQLite database file as specified by the
+** filename argument. ^The filename argument is interpreted as UTF-8 for
+** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
+** order for sqlite3_open16(). ^(A [database connection] handle is usually
+** returned in *ppDb, even if an error occurs. The only exception is that
+** if SQLite is unable to allocate memory to hold the [sqlite3] object,
+** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
+** object.)^ ^(If the database is opened (and/or created) successfully, then
+** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The
+** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain
+** an English language description of the error following a failure of any
+** of the sqlite3_open() routines.
+**
+** ^The default encoding for the database will be UTF-8 if
+** sqlite3_open() or sqlite3_open_v2() is called and
+** UTF-16 in the native byte order if sqlite3_open16() is used.
+**
+** Whether or not an error occurs when it is opened, resources
+** associated with the [database connection] handle should be released by
+** passing it to [sqlite3_close()] when it is no longer required.
+**
+** The sqlite3_open_v2() interface works like sqlite3_open()
+** except that it accepts two additional parameters for additional control
+** over the new database connection. ^(The flags parameter to
+** sqlite3_open_v2() can take one of
+** the following three values, optionally combined with the
+** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
+** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
+**
+** <dl>
+** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
+** <dd>The database is opened in read-only mode. If the database does not
+** already exist, an error is returned.</dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_READWRITE]</dt>
+** <dd>The database is opened for reading and writing if possible, or reading
+** only if the file is write protected by the operating system. In either
+** case the database must already exist, otherwise an error is returned.</dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
+** <dd>The database is opened for reading and writing, and is created if
+** it does not already exist. This is the behavior that is always used for
+** sqlite3_open() and sqlite3_open16().</dd>)^
+** </dl>
+**
+** If the 3rd parameter to sqlite3_open_v2() is not one of the
+** combinations shown above optionally combined with other
+** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
+** then the behavior is undefined.
+**
+** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
+** opens in the multi-thread [threading mode] as long as the single-thread
+** mode has not been set at compile-time or start-time. ^If the
+** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
+** in the serialized [threading mode] unless single-thread was
+** previously selected at compile-time or start-time.
+** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
+** eligible to use [shared cache mode], regardless of whether or not shared
+** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
+** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
+** participate in [shared cache mode] even if it is enabled.
+**
+** ^The fourth parameter to sqlite3_open_v2() is the name of the
+** [sqlite3_vfs] object that defines the operating system interface that
+** the new database connection should use. ^If the fourth parameter is
+** a NULL pointer then the default [sqlite3_vfs] object is used.
+**
+** ^If the filename is ":memory:", then a private, temporary in-memory database
+** is created for the connection. ^This in-memory database will vanish when
+** the database connection is closed. Future versions of SQLite might
+** make use of additional special filenames that begin with the ":" character.
+** It is recommended that when a database filename actually does begin with
+** a ":" character you should prefix the filename with a pathname such as
+** "./" to avoid ambiguity.
+**
+** ^If the filename is an empty string, then a private, temporary
+** on-disk database will be created. ^This private database will be
+** automatically deleted as soon as the database connection is closed.
+**
+** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
+**
+** ^If [URI filename] interpretation is enabled, and the filename argument
+** begins with "file:", then the filename is interpreted as a URI. ^URI
+** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
+** set in the fourth argument to sqlite3_open_v2(), or if it has
+** been enabled globally using the [SQLITE_CONFIG_URI] option with the
+** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
+** As of SQLite version 3.7.7, URI filename interpretation is turned off
+** by default, but future releases of SQLite might enable URI filename
+** interpretation by default. See "[URI filenames]" for additional
+** information.
+**
+** URI filenames are parsed according to RFC 3986. ^If the URI contains an
+** authority, then it must be either an empty string or the string
+** "localhost". ^If the authority is not an empty string or "localhost", an
+** error is returned to the caller. ^The fragment component of a URI, if
+** present, is ignored.
+**
+** ^SQLite uses the path component of the URI as the name of the disk file
+** which contains the database. ^If the path begins with a '/' character,
+** then it is interpreted as an absolute path. ^If the path does not begin
+** with a '/' (meaning that the authority section is omitted from the URI)
+** then the path is interpreted as a relative path.
+** ^On windows, the first component of an absolute path
+** is a drive specification (e.g. "C:").
+**
+** [[core URI query parameters]]
+** The query component of a URI may contain parameters that are interpreted
+** either by SQLite itself, or by a [VFS | custom VFS implementation].
+** SQLite interprets the following three query parameters:
+**
+** <ul>
+** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
+** a VFS object that provides the operating system interface that should
+** be used to access the database file on disk. ^If this option is set to
+** an empty string the default VFS object is used. ^Specifying an unknown
+** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
+** present, then the VFS specified by the option takes precedence over
+** the value passed as the fourth parameter to sqlite3_open_v2().
+**
+** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
+** "rwc", or "memory". Attempting to set it to any other value is
+** an error)^.
+** ^If "ro" is specified, then the database is opened for read-only
+** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
+** third argument to sqlite3_open_v2(). ^If the mode option is set to
+** "rw", then the database is opened for read-write (but not create)
+** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
+** been set. ^Value "rwc" is equivalent to setting both
+** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is
+** set to "memory" then a pure [in-memory database] that never reads
+** or writes from disk is used. ^It is an error to specify a value for
+** the mode parameter that is less restrictive than that specified by
+** the flags passed in the third parameter to sqlite3_open_v2().
+**
+** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
+** "private". ^Setting it to "shared" is equivalent to setting the
+** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
+** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
+** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
+** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
+** a URI filename, its value overrides any behavior requested by setting
+** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+** </ul>
+**
+** ^Specifying an unknown parameter in the query component of a URI is not an
+** error. Future versions of SQLite might understand additional query
+** parameters. See "[query parameters with special meaning to SQLite]" for
+** additional information.
+**
+** [[URI filename examples]] <h3>URI filename examples</h3>
+**
+** <table border="1" align=center cellpadding=5>
+** <tr><th> URI filenames <th> Results
+** <tr><td> file:data.db <td>
+** Open the file "data.db" in the current directory.
+** <tr><td> file:/home/fred/data.db<br>
+** file:///home/fred/data.db <br>
+** file://localhost/home/fred/data.db <br> <td>
+** Open the database file "/home/fred/data.db".
+** <tr><td> file://darkstar/home/fred/data.db <td>
+** An error. "darkstar" is not a recognized authority.
+** <tr><td style="white-space:nowrap">
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
+** <td> Windows only: Open the file "data.db" on fred's desktop on drive
+** C:. Note that the %20 escaping in this example is not strictly
+** necessary - space characters can be used literally
+** in URI filenames.
+** <tr><td> file:data.db?mode=ro&cache=private <td>
+** Open file "data.db" in the current directory for read-only access.
+** Regardless of whether or not shared-cache mode is enabled by
+** default, use a private cache.
+** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
+** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+** <tr><td> file:data.db?mode=readonly <td>
+** An error. "readonly" is not a valid option for the "mode" parameter.
+** </table>
+**
+** ^URI hexadecimal escape sequences (%HH) are supported within the path and
+** query components of a URI. A hexadecimal escape sequence consists of a
+** percent sign - "%" - followed by exactly two hexadecimal digits
+** specifying an octet value. ^Before the path or query components of a
+** URI filename are interpreted, they are encoded using UTF-8 and all
+** hexadecimal escape sequences replaced by a single byte containing the
+** corresponding octet. If this process generates an invalid UTF-8 encoding,
+** the results are undefined.
+**
+** <b>Note to Windows users:</b> The encoding used for the filename argument
+** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
+** codepage is currently defined. Filenames containing international
+** characters must be converted to UTF-8 prior to passing them into
+** sqlite3_open() or sqlite3_open_v2().
+**
+** <b>Note to Windows Runtime users:</b> The temporary directory must be set
+** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various
+** features that require the use of temporary files may fail.
+**
+** See also: [sqlite3_temp_directory]
+*/
+SQLITE_API int sqlite3_open(
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
+);
+SQLITE_API int sqlite3_open16(
+ const void *filename, /* Database filename (UTF-16) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
+);
+SQLITE_API int sqlite3_open_v2(
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb, /* OUT: SQLite db handle */
+ int flags, /* Flags */
+ const char *zVfs /* Name of VFS module to use */
+);
+
+/*
+** CAPI3REF: Obtain Values For URI Parameters
+**
+** These are utility routines, useful to VFS implementations, that check
+** to see if a database file was a URI that contained a specific query
+** parameter, and if so obtains the value of that query parameter.
+**
+** If F is the database filename pointer passed into the xOpen() method of
+** a VFS implementation when the flags parameter to xOpen() has one or
+** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
+** P is the name of the query parameter, then
+** sqlite3_uri_parameter(F,P) returns the value of the P
+** parameter if it exists or a NULL pointer if P does not appear as a
+** query parameter on F. If P is a query parameter of F
+** has no explicit value, then sqlite3_uri_parameter(F,P) returns
+** a pointer to an empty string.
+**
+** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
+** parameter and returns true (1) or false (0) according to the value
+** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
+** value of query parameter P is one of "yes", "true", or "on" in any
+** case or if the value begins with a non-zero number. The
+** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
+** query parameter P is one of "no", "false", or "off" in any case or
+** if the value begins with a numeric zero. If P is not a query
+** parameter on F or if the value of P is does not match any of the
+** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
+**
+** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
+** 64-bit signed integer and returns that integer, or D if P does not
+** exist. If the value of P is something other than an integer, then
+** zero is returned.
+**
+** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
+** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
+** is not a database file pathname pointer that SQLite passed into the xOpen
+** VFS method, then the behavior of this routine is undefined and probably
+** undesirable.
+*/
+SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
+SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+
+
+/*
+** CAPI3REF: Error Codes And Messages
+**
+** ^The sqlite3_errcode() interface returns the numeric [result code] or
+** [extended result code] for the most recent failed sqlite3_* API call
+** associated with a [database connection]. If a prior API call failed
+** but the most recent API call succeeded, the return value from
+** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
+** interface is the same except that it always returns the
+** [extended result code] even when extended result codes are
+** disabled.
+**
+** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
+** text that describes the error, as either UTF-8 or UTF-16 respectively.
+** ^(Memory to hold the error message string is managed internally.
+** The application does not need to worry about freeing the result.
+** However, the error string might be overwritten or deallocated by
+** subsequent calls to other SQLite interface functions.)^
+**
+** ^The sqlite3_errstr() interface returns the English-language text
+** that describes the [result code], as UTF-8.
+** ^(Memory to hold the error message string is managed internally
+** and must not be freed by the application)^.
+**
+** When the serialized [threading mode] is in use, it might be the
+** case that a second error occurs on a separate thread in between
+** the time of the first error and the call to these interfaces.
+** When that happens, the second error will be reported since these
+** interfaces always report the most recent result. To avoid
+** this, each thread can obtain exclusive use of the [database connection] D
+** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
+** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
+** all calls to the interfaces listed here are completed.
+**
+** If an interface fails with SQLITE_MISUSE, that means the interface
+** was invoked incorrectly by the application. In that case, the
+** error code and message may or may not be set.
+*/
+SQLITE_API int sqlite3_errcode(sqlite3 *db);
+SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
+SQLITE_API const char *sqlite3_errmsg(sqlite3*);
+SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errstr(int);
+
+/*
+** CAPI3REF: SQL Statement Object
+** KEYWORDS: {prepared statement} {prepared statements}
+**
+** An instance of this object represents a single SQL statement.
+** This object is variously known as a "prepared statement" or a
+** "compiled SQL statement" or simply as a "statement".
+**
+** The life of a statement object goes something like this:
+**
+** <ol>
+** <li> Create the object using [sqlite3_prepare_v2()] or a related
+** function.
+** <li> Bind values to [host parameters] using the sqlite3_bind_*()
+** interfaces.
+** <li> Run the SQL by calling [sqlite3_step()] one or more times.
+** <li> Reset the statement using [sqlite3_reset()] then go back
+** to step 2. Do this zero or more times.
+** <li> Destroy the object using [sqlite3_finalize()].
+** </ol>
+**
+** Refer to documentation on individual methods above for additional
+** information.
+*/
+typedef struct sqlite3_stmt sqlite3_stmt;
+
+/*
+** CAPI3REF: Run-time Limits
+**
+** ^(This interface allows the size of various constructs to be limited
+** on a connection by connection basis. The first parameter is the
+** [database connection] whose limit is to be set or queried. The
+** second parameter is one of the [limit categories] that define a
+** class of constructs to be size limited. The third parameter is the
+** new limit for that construct.)^
+**
+** ^If the new limit is a negative number, the limit is unchanged.
+** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a
+** [limits | hard upper bound]
+** set at compile-time by a C preprocessor macro called
+** [limits | SQLITE_MAX_<i>NAME</i>].
+** (The "_LIMIT_" in the name is changed to "_MAX_".))^
+** ^Attempts to increase a limit above its hard upper bound are
+** silently truncated to the hard upper bound.
+**
+** ^Regardless of whether or not the limit was changed, the
+** [sqlite3_limit()] interface returns the prior value of the limit.
+** ^Hence, to find the current value of a limit without changing it,
+** simply invoke this interface with the third parameter set to -1.
+**
+** Run-time limits are intended for use in applications that manage
+** both their own internal database and also databases that are controlled
+** by untrusted external sources. An example application might be a
+** web browser that has its own databases for storing history and
+** separate databases controlled by JavaScript applications downloaded
+** off the Internet. The internal databases can be given the
+** large, default limits. Databases managed by external sources can
+** be given much smaller limits designed to prevent a denial of service
+** attack. Developers might also want to use the [sqlite3_set_authorizer()]
+** interface to further control untrusted SQL. The size of the database
+** created by an untrusted script can be contained using the
+** [max_page_count] [PRAGMA].
+**
+** New run-time limit categories may be added in future releases.
+*/
+SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
+
+/*
+** CAPI3REF: Run-Time Limit Categories
+** KEYWORDS: {limit category} {*limit categories}
+**
+** These constants define various performance limits
+** that can be lowered at run-time using [sqlite3_limit()].
+** The synopsis of the meanings of the various limits is shown below.
+** Additional information is available at [limits | Limits in SQLite].
+**
+** <dl>
+** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
+** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
+**
+** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
+** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
+**
+** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
+** <dd>The maximum number of columns in a table definition or in the
+** result set of a [SELECT] or the maximum number of columns in an index
+** or in an ORDER BY or GROUP BY clause.</dd>)^
+**
+** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
+** <dd>The maximum depth of the parse tree on any expression.</dd>)^
+**
+** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
+** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
+**
+** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
+** <dd>The maximum number of instructions in a virtual machine program
+** used to implement an SQL statement. This limit is not currently
+** enforced, though that might be added in some future release of
+** SQLite.</dd>)^
+**
+** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
+** <dd>The maximum number of arguments on a function.</dd>)^
+**
+** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
+** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
+**
+** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
+** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
+** <dd>The maximum length of the pattern argument to the [LIKE] or
+** [GLOB] operators.</dd>)^
+**
+** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
+** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
+** <dd>The maximum index number of any [parameter] in an SQL statement.)^
+**
+** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
+** <dd>The maximum depth of recursion for triggers.</dd>)^
+** </dl>
+*/
+#define SQLITE_LIMIT_LENGTH 0
+#define SQLITE_LIMIT_SQL_LENGTH 1
+#define SQLITE_LIMIT_COLUMN 2
+#define SQLITE_LIMIT_EXPR_DEPTH 3
+#define SQLITE_LIMIT_COMPOUND_SELECT 4
+#define SQLITE_LIMIT_VDBE_OP 5
+#define SQLITE_LIMIT_FUNCTION_ARG 6
+#define SQLITE_LIMIT_ATTACHED 7
+#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
+#define SQLITE_LIMIT_VARIABLE_NUMBER 9
+#define SQLITE_LIMIT_TRIGGER_DEPTH 10
+
+/*
+** CAPI3REF: Compiling An SQL Statement
+** KEYWORDS: {SQL statement compiler}
+**
+** To execute an SQL query, it must first be compiled into a byte-code
+** program using one of these routines.
+**
+** The first argument, "db", is a [database connection] obtained from a
+** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
+** [sqlite3_open16()]. The database connection must not have been closed.
+**
+** The second argument, "zSql", is the statement to be compiled, encoded
+** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
+** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
+** use UTF-16.
+**
+** ^If the nByte argument is less than zero, then zSql is read up to the
+** first zero terminator. ^If nByte is non-negative, then it is the maximum
+** number of bytes read from zSql. ^When nByte is non-negative, the
+** zSql string ends at either the first '\000' or '\u0000' character or
+** the nByte-th byte, whichever comes first. If the caller knows
+** that the supplied string is nul-terminated, then there is a small
+** performance advantage to be gained by passing an nByte parameter that
+** is equal to the number of bytes in the input string <i>including</i>
+** the nul-terminator bytes as this saves SQLite from having to
+** make a copy of the input string.
+**
+** ^If pzTail is not NULL then *pzTail is made to point to the first byte
+** past the end of the first SQL statement in zSql. These routines only
+** compile the first statement in zSql, so *pzTail is left pointing to
+** what remains uncompiled.
+**
+** ^*ppStmt is left pointing to a compiled [prepared statement] that can be
+** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set
+** to NULL. ^If the input text contains no SQL (if the input is an empty
+** string or a comment) then *ppStmt is set to NULL.
+** The calling procedure is responsible for deleting the compiled
+** SQL statement using [sqlite3_finalize()] after it has finished with it.
+** ppStmt may not be NULL.
+**
+** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK];
+** otherwise an [error code] is returned.
+**
+** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
+** recommended for all new programs. The two older interfaces are retained
+** for backwards compatibility, but their use is discouraged.
+** ^In the "v2" interfaces, the prepared statement
+** that is returned (the [sqlite3_stmt] object) contains a copy of the
+** original SQL text. This causes the [sqlite3_step()] interface to
+** behave differently in three ways:
+**
+** <ol>
+** <li>
+** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it
+** always used to do, [sqlite3_step()] will automatically recompile the SQL
+** statement and try to run it again.
+** </li>
+**
+** <li>
+** ^When an error occurs, [sqlite3_step()] will return one of the detailed
+** [error codes] or [extended error codes]. ^The legacy behavior was that
+** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code
+** and the application would have to make a second call to [sqlite3_reset()]
+** in order to find the underlying cause of the problem. With the "v2" prepare
+** interfaces, the underlying reason for the error is returned immediately.
+** </li>
+**
+** <li>
+** ^If the specific value bound to [parameter | host parameter] in the
+** WHERE clause might influence the choice of query plan for a statement,
+** then the statement will be automatically recompiled, as if there had been
+** a schema change, on the first [sqlite3_step()] call following any change
+** to the [sqlite3_bind_text | bindings] of that [parameter].
+** ^The specific value of WHERE-clause [parameter] might influence the
+** choice of query plan if the parameter is the left-hand side of a [LIKE]
+** or [GLOB] operator or if the parameter is compared to an indexed column
+** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
+** the
+** </li>
+** </ol>
+*/
+SQLITE_API int sqlite3_prepare(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+SQLITE_API int sqlite3_prepare_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+SQLITE_API int sqlite3_prepare16(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+SQLITE_API int sqlite3_prepare16_v2(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+
+/*
+** CAPI3REF: Retrieving Statement SQL
+**
+** ^This interface can be used to retrieve a saved copy of the original
+** SQL text used to create a [prepared statement] if that statement was
+** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
+*/
+SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Determine If An SQL Statement Writes The Database
+**
+** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
+** and only if the [prepared statement] X makes no direct changes to
+** the content of the database file.
+**
+** Note that [application-defined SQL functions] or
+** [virtual tables] might change the database indirectly as a side effect.
+** ^(For example, if an application defines a function "eval()" that
+** calls [sqlite3_exec()], then the following SQL statement would
+** change the database file through side-effects:
+**
+** <blockquote><pre>
+** SELECT eval('DELETE FROM t1') FROM t2;
+** </pre></blockquote>
+**
+** But because the [SELECT] statement does not change the database file
+** directly, sqlite3_stmt_readonly() would still return true.)^
+**
+** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
+** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
+** since the statements themselves do not actually modify the database but
+** rather they control the timing of when other statements modify the
+** database. ^The [ATTACH] and [DETACH] statements also cause
+** sqlite3_stmt_readonly() to return true since, while those statements
+** change the configuration of a database connection, they do not make
+** changes to the content of the database files on disk.
+*/
+SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Determine If A Prepared Statement Has Been Reset
+**
+** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
+** [prepared statement] S has been stepped at least once using
+** [sqlite3_step(S)] but has not run to completion and/or has not
+** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
+** interface returns false if S is a NULL pointer. If S is not a
+** NULL pointer and is not a pointer to a valid [prepared statement]
+** object, then the behavior is undefined and probably undesirable.
+**
+** This interface can be used in combination [sqlite3_next_stmt()]
+** to locate all prepared statements associated with a database
+** connection that are in need of being reset. This can be used,
+** for example, in diagnostic routines to search for prepared
+** statements that are holding a transaction open.
+*/
+SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Dynamically Typed Value Object
+** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
+**
+** SQLite uses the sqlite3_value object to represent all values
+** that can be stored in a database table. SQLite uses dynamic typing
+** for the values it stores. ^Values stored in sqlite3_value objects
+** can be integers, floating point values, strings, BLOBs, or NULL.
+**
+** An sqlite3_value object may be either "protected" or "unprotected".
+** Some interfaces require a protected sqlite3_value. Other interfaces
+** will accept either a protected or an unprotected sqlite3_value.
+** Every interface that accepts sqlite3_value arguments specifies
+** whether or not it requires a protected sqlite3_value.
+**
+** The terms "protected" and "unprotected" refer to whether or not
+** a mutex is held. An internal mutex is held for a protected
+** sqlite3_value object but no mutex is held for an unprotected
+** sqlite3_value object. If SQLite is compiled to be single-threaded
+** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
+** or if SQLite is run in one of reduced mutex modes
+** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
+** then there is no distinction between protected and unprotected
+** sqlite3_value objects and they can be used interchangeably. However,
+** for maximum code portability it is recommended that applications
+** still make the distinction between protected and unprotected
+** sqlite3_value objects even when not strictly required.
+**
+** ^The sqlite3_value objects that are passed as parameters into the
+** implementation of [application-defined SQL functions] are protected.
+** ^The sqlite3_value object returned by
+** [sqlite3_column_value()] is unprotected.
+** Unprotected sqlite3_value objects may only be used with
+** [sqlite3_result_value()] and [sqlite3_bind_value()].
+** The [sqlite3_value_blob | sqlite3_value_type()] family of
+** interfaces require protected sqlite3_value objects.
+*/
+typedef struct Mem sqlite3_value;
+
+/*
+** CAPI3REF: SQL Function Context Object
+**
+** The context in which an SQL function executes is stored in an
+** sqlite3_context object. ^A pointer to an sqlite3_context object
+** is always first parameter to [application-defined SQL functions].
+** The application-defined SQL function implementation will pass this
+** pointer through into calls to [sqlite3_result_int | sqlite3_result()],
+** [sqlite3_aggregate_context()], [sqlite3_user_data()],
+** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()],
+** and/or [sqlite3_set_auxdata()].
+*/
+typedef struct sqlite3_context sqlite3_context;
+
+/*
+** CAPI3REF: Binding Values To Prepared Statements
+** KEYWORDS: {host parameter} {host parameters} {host parameter name}
+** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
+**
+** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
+** literals may be replaced by a [parameter] that matches one of following
+** templates:
+**
+** <ul>
+** <li> ?
+** <li> ?NNN
+** <li> :VVV
+** <li> @VVV
+** <li> $VVV
+** </ul>
+**
+** In the templates above, NNN represents an integer literal,
+** and VVV represents an alphanumeric identifier.)^ ^The values of these
+** parameters (also called "host parameter names" or "SQL parameters")
+** can be set using the sqlite3_bind_*() routines defined here.
+**
+** ^The first argument to the sqlite3_bind_*() routines is always
+** a pointer to the [sqlite3_stmt] object returned from
+** [sqlite3_prepare_v2()] or its variants.
+**
+** ^The second argument is the index of the SQL parameter to be set.
+** ^The leftmost SQL parameter has an index of 1. ^When the same named
+** SQL parameter is used more than once, second and subsequent
+** occurrences have the same index as the first occurrence.
+** ^The index for named parameters can be looked up using the
+** [sqlite3_bind_parameter_index()] API if desired. ^The index
+** for "?NNN" parameters is the value of NNN.
+** ^The NNN value must be between 1 and the [sqlite3_limit()]
+** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
+**
+** ^The third argument is the value to bind to the parameter.
+**
+** ^(In those routines that have a fourth argument, its value is the
+** number of bytes in the parameter. To be clear: the value is the
+** number of <u>bytes</u> in the value, not the number of characters.)^
+** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** is negative, then the length of the string is
+** the number of bytes up to the first zero terminator.
+** If the fourth parameter to sqlite3_bind_blob() is negative, then
+** the behavior is undefined.
+** If a non-negative fourth parameter is provided to sqlite3_bind_text()
+** or sqlite3_bind_text16() then that parameter must be the byte offset
+** where the NUL terminator would occur assuming the string were NUL
+** terminated. If any NUL characters occur at byte offsets less than
+** the value of the fourth parameter then the resulting string value will
+** contain embedded NULs. The result of expressions involving strings
+** with embedded NULs is undefined.
+**
+** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
+** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
+** string after SQLite has finished with it. ^The destructor is called
+** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
+** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
+** ^If the fifth argument is
+** the special value [SQLITE_STATIC], then SQLite assumes that the
+** information is in static, unmanaged space and does not need to be freed.
+** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
+** SQLite makes its own private copy of the data immediately, before
+** the sqlite3_bind_*() routine returns.
+**
+** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
+** is filled with zeroes. ^A zeroblob uses a fixed amount of memory
+** (just an integer to hold its size) while it is being processed.
+** Zeroblobs are intended to serve as placeholders for BLOBs whose
+** content is later written using
+** [sqlite3_blob_open | incremental BLOB I/O] routines.
+** ^A negative value for the zeroblob results in a zero-length BLOB.
+**
+** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
+** for the [prepared statement] or with a prepared statement for which
+** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
+** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_()
+** routine is passed a [prepared statement] that has been finalized, the
+** result is undefined and probably harmful.
+**
+** ^Bindings are not cleared by the [sqlite3_reset()] routine.
+** ^Unbound parameters are interpreted as NULL.
+**
+** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
+** [error code] if anything goes wrong.
+** ^[SQLITE_RANGE] is returned if the parameter
+** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails.
+**
+** See also: [sqlite3_bind_parameter_count()],
+** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
+SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
+SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
+SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
+SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
+SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
+SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
+SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+
+/*
+** CAPI3REF: Number Of SQL Parameters
+**
+** ^This routine can be used to find the number of [SQL parameters]
+** in a [prepared statement]. SQL parameters are tokens of the
+** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
+** placeholders for values that are [sqlite3_bind_blob | bound]
+** to the parameters at a later time.
+**
+** ^(This routine actually returns the index of the largest (rightmost)
+** parameter. For all forms except ?NNN, this will correspond to the
+** number of unique parameters. If parameters of the ?NNN form are used,
+** there may be gaps in the list.)^
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_name()], and
+** [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Name Of A Host Parameter
+**
+** ^The sqlite3_bind_parameter_name(P,N) interface returns
+** the name of the N-th [SQL parameter] in the [prepared statement] P.
+** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** respectively.
+** In other words, the initial ":" or "$" or "@" or "?"
+** is included as part of the name.)^
+** ^Parameters of the form "?" without a following integer have no name
+** and are referred to as "nameless" or "anonymous parameters".
+**
+** ^The first host parameter has an index of 1, not 0.
+**
+** ^If the value N is out of range or if the N-th parameter is
+** nameless, then NULL is returned. ^The returned string is
+** always in UTF-8 encoding even if the named parameter was
+** originally specified as UTF-16 in [sqlite3_prepare16()] or
+** [sqlite3_prepare16_v2()].
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_count()], and
+** [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+
+/*
+** CAPI3REF: Index Of A Parameter With A Given Name
+**
+** ^Return the index of an SQL parameter given its name. ^The
+** index value returned is suitable for use as the second
+** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero
+** is returned if no matching parameter is found. ^The parameter
+** name must be given in UTF-8 even if the original statement
+** was prepared from UTF-16 text using [sqlite3_prepare16_v2()].
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_count()], and
+** [sqlite3_bind_parameter_index()].
+*/
+SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+
+/*
+** CAPI3REF: Reset All Bindings On A Prepared Statement
+**
+** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
+** the [sqlite3_bind_blob | bindings] on a [prepared statement].
+** ^Use this routine to reset all host parameters to NULL.
+*/
+SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Number Of Columns In A Result Set
+**
+** ^Return the number of columns in the result set returned by the
+** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
+** statement that does not return data (for example an [UPDATE]).
+**
+** See also: [sqlite3_data_count()]
+*/
+SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Column Names In A Result Set
+**
+** ^These routines return the name assigned to a particular column
+** in the result set of a [SELECT] statement. ^The sqlite3_column_name()
+** interface returns a pointer to a zero-terminated UTF-8 string
+** and sqlite3_column_name16() returns a pointer to a zero-terminated
+** UTF-16 string. ^The first parameter is the [prepared statement]
+** that implements the [SELECT] statement. ^The second parameter is the
+** column number. ^The leftmost column is number 0.
+**
+** ^The returned string pointer is valid until either the [prepared statement]
+** is destroyed by [sqlite3_finalize()] or until the statement is automatically
+** reprepared by the first call to [sqlite3_step()] for a particular run
+** or until the next call to
+** sqlite3_column_name() or sqlite3_column_name16() on the same column.
+**
+** ^If sqlite3_malloc() fails during the processing of either routine
+** (for example during a conversion from UTF-8 to UTF-16) then a
+** NULL pointer is returned.
+**
+** ^The name of a result column is the value of the "AS" clause for
+** that column, if there is an AS clause. If there is no AS clause
+** then the name of the column is unspecified and may change from
+** one release of SQLite to the next.
+*/
+SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
+SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+
+/*
+** CAPI3REF: Source Of Data In A Query Result
+**
+** ^These routines provide a means to determine the database, table, and
+** table column that is the origin of a particular result column in
+** [SELECT] statement.
+** ^The name of the database or table or column can be returned as
+** either a UTF-8 or UTF-16 string. ^The _database_ routines return
+** the database name, the _table_ routines return the table name, and
+** the origin_ routines return the column name.
+** ^The returned string is valid until the [prepared statement] is destroyed
+** using [sqlite3_finalize()] or until the statement is automatically
+** reprepared by the first call to [sqlite3_step()] for a particular run
+** or until the same information is requested
+** again in a different encoding.
+**
+** ^The names returned are the original un-aliased names of the
+** database, table, and column.
+**
+** ^The first argument to these interfaces is a [prepared statement].
+** ^These functions return information about the Nth result column returned by
+** the statement, where N is the second function argument.
+** ^The left-most column is column 0 for these routines.
+**
+** ^If the Nth column returned by the statement is an expression or
+** subquery and is not a column value, then all of these functions return
+** NULL. ^These routine might also return NULL if a memory allocation error
+** occurs. ^Otherwise, they return the name of the attached database, table,
+** or column that query result column was extracted from.
+**
+** ^As with all other SQLite APIs, those whose names end with "16" return
+** UTF-16 encoded strings and the other functions return UTF-8.
+**
+** ^These APIs are only available if the library was compiled with the
+** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
+**
+** If two or more threads call one or more of these routines against the same
+** prepared statement and column at the same time then the results are
+** undefined.
+**
+** If two or more threads call one or more
+** [sqlite3_column_database_name | column metadata interfaces]
+** for the same [prepared statement] and result column
+** at the same time then the results are undefined.
+*/
+SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+
+/*
+** CAPI3REF: Declared Datatype Of A Query Result
+**
+** ^(The first parameter is a [prepared statement].
+** If this statement is a [SELECT] statement and the Nth column of the
+** returned result set of that [SELECT] is a table column (not an
+** expression or subquery) then the declared type of the table
+** column is returned.)^ ^If the Nth column of the result set is an
+** expression or subquery, then a NULL pointer is returned.
+** ^The returned string is always UTF-8 encoded.
+**
+** ^(For example, given the database schema:
+**
+** CREATE TABLE t1(c1 VARIANT);
+**
+** and the following statement to be compiled:
+**
+** SELECT c1 + 1, c1 FROM t1;
+**
+** this routine would return the string "VARIANT" for the second result
+** column (i==1), and a NULL pointer for the first result column (i==0).)^
+**
+** ^SQLite uses dynamic run-time typing. ^So just because a column
+** is declared to contain a particular type does not mean that the
+** data stored in that column is of the declared type. SQLite is
+** strongly typed, but the typing is dynamic not static. ^Type
+** is associated with individual values, not with the containers
+** used to hold those values.
+*/
+SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
+SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+
+/*
+** CAPI3REF: Evaluate An SQL Statement
+**
+** After a [prepared statement] has been prepared using either
+** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
+** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
+** must be called one or more times to evaluate the statement.
+**
+** The details of the behavior of the sqlite3_step() interface depend
+** on whether the statement was prepared using the newer "v2" interface
+** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy
+** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
+** new "v2" interface is recommended for new applications but the legacy
+** interface will continue to be supported.
+**
+** ^In the legacy interface, the return value will be either [SQLITE_BUSY],
+** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE].
+** ^With the "v2" interface, any of the other [result codes] or
+** [extended result codes] might be returned as well.
+**
+** ^[SQLITE_BUSY] means that the database engine was unable to acquire the
+** database locks it needs to do its job. ^If the statement is a [COMMIT]
+** or occurs outside of an explicit transaction, then you can retry the
+** statement. If the statement is not a [COMMIT] and occurs within an
+** explicit transaction then you should rollback the transaction before
+** continuing.
+**
+** ^[SQLITE_DONE] means that the statement has finished executing
+** successfully. sqlite3_step() should not be called again on this virtual
+** machine without first calling [sqlite3_reset()] to reset the virtual
+** machine back to its initial state.
+**
+** ^If the SQL statement being executed returns any data, then [SQLITE_ROW]
+** is returned each time a new row of data is ready for processing by the
+** caller. The values may be accessed using the [column access functions].
+** sqlite3_step() is called again to retrieve the next row of data.
+**
+** ^[SQLITE_ERROR] means that a run-time error (such as a constraint
+** violation) has occurred. sqlite3_step() should not be called again on
+** the VM. More information may be found by calling [sqlite3_errmsg()].
+** ^With the legacy interface, a more specific error code (for example,
+** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth)
+** can be obtained by calling [sqlite3_reset()] on the
+** [prepared statement]. ^In the "v2" interface,
+** the more specific error code is returned directly by sqlite3_step().
+**
+** [SQLITE_MISUSE] means that the this routine was called inappropriately.
+** Perhaps it was called on a [prepared statement] that has
+** already been [sqlite3_finalize | finalized] or on one that had
+** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could
+** be the case that the same database connection is being used by two or
+** more threads at the same moment in time.
+**
+** For all versions of SQLite up to and including 3.6.23.1, a call to
+** [sqlite3_reset()] was required after sqlite3_step() returned anything
+** other than [SQLITE_ROW] before any subsequent invocation of
+** sqlite3_step(). Failure to reset the prepared statement using
+** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
+** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began
+** calling [sqlite3_reset()] automatically in this circumstance rather
+** than returning [SQLITE_MISUSE]. This is not considered a compatibility
+** break because any application that ever receives an SQLITE_MISUSE error
+** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
+** can be used to restore the legacy behavior.
+**
+** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
+** API always returns a generic error code, [SQLITE_ERROR], following any
+** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
+** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the
+** specific [error codes] that better describes the error.
+** We admit that this is a goofy design. The problem has been fixed
+** with the "v2" interface. If you prepare all of your SQL statements
+** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead
+** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
+** then the more specific [error codes] are returned directly
+** by sqlite3_step(). The use of the "v2" interface is recommended.
+*/
+SQLITE_API int sqlite3_step(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Number of columns in a result set
+**
+** ^The sqlite3_data_count(P) interface returns the number of columns in the
+** current row of the result set of [prepared statement] P.
+** ^If prepared statement P does not have results ready to return
+** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
+** interfaces) then sqlite3_data_count(P) returns 0.
+** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
+** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
+** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P)
+** will return non-zero if previous call to [sqlite3_step](P) returned
+** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
+** where it always returns zero since each step of that multi-step
+** pragma returns 0 columns of data.
+**
+** See also: [sqlite3_column_count()]
+*/
+SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Fundamental Datatypes
+** KEYWORDS: SQLITE_TEXT
+**
+** ^(Every value in SQLite has one of five fundamental datatypes:
+**
+** <ul>
+** <li> 64-bit signed integer
+** <li> 64-bit IEEE floating point number
+** <li> string
+** <li> BLOB
+** <li> NULL
+** </ul>)^
+**
+** These constants are codes for each of those types.
+**
+** Note that the SQLITE_TEXT constant was also used in SQLite version 2
+** for a completely different meaning. Software that links against both
+** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not
+** SQLITE_TEXT.
+*/
+#define SQLITE_INTEGER 1
+#define SQLITE_FLOAT 2
+#define SQLITE_BLOB 4
+#define SQLITE_NULL 5
+#ifdef SQLITE_TEXT
+# undef SQLITE_TEXT
+#else
+# define SQLITE_TEXT 3
+#endif
+#define SQLITE3_TEXT 3
+
+/*
+** CAPI3REF: Result Values From A Query
+** KEYWORDS: {column access functions}
+**
+** These routines form the "result set" interface.
+**
+** ^These routines return information about a single column of the current
+** result row of a query. ^In every case the first argument is a pointer
+** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
+** that was returned from [sqlite3_prepare_v2()] or one of its variants)
+** and the second argument is the index of the column for which information
+** should be returned. ^The leftmost column of the result set has the index 0.
+** ^The number of columns in the result can be determined using
+** [sqlite3_column_count()].
+**
+** If the SQL statement does not currently point to a valid row, or if the
+** column index is out of range, the result is undefined.
+** These routines may only be called when the most recent call to
+** [sqlite3_step()] has returned [SQLITE_ROW] and neither
+** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently.
+** If any of these routines are called after [sqlite3_reset()] or
+** [sqlite3_finalize()] or after [sqlite3_step()] has returned
+** something other than [SQLITE_ROW], the results are undefined.
+** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()]
+** are called from a different thread while any of these routines
+** are pending, then the results are undefined.
+**
+** ^The sqlite3_column_type() routine returns the
+** [SQLITE_INTEGER | datatype code] for the initial data type
+** of the result column. ^The returned value is one of [SQLITE_INTEGER],
+** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value
+** returned by sqlite3_column_type() is only meaningful if no type
+** conversions have occurred as described below. After a type conversion,
+** the value returned by sqlite3_column_type() is undefined. Future
+** versions of SQLite may change the behavior of sqlite3_column_type()
+** following a type conversion.
+**
+** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes()
+** routine returns the number of bytes in that BLOB or string.
+** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts
+** the string to UTF-8 and then returns the number of bytes.
+** ^If the result is a numeric value then sqlite3_column_bytes() uses
+** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns
+** the number of bytes in that string.
+** ^If the result is NULL, then sqlite3_column_bytes() returns zero.
+**
+** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16()
+** routine returns the number of bytes in that BLOB or string.
+** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts
+** the string to UTF-16 and then returns the number of bytes.
+** ^If the result is a numeric value then sqlite3_column_bytes16() uses
+** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns
+** the number of bytes in that string.
+** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
+**
+** ^The values returned by [sqlite3_column_bytes()] and
+** [sqlite3_column_bytes16()] do not include the zero terminators at the end
+** of the string. ^For clarity: the values returned by
+** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
+** bytes in the string, not the number of characters.
+**
+** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
+** even empty strings, are always zero-terminated. ^The return
+** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
+**
+** ^The object returned by [sqlite3_column_value()] is an
+** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
+** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
+** If the [unprotected sqlite3_value] object returned by
+** [sqlite3_column_value()] is used in any other way, including calls
+** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
+** or [sqlite3_value_bytes()], then the behavior is undefined.
+**
+** These routines attempt to convert the value where appropriate. ^For
+** example, if the internal representation is FLOAT and a text result
+** is requested, [sqlite3_snprintf()] is used internally to perform the
+** conversion automatically. ^(The following table details the conversions
+** that are applied:
+**
+** <blockquote>
+** <table border="1">
+** <tr><th> Internal<br>Type <th> Requested<br>Type <th> Conversion
+**
+** <tr><td> NULL <td> INTEGER <td> Result is 0
+** <tr><td> NULL <td> FLOAT <td> Result is 0.0
+** <tr><td> NULL <td> TEXT <td> Result is NULL pointer
+** <tr><td> NULL <td> BLOB <td> Result is NULL pointer
+** <tr><td> INTEGER <td> FLOAT <td> Convert from integer to float
+** <tr><td> INTEGER <td> TEXT <td> ASCII rendering of the integer
+** <tr><td> INTEGER <td> BLOB <td> Same as INTEGER->TEXT
+** <tr><td> FLOAT <td> INTEGER <td> Convert from float to integer
+** <tr><td> FLOAT <td> TEXT <td> ASCII rendering of the float
+** <tr><td> FLOAT <td> BLOB <td> Same as FLOAT->TEXT
+** <tr><td> TEXT <td> INTEGER <td> Use atoi()
+** <tr><td> TEXT <td> FLOAT <td> Use atof()
+** <tr><td> TEXT <td> BLOB <td> No change
+** <tr><td> BLOB <td> INTEGER <td> Convert to TEXT then use atoi()
+** <tr><td> BLOB <td> FLOAT <td> Convert to TEXT then use atof()
+** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
+** </table>
+** </blockquote>)^
+**
+** The table above makes reference to standard C library functions atoi()
+** and atof(). SQLite does not really use these functions. It has its
+** own equivalent internal routines. The atoi() and atof() names are
+** used in the table for brevity and because they are familiar to most
+** C programmers.
+**
+** Note that when type conversions occur, pointers returned by prior
+** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
+** sqlite3_column_text16() may be invalidated.
+** Type conversions and pointer invalidations might occur
+** in the following cases:
+**
+** <ul>
+** <li> The initial content is a BLOB and sqlite3_column_text() or
+** sqlite3_column_text16() is called. A zero-terminator might
+** need to be added to the string.</li>
+** <li> The initial content is UTF-8 text and sqlite3_column_bytes16() or
+** sqlite3_column_text16() is called. The content must be converted
+** to UTF-16.</li>
+** <li> The initial content is UTF-16 text and sqlite3_column_bytes() or
+** sqlite3_column_text() is called. The content must be converted
+** to UTF-8.</li>
+** </ul>
+**
+** ^Conversions between UTF-16be and UTF-16le are always done in place and do
+** not invalidate a prior pointer, though of course the content of the buffer
+** that the prior pointer references will have been modified. Other kinds
+** of conversion are done in place when it is possible, but sometimes they
+** are not possible and in those cases prior pointers are invalidated.
+**
+** The safest and easiest to remember policy is to invoke these routines
+** in one of the following ways:
+**
+** <ul>
+** <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li>
+** <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li>
+** <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li>
+** </ul>
+**
+** In other words, you should call sqlite3_column_text(),
+** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result
+** into the desired format, then invoke sqlite3_column_bytes() or
+** sqlite3_column_bytes16() to find the size of the result. Do not mix calls
+** to sqlite3_column_text() or sqlite3_column_blob() with calls to
+** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16()
+** with calls to sqlite3_column_bytes().
+**
+** ^The pointers returned are valid until a type conversion occurs as
+** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
+** [sqlite3_finalize()] is called. ^The memory space used to hold strings
+** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
+** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
+** [sqlite3_free()].
+**
+** ^(If a memory allocation error occurs during the evaluation of any
+** of these routines, a default value is returned. The default value
+** is either the integer 0, the floating point number 0.0, or a NULL
+** pointer. Subsequent calls to [sqlite3_errcode()] will return
+** [SQLITE_NOMEM].)^
+*/
+SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
+SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
+SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+
+/*
+** CAPI3REF: Destroy A Prepared Statement Object
+**
+** ^The sqlite3_finalize() function is called to delete a [prepared statement].
+** ^If the most recent evaluation of the statement encountered no errors
+** or if the statement is never been evaluated, then sqlite3_finalize() returns
+** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
+** sqlite3_finalize(S) returns the appropriate [error code] or
+** [extended error code].
+**
+** ^The sqlite3_finalize(S) routine can be called at any point during
+** the life cycle of [prepared statement] S:
+** before statement S is ever evaluated, after
+** one or more calls to [sqlite3_reset()], or after any call
+** to [sqlite3_step()] regardless of whether or not the statement has
+** completed execution.
+**
+** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
+**
+** The application must finalize every [prepared statement] in order to avoid
+** resource leaks. It is a grievous error for the application to try to use
+** a prepared statement after it has been finalized. Any use of a prepared
+** statement after it has been finalized can result in undefined and
+** undesirable behavior such as segfaults and heap corruption.
+*/
+SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Reset A Prepared Statement Object
+**
+** The sqlite3_reset() function is called to reset a [prepared statement]
+** object back to its initial state, ready to be re-executed.
+** ^Any SQL statement variables that had values bound to them using
+** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values.
+** Use [sqlite3_clear_bindings()] to reset the bindings.
+**
+** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
+** back to the beginning of its program.
+**
+** ^If the most recent call to [sqlite3_step(S)] for the
+** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
+** or if [sqlite3_step(S)] has never before been called on S,
+** then [sqlite3_reset(S)] returns [SQLITE_OK].
+**
+** ^If the most recent call to [sqlite3_step(S)] for the
+** [prepared statement] S indicated an error, then
+** [sqlite3_reset(S)] returns an appropriate [error code].
+**
+** ^The [sqlite3_reset(S)] interface does not change the values
+** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
+*/
+SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Create Or Redefine SQL Functions
+** KEYWORDS: {function creation routines}
+** KEYWORDS: {application-defined SQL function}
+** KEYWORDS: {application-defined SQL functions}
+**
+** ^These functions (collectively known as "function creation routines")
+** are used to add SQL functions or aggregates or to redefine the behavior
+** of existing SQL functions or aggregates. The only differences between
+** these routines are the text encoding expected for
+** the second parameter (the name of the function being created)
+** and the presence or absence of a destructor callback for
+** the application data pointer.
+**
+** ^The first parameter is the [database connection] to which the SQL
+** function is to be added. ^If an application uses more than one database
+** connection then application-defined SQL functions must be added
+** to each database connection separately.
+**
+** ^The second parameter is the name of the SQL function to be created or
+** redefined. ^The length of the name is limited to 255 bytes in a UTF-8
+** representation, exclusive of the zero-terminator. ^Note that the name
+** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
+** ^Any attempt to create a function with a longer name
+** will result in [SQLITE_MISUSE] being returned.
+**
+** ^The third parameter (nArg)
+** is the number of arguments that the SQL function or
+** aggregate takes. ^If this parameter is -1, then the SQL function or
+** aggregate may take any number of arguments between 0 and the limit
+** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third
+** parameter is less than -1 or greater than 127 then the behavior is
+** undefined.
+**
+** ^The fourth parameter, eTextRep, specifies what
+** [SQLITE_UTF8 | text encoding] this SQL function prefers for
+** its parameters. Every SQL function implementation must be able to work
+** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be
+** more efficient with one encoding than another. ^An application may
+** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
+** times with the same function but with different values of eTextRep.
+** ^When multiple implementations of the same function are available, SQLite
+** will pick the one that involves the least amount of data conversion.
+** If there is only a single implementation which does not care what text
+** encoding is used, then the fourth argument should be [SQLITE_ANY].
+**
+** ^(The fifth parameter is an arbitrary pointer. The implementation of the
+** function can gain access to this pointer using [sqlite3_user_data()].)^
+**
+** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are
+** pointers to C-language functions that implement the SQL function or
+** aggregate. ^A scalar SQL function requires an implementation of the xFunc
+** callback only; NULL pointers must be passed as the xStep and xFinal
+** parameters. ^An aggregate SQL function requires an implementation of xStep
+** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing
+** SQL function or aggregate, pass NULL pointers for all three function
+** callbacks.
+**
+** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
+** then it is destructor for the application data pointer.
+** The destructor is invoked when the function is deleted, either by being
+** overloaded or when the database connection closes.)^
+** ^The destructor is also invoked if the call to
+** sqlite3_create_function_v2() fails.
+** ^When the destructor callback of the tenth parameter is invoked, it
+** is passed a single argument which is a copy of the application data
+** pointer which was the fifth parameter to sqlite3_create_function_v2().
+**
+** ^It is permitted to register multiple implementations of the same
+** functions with the same name but with either differing numbers of
+** arguments or differing preferred text encodings. ^SQLite will use
+** the implementation that most closely matches the way in which the
+** SQL function is used. ^A function implementation with a non-negative
+** nArg parameter is a better match than a function implementation with
+** a negative nArg. ^A function where the preferred text encoding
+** matches the database encoding is a better
+** match than a function where the encoding is different.
+** ^A function where the encoding difference is between UTF16le and UTF16be
+** is a closer match than a function where the encoding difference is
+** between UTF8 and UTF16.
+**
+** ^Built-in functions may be overloaded by new application-defined functions.
+**
+** ^An application-defined function is permitted to call other
+** SQLite interfaces. However, such calls must not
+** close the database connection nor finalize or reset the prepared
+** statement in which the function is running.
+*/
+SQLITE_API int sqlite3_create_function(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*)
+);
+SQLITE_API int sqlite3_create_function16(
+ sqlite3 *db,
+ const void *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*)
+);
+SQLITE_API int sqlite3_create_function_v2(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*),
+ void(*xDestroy)(void*)
+);
+
+/*
+** CAPI3REF: Text Encodings
+**
+** These constant define integer codes that represent the various
+** text encodings supported by SQLite.
+*/
+#define SQLITE_UTF8 1
+#define SQLITE_UTF16LE 2
+#define SQLITE_UTF16BE 3
+#define SQLITE_UTF16 4 /* Use native byte order */
+#define SQLITE_ANY 5 /* sqlite3_create_function only */
+#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
+
+/*
+** CAPI3REF: Deprecated Functions
+** DEPRECATED
+**
+** These functions are [deprecated]. In order to maintain
+** backwards compatibility with older code, these functions continue
+** to be supported. However, new applications should avoid
+** the use of these functions. To help encourage people to avoid
+** using these functions, we are not going to tell you what they do.
+*/
+#ifndef SQLITE_OMIT_DEPRECATED
+SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
+SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+ void*,sqlite3_int64);
+#endif
+
+/*
+** CAPI3REF: Obtaining SQL Function Parameter Values
+**
+** The C-language implementation of SQL functions and aggregates uses
+** this set of interface routines to access the parameter values on
+** the function or aggregate.
+**
+** The xFunc (for scalar functions) or xStep (for aggregates) parameters
+** to [sqlite3_create_function()] and [sqlite3_create_function16()]
+** define callbacks that implement the SQL functions and aggregates.
+** The 3rd parameter to these callbacks is an array of pointers to
+** [protected sqlite3_value] objects. There is one [sqlite3_value] object for
+** each parameter to the SQL function. These routines are used to
+** extract values from the [sqlite3_value] objects.
+**
+** These routines work only with [protected sqlite3_value] objects.
+** Any attempt to use these routines on an [unprotected sqlite3_value]
+** object results in undefined behavior.
+**
+** ^These routines work just like the corresponding [column access functions]
+** except that these routines take a single [protected sqlite3_value] object
+** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
+**
+** ^The sqlite3_value_text16() interface extracts a UTF-16 string
+** in the native byte-order of the host machine. ^The
+** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
+** extract UTF-16 strings as big-endian and little-endian respectively.
+**
+** ^(The sqlite3_value_numeric_type() interface attempts to apply
+** numeric affinity to the value. This means that an attempt is
+** made to convert the value to an integer or floating point. If
+** such a conversion is possible without loss of information (in other
+** words, if the value is a string that looks like a number)
+** then the conversion is performed. Otherwise no conversion occurs.
+** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
+**
+** Please pay particular attention to the fact that the pointer returned
+** from [sqlite3_value_blob()], [sqlite3_value_text()], or
+** [sqlite3_value_text16()] can be invalidated by a subsequent call to
+** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
+** or [sqlite3_value_text16()].
+**
+** These routines must be called from the same thread as
+** the SQL function that supplied the [sqlite3_value*] parameters.
+*/
+SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
+SQLITE_API double sqlite3_value_double(sqlite3_value*);
+SQLITE_API int sqlite3_value_int(sqlite3_value*);
+SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
+SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
+SQLITE_API int sqlite3_value_type(sqlite3_value*);
+SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
+
+/*
+** CAPI3REF: Obtain Aggregate Function Context
+**
+** Implementations of aggregate SQL functions use this
+** routine to allocate memory for storing their state.
+**
+** ^The first time the sqlite3_aggregate_context(C,N) routine is called
+** for a particular aggregate function, SQLite
+** allocates N of memory, zeroes out that memory, and returns a pointer
+** to the new memory. ^On second and subsequent calls to
+** sqlite3_aggregate_context() for the same aggregate function instance,
+** the same buffer is returned. Sqlite3_aggregate_context() is normally
+** called once for each invocation of the xStep callback and then one
+** last time when the xFinal callback is invoked. ^(When no rows match
+** an aggregate query, the xStep() callback of the aggregate function
+** implementation is never called and xFinal() is called exactly once.
+** In those cases, sqlite3_aggregate_context() might be called for the
+** first time from within xFinal().)^
+**
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
+** when first called if N is less than or equal to zero or if a memory
+** allocate error occurs.
+**
+** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
+** determined by the N parameter on first successful call. Changing the
+** value of N in subsequent call to sqlite3_aggregate_context() within
+** the same aggregate function instance will not resize the memory
+** allocation.)^ Within the xFinal callback, it is customary to set
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
+** pointless memory allocations occur.
+**
+** ^SQLite automatically frees the memory allocated by
+** sqlite3_aggregate_context() when the aggregate query concludes.
+**
+** The first parameter must be a copy of the
+** [sqlite3_context | SQL function context] that is the first parameter
+** to the xStep or xFinal callback routine that implements the aggregate
+** function.
+**
+** This routine must be called from the same thread in which
+** the aggregate SQL function is running.
+*/
+SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+
+/*
+** CAPI3REF: User Data For Functions
+**
+** ^The sqlite3_user_data() interface returns a copy of
+** the pointer that was the pUserData parameter (the 5th parameter)
+** of the [sqlite3_create_function()]
+** and [sqlite3_create_function16()] routines that originally
+** registered the application defined function.
+**
+** This routine must be called from the same thread in which
+** the application-defined function is running.
+*/
+SQLITE_API void *sqlite3_user_data(sqlite3_context*);
+
+/*
+** CAPI3REF: Database Connection For Functions
+**
+** ^The sqlite3_context_db_handle() interface returns a copy of
+** the pointer to the [database connection] (the 1st parameter)
+** of the [sqlite3_create_function()]
+** and [sqlite3_create_function16()] routines that originally
+** registered the application defined function.
+*/
+SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+
+/*
+** CAPI3REF: Function Auxiliary Data
+**
+** The following two functions may be used by scalar SQL functions to
+** associate metadata with argument values. If the same value is passed to
+** multiple invocations of the same SQL function during query execution, under
+** some circumstances the associated metadata may be preserved. This may
+** be used, for example, to add a regular-expression matching scalar
+** function. The compiled version of the regular expression is stored as
+** metadata associated with the SQL value passed as the regular expression
+** pattern. The compiled regular expression can be reused on multiple
+** invocations of the same function so that the original pattern string
+** does not need to be recompiled on each invocation.
+**
+** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
+** associated by the sqlite3_set_auxdata() function with the Nth argument
+** value to the application-defined function. ^If no metadata has been ever
+** been set for the Nth argument of the function, or if the corresponding
+** function parameter has changed since the meta-data was set,
+** then sqlite3_get_auxdata() returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata() interface saves the metadata
+** pointed to by its 3rd parameter as the metadata for the N-th
+** argument of the application-defined function. Subsequent
+** calls to sqlite3_get_auxdata() might return this data, if it has
+** not been destroyed.
+** ^If it is not NULL, SQLite will invoke the destructor
+** function given by the 4th parameter to sqlite3_set_auxdata() on
+** the metadata when the corresponding function parameter changes
+** or when the SQL statement completes, whichever comes first.
+**
+** SQLite is free to call the destructor and drop metadata on any
+** parameter of any function at any time. ^The only guarantee is that
+** the destructor will be called before the metadata is dropped.
+**
+** ^(In practice, metadata is preserved between function calls for
+** expressions that are constant at compile time. This includes literal
+** values and [parameters].)^
+**
+** These routines must be called from the same thread in which
+** the SQL function is running.
+*/
+SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
+SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+
+
+/*
+** CAPI3REF: Constants Defining Special Destructor Behavior
+**
+** These are special values for the destructor that is passed in as the
+** final argument to routines like [sqlite3_result_blob()]. ^If the destructor
+** argument is SQLITE_STATIC, it means that the content pointer is constant
+** and will never change. It does not need to be destroyed. ^The
+** SQLITE_TRANSIENT value means that the content will likely change in
+** the near future and that SQLite should make its own private copy of
+** the content before returning.
+**
+** The typedef is necessary to work around problems in certain
+** C++ compilers. See ticket #2191.
+*/
+typedef void (*sqlite3_destructor_type)(void*);
+#define SQLITE_STATIC ((sqlite3_destructor_type)0)
+#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
+
+/*
+** CAPI3REF: Setting The Result Of An SQL Function
+**
+** These routines are used by the xFunc or xFinal callbacks that
+** implement SQL functions and aggregates. See
+** [sqlite3_create_function()] and [sqlite3_create_function16()]
+** for additional information.
+**
+** These functions work very much like the [parameter binding] family of
+** functions used to bind values to host parameters in prepared statements.
+** Refer to the [SQL parameter] documentation for additional information.
+**
+** ^The sqlite3_result_blob() interface sets the result from
+** an application-defined function to be the BLOB whose content is pointed
+** to by the second parameter and which is N bytes long where N is the
+** third parameter.
+**
+** ^The sqlite3_result_zeroblob() interfaces set the result of
+** the application-defined function to be a BLOB containing all zero
+** bytes and N bytes in size, where N is the value of the 2nd parameter.
+**
+** ^The sqlite3_result_double() interface sets the result from
+** an application-defined function to be a floating point value specified
+** by its 2nd argument.
+**
+** ^The sqlite3_result_error() and sqlite3_result_error16() functions
+** cause the implemented SQL function to throw an exception.
+** ^SQLite uses the string pointed to by the
+** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
+** as the text of an error message. ^SQLite interprets the error
+** message string from sqlite3_result_error() as UTF-8. ^SQLite
+** interprets the string from sqlite3_result_error16() as UTF-16 in native
+** byte order. ^If the third parameter to sqlite3_result_error()
+** or sqlite3_result_error16() is negative then SQLite takes as the error
+** message all text up through the first zero character.
+** ^If the third parameter to sqlite3_result_error() or
+** sqlite3_result_error16() is non-negative then SQLite takes that many
+** bytes (not characters) from the 2nd parameter as the error message.
+** ^The sqlite3_result_error() and sqlite3_result_error16()
+** routines make a private copy of the error message text before
+** they return. Hence, the calling function can deallocate or
+** modify the text after they return without harm.
+** ^The sqlite3_result_error_code() function changes the error code
+** returned by SQLite as a result of an error in a function. ^By default,
+** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error()
+** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
+**
+** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
+** error indicating that a string or BLOB is too long to represent.
+**
+** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
+** error indicating that a memory allocation failed.
+**
+** ^The sqlite3_result_int() interface sets the return value
+** of the application-defined function to be the 32-bit signed integer
+** value given in the 2nd argument.
+** ^The sqlite3_result_int64() interface sets the return value
+** of the application-defined function to be the 64-bit signed integer
+** value given in the 2nd argument.
+**
+** ^The sqlite3_result_null() interface sets the return value
+** of the application-defined function to be NULL.
+**
+** ^The sqlite3_result_text(), sqlite3_result_text16(),
+** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
+** set the return value of the application-defined function to be
+** a text string which is represented as UTF-8, UTF-16 native byte order,
+** UTF-16 little endian, or UTF-16 big endian, respectively.
+** ^SQLite takes the text result from the application from
+** the 2nd parameter of the sqlite3_result_text* interfaces.
+** ^If the 3rd parameter to the sqlite3_result_text* interfaces
+** is negative, then SQLite takes result text from the 2nd parameter
+** through the first zero character.
+** ^If the 3rd parameter to the sqlite3_result_text* interfaces
+** is non-negative, then as many bytes (not characters) of the text
+** pointed to by the 2nd parameter are taken as the application-defined
+** function result. If the 3rd parameter is non-negative, then it
+** must be the byte offset into the string where the NUL terminator would
+** appear if the string where NUL terminated. If any NUL characters occur
+** in the string at a byte offset that is less than the value of the 3rd
+** parameter, then the resulting string will contain embedded NULs and the
+** result of expressions operating on strings with embedded NULs is undefined.
+** ^If the 4th parameter to the sqlite3_result_text* interfaces
+** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
+** function as the destructor on the text or BLOB result when it has
+** finished using that result.
+** ^If the 4th parameter to the sqlite3_result_text* interfaces or to
+** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite
+** assumes that the text or BLOB result is in constant space and does not
+** copy the content of the parameter nor call a destructor on the content
+** when it has finished using that result.
+** ^If the 4th parameter to the sqlite3_result_text* interfaces
+** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
+** then SQLite makes a copy of the result into space obtained from
+** from [sqlite3_malloc()] before it returns.
+**
+** ^The sqlite3_result_value() interface sets the result of
+** the application-defined function to be a copy the
+** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
+** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
+** so that the [sqlite3_value] specified in the parameter may change or
+** be deallocated after sqlite3_result_value() returns without harm.
+** ^A [protected sqlite3_value] object may always be used where an
+** [unprotected sqlite3_value] object is required, so either
+** kind of [sqlite3_value] object can be used with this interface.
+**
+** If these routines are called from within the different thread
+** than the one containing the application-defined function that received
+** the [sqlite3_context] pointer, the results are undefined.
+*/
+SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
+SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
+SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
+SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
+SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
+SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
+SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
+SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
+SQLITE_API void sqlite3_result_null(sqlite3_context*);
+SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
+SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
+
+/*
+** CAPI3REF: Define New Collating Sequences
+**
+** ^These functions add, remove, or modify a [collation] associated
+** with the [database connection] specified as the first argument.
+**
+** ^The name of the collation is a UTF-8 string
+** for sqlite3_create_collation() and sqlite3_create_collation_v2()
+** and a UTF-16 string in native byte order for sqlite3_create_collation16().
+** ^Collation names that compare equal according to [sqlite3_strnicmp()] are
+** considered to be the same name.
+**
+** ^(The third argument (eTextRep) must be one of the constants:
+** <ul>
+** <li> [SQLITE_UTF8],
+** <li> [SQLITE_UTF16LE],
+** <li> [SQLITE_UTF16BE],
+** <li> [SQLITE_UTF16], or
+** <li> [SQLITE_UTF16_ALIGNED].
+** </ul>)^
+** ^The eTextRep argument determines the encoding of strings passed
+** to the collating function callback, xCallback.
+** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
+** force strings to be UTF16 with native byte order.
+** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
+** on an even byte address.
+**
+** ^The fourth argument, pArg, is an application data pointer that is passed
+** through as the first argument to the collating function callback.
+**
+** ^The fifth argument, xCallback, is a pointer to the collating function.
+** ^Multiple collating functions can be registered using the same name but
+** with different eTextRep parameters and SQLite will use whichever
+** function requires the least amount of data transformation.
+** ^If the xCallback argument is NULL then the collating function is
+** deleted. ^When all collating functions having the same name are deleted,
+** that collation is no longer usable.
+**
+** ^The collating function callback is invoked with a copy of the pArg
+** application data pointer and with two strings in the encoding specified
+** by the eTextRep argument. The collating function must return an
+** integer that is negative, zero, or positive
+** if the first string is less than, equal to, or greater than the second,
+** respectively. A collating function must always return the same answer
+** given the same inputs. If two or more collating functions are registered
+** to the same collation name (using different eTextRep values) then all
+** must give an equivalent answer when invoked with equivalent strings.
+** The collating function must obey the following properties for all
+** strings A, B, and C:
+**
+** <ol>
+** <li> If A==B then B==A.
+** <li> If A==B and B==C then A==C.
+** <li> If A&lt;B THEN B&gt;A.
+** <li> If A&lt;B and B&lt;C then A&lt;C.
+** </ol>
+**
+** If a collating function fails any of the above constraints and that
+** collating function is registered and used, then the behavior of SQLite
+** is undefined.
+**
+** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
+** with the addition that the xDestroy callback is invoked on pArg when
+** the collating function is deleted.
+** ^Collating functions are deleted when they are overridden by later
+** calls to the collation creation functions or when the
+** [database connection] is closed using [sqlite3_close()].
+**
+** ^The xDestroy callback is <u>not</u> called if the
+** sqlite3_create_collation_v2() function fails. Applications that invoke
+** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
+** check the return code and dispose of the application data pointer
+** themselves rather than expecting SQLite to deal with it for them.
+** This is different from every other SQLite interface. The inconsistency
+** is unfortunate but cannot be changed without breaking backwards
+** compatibility.
+**
+** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
+*/
+SQLITE_API int sqlite3_create_collation(
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
+ void *pArg,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+);
+SQLITE_API int sqlite3_create_collation_v2(
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
+ void *pArg,
+ int(*xCompare)(void*,int,const void*,int,const void*),
+ void(*xDestroy)(void*)
+);
+SQLITE_API int sqlite3_create_collation16(
+ sqlite3*,
+ const void *zName,
+ int eTextRep,
+ void *pArg,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+);
+
+/*
+** CAPI3REF: Collation Needed Callbacks
+**
+** ^To avoid having to register all collation sequences before a database
+** can be used, a single callback function may be registered with the
+** [database connection] to be invoked whenever an undefined collation
+** sequence is required.
+**
+** ^If the function is registered using the sqlite3_collation_needed() API,
+** then it is passed the names of undefined collation sequences as strings
+** encoded in UTF-8. ^If sqlite3_collation_needed16() is used,
+** the names are passed as UTF-16 in machine native byte order.
+** ^A call to either function replaces the existing collation-needed callback.
+**
+** ^(When the callback is invoked, the first argument passed is a copy
+** of the second argument to sqlite3_collation_needed() or
+** sqlite3_collation_needed16(). The second argument is the database
+** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE],
+** or [SQLITE_UTF16LE], indicating the most desirable form of the collation
+** sequence function required. The fourth parameter is the name of the
+** required collation sequence.)^
+**
+** The callback function should register the desired collation using
+** [sqlite3_create_collation()], [sqlite3_create_collation16()], or
+** [sqlite3_create_collation_v2()].
+*/
+SQLITE_API int sqlite3_collation_needed(
+ sqlite3*,
+ void*,
+ void(*)(void*,sqlite3*,int eTextRep,const char*)
+);
+SQLITE_API int sqlite3_collation_needed16(
+ sqlite3*,
+ void*,
+ void(*)(void*,sqlite3*,int eTextRep,const void*)
+);
+
+#ifdef SQLITE_HAS_CODEC
+/*
+** Specify the key for an encrypted database. This routine should be
+** called right after sqlite3_open().
+**
+** The code to implement this API is not available in the public release
+** of SQLite.
+*/
+SQLITE_API int sqlite3_key(
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The key */
+);
+
+/*
+** Change the key on an open database. If the current database is not
+** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
+** database is decrypted.
+**
+** The code to implement this API is not available in the public release
+** of SQLite.
+*/
+SQLITE_API int sqlite3_rekey(
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The new key */
+);
+
+/*
+** Specify the activation key for a SEE database. Unless
+** activated, none of the SEE routines will work.
+*/
+SQLITE_API void sqlite3_activate_see(
+ const char *zPassPhrase /* Activation phrase */
+);
+#endif
+
+#ifdef SQLITE_ENABLE_CEROD
+/*
+** Specify the activation key for a CEROD database. Unless
+** activated, none of the CEROD routines will work.
+*/
+SQLITE_API void sqlite3_activate_cerod(
+ const char *zPassPhrase /* Activation phrase */
+);
+#endif
+
+/*
+** CAPI3REF: Suspend Execution For A Short Time
+**
+** The sqlite3_sleep() function causes the current thread to suspend execution
+** for at least a number of milliseconds specified in its parameter.
+**
+** If the operating system does not support sleep requests with
+** millisecond time resolution, then the time will be rounded up to
+** the nearest second. The number of milliseconds of sleep actually
+** requested from the operating system is returned.
+**
+** ^SQLite implements this interface by calling the xSleep()
+** method of the default [sqlite3_vfs] object. If the xSleep() method
+** of the default VFS is not implemented correctly, or not implemented at
+** all, then the behavior of sqlite3_sleep() may deviate from the description
+** in the previous paragraphs.
+*/
+SQLITE_API int sqlite3_sleep(int);
+
+/*
+** CAPI3REF: Name Of The Folder Holding Temporary Files
+**
+** ^(If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all temporary files
+** created by SQLite when using a built-in [sqlite3_vfs | VFS]
+** will be placed in that directory.)^ ^If this variable
+** is a NULL pointer, then SQLite performs a search for an appropriate
+** temporary file directory.
+**
+** It is not safe to read or modify this variable in more than one
+** thread at a time. It is not safe to read or modify this variable
+** if a [database connection] is being used at the same time in a separate
+** thread.
+** It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been called and that this variable remain unchanged
+** thereafter.
+**
+** ^The [temp_store_directory pragma] may modify this variable and cause
+** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
+** the [temp_store_directory pragma] always assumes that any string
+** that this variable points to is held in memory obtained from
+** [sqlite3_malloc] and the pragma may attempt to free that memory
+** using [sqlite3_free].
+** Hence, if this variable is modified directly, either it should be
+** made NULL or made to point to memory obtained from [sqlite3_malloc]
+** or else the use of the [temp_store_directory pragma] should be avoided.
+**
+** <b>Note to Windows Runtime users:</b> The temporary directory must be set
+** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
+** features that require the use of temporary files may fail. Here is an
+** example of how to do this using C++ with the Windows Runtime:
+**
+** <blockquote><pre>
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+** &nbsp; TemporaryFolder->Path->Data();
+** char zPathBuf&#91;MAX_PATH + 1&#93;;
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+** &nbsp; NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** </pre></blockquote>
+*/
+SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory;
+
+/*
+** CAPI3REF: Name Of The Folder Holding Database Files
+**
+** ^(If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all database files
+** specified with a relative pathname and created or accessed by
+** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
+** to be relative to that directory.)^ ^If this variable is a NULL
+** pointer, then SQLite assumes that all database files specified
+** with a relative pathname are relative to the current directory
+** for the process. Only the windows VFS makes use of this global
+** variable; it is ignored by the unix VFS.
+**
+** Changing the value of this variable while a database connection is
+** open can result in a corrupt database.
+**
+** It is not safe to read or modify this variable in more than one
+** thread at a time. It is not safe to read or modify this variable
+** if a [database connection] is being used at the same time in a separate
+** thread.
+** It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been called and that this variable remain unchanged
+** thereafter.
+**
+** ^The [data_store_directory pragma] may modify this variable and cause
+** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
+** the [data_store_directory pragma] always assumes that any string
+** that this variable points to is held in memory obtained from
+** [sqlite3_malloc] and the pragma may attempt to free that memory
+** using [sqlite3_free].
+** Hence, if this variable is modified directly, either it should be
+** made NULL or made to point to memory obtained from [sqlite3_malloc]
+** or else the use of the [data_store_directory pragma] should be avoided.
+*/
+SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
+
+/*
+** CAPI3REF: Test For Auto-Commit Mode
+** KEYWORDS: {autocommit mode}
+**
+** ^The sqlite3_get_autocommit() interface returns non-zero or
+** zero if the given database connection is or is not in autocommit mode,
+** respectively. ^Autocommit mode is on by default.
+** ^Autocommit mode is disabled by a [BEGIN] statement.
+** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK].
+**
+** If certain kinds of errors occur on a statement within a multi-statement
+** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR],
+** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the
+** transaction might be rolled back automatically. The only way to
+** find out whether SQLite automatically rolled back the transaction after
+** an error is to use this function.
+**
+** If another thread changes the autocommit status of the database
+** connection while this routine is running, then the return value
+** is undefined.
+*/
+SQLITE_API int sqlite3_get_autocommit(sqlite3*);
+
+/*
+** CAPI3REF: Find The Database Handle Of A Prepared Statement
+**
+** ^The sqlite3_db_handle interface returns the [database connection] handle
+** to which a [prepared statement] belongs. ^The [database connection]
+** returned by sqlite3_db_handle is the same [database connection]
+** that was the first argument
+** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
+** create the statement in the first place.
+*/
+SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Return The Filename For A Database Connection
+**
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
+** associated with database N of connection D. ^The main database file
+** has the name "main". If there is no attached database N on the database
+** connection D, or if database N is a temporary or in-memory database, then
+** a NULL pointer is returned.
+**
+** ^The filename returned by this function is the output of the
+** xFullPathname method of the [VFS]. ^In other words, the filename
+** will be an absolute pathname, even if the filename used
+** to open the database originally was a URI or relative pathname.
+*/
+SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+
+/*
+** CAPI3REF: Determine if a database is read-only
+**
+** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
+** of connection D is read-only, 0 if it is read/write, or -1 if N is not
+** the name of a database on connection D.
+*/
+SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
+
+/*
+** CAPI3REF: Find the next prepared statement
+**
+** ^This interface returns a pointer to the next [prepared statement] after
+** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
+** then this interface returns a pointer to the first prepared statement
+** associated with the database connection pDb. ^If no prepared statement
+** satisfies the conditions of this routine, it returns NULL.
+**
+** The [database connection] pointer D in a call to
+** [sqlite3_next_stmt(D,S)] must refer to an open database
+** connection and in particular must not be a NULL pointer.
+*/
+SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Commit And Rollback Notification Callbacks
+**
+** ^The sqlite3_commit_hook() interface registers a callback
+** function to be invoked whenever a transaction is [COMMIT | committed].
+** ^Any callback set by a previous call to sqlite3_commit_hook()
+** for the same database connection is overridden.
+** ^The sqlite3_rollback_hook() interface registers a callback
+** function to be invoked whenever a transaction is [ROLLBACK | rolled back].
+** ^Any callback set by a previous call to sqlite3_rollback_hook()
+** for the same database connection is overridden.
+** ^The pArg argument is passed through to the callback.
+** ^If the callback on a commit hook function returns non-zero,
+** then the commit is converted into a rollback.
+**
+** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions
+** return the P argument from the previous call of the same function
+** on the same [database connection] D, or NULL for
+** the first call for each function on D.
+**
+** The commit and rollback hook callbacks are not reentrant.
+** The callback implementation must not do anything that will modify
+** the database connection that invoked the callback. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the commit
+** or rollback hook in the first place.
+** Note that running any other SQL statements, including SELECT statements,
+** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify
+** the database connections for the meaning of "modify" in this paragraph.
+**
+** ^Registering a NULL function disables the callback.
+**
+** ^When the commit hook callback routine returns zero, the [COMMIT]
+** operation is allowed to continue normally. ^If the commit hook
+** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK].
+** ^The rollback hook is invoked on a rollback that results from a commit
+** hook returning non-zero, just as it would be with any other rollback.
+**
+** ^For the purposes of this API, a transaction is said to have been
+** rolled back if an explicit "ROLLBACK" statement is executed, or
+** an error or constraint causes an implicit rollback to occur.
+** ^The rollback callback is not invoked if a transaction is
+** automatically rolled back because the database connection is closed.
+**
+** See also the [sqlite3_update_hook()] interface.
+*/
+SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
+SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+
+/*
+** CAPI3REF: Data Change Notification Callbacks
+**
+** ^The sqlite3_update_hook() interface registers a callback function
+** with the [database connection] identified by the first argument
+** to be invoked whenever a row is updated, inserted or deleted.
+** ^Any callback set by a previous call to this function
+** for the same database connection is overridden.
+**
+** ^The second argument is a pointer to the function to invoke when a
+** row is updated, inserted or deleted.
+** ^The first argument to the callback is a copy of the third argument
+** to sqlite3_update_hook().
+** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
+** or [SQLITE_UPDATE], depending on the operation that caused the callback
+** to be invoked.
+** ^The third and fourth arguments to the callback contain pointers to the
+** database and table name containing the affected row.
+** ^The final callback parameter is the [rowid] of the row.
+** ^In the case of an update, this is the [rowid] after the update takes place.
+**
+** ^(The update hook is not invoked when internal system tables are
+** modified (i.e. sqlite_master and sqlite_sequence).)^
+**
+** ^In the current implementation, the update hook
+** is not invoked when duplication rows are deleted because of an
+** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
+** invoked when rows are deleted using the [truncate optimization].
+** The exceptions defined in this paragraph might change in a future
+** release of SQLite.
+**
+** The update hook implementation must not do anything that will modify
+** the database connection that invoked the update hook. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the update hook.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
+** ^The sqlite3_update_hook(D,C,P) function
+** returns the P argument from the previous call
+** on the same [database connection] D, or NULL for
+** the first call on D.
+**
+** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()]
+** interfaces.
+*/
+SQLITE_API void *sqlite3_update_hook(
+ sqlite3*,
+ void(*)(void *,int ,char const *,char const *,sqlite3_int64),
+ void*
+);
+
+/*
+** CAPI3REF: Enable Or Disable Shared Pager Cache
+**
+** ^(This routine enables or disables the sharing of the database cache
+** and schema data structures between [database connection | connections]
+** to the same database. Sharing is enabled if the argument is true
+** and disabled if the argument is false.)^
+**
+** ^Cache sharing is enabled and disabled for an entire process.
+** This is a change as of SQLite version 3.5.0. In prior versions of SQLite,
+** sharing was enabled or disabled for each thread separately.
+**
+** ^(The cache sharing mode set by this interface effects all subsequent
+** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
+** Existing database connections continue use the sharing mode
+** that was in effect at the time they were opened.)^
+**
+** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
+** successfully. An [error code] is returned otherwise.)^
+**
+** ^Shared cache is disabled by default. But this might change in
+** future releases of SQLite. Applications that care about shared
+** cache setting should set it explicitly.
+**
+** This interface is threadsafe on processors where writing a
+** 32-bit integer is atomic.
+**
+** See Also: [SQLite Shared-Cache Mode]
+*/
+SQLITE_API int sqlite3_enable_shared_cache(int);
+
+/*
+** CAPI3REF: Attempt To Free Heap Memory
+**
+** ^The sqlite3_release_memory() interface attempts to free N bytes
+** of heap memory by deallocating non-essential memory allocations
+** held by the database library. Memory used to cache database
+** pages to improve performance is an example of non-essential memory.
+** ^sqlite3_release_memory() returns the number of bytes actually freed,
+** which might be more or less than the amount requested.
+** ^The sqlite3_release_memory() routine is a no-op returning zero
+** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT].
+**
+** See also: [sqlite3_db_release_memory()]
+*/
+SQLITE_API int sqlite3_release_memory(int);
+
+/*
+** CAPI3REF: Free Memory Used By A Database Connection
+**
+** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
+** memory as possible from database connection D. Unlike the
+** [sqlite3_release_memory()] interface, this interface is effect even
+** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
+** omitted.
+**
+** See also: [sqlite3_release_memory()]
+*/
+SQLITE_API int sqlite3_db_release_memory(sqlite3*);
+
+/*
+** CAPI3REF: Impose A Limit On Heap Size
+**
+** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
+** soft limit on the amount of heap memory that may be allocated by SQLite.
+** ^SQLite strives to keep heap memory utilization below the soft heap
+** limit by reducing the number of pages held in the page cache
+** as heap memory usages approaches the limit.
+** ^The soft heap limit is "soft" because even though SQLite strives to stay
+** below the limit, it will exceed the limit rather than generate
+** an [SQLITE_NOMEM] error. In other words, the soft heap limit
+** is advisory only.
+**
+** ^The return value from sqlite3_soft_heap_limit64() is the size of
+** the soft heap limit prior to the call, or negative in the case of an
+** error. ^If the argument N is negative
+** then no change is made to the soft heap limit. Hence, the current
+** size of the soft heap limit can be determined by invoking
+** sqlite3_soft_heap_limit64() with a negative argument.
+**
+** ^If the argument N is zero then the soft heap limit is disabled.
+**
+** ^(The soft heap limit is not enforced in the current implementation
+** if one or more of following conditions are true:
+**
+** <ul>
+** <li> The soft heap limit is set to zero.
+** <li> Memory accounting is disabled using a combination of the
+** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
+** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
+** <li> An alternative page cache implementation is specified using
+** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...).
+** <li> The page cache allocates from its own memory pool supplied
+** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
+** from the heap.
+** </ul>)^
+**
+** Beginning with SQLite version 3.7.3, the soft heap limit is enforced
+** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
+** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
+** the soft heap limit is enforced on every memory allocation. Without
+** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
+** when memory is allocated by the page cache. Testing suggests that because
+** the page cache is the predominate memory user in SQLite, most
+** applications will achieve adequate soft heap limit enforcement without
+** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
+**
+** The circumstances under which SQLite will enforce the soft heap limit may
+** changes in future releases of SQLite.
+*/
+SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+
+/*
+** CAPI3REF: Deprecated Soft Heap Limit Interface
+** DEPRECATED
+**
+** This is a deprecated version of the [sqlite3_soft_heap_limit64()]
+** interface. This routine is provided for historical compatibility
+** only. All new applications should use the
+** [sqlite3_soft_heap_limit64()] interface rather than this one.
+*/
+SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
+
+
+/*
+** CAPI3REF: Extract Metadata About A Column Of A Table
+**
+** ^This routine returns metadata about a specific column of a specific
+** database table accessible using the [database connection] handle
+** passed as the first function argument.
+**
+** ^The column is identified by the second, third and fourth parameters to
+** this function. ^The second parameter is either the name of the database
+** (i.e. "main", "temp", or an attached database) containing the specified
+** table or NULL. ^If it is NULL, then all attached databases are searched
+** for the table using the same algorithm used by the database engine to
+** resolve unqualified table references.
+**
+** ^The third and fourth parameters to this function are the table and column
+** name of the desired column, respectively. Neither of these parameters
+** may be NULL.
+**
+** ^Metadata is returned by writing to the memory locations passed as the 5th
+** and subsequent parameters to this function. ^Any of these arguments may be
+** NULL, in which case the corresponding element of metadata is omitted.
+**
+** ^(<blockquote>
+** <table border="1">
+** <tr><th> Parameter <th> Output<br>Type <th> Description
+**
+** <tr><td> 5th <td> const char* <td> Data type
+** <tr><td> 6th <td> const char* <td> Name of default collation sequence
+** <tr><td> 7th <td> int <td> True if column has a NOT NULL constraint
+** <tr><td> 8th <td> int <td> True if column is part of the PRIMARY KEY
+** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
+** </table>
+** </blockquote>)^
+**
+** ^The memory pointed to by the character pointers returned for the
+** declaration type and collation sequence is valid only until the next
+** call to any SQLite API function.
+**
+** ^If the specified table is actually a view, an [error code] is returned.
+**
+** ^If the specified column is "rowid", "oid" or "_rowid_" and an
+** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
+** parameters are set for the explicitly declared column. ^(If there is no
+** explicitly declared [INTEGER PRIMARY KEY] column, then the output
+** parameters are set as follows:
+**
+** <pre>
+** data type: "INTEGER"
+** collation sequence: "BINARY"
+** not null: 0
+** primary key: 1
+** auto increment: 0
+** </pre>)^
+**
+** ^(This function may load one or more schemas from database files. If an
+** error occurs during this process, or if the requested table or column
+** cannot be found, an [error code] is returned and an error message left
+** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^
+**
+** ^This API is only available if the library was compiled with the
+** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
+*/
+SQLITE_API int sqlite3_table_column_metadata(
+ sqlite3 *db, /* Connection handle */
+ const char *zDbName, /* Database name or NULL */
+ const char *zTableName, /* Table name */
+ const char *zColumnName, /* Column name */
+ char const **pzDataType, /* OUTPUT: Declared data type */
+ char const **pzCollSeq, /* OUTPUT: Collation sequence name */
+ int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
+ int *pPrimaryKey, /* OUTPUT: True if column part of PK */
+ int *pAutoinc /* OUTPUT: True if column is auto-increment */
+);
+
+/*
+** CAPI3REF: Load An Extension
+**
+** ^This interface loads an SQLite extension library from the named file.
+**
+** ^The sqlite3_load_extension() interface attempts to load an
+** SQLite extension library contained in the file zFile.
+**
+** ^The entry point is zProc.
+** ^zProc may be 0, in which case the name of the entry point
+** defaults to "sqlite3_extension_init".
+** ^The sqlite3_load_extension() interface returns
+** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
+** ^If an error occurs and pzErrMsg is not 0, then the
+** [sqlite3_load_extension()] interface shall attempt to
+** fill *pzErrMsg with error message text stored in memory
+** obtained from [sqlite3_malloc()]. The calling function
+** should free this memory by calling [sqlite3_free()].
+**
+** ^Extension loading must be enabled using
+** [sqlite3_enable_load_extension()] prior to calling this API,
+** otherwise an error will be returned.
+**
+** See also the [load_extension() SQL function].
+*/
+SQLITE_API int sqlite3_load_extension(
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Derived from zFile if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
+);
+
+/*
+** CAPI3REF: Enable Or Disable Extension Loading
+**
+** ^So as not to open security holes in older applications that are
+** unprepared to deal with extension loading, and as a means of disabling
+** extension loading while evaluating user-entered SQL, the following API
+** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
+**
+** ^Extension loading is off by default. See ticket #1863.
+** ^Call the sqlite3_enable_load_extension() routine with onoff==1
+** to turn extension loading on and call it with onoff==0 to turn
+** it back off again.
+*/
+SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+
+/*
+** CAPI3REF: Automatically Load Statically Linked Extensions
+**
+** ^This interface causes the xEntryPoint() function to be invoked for
+** each new [database connection] that is created. The idea here is that
+** xEntryPoint() is the entry point for a statically linked SQLite extension
+** that is to be automatically loaded into all new database connections.
+**
+** ^(Even though the function prototype shows that xEntryPoint() takes
+** no arguments and returns void, SQLite invokes xEntryPoint() with three
+** arguments and expects and integer result as if the signature of the
+** entry point where as follows:
+**
+** <blockquote><pre>
+** &nbsp; int xEntryPoint(
+** &nbsp; sqlite3 *db,
+** &nbsp; const char **pzErrMsg,
+** &nbsp; const struct sqlite3_api_routines *pThunk
+** &nbsp; );
+** </pre></blockquote>)^
+**
+** If the xEntryPoint routine encounters an error, it should make *pzErrMsg
+** point to an appropriate error message (obtained from [sqlite3_mprintf()])
+** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg
+** is NULL before calling the xEntryPoint(). ^SQLite will invoke
+** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any
+** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()],
+** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail.
+**
+** ^Calling sqlite3_auto_extension(X) with an entry point X that is already
+** on the list of automatic extensions is a harmless no-op. ^No entry point
+** will be called more than once for each database connection that is opened.
+**
+** See also: [sqlite3_reset_auto_extension()].
+*/
+SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
+
+/*
+** CAPI3REF: Reset Automatic Extension Loading
+**
+** ^This interface disables all automatic extensions previously
+** registered using [sqlite3_auto_extension()].
+*/
+SQLITE_API void sqlite3_reset_auto_extension(void);
+
+/*
+** The interface to the virtual-table mechanism is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stabilizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+*/
+
+/*
+** Structures used by the virtual table interface
+*/
+typedef struct sqlite3_vtab sqlite3_vtab;
+typedef struct sqlite3_index_info sqlite3_index_info;
+typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
+typedef struct sqlite3_module sqlite3_module;
+
+/*
+** CAPI3REF: Virtual Table Object
+** KEYWORDS: sqlite3_module {virtual table module}
+**
+** This structure, sometimes called a "virtual table module",
+** defines the implementation of a [virtual tables].
+** This structure consists mostly of methods for the module.
+**
+** ^A virtual table module is created by filling in a persistent
+** instance of this structure and passing a pointer to that instance
+** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
+** ^The registration remains valid until it is replaced by a different
+** module or until the [database connection] closes. The content
+** of this structure must not change while it is registered with
+** any database connection.
+*/
+struct sqlite3_module {
+ int iVersion;
+ int (*xCreate)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xConnect)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
+ int (*xDisconnect)(sqlite3_vtab *pVTab);
+ int (*xDestroy)(sqlite3_vtab *pVTab);
+ int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
+ int (*xClose)(sqlite3_vtab_cursor*);
+ int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv);
+ int (*xNext)(sqlite3_vtab_cursor*);
+ int (*xEof)(sqlite3_vtab_cursor*);
+ int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
+ int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
+ int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
+ int (*xBegin)(sqlite3_vtab *pVTab);
+ int (*xSync)(sqlite3_vtab *pVTab);
+ int (*xCommit)(sqlite3_vtab *pVTab);
+ int (*xRollback)(sqlite3_vtab *pVTab);
+ int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
+ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+ void **ppArg);
+ int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
+ /* The methods above are in version 1 of the sqlite_module object. Those
+ ** below are for version 2 and greater. */
+ int (*xSavepoint)(sqlite3_vtab *pVTab, int);
+ int (*xRelease)(sqlite3_vtab *pVTab, int);
+ int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+};
+
+/*
+** CAPI3REF: Virtual Table Indexing Information
+** KEYWORDS: sqlite3_index_info
+**
+** The sqlite3_index_info structure and its substructures is used as part
+** of the [virtual table] interface to
+** pass information into and receive the reply from the [xBestIndex]
+** method of a [virtual table module]. The fields under **Inputs** are the
+** inputs to xBestIndex and are read-only. xBestIndex inserts its
+** results into the **Outputs** fields.
+**
+** ^(The aConstraint[] array records WHERE clause constraints of the form:
+**
+** <blockquote>column OP expr</blockquote>
+**
+** where OP is =, &lt;, &lt;=, &gt;, or &gt;=.)^ ^(The particular operator is
+** stored in aConstraint[].op using one of the
+** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^
+** ^(The index of the column is stored in
+** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the
+** expr on the right-hand side can be evaluated (and thus the constraint
+** is usable) and false if it cannot.)^
+**
+** ^The optimizer automatically inverts terms of the form "expr OP column"
+** and makes other simplifications to the WHERE clause in an attempt to
+** get as many WHERE clause terms into the form shown above as possible.
+** ^The aConstraint[] array only reports WHERE clause terms that are
+** relevant to the particular virtual table being queried.
+**
+** ^Information about the ORDER BY clause is stored in aOrderBy[].
+** ^Each term of aOrderBy records a column of the ORDER BY clause.
+**
+** The [xBestIndex] method must fill aConstraintUsage[] with information
+** about what parameters to pass to xFilter. ^If argvIndex>0 then
+** the right-hand side of the corresponding aConstraint[] is evaluated
+** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
+** is true, then the constraint is assumed to be fully handled by the
+** virtual table and is not checked again by SQLite.)^
+**
+** ^The idxNum and idxPtr values are recorded and passed into the
+** [xFilter] method.
+** ^[sqlite3_free()] is used to free idxPtr if and only if
+** needToFreeIdxPtr is true.
+**
+** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in
+** the correct order to satisfy the ORDER BY clause so that no separate
+** sorting step is required.
+**
+** ^The estimatedCost value is an estimate of the cost of doing the
+** particular lookup. A full scan of a table with N entries should have
+** a cost of N. A binary search of a table of N entries should have a
+** cost of approximately log(N).
+*/
+struct sqlite3_index_info {
+ /* Inputs */
+ int nConstraint; /* Number of entries in aConstraint */
+ struct sqlite3_index_constraint {
+ int iColumn; /* Column on left-hand side of constraint */
+ unsigned char op; /* Constraint operator */
+ unsigned char usable; /* True if this constraint is usable */
+ int iTermOffset; /* Used internally - xBestIndex should ignore */
+ } *aConstraint; /* Table of WHERE clause constraints */
+ int nOrderBy; /* Number of terms in the ORDER BY clause */
+ struct sqlite3_index_orderby {
+ int iColumn; /* Column number */
+ unsigned char desc; /* True for DESC. False for ASC. */
+ } *aOrderBy; /* The ORDER BY clause */
+ /* Outputs */
+ struct sqlite3_index_constraint_usage {
+ int argvIndex; /* if >0, constraint is part of argv to xFilter */
+ unsigned char omit; /* Do not code a test for this constraint */
+ } *aConstraintUsage;
+ int idxNum; /* Number used to identify the index */
+ char *idxStr; /* String, possibly obtained from sqlite3_malloc */
+ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
+ int orderByConsumed; /* True if output is already ordered */
+ double estimatedCost; /* Estimated cost of using this index */
+};
+
+/*
+** CAPI3REF: Virtual Table Constraint Operator Codes
+**
+** These macros defined the allowed values for the
+** [sqlite3_index_info].aConstraint[].op field. Each value represents
+** an operator that is part of a constraint term in the wHERE clause of
+** a query that uses a [virtual table].
+*/
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+
+/*
+** CAPI3REF: Register A Virtual Table Implementation
+**
+** ^These routines are used to register a new [virtual table module] name.
+** ^Module names must be registered before
+** creating a new [virtual table] using the module and before using a
+** preexisting [virtual table] for the module.
+**
+** ^The module name is registered on the [database connection] specified
+** by the first parameter. ^The name of the module is given by the
+** second parameter. ^The third parameter is a pointer to
+** the implementation of the [virtual table module]. ^The fourth
+** parameter is an arbitrary client data pointer that is passed through
+** into the [xCreate] and [xConnect] methods of the virtual table module
+** when a new virtual table is be being created or reinitialized.
+**
+** ^The sqlite3_create_module_v2() interface has a fifth parameter which
+** is a pointer to a destructor for the pClientData. ^SQLite will
+** invoke the destructor function (if it is not NULL) when SQLite
+** no longer needs the pClientData pointer. ^The destructor will also
+** be invoked if the call to sqlite3_create_module_v2() fails.
+** ^The sqlite3_create_module()
+** interface is equivalent to sqlite3_create_module_v2() with a NULL
+** destructor.
+*/
+SQLITE_API int sqlite3_create_module(
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData /* Client data for xCreate/xConnect */
+);
+SQLITE_API int sqlite3_create_module_v2(
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData, /* Client data for xCreate/xConnect */
+ void(*xDestroy)(void*) /* Module destructor function */
+);
+
+/*
+** CAPI3REF: Virtual Table Instance Object
+** KEYWORDS: sqlite3_vtab
+**
+** Every [virtual table module] implementation uses a subclass
+** of this object to describe a particular instance
+** of the [virtual table]. Each subclass will
+** be tailored to the specific needs of the module implementation.
+** The purpose of this superclass is to define certain fields that are
+** common to all module implementations.
+**
+** ^Virtual tables methods can set an error message by assigning a
+** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should
+** take care that any prior string is freed by a call to [sqlite3_free()]
+** prior to assigning a new string to zErrMsg. ^After the error message
+** is delivered up to the client application, the string will be automatically
+** freed by sqlite3_free() and the zErrMsg field will be zeroed.
+*/
+struct sqlite3_vtab {
+ const sqlite3_module *pModule; /* The module for this virtual table */
+ int nRef; /* NO LONGER USED */
+ char *zErrMsg; /* Error message from sqlite3_mprintf() */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/*
+** CAPI3REF: Virtual Table Cursor Object
+** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
+**
+** Every [virtual table module] implementation uses a subclass of the
+** following structure to describe cursors that point into the
+** [virtual table] and are used
+** to loop through the virtual table. Cursors are created using the
+** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed
+** by the [sqlite3_module.xClose | xClose] method. Cursors are used
+** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
+** of the module. Each module implementation will define
+** the content of a cursor structure to suit its own needs.
+**
+** This superclass exists in order to define fields of the cursor that
+** are common to all implementations.
+*/
+struct sqlite3_vtab_cursor {
+ sqlite3_vtab *pVtab; /* Virtual table of this cursor */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/*
+** CAPI3REF: Declare The Schema Of A Virtual Table
+**
+** ^The [xCreate] and [xConnect] methods of a
+** [virtual table module] call this interface
+** to declare the format (the names and datatypes of the columns) of
+** the virtual tables they implement.
+*/
+SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+
+/*
+** CAPI3REF: Overload A Function For A Virtual Table
+**
+** ^(Virtual tables can provide alternative implementations of functions
+** using the [xFindFunction] method of the [virtual table module].
+** But global versions of those functions
+** must exist in order to be overloaded.)^
+**
+** ^(This API makes sure a global version of a function with a particular
+** name and number of parameters exists. If no such function exists
+** before this API is called, a new function is created.)^ ^The implementation
+** of the new function always causes an exception to be thrown. So
+** the new function is not good for anything by itself. Its only
+** purpose is to be a placeholder function that can be overloaded
+** by a [virtual table].
+*/
+SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+
+/*
+** The interface to the virtual-table mechanism defined above (back up
+** to a comment remarkably similar to this one) is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stabilizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+*/
+
+/*
+** CAPI3REF: A Handle To An Open BLOB
+** KEYWORDS: {BLOB handle} {BLOB handles}
+**
+** An instance of this object represents an open BLOB on which
+** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
+** ^Objects of this type are created by [sqlite3_blob_open()]
+** and destroyed by [sqlite3_blob_close()].
+** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces
+** can be used to read or write small subsections of the BLOB.
+** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes.
+*/
+typedef struct sqlite3_blob sqlite3_blob;
+
+/*
+** CAPI3REF: Open A BLOB For Incremental I/O
+**
+** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
+** in row iRow, column zColumn, table zTable in database zDb;
+** in other words, the same BLOB that would be selected by:
+**
+** <pre>
+** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
+** </pre>)^
+**
+** ^If the flags parameter is non-zero, then the BLOB is opened for read
+** and write access. ^If it is zero, the BLOB is opened for read access.
+** ^It is not possible to open a column that is part of an index or primary
+** key for writing. ^If [foreign key constraints] are enabled, it is
+** not possible to open a column that is part of a [child key] for writing.
+**
+** ^Note that the database name is not the filename that contains
+** the database but rather the symbolic name of the database that
+** appears after the AS keyword when the database is connected using [ATTACH].
+** ^For the main database file, the database name is "main".
+** ^For TEMP tables, the database name is "temp".
+**
+** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written
+** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set
+** to be a null pointer.)^
+** ^This function sets the [database connection] error code and message
+** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related
+** functions. ^Note that the *ppBlob variable is always initialized in a
+** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob
+** regardless of the success or failure of this routine.
+**
+** ^(If the row that a BLOB handle points to is modified by an
+** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
+** then the BLOB handle is marked as "expired".
+** This is true if any column of the row is changed, even a column
+** other than the one the BLOB handle is open on.)^
+** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for
+** an expired BLOB handle fail with a return code of [SQLITE_ABORT].
+** ^(Changes written into a BLOB prior to the BLOB expiring are not
+** rolled back by the expiration of the BLOB. Such changes will eventually
+** commit if the transaction continues to completion.)^
+**
+** ^Use the [sqlite3_blob_bytes()] interface to determine the size of
+** the opened blob. ^The size of a blob may not be changed by this
+** interface. Use the [UPDATE] SQL command to change the size of a
+** blob.
+**
+** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
+** and the built-in [zeroblob] SQL function can be used, if desired,
+** to create an empty, zero-filled blob in which to read or write using
+** this interface.
+**
+** To avoid a resource leak, every open [BLOB handle] should eventually
+** be released by a call to [sqlite3_blob_close()].
+*/
+SQLITE_API int sqlite3_blob_open(
+ sqlite3*,
+ const char *zDb,
+ const char *zTable,
+ const char *zColumn,
+ sqlite3_int64 iRow,
+ int flags,
+ sqlite3_blob **ppBlob
+);
+
+/*
+** CAPI3REF: Move a BLOB Handle to a New Row
+**
+** ^This function is used to move an existing blob handle so that it points
+** to a different row of the same database table. ^The new row is identified
+** by the rowid value passed as the second argument. Only the row can be
+** changed. ^The database, table and column on which the blob handle is open
+** remain the same. Moving an existing blob handle to a new row can be
+** faster than closing the existing handle and opening a new one.
+**
+** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
+** it must exist and there must be either a blob or text value stored in
+** the nominated column.)^ ^If the new row is not present in the table, or if
+** it does not contain a blob or text value, or if another error occurs, an
+** SQLite error code is returned and the blob handle is considered aborted.
+** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or
+** [sqlite3_blob_reopen()] on an aborted blob handle immediately return
+** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle
+** always returns zero.
+**
+** ^This function sets the database handle error code and message.
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
+
+/*
+** CAPI3REF: Close A BLOB Handle
+**
+** ^Closes an open [BLOB handle].
+**
+** ^Closing a BLOB shall cause the current transaction to commit
+** if there are no other BLOBs, no pending prepared statements, and the
+** database connection is in [autocommit mode].
+** ^If any writes were made to the BLOB, they might be held in cache
+** until the close operation if they will fit.
+**
+** ^(Closing the BLOB often forces the changes
+** out to disk and so if any I/O errors occur, they will likely occur
+** at the time when the BLOB is closed. Any errors that occur during
+** closing are reported as a non-zero return value.)^
+**
+** ^(The BLOB is closed unconditionally. Even if this routine returns
+** an error code, the BLOB is still closed.)^
+**
+** ^Calling this routine with a null pointer (such as would be returned
+** by a failed call to [sqlite3_blob_open()]) is a harmless no-op.
+*/
+SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
+
+/*
+** CAPI3REF: Return The Size Of An Open BLOB
+**
+** ^Returns the size in bytes of the BLOB accessible via the
+** successfully opened [BLOB handle] in its only argument. ^The
+** incremental blob I/O routines can only read or overwriting existing
+** blob content; they cannot change the size of a blob.
+**
+** This routine only works on a [BLOB handle] which has been created
+** by a prior successful call to [sqlite3_blob_open()] and which has not
+** been closed by [sqlite3_blob_close()]. Passing any other pointer in
+** to this routine results in undefined and probably undesirable behavior.
+*/
+SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
+
+/*
+** CAPI3REF: Read Data From A BLOB Incrementally
+**
+** ^(This function is used to read data from an open [BLOB handle] into a
+** caller-supplied buffer. N bytes of data are copied into buffer Z
+** from the open BLOB, starting at offset iOffset.)^
+**
+** ^If offset iOffset is less than N bytes from the end of the BLOB,
+** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is
+** less than zero, [SQLITE_ERROR] is returned and no data is read.
+** ^The size of the blob (and hence the maximum value of N+iOffset)
+** can be determined using the [sqlite3_blob_bytes()] interface.
+**
+** ^An attempt to read from an expired [BLOB handle] fails with an
+** error code of [SQLITE_ABORT].
+**
+** ^(On success, sqlite3_blob_read() returns SQLITE_OK.
+** Otherwise, an [error code] or an [extended error code] is returned.)^
+**
+** This routine only works on a [BLOB handle] which has been created
+** by a prior successful call to [sqlite3_blob_open()] and which has not
+** been closed by [sqlite3_blob_close()]. Passing any other pointer in
+** to this routine results in undefined and probably undesirable behavior.
+**
+** See also: [sqlite3_blob_write()].
+*/
+SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
+
+/*
+** CAPI3REF: Write Data Into A BLOB Incrementally
+**
+** ^This function is used to write data into an open [BLOB handle] from a
+** caller-supplied buffer. ^N bytes of data are copied from the buffer Z
+** into the open BLOB, starting at offset iOffset.
+**
+** ^If the [BLOB handle] passed as the first argument was not opened for
+** writing (the flags parameter to [sqlite3_blob_open()] was zero),
+** this function returns [SQLITE_READONLY].
+**
+** ^This function may only modify the contents of the BLOB; it is
+** not possible to increase the size of a BLOB using this API.
+** ^If offset iOffset is less than N bytes from the end of the BLOB,
+** [SQLITE_ERROR] is returned and no data is written. ^If N is
+** less than zero [SQLITE_ERROR] is returned and no data is written.
+** The size of the BLOB (and hence the maximum value of N+iOffset)
+** can be determined using the [sqlite3_blob_bytes()] interface.
+**
+** ^An attempt to write to an expired [BLOB handle] fails with an
+** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred
+** before the [BLOB handle] expired are not rolled back by the
+** expiration of the handle, though of course those changes might
+** have been overwritten by the statement that expired the BLOB handle
+** or by other independent statements.
+**
+** ^(On success, sqlite3_blob_write() returns SQLITE_OK.
+** Otherwise, an [error code] or an [extended error code] is returned.)^
+**
+** This routine only works on a [BLOB handle] which has been created
+** by a prior successful call to [sqlite3_blob_open()] and which has not
+** been closed by [sqlite3_blob_close()]. Passing any other pointer in
+** to this routine results in undefined and probably undesirable behavior.
+**
+** See also: [sqlite3_blob_read()].
+*/
+SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
+
+/*
+** CAPI3REF: Virtual File System Objects
+**
+** A virtual filesystem (VFS) is an [sqlite3_vfs] object
+** that SQLite uses to interact
+** with the underlying operating system. Most SQLite builds come with a
+** single default VFS that is appropriate for the host computer.
+** New VFSes can be registered and existing VFSes can be unregistered.
+** The following interfaces are provided.
+**
+** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name.
+** ^Names are case sensitive.
+** ^Names are zero-terminated UTF-8 strings.
+** ^If there is no match, a NULL pointer is returned.
+** ^If zVfsName is NULL then the default VFS is returned.
+**
+** ^New VFSes are registered with sqlite3_vfs_register().
+** ^Each new VFS becomes the default VFS if the makeDflt flag is set.
+** ^The same VFS can be registered multiple times without injury.
+** ^To make an existing VFS into the default VFS, register it again
+** with the makeDflt flag set. If two different VFSes with the
+** same name are registered, the behavior is undefined. If a
+** VFS is registered with a name that is NULL or an empty string,
+** then the behavior is undefined.
+**
+** ^Unregister a VFS with the sqlite3_vfs_unregister() interface.
+** ^(If the default VFS is unregistered, another VFS is chosen as
+** the default. The choice for the new VFS is arbitrary.)^
+*/
+SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
+SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
+SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
+
+/*
+** CAPI3REF: Mutexes
+**
+** The SQLite core uses these routines for thread
+** synchronization. Though they are intended for internal
+** use by SQLite, code that links against SQLite is
+** permitted to use any of these routines.
+**
+** The SQLite source code contains multiple implementations
+** of these mutex routines. An appropriate implementation
+** is selected automatically at compile-time. ^(The following
+** implementations are available in the SQLite core:
+**
+** <ul>
+** <li> SQLITE_MUTEX_PTHREADS
+** <li> SQLITE_MUTEX_W32
+** <li> SQLITE_MUTEX_NOOP
+** </ul>)^
+**
+** ^The SQLITE_MUTEX_NOOP implementation is a set of routines
+** that does no real locking and is appropriate for use in
+** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and
+** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
+** and Windows.
+**
+** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
+** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
+** implementation is included with the library. In this case the
+** application must supply a custom mutex implementation using the
+** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
+** before calling sqlite3_initialize() or any other public sqlite3_
+** function that calls sqlite3_initialize().)^
+**
+** ^The sqlite3_mutex_alloc() routine allocates a new
+** mutex and returns a pointer to it. ^If it returns NULL
+** that means that a mutex could not be allocated. ^SQLite
+** will unwind its stack and return an error. ^(The argument
+** to sqlite3_mutex_alloc() is one of these integer constants:
+**
+** <ul>
+** <li> SQLITE_MUTEX_FAST
+** <li> SQLITE_MUTEX_RECURSIVE
+** <li> SQLITE_MUTEX_STATIC_MASTER
+** <li> SQLITE_MUTEX_STATIC_MEM
+** <li> SQLITE_MUTEX_STATIC_MEM2
+** <li> SQLITE_MUTEX_STATIC_PRNG
+** <li> SQLITE_MUTEX_STATIC_LRU
+** <li> SQLITE_MUTEX_STATIC_LRU2
+** </ul>)^
+**
+** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
+** cause sqlite3_mutex_alloc() to create
+** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
+** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
+** The mutex implementation does not need to make a distinction
+** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
+** not want to. ^SQLite will only request a recursive mutex in
+** cases where it really needs one. ^If a faster non-recursive mutex
+** implementation is available on the host platform, the mutex subsystem
+** might return such a mutex in response to SQLITE_MUTEX_FAST.
+**
+** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other
+** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
+** a pointer to a static preexisting mutex. ^Six static mutexes are
+** used by the current version of SQLite. Future versions of SQLite
+** may add additional static mutexes. Static mutexes are for internal
+** use by SQLite only. Applications that use SQLite mutexes should
+** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
+** SQLITE_MUTEX_RECURSIVE.
+**
+** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
+** returns a different mutex on every call. ^But for the static
+** mutex types, the same mutex is returned on every call that has
+** the same type number.
+**
+** ^The sqlite3_mutex_free() routine deallocates a previously
+** allocated dynamic mutex. ^SQLite is careful to deallocate every
+** dynamic mutex that it allocates. The dynamic mutexes must not be in
+** use when they are deallocated. Attempting to deallocate a static
+** mutex results in undefined behavior. ^SQLite never deallocates
+** a static mutex.
+**
+** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+** to enter a mutex. ^If another thread is already within the mutex,
+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK]
+** upon successful entry. ^(Mutexes created using
+** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread.
+** In such cases the,
+** mutex must be exited an equal number of times before another thread
+** can enter.)^ ^(If the same thread tries to enter any other
+** kind of mutex more than once, the behavior is undefined.
+** SQLite will never exhibit
+** such behavior in its own use of mutexes.)^
+**
+** ^(Some systems (for example, Windows 95) do not support the operation
+** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
+** will always return SQLITE_BUSY. The SQLite core only ever uses
+** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^
+**
+** ^The sqlite3_mutex_leave() routine exits a mutex that was
+** previously entered by the same thread. ^(The behavior
+** is undefined if the mutex is not currently entered by the
+** calling thread or is not currently allocated. SQLite will
+** never do either.)^
+**
+** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
+** sqlite3_mutex_leave() is a NULL pointer, then all three routines
+** behave as no-ops.
+**
+** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
+*/
+SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
+SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
+SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
+SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
+SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
+
+/*
+** CAPI3REF: Mutex Methods Object
+**
+** An instance of this structure defines the low-level routines
+** used to allocate and use mutexes.
+**
+** Usually, the default mutex implementations provided by SQLite are
+** sufficient, however the user has the option of substituting a custom
+** implementation for specialized deployments or systems for which SQLite
+** does not provide a suitable implementation. In this case, the user
+** creates and populates an instance of this structure to pass
+** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option.
+** Additionally, an instance of this structure can be used as an
+** output variable when querying the system for the current mutex
+** implementation, using the [SQLITE_CONFIG_GETMUTEX] option.
+**
+** ^The xMutexInit method defined by this structure is invoked as
+** part of system initialization by the sqlite3_initialize() function.
+** ^The xMutexInit routine is called by SQLite exactly once for each
+** effective call to [sqlite3_initialize()].
+**
+** ^The xMutexEnd method defined by this structure is invoked as
+** part of system shutdown by the sqlite3_shutdown() function. The
+** implementation of this method is expected to release all outstanding
+** resources obtained by the mutex methods implementation, especially
+** those obtained by the xMutexInit method. ^The xMutexEnd()
+** interface is invoked exactly once for each call to [sqlite3_shutdown()].
+**
+** ^(The remaining seven methods defined by this structure (xMutexAlloc,
+** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and
+** xMutexNotheld) implement the following interfaces (respectively):
+**
+** <ul>
+** <li> [sqlite3_mutex_alloc()] </li>
+** <li> [sqlite3_mutex_free()] </li>
+** <li> [sqlite3_mutex_enter()] </li>
+** <li> [sqlite3_mutex_try()] </li>
+** <li> [sqlite3_mutex_leave()] </li>
+** <li> [sqlite3_mutex_held()] </li>
+** <li> [sqlite3_mutex_notheld()] </li>
+** </ul>)^
+**
+** The only difference is that the public sqlite3_XXX functions enumerated
+** above silently ignore any invocations that pass a NULL pointer instead
+** of a valid mutex handle. The implementations of the methods defined
+** by this structure are not required to handle this case, the results
+** of passing a NULL pointer instead of a valid mutex handle are undefined
+** (i.e. it is acceptable to provide an implementation that segfaults if
+** it is passed a NULL pointer).
+**
+** The xMutexInit() method must be threadsafe. ^It must be harmless to
+** invoke xMutexInit() multiple times within the same process and without
+** intervening calls to xMutexEnd(). Second and subsequent calls to
+** xMutexInit() must be no-ops.
+**
+** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()]
+** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory
+** allocation for a static mutex. ^However xMutexAlloc() may use SQLite
+** memory allocation for a fast or recursive mutex.
+**
+** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is
+** called, but only if the prior call to xMutexInit returned SQLITE_OK.
+** If xMutexInit fails in any way, it is expected to clean up after itself
+** prior to returning.
+*/
+typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
+struct sqlite3_mutex_methods {
+ int (*xMutexInit)(void);
+ int (*xMutexEnd)(void);
+ sqlite3_mutex *(*xMutexAlloc)(int);
+ void (*xMutexFree)(sqlite3_mutex *);
+ void (*xMutexEnter)(sqlite3_mutex *);
+ int (*xMutexTry)(sqlite3_mutex *);
+ void (*xMutexLeave)(sqlite3_mutex *);
+ int (*xMutexHeld)(sqlite3_mutex *);
+ int (*xMutexNotheld)(sqlite3_mutex *);
+};
+
+/*
+** CAPI3REF: Mutex Verification Routines
+**
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines
+** are intended for use inside assert() statements. ^The SQLite core
+** never uses these routines except inside an assert() and applications
+** are advised to follow the lead of the core. ^The SQLite core only
+** provides implementations for these routines when it is compiled
+** with the SQLITE_DEBUG flag. ^External mutex implementations
+** are only required to provide these routines if SQLITE_DEBUG is
+** defined and if NDEBUG is not defined.
+**
+** ^These routines should return true if the mutex in their argument
+** is held or not held, respectively, by the calling thread.
+**
+** ^The implementation is not required to provide versions of these
+** routines that actually work. If the implementation does not provide working
+** versions of these routines, it should at least provide stubs that always
+** return true so that one does not get spurious assertion failures.
+**
+** ^If the argument to sqlite3_mutex_held() is a NULL pointer then
+** the routine should return 1. This seems counter-intuitive since
+** clearly the mutex cannot be held if it does not exist. But
+** the reason the mutex does not exist is because the build is not
+** using mutexes. And we do not want the assert() containing the
+** call to sqlite3_mutex_held() to fail, so a non-zero return is
+** the appropriate thing to do. ^The sqlite3_mutex_notheld()
+** interface should also return 1 when given a NULL pointer.
+*/
+#ifndef NDEBUG
+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
+SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
+#endif
+
+/*
+** CAPI3REF: Mutex Types
+**
+** The [sqlite3_mutex_alloc()] interface takes a single argument
+** which is one of these integer constants.
+**
+** The set of static mutexes may change from one SQLite release to the
+** next. Applications that override the built-in mutex logic must be
+** prepared to accommodate additional static mutexes.
+*/
+#define SQLITE_MUTEX_FAST 0
+#define SQLITE_MUTEX_RECURSIVE 1
+#define SQLITE_MUTEX_STATIC_MASTER 2
+#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
+#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
+#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
+#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
+#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
+#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
+#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
+
+/*
+** CAPI3REF: Retrieve the mutex for a database connection
+**
+** ^This interface returns a pointer the [sqlite3_mutex] object that
+** serializes access to the [database connection] given in the argument
+** when the [threading mode] is Serialized.
+** ^If the [threading mode] is Single-thread or Multi-thread then this
+** routine returns a NULL pointer.
+*/
+SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+
+/*
+** CAPI3REF: Low-Level Control Of Database Files
+**
+** ^The [sqlite3_file_control()] interface makes a direct call to the
+** xFileControl method for the [sqlite3_io_methods] object associated
+** with a particular database identified by the second argument. ^The
+** name of the database is "main" for the main database or "temp" for the
+** TEMP database, or the name that appears after the AS keyword for
+** databases that are added using the [ATTACH] SQL command.
+** ^A NULL pointer can be used in place of "main" to refer to the
+** main database file.
+** ^The third and fourth parameters to this routine
+** are passed directly through to the second and third parameters of
+** the xFileControl method. ^The return value of the xFileControl
+** method becomes the return value of this routine.
+**
+** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes
+** a pointer to the underlying [sqlite3_file] object to be written into
+** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER
+** case is a short-circuit path which does not actually invoke the
+** underlying sqlite3_io_methods.xFileControl method.
+**
+** ^If the second parameter (zDbName) does not match the name of any
+** open database file, then SQLITE_ERROR is returned. ^This error
+** code is not remembered and will not be recalled by [sqlite3_errcode()]
+** or [sqlite3_errmsg()]. The underlying xFileControl method might
+** also return SQLITE_ERROR. There is no way to distinguish between
+** an incorrect zDbName and an SQLITE_ERROR return from the underlying
+** xFileControl method.
+**
+** See also: [SQLITE_FCNTL_LOCKSTATE]
+*/
+SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+
+/*
+** CAPI3REF: Testing Interface
+**
+** ^The sqlite3_test_control() interface is used to read out internal
+** state of SQLite and to inject faults into SQLite for testing
+** purposes. ^The first parameter is an operation code that determines
+** the number, meaning, and operation of all subsequent parameters.
+**
+** This interface is not for use by applications. It exists solely
+** for verifying the correct operation of the SQLite library. Depending
+** on how the SQLite library is compiled, this interface might not exist.
+**
+** The details of the operation codes, their meanings, the parameters
+** they take, and what they do are all subject to change without notice.
+** Unlike most of the SQLite API, this function is not guaranteed to
+** operate consistently from one release to the next.
+*/
+SQLITE_API int sqlite3_test_control(int op, ...);
+
+/*
+** CAPI3REF: Testing Interface Operation Codes
+**
+** These constants are the valid operation code parameters used
+** as the first argument to [sqlite3_test_control()].
+**
+** These parameters and their meanings are subject to change
+** without notice. These values are for testing purposes only.
+** Applications should not use any of these parameters or the
+** [sqlite3_test_control()] interface.
+*/
+#define SQLITE_TESTCTRL_FIRST 5
+#define SQLITE_TESTCTRL_PRNG_SAVE 5
+#define SQLITE_TESTCTRL_PRNG_RESTORE 6
+#define SQLITE_TESTCTRL_PRNG_RESET 7
+#define SQLITE_TESTCTRL_BITVEC_TEST 8
+#define SQLITE_TESTCTRL_FAULT_INSTALL 9
+#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
+#define SQLITE_TESTCTRL_PENDING_BYTE 11
+#define SQLITE_TESTCTRL_ASSERT 12
+#define SQLITE_TESTCTRL_ALWAYS 13
+#define SQLITE_TESTCTRL_RESERVE 14
+#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
+#define SQLITE_TESTCTRL_ISKEYWORD 16
+#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
+#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
+#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
+#define SQLITE_TESTCTRL_LAST 19
+
+/*
+** CAPI3REF: SQLite Runtime Status
+**
+** ^This interface is used to retrieve runtime status information
+** about the performance of SQLite, and optionally to reset various
+** highwater marks. ^The first argument is an integer code for
+** the specific parameter to measure. ^(Recognized integer codes
+** are of the form [status parameters | SQLITE_STATUS_...].)^
+** ^The current value of the parameter is returned into *pCurrent.
+** ^The highest recorded value is returned in *pHighwater. ^If the
+** resetFlag is true, then the highest record value is reset after
+** *pHighwater is written. ^(Some parameters do not record the highest
+** value. For those parameters
+** nothing is written into *pHighwater and the resetFlag is ignored.)^
+** ^(Other parameters record only the highwater mark and not the current
+** value. For these latter parameters nothing is written into *pCurrent.)^
+**
+** ^The sqlite3_status() routine returns SQLITE_OK on success and a
+** non-zero [error code] on failure.
+**
+** This routine is threadsafe but is not atomic. This routine can be
+** called while other threads are running the same or different SQLite
+** interfaces. However the values returned in *pCurrent and
+** *pHighwater reflect the status of SQLite at different points in time
+** and it is possible that another thread might change the parameter
+** in between the times when *pCurrent and *pHighwater are written.
+**
+** See also: [sqlite3_db_status()]
+*/
+SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+
+
+/*
+** CAPI3REF: Status Parameters
+** KEYWORDS: {status parameters}
+**
+** These integer constants designate various run-time status parameters
+** that can be returned by [sqlite3_status()].
+**
+** <dl>
+** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
+** <dd>This parameter is the current amount of memory checked out
+** using [sqlite3_malloc()], either directly or indirectly. The
+** figure includes calls made to [sqlite3_malloc()] by the application
+** and internal memory usage by the SQLite library. Scratch memory
+** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
+** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
+** this parameter. The amount returned is the sum of the allocation
+** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
+**
+** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
+** internal equivalents). Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>)^
+**
+** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
+** <dd>This parameter records the number of separate memory allocations
+** currently checked out.</dd>)^
+**
+** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
+** <dd>This parameter returns the number of pages used out of the
+** [pagecache memory allocator] that was configured using
+** [SQLITE_CONFIG_PAGECACHE]. The
+** value returned is in pages, not in bytes.</dd>)^
+**
+** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
+** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
+** <dd>This parameter returns the number of bytes of page cache
+** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
+** buffer and where forced to overflow to [sqlite3_malloc()]. The
+** returned value includes allocations that overflowed because they
+** where too large (they were larger than the "sz" parameter to
+** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
+** no space was left in the page cache.</dd>)^
+**
+** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [pagecache memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>)^
+**
+** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
+** <dd>This parameter returns the number of allocations used out of the
+** [scratch memory allocator] configured using
+** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
+** in bytes. Since a single thread may only have one scratch allocation
+** outstanding at time, this parameter also reports the number of threads
+** using scratch memory at the same time.</dd>)^
+**
+** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
+** <dd>This parameter returns the number of bytes of scratch memory
+** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
+** buffer and where forced to overflow to [sqlite3_malloc()]. The values
+** returned include overflows because the requested allocation was too
+** larger (that is, because the requested allocation was larger than the
+** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
+** slots were available.
+** </dd>)^
+**
+** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [scratch memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>)^
+**
+** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
+** <dd>This parameter records the deepest parser stack. It is only
+** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
+** </dl>
+**
+** New status parameters may be added from time to time.
+*/
+#define SQLITE_STATUS_MEMORY_USED 0
+#define SQLITE_STATUS_PAGECACHE_USED 1
+#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
+#define SQLITE_STATUS_SCRATCH_USED 3
+#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
+#define SQLITE_STATUS_MALLOC_SIZE 5
+#define SQLITE_STATUS_PARSER_STACK 6
+#define SQLITE_STATUS_PAGECACHE_SIZE 7
+#define SQLITE_STATUS_SCRATCH_SIZE 8
+#define SQLITE_STATUS_MALLOC_COUNT 9
+
+/*
+** CAPI3REF: Database Connection Status
+**
+** ^This interface is used to retrieve runtime status information
+** about a single [database connection]. ^The first argument is the
+** database connection object to be interrogated. ^The second argument
+** is an integer constant, taken from the set of
+** [SQLITE_DBSTATUS options], that
+** determines the parameter to interrogate. The set of
+** [SQLITE_DBSTATUS options] is likely
+** to grow in future releases of SQLite.
+**
+** ^The current value of the requested parameter is written into *pCur
+** and the highest instantaneous value is written into *pHiwtr. ^If
+** the resetFlg is true, then the highest instantaneous value is
+** reset back down to the current value.
+**
+** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a
+** non-zero [error code] on failure.
+**
+** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
+*/
+SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters for database connections
+** KEYWORDS: {SQLITE_DBSTATUS options}
+**
+** These constants are the available integer "verbs" that can be passed as
+** the second argument to the [sqlite3_db_status()] interface.
+**
+** New verbs may be added in future releases of SQLite. Existing verbs
+** might be discontinued. Applications should check the return code from
+** [sqlite3_db_status()] to make sure that the call worked.
+** The [sqlite3_db_status()] interface will return a non-zero error code
+** if a discontinued or unsupported verb is invoked.
+**
+** <dl>
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
+** <dd>This parameter returns the number of lookaside memory slots currently
+** checked out.</dd>)^
+**
+** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
+** <dd>This parameter returns the number malloc attempts that were
+** satisfied using lookaside memory. Only the high-water value is meaningful;
+** the current value is always zero.)^
+**
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
+** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
+** <dd>This parameter returns the number malloc attempts that might have
+** been satisfied using lookaside memory but failed due to the amount of
+** memory requested being larger than the lookaside slot size.
+** Only the high-water value is meaningful;
+** the current value is always zero.)^
+**
+** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
+** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
+** <dd>This parameter returns the number malloc attempts that might have
+** been satisfied using lookaside memory but failed due to all lookaside
+** memory already being in use.
+** Only the high-water value is meaningful;
+** the current value is always zero.)^
+**
+** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
+** <dd>This parameter returns the approximate number of of bytes of heap
+** memory used by all pager caches associated with the database connection.)^
+** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
+**
+** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
+** <dd>This parameter returns the approximate number of of bytes of heap
+** memory used to store the schema for all databases associated
+** with the connection - main, temp, and any [ATTACH]-ed databases.)^
+** ^The full amount of memory used by the schemas is reported, even if the
+** schema memory is shared with other database connections due to
+** [shared cache mode] being enabled.
+** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
+**
+** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
+** <dd>This parameter returns the approximate number of of bytes of heap
+** and lookaside memory used by all prepared statements associated with
+** the database connection.)^
+** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
+** <dd>This parameter returns the number of pager cache hits that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
+** is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
+** <dd>This parameter returns the number of pager cache misses that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
+** is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
+** <dd>This parameter returns the number of dirty cache entries that have
+** been written to disk. Specifically, the number of pages written to the
+** wal file in wal mode databases, or the number of pages written to the
+** database file in rollback mode databases. Any pages written as part of
+** transaction rollback or database recovery operations are not included.
+** If an IO or other error occurs while writing a page to disk, the effect
+** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
+** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
+** </dd>
+** </dl>
+*/
+#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
+#define SQLITE_DBSTATUS_CACHE_USED 1
+#define SQLITE_DBSTATUS_SCHEMA_USED 2
+#define SQLITE_DBSTATUS_STMT_USED 3
+#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
+#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
+#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
+#define SQLITE_DBSTATUS_CACHE_HIT 7
+#define SQLITE_DBSTATUS_CACHE_MISS 8
+#define SQLITE_DBSTATUS_CACHE_WRITE 9
+#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
+
+
+/*
+** CAPI3REF: Prepared Statement Status
+**
+** ^(Each prepared statement maintains various
+** [SQLITE_STMTSTATUS counters] that measure the number
+** of times it has performed specific operations.)^ These counters can
+** be used to monitor the performance characteristics of the prepared
+** statements. For example, if the number of table steps greatly exceeds
+** the number of table searches or result rows, that would tend to indicate
+** that the prepared statement is using a full table scan rather than
+** an index.
+**
+** ^(This interface is used to retrieve and reset counter values from
+** a [prepared statement]. The first argument is the prepared statement
+** object to be interrogated. The second argument
+** is an integer code for a specific [SQLITE_STMTSTATUS counter]
+** to be interrogated.)^
+** ^The current value of the requested counter is returned.
+** ^If the resetFlg is true, then the counter is reset to zero after this
+** interface call returns.
+**
+** See also: [sqlite3_status()] and [sqlite3_db_status()].
+*/
+SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters for prepared statements
+** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
+**
+** These preprocessor macros define integer codes that name counter
+** values associated with the [sqlite3_stmt_status()] interface.
+** The meanings of the various counters are as follows:
+**
+** <dl>
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
+** <dd>^This is the number of times that SQLite has stepped forward in
+** a table as part of a full table scan. Large numbers for this counter
+** may indicate opportunities for performance improvement through
+** careful use of indices.</dd>
+**
+** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
+** <dd>^This is the number of sort operations that have occurred.
+** A non-zero value in this counter may indicate an opportunity to
+** improvement performance through careful use of indices.</dd>
+**
+** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
+** <dd>^This is the number of rows inserted into transient indices that
+** were created automatically in order to help joins run faster.
+** A non-zero value in this counter may indicate an opportunity to
+** improvement performance by adding permanent indices that do not
+** need to be reinitialized each time the statement is run.</dd>
+** </dl>
+*/
+#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
+#define SQLITE_STMTSTATUS_SORT 2
+#define SQLITE_STMTSTATUS_AUTOINDEX 3
+
+/*
+** CAPI3REF: Custom Page Cache Object
+**
+** The sqlite3_pcache type is opaque. It is implemented by
+** the pluggable module. The SQLite core has no knowledge of
+** its size or internal structure and never deals with the
+** sqlite3_pcache object except by holding and passing pointers
+** to the object.
+**
+** See [sqlite3_pcache_methods2] for additional information.
+*/
+typedef struct sqlite3_pcache sqlite3_pcache;
+
+/*
+** CAPI3REF: Custom Page Cache Object
+**
+** The sqlite3_pcache_page object represents a single page in the
+** page cache. The page cache will allocate instances of this
+** object. Various methods of the page cache use pointers to instances
+** of this object as parameters or as their return value.
+**
+** See [sqlite3_pcache_methods2] for additional information.
+*/
+typedef struct sqlite3_pcache_page sqlite3_pcache_page;
+struct sqlite3_pcache_page {
+ void *pBuf; /* The content of the page */
+ void *pExtra; /* Extra information associated with the page */
+};
+
+/*
+** CAPI3REF: Application Defined Page Cache.
+** KEYWORDS: {page cache}
+**
+** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
+** register an alternative page cache implementation by passing in an
+** instance of the sqlite3_pcache_methods2 structure.)^
+** In many applications, most of the heap memory allocated by
+** SQLite is used for the page cache.
+** By implementing a
+** custom page cache using this API, an application can better control
+** the amount of memory consumed by SQLite, the way in which
+** that memory is allocated and released, and the policies used to
+** determine exactly which parts of a database file are cached and for
+** how long.
+**
+** The alternative page cache mechanism is an
+** extreme measure that is only needed by the most demanding applications.
+** The built-in page cache is recommended for most uses.
+**
+** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an
+** internal buffer by SQLite within the call to [sqlite3_config]. Hence
+** the application may discard the parameter after the call to
+** [sqlite3_config()] returns.)^
+**
+** [[the xInit() page cache method]]
+** ^(The xInit() method is called once for each effective
+** call to [sqlite3_initialize()])^
+** (usually only once during the lifetime of the process). ^(The xInit()
+** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
+** The intent of the xInit() method is to set up global data structures
+** required by the custom page cache implementation.
+** ^(If the xInit() method is NULL, then the
+** built-in default page cache is used instead of the application defined
+** page cache.)^
+**
+** [[the xShutdown() page cache method]]
+** ^The xShutdown() method is called by [sqlite3_shutdown()].
+** It can be used to clean up
+** any outstanding resources before process shutdown, if required.
+** ^The xShutdown() method may be NULL.
+**
+** ^SQLite automatically serializes calls to the xInit method,
+** so the xInit method need not be threadsafe. ^The
+** xShutdown method is only called from [sqlite3_shutdown()] so it does
+** not need to be threadsafe either. All other methods must be threadsafe
+** in multithreaded applications.
+**
+** ^SQLite will never invoke xInit() more than once without an intervening
+** call to xShutdown().
+**
+** [[the xCreate() page cache methods]]
+** ^SQLite invokes the xCreate() method to construct a new cache instance.
+** SQLite will typically create one cache instance for each open database file,
+** though this is not guaranteed. ^The
+** first parameter, szPage, is the size in bytes of the pages that must
+** be allocated by the cache. ^szPage will always a power of two. ^The
+** second parameter szExtra is a number of bytes of extra storage
+** associated with each page cache entry. ^The szExtra parameter will
+** a number less than 250. SQLite will use the
+** extra szExtra bytes on each page to store metadata about the underlying
+** database page on disk. The value passed into szExtra depends
+** on the SQLite version, the target platform, and how SQLite was compiled.
+** ^The third argument to xCreate(), bPurgeable, is true if the cache being
+** created will be used to cache database pages of a file stored on disk, or
+** false if it is used for an in-memory database. The cache implementation
+** does not have to do anything special based with the value of bPurgeable;
+** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
+** never invoke xUnpin() except to deliberately delete a page.
+** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
+** false will always have the "discard" flag set to true.
+** ^Hence, a cache created with bPurgeable false will
+** never contain any unpinned pages.
+**
+** [[the xCachesize() page cache method]]
+** ^(The xCachesize() method may be called at any time by SQLite to set the
+** suggested maximum cache-size (number of pages stored by) the cache
+** instance passed as the first argument. This is the value configured using
+** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
+** parameter, the implementation is not required to do anything with this
+** value; it is advisory only.
+**
+** [[the xPagecount() page cache methods]]
+** The xPagecount() method must return the number of pages currently
+** stored in the cache, both pinned and unpinned.
+**
+** [[the xFetch() page cache methods]]
+** The xFetch() method locates a page in the cache and returns a pointer to
+** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
+** The pBuf element of the returned sqlite3_pcache_page object will be a
+** pointer to a buffer of szPage bytes used to store the content of a
+** single database page. The pExtra element of sqlite3_pcache_page will be
+** a pointer to the szExtra bytes of extra storage that SQLite has requested
+** for each entry in the page cache.
+**
+** The page to be fetched is determined by the key. ^The minimum key value
+** is 1. After it has been retrieved using xFetch, the page is considered
+** to be "pinned".
+**
+** If the requested page is already in the page cache, then the page cache
+** implementation must return a pointer to the page buffer with its content
+** intact. If the requested page is not already in the cache, then the
+** cache implementation should use the value of the createFlag
+** parameter to help it determined what action to take:
+**
+** <table border=1 width=85% align=center>
+** <tr><th> createFlag <th> Behavior when page is not already in cache
+** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
+** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
+** Otherwise return NULL.
+** <tr><td> 2 <td> Make every effort to allocate a new page. Only return
+** NULL if allocating a new page is effectively impossible.
+** </table>
+**
+** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
+** will only use a createFlag of 2 after a prior call with a createFlag of 1
+** failed.)^ In between the to xFetch() calls, SQLite may
+** attempt to unpin one or more cache pages by spilling the content of
+** pinned pages to disk and synching the operating system disk cache.
+**
+** [[the xUnpin() page cache method]]
+** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
+** as its second argument. If the third parameter, discard, is non-zero,
+** then the page must be evicted from the cache.
+** ^If the discard parameter is
+** zero, then the page may be discarded or retained at the discretion of
+** page cache implementation. ^The page cache implementation
+** may choose to evict unpinned pages at any time.
+**
+** The cache must not perform any reference counting. A single
+** call to xUnpin() unpins the page regardless of the number of prior calls
+** to xFetch().
+**
+** [[the xRekey() page cache methods]]
+** The xRekey() method is used to change the key value associated with the
+** page passed as the second argument. If the cache
+** previously contains an entry associated with newKey, it must be
+** discarded. ^Any prior cache entry associated with newKey is guaranteed not
+** to be pinned.
+**
+** When SQLite calls the xTruncate() method, the cache must discard all
+** existing cache entries with page numbers (keys) greater than or equal
+** to the value of the iLimit parameter passed to xTruncate(). If any
+** of these pages are pinned, they are implicitly unpinned, meaning that
+** they can be safely discarded.
+**
+** [[the xDestroy() page cache method]]
+** ^The xDestroy() method is used to delete a cache allocated by xCreate().
+** All resources associated with the specified cache should be freed. ^After
+** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
+** handle invalid, and will not use it with any other sqlite3_pcache_methods2
+** functions.
+**
+** [[the xShrink() page cache method]]
+** ^SQLite invokes the xShrink() method when it wants the page cache to
+** free up as much of heap memory as possible. The page cache implementation
+** is not obligated to free any memory, but well-behaved implementations should
+** do their best.
+*/
+typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
+struct sqlite3_pcache_methods2 {
+ int iVersion;
+ void *pArg;
+ int (*xInit)(void*);
+ void (*xShutdown)(void*);
+ sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
+ void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+ int (*xPagecount)(sqlite3_pcache*);
+ sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+ void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
+ void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
+ unsigned oldKey, unsigned newKey);
+ void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+ void (*xDestroy)(sqlite3_pcache*);
+ void (*xShrink)(sqlite3_pcache*);
+};
+
+/*
+** This is the obsolete pcache_methods object that has now been replaced
+** by sqlite3_pcache_methods2. This object is not used by SQLite. It is
+** retained in the header file for backwards compatibility only.
+*/
+typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
+struct sqlite3_pcache_methods {
+ void *pArg;
+ int (*xInit)(void*);
+ void (*xShutdown)(void*);
+ sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
+ void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+ int (*xPagecount)(sqlite3_pcache*);
+ void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+ void (*xUnpin)(sqlite3_pcache*, void*, int discard);
+ void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
+ void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+ void (*xDestroy)(sqlite3_pcache*);
+};
+
+
+/*
+** CAPI3REF: Online Backup Object
+**
+** The sqlite3_backup object records state information about an ongoing
+** online backup operation. ^The sqlite3_backup object is created by
+** a call to [sqlite3_backup_init()] and is destroyed by a call to
+** [sqlite3_backup_finish()].
+**
+** See Also: [Using the SQLite Online Backup API]
+*/
+typedef struct sqlite3_backup sqlite3_backup;
+
+/*
+** CAPI3REF: Online Backup API.
+**
+** The backup API copies the content of one database into another.
+** It is useful either for creating backups of databases or
+** for copying in-memory databases to or from persistent files.
+**
+** See Also: [Using the SQLite Online Backup API]
+**
+** ^SQLite holds a write transaction open on the destination database file
+** for the duration of the backup operation.
+** ^The source database is read-locked only while it is being read;
+** it is not locked continuously for the entire backup operation.
+** ^Thus, the backup may be performed on a live source database without
+** preventing other database connections from
+** reading or writing to the source database while the backup is underway.
+**
+** ^(To perform a backup operation:
+** <ol>
+** <li><b>sqlite3_backup_init()</b> is called once to initialize the
+** backup,
+** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
+** the data between the two databases, and finally
+** <li><b>sqlite3_backup_finish()</b> is called to release all resources
+** associated with the backup operation.
+** </ol>)^
+** There should be exactly one call to sqlite3_backup_finish() for each
+** successful call to sqlite3_backup_init().
+**
+** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
+**
+** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
+** [database connection] associated with the destination database
+** and the database name, respectively.
+** ^The database name is "main" for the main database, "temp" for the
+** temporary database, or the name specified after the AS keyword in
+** an [ATTACH] statement for an attached database.
+** ^The S and M arguments passed to
+** sqlite3_backup_init(D,N,S,M) identify the [database connection]
+** and database name of the source database, respectively.
+** ^The source and destination [database connections] (parameters S and D)
+** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
+** an error.
+**
+** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is
+** returned and an error code and error message are stored in the
+** destination [database connection] D.
+** ^The error code and message for the failed call to sqlite3_backup_init()
+** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or
+** [sqlite3_errmsg16()] functions.
+** ^A successful call to sqlite3_backup_init() returns a pointer to an
+** [sqlite3_backup] object.
+** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
+** sqlite3_backup_finish() functions to perform the specified backup
+** operation.
+**
+** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
+**
+** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
+** the source and destination databases specified by [sqlite3_backup] object B.
+** ^If N is negative, all remaining source pages are copied.
+** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
+** are still more pages to be copied, then the function returns [SQLITE_OK].
+** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
+** from source to destination, then it returns [SQLITE_DONE].
+** ^If an error occurs while running sqlite3_backup_step(B,N),
+** then an [error code] is returned. ^As well as [SQLITE_OK] and
+** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY],
+** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an
+** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code.
+**
+** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if
+** <ol>
+** <li> the destination database was opened read-only, or
+** <li> the destination database is using write-ahead-log journaling
+** and the destination and source page sizes differ, or
+** <li> the destination database is an in-memory database and the
+** destination and source page sizes differ.
+** </ol>)^
+**
+** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
+** the [sqlite3_busy_handler | busy-handler function]
+** is invoked (if one is specified). ^If the
+** busy-handler returns non-zero before the lock is available, then
+** [SQLITE_BUSY] is returned to the caller. ^In this case the call to
+** sqlite3_backup_step() can be retried later. ^If the source
+** [database connection]
+** is being used to write to the source database when sqlite3_backup_step()
+** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this
+** case the call to sqlite3_backup_step() can be retried later on. ^(If
+** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or
+** [SQLITE_READONLY] is returned, then
+** there is no point in retrying the call to sqlite3_backup_step(). These
+** errors are considered fatal.)^ The application must accept
+** that the backup operation has failed and pass the backup operation handle
+** to the sqlite3_backup_finish() to release associated resources.
+**
+** ^The first call to sqlite3_backup_step() obtains an exclusive lock
+** on the destination file. ^The exclusive lock is not released until either
+** sqlite3_backup_finish() is called or the backup operation is complete
+** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to
+** sqlite3_backup_step() obtains a [shared lock] on the source database that
+** lasts for the duration of the sqlite3_backup_step() call.
+** ^Because the source database is not locked between calls to
+** sqlite3_backup_step(), the source database may be modified mid-way
+** through the backup process. ^If the source database is modified by an
+** external process or via a database connection other than the one being
+** used by the backup operation, then the backup will be automatically
+** restarted by the next call to sqlite3_backup_step(). ^If the source
+** database is modified by the using the same database connection as is used
+** by the backup operation, then the backup database is automatically
+** updated at the same time.
+**
+** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
+**
+** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
+** application wishes to abandon the backup operation, the application
+** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
+** ^The sqlite3_backup_finish() interfaces releases all
+** resources associated with the [sqlite3_backup] object.
+** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any
+** active write-transaction on the destination database is rolled back.
+** The [sqlite3_backup] object is invalid
+** and may not be used following a call to sqlite3_backup_finish().
+**
+** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
+** sqlite3_backup_step() errors occurred, regardless or whether or not
+** sqlite3_backup_step() completed.
+** ^If an out-of-memory condition or IO error occurred during any prior
+** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
+** sqlite3_backup_finish() returns the corresponding [error code].
+**
+** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
+** is not a permanent error and does not affect the return value of
+** sqlite3_backup_finish().
+**
+** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
+** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
+**
+** ^Each call to sqlite3_backup_step() sets two values inside
+** the [sqlite3_backup] object: the number of pages still to be backed
+** up and the total number of pages in the source database file.
+** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
+** retrieve these two values, respectively.
+**
+** ^The values returned by these functions are only updated by
+** sqlite3_backup_step(). ^If the source database is modified during a backup
+** operation, then the values are not updated to account for any extra
+** pages that need to be updated or the size of the source database file
+** changing.
+**
+** <b>Concurrent Usage of Database Handles</b>
+**
+** ^The source [database connection] may be used by the application for other
+** purposes while a backup operation is underway or being initialized.
+** ^If SQLite is compiled and configured to support threadsafe database
+** connections, then the source database connection may be used concurrently
+** from within other threads.
+**
+** However, the application must guarantee that the destination
+** [database connection] is not passed to any other API (by any thread) after
+** sqlite3_backup_init() is called and before the corresponding call to
+** sqlite3_backup_finish(). SQLite does not currently check to see
+** if the application incorrectly accesses the destination [database connection]
+** and so no error code is reported, but the operations may malfunction
+** nevertheless. Use of the destination database connection while a
+** backup is in progress might also also cause a mutex deadlock.
+**
+** If running in [shared cache mode], the application must
+** guarantee that the shared cache used by the destination database
+** is not accessed while the backup is running. In practice this means
+** that the application must guarantee that the disk file being
+** backed up to is not accessed by any connection within the process,
+** not just the specific connection that was passed to sqlite3_backup_init().
+**
+** The [sqlite3_backup] object itself is partially threadsafe. Multiple
+** threads may safely make multiple concurrent calls to sqlite3_backup_step().
+** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount()
+** APIs are not strictly speaking threadsafe. If they are invoked at the
+** same time as another thread is invoking sqlite3_backup_step() it is
+** possible that they return invalid values.
+*/
+SQLITE_API sqlite3_backup *sqlite3_backup_init(
+ sqlite3 *pDest, /* Destination database handle */
+ const char *zDestName, /* Destination database name */
+ sqlite3 *pSource, /* Source database handle */
+ const char *zSourceName /* Source database name */
+);
+SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage);
+SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p);
+SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p);
+SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
+
+/*
+** CAPI3REF: Unlock Notification
+**
+** ^When running in shared-cache mode, a database operation may fail with
+** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
+** individual tables within the shared-cache cannot be obtained. See
+** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
+** ^This API may be used to register a callback that SQLite will invoke
+** when the connection currently holding the required lock relinquishes it.
+** ^This API is only available if the library was compiled with the
+** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
+**
+** See Also: [Using the SQLite Unlock Notification Feature].
+**
+** ^Shared-cache locks are released when a database connection concludes
+** its current transaction, either by committing it or rolling it back.
+**
+** ^When a connection (known as the blocked connection) fails to obtain a
+** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
+** identity of the database connection (the blocking connection) that
+** has locked the required resource is stored internally. ^After an
+** application receives an SQLITE_LOCKED error, it may call the
+** sqlite3_unlock_notify() method with the blocked connection handle as
+** the first argument to register for a callback that will be invoked
+** when the blocking connections current transaction is concluded. ^The
+** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
+** call that concludes the blocking connections transaction.
+**
+** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
+** there is a chance that the blocking connection will have already
+** concluded its transaction by the time sqlite3_unlock_notify() is invoked.
+** If this happens, then the specified callback is invoked immediately,
+** from within the call to sqlite3_unlock_notify().)^
+**
+** ^If the blocked connection is attempting to obtain a write-lock on a
+** shared-cache table, and more than one other connection currently holds
+** a read-lock on the same table, then SQLite arbitrarily selects one of
+** the other connections to use as the blocking connection.
+**
+** ^(There may be at most one unlock-notify callback registered by a
+** blocked connection. If sqlite3_unlock_notify() is called when the
+** blocked connection already has a registered unlock-notify callback,
+** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
+** called with a NULL pointer as its second argument, then any existing
+** unlock-notify callback is canceled. ^The blocked connections
+** unlock-notify callback may also be canceled by closing the blocked
+** connection using [sqlite3_close()].
+**
+** The unlock-notify callback is not reentrant. If an application invokes
+** any sqlite3_xxx API functions from within an unlock-notify callback, a
+** crash or deadlock may be the result.
+**
+** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always
+** returns SQLITE_OK.
+**
+** <b>Callback Invocation Details</b>
+**
+** When an unlock-notify callback is registered, the application provides a
+** single void* pointer that is passed to the callback when it is invoked.
+** However, the signature of the callback function allows SQLite to pass
+** it an array of void* context pointers. The first argument passed to
+** an unlock-notify callback is a pointer to an array of void* pointers,
+** and the second is the number of entries in the array.
+**
+** When a blocking connections transaction is concluded, there may be
+** more than one blocked connection that has registered for an unlock-notify
+** callback. ^If two or more such blocked connections have specified the
+** same callback function, then instead of invoking the callback function
+** multiple times, it is invoked once with the set of void* context pointers
+** specified by the blocked connections bundled together into an array.
+** This gives the application an opportunity to prioritize any actions
+** related to the set of unblocked database connections.
+**
+** <b>Deadlock Detection</b>
+**
+** Assuming that after registering for an unlock-notify callback a
+** database waits for the callback to be issued before taking any further
+** action (a reasonable assumption), then using this API may cause the
+** application to deadlock. For example, if connection X is waiting for
+** connection Y's transaction to be concluded, and similarly connection
+** Y is waiting on connection X's transaction, then neither connection
+** will proceed and the system may remain deadlocked indefinitely.
+**
+** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock
+** detection. ^If a given call to sqlite3_unlock_notify() would put the
+** system in a deadlocked state, then SQLITE_LOCKED is returned and no
+** unlock-notify callback is registered. The system is said to be in
+** a deadlocked state if connection A has registered for an unlock-notify
+** callback on the conclusion of connection B's transaction, and connection
+** B has itself registered for an unlock-notify callback when connection
+** A's transaction is concluded. ^Indirect deadlock is also detected, so
+** the system is also considered to be deadlocked if connection B has
+** registered for an unlock-notify callback on the conclusion of connection
+** C's transaction, where connection C is waiting on connection A. ^Any
+** number of levels of indirection are allowed.
+**
+** <b>The "DROP TABLE" Exception</b>
+**
+** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
+** always appropriate to call sqlite3_unlock_notify(). There is however,
+** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
+** SQLite checks if there are any currently executing SELECT statements
+** that belong to the same connection. If there are, SQLITE_LOCKED is
+** returned. In this case there is no "blocking connection", so invoking
+** sqlite3_unlock_notify() results in the unlock-notify callback being
+** invoked immediately. If the application then re-attempts the "DROP TABLE"
+** or "DROP INDEX" query, an infinite loop might be the result.
+**
+** One way around this problem is to check the extended error code returned
+** by an sqlite3_step() call. ^(If there is a blocking connection, then the
+** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
+** the special "DROP TABLE/INDEX" case, the extended error code is just
+** SQLITE_LOCKED.)^
+*/
+SQLITE_API int sqlite3_unlock_notify(
+ sqlite3 *pBlocked, /* Waiting connection */
+ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
+ void *pNotifyArg /* Argument to pass to xNotify */
+);
+
+
+/*
+** CAPI3REF: String Comparison
+**
+** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
+** and extensions to compare the contents of two buffers containing UTF-8
+** strings in a case-independent fashion, using the same definition of "case
+** independence" that SQLite uses internally when comparing identifiers.
+*/
+SQLITE_API int sqlite3_stricmp(const char *, const char *);
+SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
+
+/*
+** CAPI3REF: Error Logging Interface
+**
+** ^The [sqlite3_log()] interface writes a message into the error log
+** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
+** ^If logging is enabled, the zFormat string and subsequent arguments are
+** used with [sqlite3_snprintf()] to generate the final output string.
+**
+** The sqlite3_log() interface is intended for use by extensions such as
+** virtual tables, collating functions, and SQL functions. While there is
+** nothing to prevent an application from calling sqlite3_log(), doing so
+** is considered bad form.
+**
+** The zFormat string must not be NULL.
+**
+** To avoid deadlocks and other threading problems, the sqlite3_log() routine
+** will not use dynamically allocated memory. The log message is stored in
+** a fixed-length buffer on the stack. If the log message is longer than
+** a few hundred characters, it will be truncated to the length of the
+** buffer.
+*/
+SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
+
+/*
+** CAPI3REF: Write-Ahead Log Commit Hook
+**
+** ^The [sqlite3_wal_hook()] function is used to register a callback that
+** will be invoked each time a database connection commits data to a
+** [write-ahead log] (i.e. whenever a transaction is committed in
+** [journal_mode | journal_mode=WAL mode]).
+**
+** ^The callback is invoked by SQLite after the commit has taken place and
+** the associated write-lock on the database released, so the implementation
+** may read, write or [checkpoint] the database as required.
+**
+** ^The first parameter passed to the callback function when it is invoked
+** is a copy of the third parameter passed to sqlite3_wal_hook() when
+** registering the callback. ^The second is a copy of the database handle.
+** ^The third parameter is the name of the database that was written to -
+** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
+** is the number of pages currently in the write-ahead log file,
+** including those that were just committed.
+**
+** The callback function should normally return [SQLITE_OK]. ^If an error
+** code is returned, that error will propagate back up through the
+** SQLite code base to cause the statement that provoked the callback
+** to report an error, though the commit will have still occurred. If the
+** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
+** that does not correspond to any valid SQLite error code, the results
+** are undefined.
+**
+** A single database handle may have at most a single write-ahead log callback
+** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
+** previously registered write-ahead log callback. ^Note that the
+** [sqlite3_wal_autocheckpoint()] interface and the
+** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
+** those overwrite any prior [sqlite3_wal_hook()] settings.
+*/
+SQLITE_API void *sqlite3_wal_hook(
+ sqlite3*,
+ int(*)(void *,sqlite3*,const char*,int),
+ void*
+);
+
+/*
+** CAPI3REF: Configure an auto-checkpoint
+**
+** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
+** [sqlite3_wal_hook()] that causes any database on [database connection] D
+** to automatically [checkpoint]
+** after committing a transaction if there are N or
+** more frames in the [write-ahead log] file. ^Passing zero or
+** a negative value as the nFrame parameter disables automatic
+** checkpoints entirely.
+**
+** ^The callback registered by this function replaces any existing callback
+** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback
+** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
+** configured by this function.
+**
+** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
+** from SQL.
+**
+** ^Every new [database connection] defaults to having the auto-checkpoint
+** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
+** pages. The use of this interface
+** is only necessary if the default setting is found to be suboptimal
+** for a particular application.
+*/
+SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
+
+/*
+** CAPI3REF: Checkpoint a database
+**
+** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
+** on [database connection] D to be [checkpointed]. ^If X is NULL or an
+** empty string, then a checkpoint is run on all databases of
+** connection D. ^If the database connection D is not in
+** [WAL | write-ahead log mode] then this interface is a harmless no-op.
+**
+** ^The [wal_checkpoint pragma] can be used to invoke this interface
+** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
+** [wal_autocheckpoint pragma] can be used to cause this interface to be
+** run whenever the WAL reaches a certain size threshold.
+**
+** See also: [sqlite3_wal_checkpoint_v2()]
+*/
+SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
+
+/*
+** CAPI3REF: Checkpoint a database
+**
+** Run a checkpoint operation on WAL database zDb attached to database
+** handle db. The specific operation is determined by the value of the
+** eMode parameter:
+**
+** <dl>
+** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
+** Checkpoint as many frames as possible without waiting for any database
+** readers or writers to finish. Sync the db file if all frames in the log
+** are checkpointed. This mode is the same as calling
+** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
+**
+** <dt>SQLITE_CHECKPOINT_FULL<dd>
+** This mode blocks (calls the busy-handler callback) until there is no
+** database writer and all readers are reading from the most recent database
+** snapshot. It then checkpoints all frames in the log file and syncs the
+** database file. This call blocks database writers while it is running,
+** but not database readers.
+**
+** <dt>SQLITE_CHECKPOINT_RESTART<dd>
+** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
+** checkpointing the log file it blocks (calls the busy-handler callback)
+** until all readers are reading from the database file only. This ensures
+** that the next client to write to the database file restarts the log file
+** from the beginning. This call blocks database writers while it is running,
+** but not database readers.
+** </dl>
+**
+** If pnLog is not NULL, then *pnLog is set to the total number of frames in
+** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to
+** the total number of checkpointed frames (including any that were already
+** checkpointed when this function is called). *pnLog and *pnCkpt may be
+** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK.
+** If no values are available because of an error, they are both set to -1
+** before returning to communicate this to the caller.
+**
+** All calls obtain an exclusive "checkpoint" lock on the database file. If
+** any other process is running a checkpoint operation at the same time, the
+** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a
+** busy-handler configured, it will not be invoked in this case.
+**
+** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive
+** "writer" lock on the database file. If the writer lock cannot be obtained
+** immediately, and a busy-handler is configured, it is invoked and the writer
+** lock retried until either the busy-handler returns 0 or the lock is
+** successfully obtained. The busy-handler is also invoked while waiting for
+** database readers as described above. If the busy-handler returns 0 before
+** the writer lock is obtained or while waiting for database readers, the
+** checkpoint operation proceeds from that point in the same way as
+** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
+** without blocking any further. SQLITE_BUSY is returned in this case.
+**
+** If parameter zDb is NULL or points to a zero length string, then the
+** specified operation is attempted on all WAL databases. In this case the
+** values written to output parameters *pnLog and *pnCkpt are undefined. If
+** an SQLITE_BUSY error is encountered when processing one or more of the
+** attached WAL databases, the operation is still attempted on any remaining
+** attached databases and SQLITE_BUSY is returned to the caller. If any other
+** error occurs while processing an attached database, processing is abandoned
+** and the error code returned to the caller immediately. If no error
+** (SQLITE_BUSY or otherwise) is encountered while processing the attached
+** databases, SQLITE_OK is returned.
+**
+** If database zDb is the name of an attached database that is not in WAL
+** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If
+** zDb is not NULL (or a zero length string) and is not the name of any
+** attached database, SQLITE_ERROR is returned to the caller.
+*/
+SQLITE_API int sqlite3_wal_checkpoint_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of attached database (or NULL) */
+ int eMode, /* SQLITE_CHECKPOINT_* value */
+ int *pnLog, /* OUT: Size of WAL log in frames */
+ int *pnCkpt /* OUT: Total number of frames checkpointed */
+);
+
+/*
+** CAPI3REF: Checkpoint operation parameters
+**
+** These constants can be used as the 3rd parameter to
+** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()]
+** documentation for additional information about the meaning and use of
+** each of these values.
+*/
+#define SQLITE_CHECKPOINT_PASSIVE 0
+#define SQLITE_CHECKPOINT_FULL 1
+#define SQLITE_CHECKPOINT_RESTART 2
+
+/*
+** CAPI3REF: Virtual Table Interface Configuration
+**
+** This function may be called by either the [xConnect] or [xCreate] method
+** of a [virtual table] implementation to configure
+** various facets of the virtual table interface.
+**
+** If this interface is invoked outside the context of an xConnect or
+** xCreate virtual table method then the behavior is undefined.
+**
+** At present, there is only one option that may be configured using
+** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
+** may be added in the future.
+*/
+SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+
+/*
+** CAPI3REF: Virtual Table Configuration Options
+**
+** These macros define the various options to the
+** [sqlite3_vtab_config()] interface that [virtual table] implementations
+** can use to customize and optimize their behavior.
+**
+** <dl>
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
+** <dd>Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
+** where X is an integer. If X is zero, then the [virtual table] whose
+** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
+** support constraints. In this configuration (which is the default) if
+** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
+** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
+** specified as part of the users SQL statement, regardless of the actual
+** ON CONFLICT mode specified.
+**
+** If X is non-zero, then the virtual table implementation guarantees
+** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
+** any modifications to internal or persistent data structures have been made.
+** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
+** is able to roll back a statement or database transaction, and abandon
+** or continue processing the current SQL statement as appropriate.
+** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
+** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
+** had been ABORT.
+**
+** Virtual table implementations that are required to handle OR REPLACE
+** must do so within the [xUpdate] method. If a call to the
+** [sqlite3_vtab_on_conflict()] function indicates that the current ON
+** CONFLICT policy is REPLACE, the virtual table implementation should
+** silently replace the appropriate rows within the xUpdate callback and
+** return SQLITE_OK. Or, if this is not possible, it may return
+** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
+** constraint handling.
+** </dl>
+*/
+#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+
+/*
+** CAPI3REF: Determine The Virtual Table Conflict Policy
+**
+** This function may only be called from within a call to the [xUpdate] method
+** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
+** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
+** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
+** of the SQL statement that triggered the call to the [xUpdate] method of the
+** [virtual table].
+*/
+SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
+
+/*
+** CAPI3REF: Conflict resolution modes
+**
+** These constants are returned by [sqlite3_vtab_on_conflict()] to
+** inform a [virtual table] implementation what the [ON CONFLICT] mode
+** is for the SQL statement being evaluated.
+**
+** Note that the [SQLITE_IGNORE] constant is also used as a potential
+** return value from the [sqlite3_set_authorizer()] callback and that
+** [SQLITE_ABORT] is also a [result code].
+*/
+#define SQLITE_ROLLBACK 1
+/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
+#define SQLITE_FAIL 3
+/* #define SQLITE_ABORT 4 // Also an error code */
+#define SQLITE_REPLACE 5
+
+
+
+/*
+** Undo the hack that converts floating point types to integer for
+** builds on processors without floating point support.
+*/
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# undef double
+#endif
+
+#ifdef __cplusplus
+} /* End of the 'extern "C"' block */
+#endif
+#endif
+
+/*
+** 2010 August 30
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+*/
+
+#ifndef _SQLITE3RTREE_H_
+#define _SQLITE3RTREE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
+
+/*
+** Register a geometry callback named zGeom that can be used as part of an
+** R-Tree geometry query as follows:
+**
+** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
+*/
+SQLITE_API int sqlite3_rtree_geometry_callback(
+ sqlite3 *db,
+ const char *zGeom,
+#ifdef SQLITE_RTREE_INT_ONLY
+ int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
+#else
+ int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
+#endif
+ void *pContext
+);
+
+
+/*
+** A pointer to a structure of the following type is passed as the first
+** argument to callbacks registered using rtree_geometry_callback().
+*/
+struct sqlite3_rtree_geometry {
+ void *pContext; /* Copy of pContext passed to s_r_g_c() */
+ int nParam; /* Size of array aParam[] */
+ double *aParam; /* Parameters passed to SQL geom function */
+ void *pUser; /* Callback implementation user data */
+ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
+};
+
+
+#ifdef __cplusplus
+} /* end of the 'extern "C"' block */
+#endif
+
+#endif /* ifndef _SQLITE3RTREE_H_ */
+
diff --git a/lib/sqlite/urls.txt b/lib/sqlite/urls.txt
new file mode 100644
index 000000000..131d70bbf
--- /dev/null
+++ b/lib/sqlite/urls.txt
@@ -0,0 +1,9 @@
+
+SQLite:
+http://www.sqlite.org
+SQLite is in public domain
+
+LuaSQLite3:
+http://lua.sqlite.org
+http://lua.sqlite.org/index.cgi/doc/tip/doc/lsqlite3.wiki -- documentation
+License for LuaSQLite is stored in $/install/LuaSQLite3-LICENSE.txt and distributed with the executables \ No newline at end of file
diff --git a/lib/tolua++/COPYRIGHT b/lib/tolua++/COPYRIGHT
new file mode 100644
index 000000000..9e99e0080
--- /dev/null
+++ b/lib/tolua++/COPYRIGHT
@@ -0,0 +1,33 @@
+tolua++ License
+---------------
+
+tolua++ is based on toLua (www.tecgraf.puc-rio.br/~celes/tolua), and
+it's licensed under the terms of the MIT license reproduced below.
+This means that Lua is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+
+===============================================================================
+
+Copyright (C) 2009 Ariel Manzur.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+===============================================================================
+
+(end of COPYRIGHT)
diff --git a/lib/tolua++/INSTALL b/lib/tolua++/INSTALL
new file mode 100644
index 000000000..5ee408f9e
--- /dev/null
+++ b/lib/tolua++/INSTALL
@@ -0,0 +1,42 @@
+This version of tolua++ uses SCons to compile (http://www.scons.org). SCons uses
+pythin. If you don't want to install python, check "Installation without scons"
+below.
+
+* Installation
+
+ 1. Edit the "config" file for your platform to suit your environment,
+ if at all necessary (for cygwin, mingw, BSD and mac OSX use
+ 'config_posix')
+ 2. Then, type "scons".
+
+ You can use 'scons -h' to see a list of available command line options.
+
+* What you get
+
+ If "scons" succeeds, you get:
+ * an executable to generate binding code in ./bin;
+ * the C library to be linked in your application in ./lib;
+ * the include file needed to compile your application in ./include.
+ These are the only directories you need for development, besides Lua.
+
+ You can use 'scons install' to install the files, see the 'prefix' option.
+
+* Installation without scons
+
+ The instructions for building tolua++ without scons depend on the particular
+ compiler you are using.
+ The simplest way is to create a folder with all .c and .h files except
+ 'toluabind_default.c', and then create a project for the executable and the
+ library, as follows:
+
+ tolua.exe: all *.c *.h in src/bin (except toluabind_default.c)
+ tolua.lib: all *.c *.h in src/lib.
+
+* Installation with Microsoft Visual Studio
+
+ The directory 'win32' contains project files for Microsoft Visual Studio 7
+ (contributed by Makoto Hamanaka). The project has 4 different build options:
+ withLua50_Release, withLua51_Release, withLua50_Debug and withLua51_Debug.
+ They all expect the lua library names used by the LuaBinaries packages
+ (http://luabinaries.luaforge.net/). The resulting files are built on /lib and
+ /bin (for the library and tolua++.exe).
diff --git a/lib/tolua++/Makefile b/lib/tolua++/Makefile
new file mode 100644
index 000000000..92ded6c4e
--- /dev/null
+++ b/lib/tolua++/Makefile
@@ -0,0 +1,5 @@
+# makefile for tolua hierarchy
+
+all:
+ @echo "Makefile is deprecated ;)"
+ @echo "see INSTALL for details on how to build tolua++"
diff --git a/lib/tolua++/README b/lib/tolua++/README
new file mode 100644
index 000000000..cee381fb3
--- /dev/null
+++ b/lib/tolua++/README
@@ -0,0 +1,30 @@
+This is tolua++-1.0
+
+* What is tolua++?
+ tolua++ is an extension of toLua, a tool to integrate C/C++ code with
+ Lua. tolua++ includes new features oriented to c++, such as class
+ templates.
+
+ tolua is a tool that greatly simplifies the integration of C/C++ code
+ with Lua. Based on a "cleaned" header file, tolua automatically generates
+ the binding code to access C/C++ features from Lua. Using Lua-5.0 API and
+ metamethod facilities, the current version automatically maps C/C++
+ constants, external variables, functions, namespace, classes, and methods
+ to Lua. It also provides facilities to create Lua modules.
+
+* Availability
+
+ tolua++ is freely available for both academic and commercial purposes.
+ See COPYRIGHT for details.
+
+ tolua++ can be downloaded from the sites below:
+ http://www.codenix.com/~tolua/
+
+* Installation
+ See INSTALL.
+
+* Contacting the author
+ tolua has been designed and implemented by Waldemar Celes.
+ tolua++ is maintained by Ariel Manzur.
+ Send your comments, bug reports and anything else to
+ tolua@codenix.com
diff --git a/lib/tolua++/README-5.1 b/lib/tolua++/README-5.1
new file mode 100644
index 000000000..f06f785e3
--- /dev/null
+++ b/lib/tolua++/README-5.1
@@ -0,0 +1,50 @@
+Compiling for lua 5.1
+---------------------
+
+Starting from version 1.0.8pre1, tolua++ can be compiled with both lua 5.0 and
+5.1. Both versions will output the same code, and the C API (tolua++.h) is the
+same.
+
+The build system is not yet ready to detect/decide when to compile for 5.1,
+the easiest way right now is to add a file called 'custom.py' on the root of
+the package, with the following:
+
+## BEGIN custom.py
+
+CCFLAGS = ['-I/usr/local/include/lua5.1', '-O2', '-ansi']
+LIBPATH = ['/usr/local/lib']
+LIBS = ['lua5.1', 'dl', 'm']
+tolua_bin = 'tolua++5.1'
+tolua_lib = 'tolua++5.1'
+TOLUAPP = 'tolua++5.1'
+
+## END custom.py
+
+This will build the binary as 'tolua++5.1' and the library as 'libtolua++5.1.a'
+(taken from tolua_bin and tolua_lib), and take the lua headers and libraries
+from /usr/local/include/lua5.1 and /usr/local/lib. It will also link with
+'-llua5.1'. Modify the parameters acording to your system.
+
+Compatibility
+-------------
+
+There are a couple of things to keep in mind when running code inside tolua
+using the -L option:
+
+* `...' and arg: you can still use 'arg' on 5.1, this is done automatically by
+adding the 'arg' declaration to functions on files loaded with dofile.
+
+For example, the line:
+
+function foo( ... )
+
+becomes
+
+function foo( ... ) local arg = {n=select('#', ...), ...};
+
+This lets you use the same code on both versions without having to make any
+modifications.
+
+* keep in mind that there are slight differences on the way string.gsub works,
+and the original version of the function is always kept, so it will behave
+diffently depending on which version of lua you're using.
diff --git a/lib/tolua++/SConstruct b/lib/tolua++/SConstruct
new file mode 100644
index 000000000..5c1e7746e
--- /dev/null
+++ b/lib/tolua++/SConstruct
@@ -0,0 +1,180 @@
+import sys;
+import os
+
+tools = ['default']
+if os.name == 'nt':
+ tools = ['mingw']
+
+env = Environment(tools = tools)
+
+options_file = None
+if sys.platform == 'linux2':
+ options_file = "linux"
+
+elif 'msvc' in env['TOOLS']:
+ options_file = "msvc"
+else:
+ options_file = "posix"
+
+opts = Options(["config_"+options_file+".py", "custom.py", "custom_"+options_file+".py"], ARGUMENTS)
+opts.Add('CC', 'The C compiler.')
+opts.Add('CXX', 'The C++ compiler (for the tests)')
+opts.Add('CCFLAGS', 'Flags for the compiler.', ['-O2', '-Wall'])
+opts.Add('LINK', 'The linker.')
+opts.Add('LINKFLAGS', 'Linker flags.', [])
+opts.Add('no_cygwin', 'Use -mno-cygwin to build using the mingw compiler on cygwin', 0)
+opts.Add('LIBS', 'libraries', [])
+opts.Add('LIBPATH', 'library path', [])
+
+opts.Add('tolua_bin', 'the resulting binary', 'tolua++')
+opts.Add('tolua_lib', 'the resulting library', 'tolua++')
+opts.Add('TOLUAPP', 'the name of the tolua++ binary (to use with built_dev=1)', 'tolua++')
+
+opts.Add('prefix', 'The installation prefix')
+opts.Add('build_dev', 'Build for development (uses tolua to rebuild toluabind.c with the embeded scripts', 0)
+opts.Add('build_failsafe', "Build using 'factory default' toluabind file (in case build_dev fails)", 0)
+opts.Add('ENV', 'The environment variables')
+opts.Add('shared', 'Build a shared object', False)
+opts.Update(env)
+Help(opts.GenerateHelpText(env))
+
+def save_config(target, source, env):
+ opts.Save('custom.py', env)
+
+cust = env.Command('custom.py', [], save_config)
+env.Alias('configure', [cust])
+
+env['TOLUAPP_BOOTSTRAP'] = env['tolua_bin']+"_bootstrap"+env['PROGSUFFIX']
+
+env['build_dev'] = int(env['build_dev'])
+
+## detecting the install directory on win32
+if 'msvc' in env['TOOLS'] and not (env.has_key('prefix') or env['prefix']):
+
+ if env['MSVS'].has_key('PLATFORMSDKDIR'):
+ env['prefix'] = env['MSVS']['PLATFORMSDKDIR']
+
+
+SConscriptChdir(0)
+
+############ helper builders
+def pkg_scan_dep(self, target, source):
+
+ import re
+
+ ## TODO: detectar si el archivo existe antes de abrirlo asi nomas
+ pkg = open(source, "rt")
+
+ for linea in pkg.xreadlines():
+ dep = re.search("^[\t\w]*\$[cphl]file\s*\"([^\"]+)\"", linea)
+ if dep:
+ self.Depends(target, '#' + dep.groups()[0]);
+
+ if dep.groups()[0][-4:] == '.pkg':
+ # recursividad
+ self.pkg_scan_dep(target, dep.groups()[0])
+
+
+def make_tolua_code(self, target, source, pkgname = None, bootstrap = False, use_own = False, use_typeid=None):
+
+ ptarget = Dir('.').path + '/' + target
+ psource = Dir('.').path + '/' + source
+ header = target[:-2] + '.h'
+ pheader = Dir('.').path + '/' + header
+
+ tolua = ""
+ if bootstrap:
+ if os.name == 'nt':
+ tolua = 'bin\\'+self['TOLUAPP_BOOTSTRAP']
+ else:
+ tolua = 'bin/'+self['TOLUAPP_BOOTSTRAP']
+ print("********* tolua is ", tolua)
+ else:
+ if use_own:
+ if 'msvc' in self['TOOLS']:
+ tolua = 'bin\\$tolua_bin'
+ else:
+ tolua = 'bin/$tolua_bin'
+ else:
+ tolua = "$TOLUAPP"
+
+ if pkgname:
+ pkgname = ' -n '+pkgname
+ else:
+ pkgname = ''
+
+ if use_typeid:
+ tolua = tolua+' -t'
+
+ comando = tolua + ' -C -H ' + pheader + ' -o ' + ptarget + pkgname + ' ' + psource
+ command = self.Command(target, source, comando)
+
+ self.SideEffect(header, target)
+ self.Depends(target, source)
+
+ self.pkg_scan_dep(target, psource)
+
+ if bootstrap:
+ self.Depends(target, "#/bin/$TOLUAPP_BOOTSTRAP")
+ if use_own:
+ self.Depends(target, "#/bin/$tolua_bin")
+
+ return command
+
+
+env.__class__.LuaBinding = make_tolua_code;
+env.__class__.pkg_scan_dep = pkg_scan_dep;
+
+def print_install_error(target, source, env):
+
+ msg = """Error: no install prefix was specified, or detected.
+
+you can use the 'prefix' option on command line to specify one. Examples:
+
+ scons prefix=/usr/local install
+
+or on Windows:
+
+ scons "prefix=c:\\program files\\visual basic" install
+
+Files will be installed on <prefix>/bin, <prefix>/lib and <prefix>/include
+"""
+ import SCons.Errors
+ raise SCons.Errors.UserError(msg)
+
+########### end of helper builders
+
+env['CPPPATH'] = '#/include'
+env['LIBPATH'] = ['#/lib'] + env['LIBPATH']
+
+if env['no_cygwin']:
+
+ env['CCFLAGS'] += ['-mno-cygwin']
+ env['LINKFLAGS'] += ['-mno-cygwin']
+
+import string
+
+Export('env')
+
+SConscript('src/lib/SCsub')
+SConscript('src/bin/SCsub')
+#SConscript('src/lib/SCsub')
+SConscript('src/tests/SCsub')
+
+env.Alias('all', [env.bin_target, env.lib_target])
+env.Alias('test', env.test_targets)
+
+Default('all')
+
+if env['prefix']:
+ env.Install(env['prefix']+'/bin', env.bin_target)
+ env.Install(env['prefix']+'/lib', env.lib_target)
+ env.Install(env['prefix']+'/include', '#include/tolua++.h')
+
+ env.Alias('install', [env['prefix']+'/bin', env['prefix']+'/include', env['prefix']+'/lib'])
+else:
+ env.Command('install', [], print_install_error)
+ env.Depends('install', 'all')
+
+env.Command('deb', [], 'dpkg-buildpackage -I.svn -Icustom.py -Itoluabind_dev.c -Itoluabind_dev.h -Itoluabind_default.o -Icustom.lua -I.sconsign', ENV=os.environ)
+
diff --git a/lib/tolua++/include/tolua++.h b/lib/tolua++/include/tolua++.h
new file mode 100644
index 000000000..8da427fe3
--- /dev/null
+++ b/lib/tolua++/include/tolua++.h
@@ -0,0 +1,186 @@
+/* tolua
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+
+#ifndef TOLUA_H
+#define TOLUA_H
+
+#ifndef TOLUA_API
+#define TOLUA_API extern
+#endif
+
+#define TOLUA_VERSION "tolua++-1.0.92"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define tolua_pushcppstring(x,y) tolua_pushstring(x,y.c_str())
+#define tolua_iscppstring tolua_isstring
+
+#define tolua_iscppstringarray tolua_isstringarray
+#define tolua_pushfieldcppstring(L,lo,idx,s) tolua_pushfieldstring(L, lo, idx, s.c_str())
+
+#ifndef TEMPLATE_BIND
+ #define TEMPLATE_BIND(p)
+#endif
+
+#define TOLUA_TEMPLATE_BIND(p)
+
+#define TOLUA_PROTECTED_DESTRUCTOR
+#define TOLUA_PROPERTY_TYPE(p)
+
+typedef int lua_Object;
+
+#include "lua/src/lua.h"
+#include "lua/src/lauxlib.h"
+
+struct tolua_Error
+{
+ int index;
+ int array;
+ const char* type;
+};
+typedef struct tolua_Error tolua_Error;
+
+#define TOLUA_NOPEER LUA_REGISTRYINDEX /* for lua 5.1 */
+
+TOLUA_API const char* tolua_typename (lua_State* L, int lo);
+TOLUA_API void tolua_error (lua_State* L, const char* msg, tolua_Error* err);
+TOLUA_API int tolua_isnoobj (lua_State* L, int lo, tolua_Error* err);
+TOLUA_API int tolua_isvalue (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isvaluenil (lua_State* L, int lo, tolua_Error* err);
+TOLUA_API int tolua_isboolean (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isnumber (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isstring (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_istable (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err);
+TOLUA_API int tolua_isuserdata (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isusertype (lua_State* L, int lo, const char* type, int def, tolua_Error* err);
+TOLUA_API int tolua_isvaluearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isbooleanarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isnumberarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isstringarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_istablearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isuserdataarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isusertypearray
+ (lua_State* L, int lo, const char* type, int dim, int def, tolua_Error* err);
+
+TOLUA_API void tolua_open (lua_State* L);
+
+TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size);
+TOLUA_API int tolua_register_gc (lua_State* L, int lo);
+TOLUA_API int tolua_default_collect (lua_State* tolua_S);
+
+TOLUA_API void tolua_usertype (lua_State* L, const char* type);
+TOLUA_API void tolua_beginmodule (lua_State* L, const char* name);
+TOLUA_API void tolua_endmodule (lua_State* L);
+TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar);
+TOLUA_API void tolua_class (lua_State* L, const char* name, const char* base);
+TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col);
+TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func);
+TOLUA_API void tolua_constant (lua_State* L, const char* name, lua_Number value);
+TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set);
+TOLUA_API void tolua_array (lua_State* L,const char* name, lua_CFunction get, lua_CFunction set);
+
+/* TOLUA_API void tolua_set_call_event(lua_State* L, lua_CFunction func, char* type); */
+/* TOLUA_API void tolua_addbase(lua_State* L, char* name, char* base); */
+
+TOLUA_API void tolua_pushvalue (lua_State* L, int lo);
+TOLUA_API void tolua_pushboolean (lua_State* L, int value);
+TOLUA_API void tolua_pushnumber (lua_State* L, lua_Number value);
+TOLUA_API void tolua_pushstring (lua_State* L, const char* value);
+TOLUA_API void tolua_pushuserdata (lua_State* L, void* value);
+TOLUA_API void tolua_pushusertype (lua_State* L, void* value, const char* type);
+TOLUA_API void tolua_pushusertype_and_takeownership(lua_State* L, void* value, const char* type);
+TOLUA_API void tolua_pushfieldvalue (lua_State* L, int lo, int index, int v);
+TOLUA_API void tolua_pushfieldboolean (lua_State* L, int lo, int index, int v);
+TOLUA_API void tolua_pushfieldnumber (lua_State* L, int lo, int index, lua_Number v);
+TOLUA_API void tolua_pushfieldstring (lua_State* L, int lo, int index, const char* v);
+TOLUA_API void tolua_pushfielduserdata (lua_State* L, int lo, int index, void* v);
+TOLUA_API void tolua_pushfieldusertype (lua_State* L, int lo, int index, void* v, const char* type);
+TOLUA_API void tolua_pushfieldusertype_and_takeownership (lua_State* L, int lo, int index, void* v, const char* type);
+
+TOLUA_API lua_Number tolua_tonumber (lua_State* L, int narg, lua_Number def);
+TOLUA_API const char* tolua_tostring (lua_State* L, int narg, const char* def);
+TOLUA_API void* tolua_touserdata (lua_State* L, int narg, void* def);
+TOLUA_API void* tolua_tousertype (lua_State* L, int narg, void* def);
+TOLUA_API int tolua_tovalue (lua_State* L, int narg, int def);
+TOLUA_API int tolua_toboolean (lua_State* L, int narg, int def);
+TOLUA_API lua_Number tolua_tofieldnumber (lua_State* L, int lo, int index, lua_Number def);
+TOLUA_API const char* tolua_tofieldstring (lua_State* L, int lo, int index, const char* def);
+TOLUA_API void* tolua_tofielduserdata (lua_State* L, int lo, int index, void* def);
+TOLUA_API void* tolua_tofieldusertype (lua_State* L, int lo, int index, void* def);
+TOLUA_API int tolua_tofieldvalue (lua_State* L, int lo, int index, int def);
+TOLUA_API int tolua_getfieldboolean (lua_State* L, int lo, int index, int def);
+
+TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, const char* name);
+
+TOLUA_API int class_gc_event (lua_State* L);
+
+#ifdef __cplusplus
+static inline const char* tolua_tocppstring (lua_State* L, int narg, const char* def) {
+
+ const char* s = tolua_tostring(L, narg, def);
+ return s?s:"";
+};
+
+static inline const char* tolua_tofieldcppstring (lua_State* L, int lo, int index, const char* def) {
+
+ const char* s = tolua_tofieldstring(L, lo, index, def);
+ return s?s:"";
+};
+
+#else
+#define tolua_tocppstring tolua_tostring
+#define tolua_tofieldcppstring tolua_tofieldstring
+#endif
+
+TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index);
+
+#ifndef Mtolua_new
+#define Mtolua_new(EXP) new EXP
+#endif
+
+#ifndef Mtolua_delete
+#define Mtolua_delete(EXP) delete EXP
+#endif
+
+#ifndef Mtolua_new_dim
+#define Mtolua_new_dim(EXP, len) new EXP[len]
+#endif
+
+#ifndef Mtolua_delete_dim
+#define Mtolua_delete_dim(EXP) delete [] EXP
+#endif
+
+#ifndef tolua_outside
+#define tolua_outside
+#endif
+
+#ifndef tolua_owned
+#define tolua_owned
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/tolua++/src/bin/SCsub b/lib/tolua++/src/bin/SCsub
new file mode 100644
index 000000000..35ccd7a24
--- /dev/null
+++ b/lib/tolua++/src/bin/SCsub
@@ -0,0 +1,12 @@
+Import('env')
+
+src = [
+ env.Object('tolua.c'),
+ ]
+
+
+toluabind = env.LuaBinding('toluabind.c', 'tolua_scons.pkg', 'tolua', bootstrap = True)
+
+env.bin_target = env.Program('#/bin/'+env['tolua_bin'], src + [toluabind], LIBS = ['$tolua_lib'] + env['LIBS'])
+
+env.bootstrap_target = env.Program('#/bin/'+env['TOLUAPP_BOOTSTRAP'], src + ['toluabind_default.c', env.lib_target_static], LIBS = env['LIBS'])
diff --git a/lib/tolua++/src/bin/lua/all.lua b/lib/tolua++/src/bin/lua/all.lua
new file mode 100644
index 000000000..83f8a3cb9
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/all.lua
@@ -0,0 +1,30 @@
+dofile(path.."compat-5.1.lua")
+dofile(path.."compat.lua")
+dofile(path.."basic.lua")
+dofile(path.."feature.lua")
+dofile(path.."verbatim.lua")
+dofile(path.."code.lua")
+dofile(path.."typedef.lua")
+dofile(path.."container.lua")
+dofile(path.."package.lua")
+dofile(path.."module.lua")
+dofile(path.."namespace.lua")
+dofile(path.."define.lua")
+dofile(path.."enumerate.lua")
+dofile(path.."declaration.lua")
+dofile(path.."variable.lua")
+dofile(path.."array.lua")
+dofile(path.."function.lua")
+dofile(path.."operator.lua")
+dofile(path.."template_class.lua")
+dofile(path.."class.lua")
+dofile(path.."clean.lua")
+--dofile(path.."custom.lua")
+dofile(path.."doit.lua")
+
+local err,msg = xpcall(doit, debug.traceback)
+if not err then
+--print("**** msg is "..tostring(msg))
+ local _,_,label,msg = strfind(msg,"(.-:.-:%s*)(.*)")
+ tolua_error(msg,label)
+end
diff --git a/lib/tolua++/src/bin/lua/array.lua b/lib/tolua++/src/bin/lua/array.lua
new file mode 100644
index 000000000..f35aa98ce
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/array.lua
@@ -0,0 +1,233 @@
+-- tolua: array class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1999
+-- $Id: array.lua,v 1.1 2000/11/06 22:03:57 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Array class
+-- Represents a extern array variable or a public member of a class.
+-- Stores all fields present in a declaration.
+classArray = {
+}
+classArray.__index = classArray
+setmetatable(classArray,classDeclaration)
+
+-- Print method
+function classArray:print (ident,close)
+ print(ident.."Array{")
+ print(ident.." mod = '"..self.mod.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.." ptr = '"..self.ptr.."',")
+ print(ident.." name = '"..self.name.."',")
+ print(ident.." def = '"..self.def.."',")
+ print(ident.." dim = '"..self.dim.."',")
+ print(ident.." ret = '"..self.ret.."',")
+ print(ident.."}"..close)
+end
+
+-- check if it is a variable
+function classArray:isvariable ()
+ return true
+end
+
+
+-- get variable value
+function classArray:getvalue (class,static)
+ if class and static then
+ return class..'::'..self.name..'[tolua_index]'
+ elseif class then
+ return 'self->'..self.name..'[tolua_index]'
+ else
+ return self.name..'[tolua_index]'
+ end
+end
+
+-- Write binding functions
+function classArray:supcode ()
+ local class = self:inclass()
+
+ -- get function ------------------------------------------------
+ if class then
+ output("/* get function:",self.name," of class ",class," */")
+ else
+ output("/* get function:",self.name," */")
+ end
+ self.cgetname = self:cfuncname("tolua_get")
+ output("#ifndef TOLUA_DISABLE_"..self.cgetname)
+ output("\nstatic int",self.cgetname,"(lua_State* tolua_S)")
+ output("{")
+ output(" int tolua_index;")
+
+ -- declare self, if the case
+ local _,_,static = strfind(self.mod,'^%s*(static)')
+ if class and static==nil then
+ output(' ',self.parent.type,'*','self;')
+ output(' lua_pushstring(tolua_S,".self");')
+ output(' lua_rawget(tolua_S,1);')
+ output(' self = ')
+ output('(',self.parent.type,'*) ')
+ output('lua_touserdata(tolua_S,-1);')
+ elseif static then
+ _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+ end
+
+ -- check index
+ output('#ifndef TOLUA_RELEASE\n')
+ output(' {')
+ output(' tolua_Error tolua_err;')
+ output(' if (!tolua_isnumber(tolua_S,2,0,&tolua_err))')
+ output(' tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);')
+ output(' }')
+ output('#endif\n')
+ if flags['1'] then -- for compatibility with tolua5 ?
+ output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0)-1;')
+ else
+ output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0);')
+ end
+ output('#ifndef TOLUA_RELEASE\n')
+ if self.dim and self.dim ~= '' then
+ output(' if (tolua_index<0 || tolua_index>='..self.dim..')')
+ else
+ output(' if (tolua_index<0)')
+ end
+ output(' tolua_error(tolua_S,"array indexing out of range.",NULL);')
+ output('#endif\n')
+
+ -- return value
+ local t,ct = isbasic(self.type)
+ local push_func = get_push_function(t)
+ if t then
+ output(' tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static)..');')
+ else
+ t = self.type
+ if self.ptr == '&' or self.ptr == '' then
+ output(' ',push_func,'(tolua_S,(void*)&'..self:getvalue(class,static)..',"',t,'");')
+ else
+ output(' ',push_func,'(tolua_S,(void*)'..self:getvalue(class,static)..',"',t,'");')
+ end
+ end
+ output(' return 1;')
+ output('}')
+ output('#endif //#ifndef TOLUA_DISABLE\n')
+ output('\n')
+
+ -- set function ------------------------------------------------
+ if not strfind(self.type,'const') then
+ if class then
+ output("/* set function:",self.name," of class ",class," */")
+ else
+ output("/* set function:",self.name," */")
+ end
+ self.csetname = self:cfuncname("tolua_set")
+ output("#ifndef TOLUA_DISABLE_"..self.csetname)
+ output("\nstatic int",self.csetname,"(lua_State* tolua_S)")
+ output("{")
+
+ -- declare index
+ output(' int tolua_index;')
+
+ -- declare self, if the case
+ local _,_,static = strfind(self.mod,'^%s*(static)')
+ if class and static==nil then
+ output(' ',self.parent.type,'*','self;')
+ output(' lua_pushstring(tolua_S,".self");')
+ output(' lua_rawget(tolua_S,1);')
+ output(' self = ')
+ output('(',self.parent.type,'*) ')
+ output('lua_touserdata(tolua_S,-1);')
+ elseif static then
+ _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+ end
+
+ -- check index
+ output('#ifndef TOLUA_RELEASE\n')
+ output(' {')
+ output(' tolua_Error tolua_err;')
+ output(' if (!tolua_isnumber(tolua_S,2,0,&tolua_err))')
+ output(' tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);')
+ output(' }')
+ output('#endif\n')
+
+ if flags['1'] then -- for compatibility with tolua5 ?
+ output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0)-1;')
+ else
+ output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0);')
+ end
+
+ output('#ifndef TOLUA_RELEASE\n')
+ if self.dim and self.dim ~= '' then
+ output(' if (tolua_index<0 || tolua_index>='..self.dim..')')
+ else
+ output(' if (tolua_index<0)')
+ end
+ output(' tolua_error(tolua_S,"array indexing out of range.",NULL);')
+ output('#endif\n')
+
+ -- assign value
+ local ptr = ''
+ if self.ptr~='' then ptr = '*' end
+ output(' ')
+ if class and static then
+ output(class..'::'..self.name..'[tolua_index]')
+ elseif class then
+ output('self->'..self.name..'[tolua_index]')
+ else
+ output(self.name..'[tolua_index]')
+ end
+ local t = isbasic(self.type)
+ output(' = ')
+ if not t and ptr=='' then output('*') end
+ output('((',self.mod,self.type)
+ if not t then
+ output('*')
+ end
+ output(') ')
+ local def = 0
+ if self.def ~= '' then def = self.def end
+ if t then
+ output('tolua_to'..t,'(tolua_S,3,',def,'));')
+ else
+ local to_func = get_to_function(self.type)
+ output(to_func,'(tolua_S,3,',def,'));')
+ end
+ output(' return 0;')
+ output('}')
+ output('#endif //#ifndef TOLUA_DISABLE\n')
+ output('\n')
+ end
+
+end
+
+function classArray:register (pre)
+ if not self:check_public_access() then
+ return
+ end
+
+ pre = pre or ''
+ if self.csetname then
+ output(pre..'tolua_array(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');')
+ else
+ output(pre..'tolua_array(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);')
+ end
+end
+
+-- Internal constructor
+function _Array (t)
+ setmetatable(t,classArray)
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects a string representing the variable declaration.
+function Array (s)
+ return _Array (Declaration(s,'var'))
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/basic.lua b/lib/tolua++/src/bin/lua/basic.lua
new file mode 100644
index 000000000..f651f1fe6
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/basic.lua
@@ -0,0 +1,414 @@
+-- tolua: basic utility functions
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- Last update: Apr 2003
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Basic C types and their corresponding Lua types
+-- All occurrences of "char*" will be replaced by "_cstring",
+-- and all occurrences of "void*" will be replaced by "_userdata"
+_basic = {
+ ['void'] = '',
+ ['char'] = 'number',
+ ['int'] = 'number',
+ ['short'] = 'number',
+ ['long'] = 'number',
+ ['unsigned'] = 'number',
+ ['float'] = 'number',
+ ['double'] = 'number',
+ ['_cstring'] = 'string',
+ ['_userdata'] = 'userdata',
+ ['char*'] = 'string',
+ ['void*'] = 'userdata',
+ ['bool'] = 'boolean',
+ ['lua_Object'] = 'value',
+ ['LUA_VALUE'] = 'value', -- for compatibility with tolua 4.0
+ ['lua_State*'] = 'state',
+ ['_lstate'] = 'state',
+ ['lua_Function'] = 'value',
+}
+
+_basic_ctype = {
+ number = "lua_Number",
+ string = "const char*",
+ userdata = "void*",
+ boolean = "bool",
+ value = "int",
+ state = "lua_State*",
+}
+
+-- functions the are used to do a 'raw push' of basic types
+_basic_raw_push = {}
+
+-- List of user defined types
+-- Each type corresponds to a variable name that stores its tag value.
+_usertype = {}
+
+-- List of types that have to be collected
+_collect = {}
+
+-- List of types
+_global_types = {n=0}
+_global_types_hash = {}
+
+-- list of classes
+_global_classes = {}
+
+-- List of enum constants
+_global_enums = {}
+
+-- List of auto renaming
+_renaming = {}
+function appendrenaming (s)
+ local b,e,old,new = strfind(s,"%s*(.-)%s*@%s*(.-)%s*$")
+ if not b then
+ error("#Invalid renaming syntax; it should be of the form: pattern@pattern")
+ end
+ tinsert(_renaming,{old=old, new=new})
+end
+
+function applyrenaming (s)
+ for i=1,getn(_renaming) do
+ local m,n = gsub(s,_renaming[i].old,_renaming[i].new)
+ if n ~= 0 then
+ return m
+ end
+ end
+ return nil
+end
+
+-- Error handler
+function tolua_error (s,f)
+if _curr_code then
+ print("***curr code for error is "..tostring(_curr_code))
+ print(debug.traceback())
+end
+ local out = _OUTPUT
+ _OUTPUT = _STDERR
+ if strsub(s,1,1) == '#' then
+ write("\n** tolua: "..strsub(s,2)..".\n\n")
+ if _curr_code then
+ local _,_,s = strfind(_curr_code,"^%s*(.-\n)") -- extract first line
+ if s==nil then s = _curr_code end
+ s = gsub(s,"_userdata","void*") -- return with 'void*'
+ s = gsub(s,"_cstring","char*") -- return with 'char*'
+ s = gsub(s,"_lstate","lua_State*") -- return with 'lua_State*'
+ write("Code being processed:\n"..s.."\n")
+ end
+ else
+ if not f then f = "(f is nil)" end
+ print("\n** tolua internal error: "..f..s..".\n\n")
+ return
+ end
+ _OUTPUT = out
+end
+
+function warning (msg)
+ if flags.q then return end
+ local out = _OUTPUT
+ _OUTPUT = _STDERR
+ write("\n** tolua warning: "..msg..".\n\n")
+ _OUTPUT = out
+end
+
+-- register an user defined type: returns full type
+function regtype (t)
+ --if isbasic(t) then
+ -- return t
+ --end
+ local ft = findtype(t)
+
+ if not _usertype[ft] then
+ return appendusertype(t)
+ end
+ return ft
+end
+
+-- return type name: returns full type
+function typevar(type)
+ if type == '' or type == 'void' then
+ return type
+ else
+ local ft = findtype(type)
+ if ft then
+ return ft
+ end
+ _usertype[type] = type
+ return type
+ end
+end
+
+-- check if basic type
+function isbasic (type)
+ local t = gsub(type,'const ','')
+ local m,t = applytypedef('', t)
+ local b = _basic[t]
+ if b then
+ return b,_basic_ctype[b]
+ end
+ return nil
+end
+
+-- split string using a token
+function split (s,t)
+ local l = {n=0}
+ local f = function (s)
+ l.n = l.n + 1
+ l[l.n] = s
+ return ""
+ end
+ local p = "%s*(.-)%s*"..t.."%s*"
+ s = gsub(s,"^%s+","")
+ s = gsub(s,"%s+$","")
+ s = gsub(s,p,f)
+ l.n = l.n + 1
+ l[l.n] = gsub(s,"(%s%s*)$","")
+ return l
+end
+
+-- splits a string using a pattern, considering the spacial cases of C code (templates, function parameters, etc)
+-- pattern can't contain the '^' (as used to identify the begining of the line)
+-- also strips whitespace
+function split_c_tokens(s, pat)
+
+ s = string.gsub(s, "^%s*", "")
+ s = string.gsub(s, "%s*$", "")
+
+ local token_begin = 1
+ local token_end = 1
+ local ofs = 1
+ local ret = {n=0}
+
+ function add_token(ofs)
+
+ local t = string.sub(s, token_begin, ofs)
+ t = string.gsub(t, "^%s*", "")
+ t = string.gsub(t, "%s*$", "")
+ ret.n = ret.n + 1
+ ret[ret.n] = t
+ end
+
+ while ofs <= string.len(s) do
+
+ local sub = string.sub(s, ofs, -1)
+ local b,e = string.find(sub, "^"..pat)
+ if b then
+ add_token(ofs-1)
+ ofs = ofs+e
+ token_begin = ofs
+ else
+ local char = string.sub(s, ofs, ofs)
+ if char == "(" or char == "<" then
+
+ local block
+ if char == "(" then block = "^%b()" end
+ if char == "<" then block = "^%b<>" end
+
+ b,e = string.find(sub, block)
+ if not b then
+ -- unterminated block?
+ ofs = ofs+1
+ else
+ ofs = ofs + e
+ end
+
+ else
+ ofs = ofs+1
+ end
+ end
+
+ end
+ add_token(ofs)
+ --if ret.n == 0 then
+
+ -- ret.n=1
+ -- ret[1] = ""
+ --end
+
+ return ret
+
+end
+
+-- concatenate strings of a table
+function concat (t,f,l,jstr)
+ jstr = jstr or " "
+ local s = ''
+ local i=f
+ while i<=l do
+ s = s..t[i]
+ i = i+1
+ if i <= l then s = s..jstr end
+ end
+ return s
+end
+
+-- concatenate all parameters, following output rules
+function concatparam (line, ...)
+ local i=1
+ while i<=arg.n do
+ if _cont and not strfind(_cont,'[%(,"]') and
+ strfind(arg[i],"^[%a_~]") then
+ line = line .. ' '
+ end
+ line = line .. arg[i]
+ if arg[i] ~= '' then
+ _cont = strsub(arg[i],-1,-1)
+ end
+ i = i+1
+ end
+ if strfind(arg[arg.n],"[%/%)%;%{%}]$") then
+ _cont=nil line = line .. '\n'
+ end
+ return line
+end
+
+-- output line
+function output (...)
+ local i=1
+ while i<=arg.n do
+ if _cont and not strfind(_cont,'[%(,"]') and
+ strfind(arg[i],"^[%a_~]") then
+ write(' ')
+ end
+ write(arg[i])
+ if arg[i] ~= '' then
+ _cont = strsub(arg[i],-1,-1)
+ end
+ i = i+1
+ end
+ if strfind(arg[arg.n],"[%/%)%;%{%}]$") then
+ _cont=nil write('\n')
+ end
+end
+
+function get_property_methods(ptype, name)
+
+ if get_property_methods_hook and get_property_methods_hook(ptype,name) then
+ return get_property_methods_hook(ptype, name)
+ end
+
+ if ptype == "default" then -- get_name, set_name
+ return "get_"..name, "set_"..name
+ end
+
+ if ptype == "qt" then -- name, setName
+ return name, "set"..string.upper(string.sub(name, 1, 1))..string.sub(name, 2, -1)
+ end
+
+ if ptype == "overload" then -- name, name
+ return name,name
+ end
+
+ return nil
+end
+
+-------------- the hooks
+
+-- called right after processing the $[ichl]file directives,
+-- right before processing anything else
+-- takes the package object as the parameter
+function preprocess_hook(p)
+ -- p.code has all the input code from the pkg
+end
+
+
+-- called for every $ifile directive
+-- takes a table with a string called 'code' inside, the filename, and any extra arguments
+-- passed to $ifile. no return value
+function include_file_hook(t, filename, ...)
+
+end
+
+-- called after processing anything that's not code (like '$renaming', comments, etc)
+-- and right before parsing the actual code.
+-- takes the Package object with all the code on the 'code' key. no return value
+function preparse_hook(package)
+
+end
+
+-- called before starting output
+function pre_output_hook(package)
+
+end
+
+-- called after writing all the output.
+-- takes the Package object
+function post_output_hook(package)
+
+end
+
+
+-- called from 'get_property_methods' to get the methods to retrieve a property
+-- according to its type
+function get_property_methods_hook(property_type, name)
+
+end
+
+-- called from ClassContainer:doparse with the string being parsed
+-- return nil, or a substring
+function parser_hook(s)
+
+ return nil
+end
+
+-- called from classFunction:supcode, before the call to the function is output
+function pre_call_hook(f)
+
+end
+
+-- called from classFunction:supcode, after the call to the function is output
+function post_call_hook(f)
+
+end
+
+-- called before the register code is output
+function pre_register_hook(package)
+
+end
+
+-- called to output an error message
+function output_error_hook(...)
+ return string.format(...)
+end
+
+-- custom pushers
+
+_push_functions = {}
+_is_functions = {}
+_to_functions = {}
+
+_base_push_functions = {}
+_base_is_functions = {}
+_base_to_functions = {}
+
+local function search_base(t, funcs)
+
+ local class = _global_classes[t]
+
+ while class do
+ if funcs[class.type] then
+ return funcs[class.type]
+ end
+ class = _global_classes[class.btype]
+ end
+ return nil
+end
+
+function get_push_function(t)
+ return _push_functions[t] or search_base(t, _base_push_functions) or "tolua_pushusertype"
+end
+
+function get_to_function(t)
+ return _to_functions[t] or search_base(t, _base_to_functions) or "tolua_tousertype"
+end
+
+function get_is_function(t)
+ return _is_functions[t] or search_base(t, _base_is_functions) or "tolua_isusertype"
+end
diff --git a/lib/tolua++/src/bin/lua/class.lua b/lib/tolua++/src/bin/lua/class.lua
new file mode 100644
index 000000000..592705282
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/class.lua
@@ -0,0 +1,202 @@
+-- tolua: class class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Class class
+-- Represents a class definition.
+-- Stores the following fields:
+-- name = class name
+-- base = class base, if any (only single inheritance is supported)
+-- {i} = list of members
+classClass = {
+ classtype = 'class',
+ name = '',
+ base = '',
+ type = '',
+ btype = '',
+ ctype = '',
+}
+classClass.__index = classClass
+setmetatable(classClass,classContainer)
+
+
+-- register class
+function classClass:register (pre)
+
+ if not self:check_public_access() then
+ return
+ end
+
+ pre = pre or ''
+ push(self)
+ if _collect[self.type] then
+ output(pre,'#ifdef __cplusplus\n')
+ output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",'.._collect[self.type]..');')
+ output(pre,'#else\n')
+ output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
+ output(pre,'#endif\n')
+ else
+ output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
+ end
+ if self.extra_bases then
+ for k,base in ipairs(self.extra_bases) do
+ -- not now
+ --output(pre..' tolua_addbase(tolua_S, "'..self.type..'", "'..base..'");')
+ end
+ end
+ output(pre..'tolua_beginmodule(tolua_S,"'..self.lname..'");')
+ local i=1
+ while self[i] do
+ self[i]:register(pre..' ')
+ i = i+1
+ end
+ output(pre..'tolua_endmodule(tolua_S);')
+ pop()
+end
+
+-- return collection requirement
+function classClass:requirecollection (t)
+ if self.flags.protected_destructor or (not self:check_public_access()) then
+ return false
+ end
+ push(self)
+ local r = false
+ local i=1
+ while self[i] do
+ r = self[i]:requirecollection(t) or r
+ i = i+1
+ end
+ pop()
+ -- only class that exports destructor can be appropriately collected
+ -- classes that export constructors need to have a collector (overrided by -D flag on command line)
+ if self._delete or ((not flags['D']) and self._new) then
+ --t[self.type] = "tolua_collect_" .. gsub(self.type,"::","_")
+ t[self.type] = "tolua_collect_" .. clean_template(self.type)
+ r = true
+ end
+ return r
+end
+
+-- output tags
+function classClass:decltype ()
+ push(self)
+ self.type = regtype(self.original_name or self.name)
+ self.btype = typevar(self.base)
+ self.ctype = 'const '..self.type
+ if self.extra_bases then
+ for i=1,table.getn(self.extra_bases) do
+ self.extra_bases[i] = typevar(self.extra_bases[i])
+ end
+ end
+ local i=1
+ while self[i] do
+ self[i]:decltype()
+ i = i+1
+ end
+ pop()
+end
+
+
+-- Print method
+function classClass:print (ident,close)
+ print(ident.."Class{")
+ print(ident.." name = '"..self.name.."',")
+ print(ident.." base = '"..self.base.."';")
+ print(ident.." lname = '"..self.lname.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.." btype = '"..self.btype.."',")
+ print(ident.." ctype = '"..self.ctype.."',")
+ local i=1
+ while self[i] do
+ self[i]:print(ident.." ",",")
+ i = i+1
+ end
+ print(ident.."}"..close)
+end
+
+function classClass:set_protected_destructor(p)
+ self.flags.protected_destructor = self.flags.protected_destructor or p
+end
+
+-- Internal constructor
+function _Class (t)
+ setmetatable(t,classClass)
+ t:buildnames()
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects the name, the base (array) and the body of the class.
+function Class (n,p,b)
+
+ if table.getn(p) > 1 then
+ b = string.sub(b, 1, -2)
+ for i=2,table.getn(p),1 do
+ b = b.."\n tolua_inherits "..p[i].." __"..p[i].."__;\n"
+ end
+ b = b.."\n}"
+ end
+
+ -- check for template
+ b = string.gsub(b, "^{%s*TEMPLATE_BIND", "{\nTOLUA_TEMPLATE_BIND")
+ local t,_,T,I = string.find(b, '^{%s*TOLUA_TEMPLATE_BIND%s*%(+%s*\"?([^\",]*)\"?%s*,%s*([^%)]*)%s*%)+')
+ if t then
+
+ -- remove quotes
+ I = string.gsub(I, "\"", "")
+ T = string.gsub(T, "\"", "")
+ -- get type list
+ local types = split_c_tokens(I, ",")
+ -- remove TEMPLATE_BIND line
+ local bs = string.gsub(b, "^{%s*TOLUA_TEMPLATE_BIND[^\n]*\n", "{\n")
+
+ local Tl = split(T, " ")
+ local tc = TemplateClass(n, p, bs, Tl)
+
+
+ tc:throw(types, true)
+ --for i=1,types.n do
+ -- tc:throw(split_c_tokens(types[i], " "), true)
+ --end
+ return
+ end
+
+ local mbase
+
+ if p then
+ mbase = table.remove(p, 1)
+ if not p[1] then p = nil end
+ end
+
+ mbase = mbase and resolve_template_types(mbase)
+
+ local c
+ local oname = string.gsub(n, "@.*$", "")
+ oname = getnamespace(classContainer.curr)..oname
+
+ if _global_classes[oname] then
+ c = _global_classes[oname]
+ if mbase and ((not c.base) or c.base == "") then
+ c.base = mbase
+ end
+ else
+ c = _Class(_Container{name=n, base=mbase, extra_bases=p})
+
+ local ft = getnamespace(c.parent)..c.original_name
+ append_global_type(ft, c)
+ end
+
+ push(c)
+ c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
+ pop()
+end
+
diff --git a/lib/tolua++/src/bin/lua/clean.lua b/lib/tolua++/src/bin/lua/clean.lua
new file mode 100644
index 000000000..fd5b7b635
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/clean.lua
@@ -0,0 +1,79 @@
+-- mark up comments and strings
+STR1 = "\001"
+STR2 = "\002"
+STR3 = "\003"
+STR4 = "\004"
+REM = "\005"
+ANY = "([\001-\005])"
+ESC1 = "\006"
+ESC2 = "\007"
+
+MASK = { -- the substitution order is important
+ {ESC1, "\\'"},
+ {ESC2, '\\"'},
+ {STR1, "'"},
+ {STR2, '"'},
+ {STR3, "%[%["},
+ {STR4, "%]%]"},
+ {REM , "%-%-"},
+}
+
+function mask (s)
+ for i = 1,getn(MASK) do
+ s = gsub(s,MASK[i][2],MASK[i][1])
+ end
+ return s
+end
+
+function unmask (s)
+ for i = 1,getn(MASK) do
+ s = gsub(s,MASK[i][1],MASK[i][2])
+ end
+ return s
+end
+
+function clean (s)
+ -- check for compilation error
+ local code = "return function ()\n" .. s .. "\n end"
+ if not dostring(code) then
+ return nil
+ end
+
+ if flags['C'] then
+ return s
+ end
+
+ local S = "" -- saved string
+
+ s = mask(s)
+
+ -- remove blanks and comments
+ while 1 do
+ local b,e,d = strfind(s,ANY)
+ if b then
+ S = S..strsub(s,1,b-1)
+ s = strsub(s,b+1)
+ if d==STR1 or d==STR2 then
+ e = strfind(s,d)
+ S = S ..d..strsub(s,1,e)
+ s = strsub(s,e+1)
+ elseif d==STR3 then
+ e = strfind(s,STR4)
+ S = S..d..strsub(s,1,e)
+ s = strsub(s,e+1)
+ elseif d==REM then
+ s = gsub(s,"[^\n]*(\n?)","%1",1)
+ end
+ else
+ S = S..s
+ break
+ end
+ end
+ -- eliminate unecessary spaces
+ S = gsub(S,"[ \t]+"," ")
+ S = gsub(S,"[ \t]*\n[ \t]*","\n")
+ S = gsub(S,"\n+","\n")
+ S = unmask(S)
+ return S
+end
+
diff --git a/lib/tolua++/src/bin/lua/code.lua b/lib/tolua++/src/bin/lua/code.lua
new file mode 100644
index 000000000..5e19b6bbf
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/code.lua
@@ -0,0 +1,105 @@
+-- tolua: code class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1999
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+-- global
+code_n = 1
+
+-- Code class
+-- Represents Lua code to be compiled and included
+-- in the initialization function.
+-- The following fields are stored:
+-- text = text code
+classCode = {
+ text = '',
+}
+classCode.__index = classCode
+setmetatable(classCode,classFeature)
+
+-- register code
+function classCode:register (pre)
+ pre = pre or ''
+ -- clean Lua code
+ local s = clean(self.text)
+ if not s then
+ --print(self.text)
+ error("parser error in embedded code")
+ end
+
+ -- get first line
+ local _, _, first_line=string.find(self.text, "^([^\n\r]*)")
+ if string.find(first_line, "^%s*%-%-") then
+ if string.find(first_line, "^%-%-##") then
+ first_line = string.gsub(first_line, "^%-%-##", "")
+ if flags['C'] then
+ s = string.gsub(s, "^%-%-##[^\n\r]*\n", "")
+ end
+ end
+ else
+ first_line = ""
+ end
+
+ -- pad to 16 bytes
+ local npad = 16 - (#s % 16)
+ local spad = ""
+ for i=1,npad do
+ spad = spad .. "-"
+ end
+ s = s..spad
+
+ -- convert to C
+ output('\n'..pre..'{ /* begin embedded lua code */\n')
+ output(pre..' int top = lua_gettop(tolua_S);')
+ output(pre..' static const unsigned char B[] = {\n ')
+ local t={n=0}
+
+ local b = gsub(s,'(.)',function (c)
+ local e = ''
+ t.n=t.n+1 if t.n==15 then t.n=0 e='\n'..pre..' ' end
+ return format('%3u,%s',strbyte(c),e)
+ end
+ )
+ output(b..strbyte(" "))
+ output('\n'..pre..' };\n')
+ if first_line and first_line ~= "" then
+ output(pre..' tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: '..first_line..'");')
+ else
+ output(pre..' tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua: embedded Lua code '..code_n..'");')
+ end
+ output(pre..' lua_settop(tolua_S, top);')
+ output(pre..'} /* end of embedded lua code */\n\n')
+ code_n = code_n +1
+end
+
+
+-- Print method
+function classCode:print (ident,close)
+ print(ident.."Code{")
+ print(ident.." text = [["..self.text.."]],")
+ print(ident.."}"..close)
+end
+
+
+-- Internal constructor
+function _Code (t)
+ setmetatable(t,classCode)
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects a string representing the code text
+function Code (l)
+ return _Code {
+ text = l
+ }
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/compat-5.1.lua b/lib/tolua++/src/bin/lua/compat-5.1.lua
new file mode 100644
index 000000000..7a2c60b69
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/compat-5.1.lua
@@ -0,0 +1,57 @@
+if string.find(_VERSION, "5%.0") then
+ return
+end
+
+-- "loadfile"
+local function pp_dofile(path)
+
+ local loaded = false
+ local getfile = function()
+
+ if loaded then
+ return
+ else
+ local file,err = io.open(path)
+ if not file then
+ error("error loading file "..path..": "..err)
+ end
+ local ret = file:read("*a")
+ file:close()
+
+ ret = string.gsub(ret, "%.%.%.%s*%)", "...) local arg = {n=select('#', ...), ...};")
+
+ loaded = true
+ return ret
+ end
+ end
+
+ local f = load(getfile, path)
+ if not f then
+
+ error("error loading file "..path)
+ end
+ return f()
+end
+
+old_dofile = dofile
+dofile = pp_dofile
+
+
+-- string.gsub
+--[[
+local ogsub = string.gsub
+local function compgsub(a,b,c,d)
+ if type(c) == "function" then
+ local oc = c
+ c = function (...) return oc(...) or '' end
+ end
+ return ogsub(a,b,c,d)
+end
+string.repl = ogsub
+--]]
+
+--string.gsub = compgsub
+
+
+
+
diff --git a/lib/tolua++/src/bin/lua/compat.lua b/lib/tolua++/src/bin/lua/compat.lua
new file mode 100644
index 000000000..45d6ae1ba
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/compat.lua
@@ -0,0 +1,193 @@
+-------------------------------------------------------------------
+-- Real globals
+-- _ALERT
+-- _ERRORMESSAGE
+-- _VERSION
+-- _G
+-- assert
+-- error
+-- metatable
+-- next
+-- print
+-- require
+-- tonumber
+-- tostring
+-- type
+-- unpack
+
+-------------------------------------------------------------------
+-- collectgarbage
+-- gcinfo
+
+-- globals
+
+-- call -> protect(f, err)
+-- loadfile
+-- loadstring
+
+-- rawget
+-- rawset
+
+-- getargs = Main.getargs ??
+
+rawtype = type
+
+function do_ (f, err)
+ if not f then print(err); return end
+ local a,b = pcall(f)
+ if not a then print(b); return nil
+ else return b or true
+ end
+end
+
+function dostring(s) return do_(loadstring(s)) end
+-- function dofile(s) return do_(loadfile(s)) end
+
+-------------------------------------------------------------------
+-- Table library
+local tab = table
+foreach = tab.foreach
+foreachi = tab.foreachi
+getn = tab.getn
+tinsert = tab.insert
+tremove = tab.remove
+sort = tab.sort
+
+-------------------------------------------------------------------
+-- Debug library
+local dbg = debug
+getinfo = dbg.getinfo
+getlocal = dbg.getlocal
+setcallhook = function () error"`setcallhook' is deprecated" end
+setlinehook = function () error"`setlinehook' is deprecated" end
+setlocal = dbg.setlocal
+
+-------------------------------------------------------------------
+-- math library
+local math = math
+abs = math.abs
+acos = function (x) return math.deg(math.acos(x)) end
+asin = function (x) return math.deg(math.asin(x)) end
+atan = function (x) return math.deg(math.atan(x)) end
+atan2 = function (x,y) return math.deg(math.atan2(x,y)) end
+ceil = math.ceil
+cos = function (x) return math.cos(math.rad(x)) end
+deg = math.deg
+exp = math.exp
+floor = math.floor
+frexp = math.frexp
+ldexp = math.ldexp
+log = math.log
+log10 = math.log10
+max = math.max
+min = math.min
+mod = math.mod
+PI = math.pi
+--??? pow = math.pow
+rad = math.rad
+random = math.random
+randomseed = math.randomseed
+sin = function (x) return math.sin(math.rad(x)) end
+sqrt = math.sqrt
+tan = function (x) return math.tan(math.rad(x)) end
+
+-------------------------------------------------------------------
+-- string library
+local str = string
+strbyte = str.byte
+strchar = str.char
+strfind = str.find
+format = str.format
+gsub = str.gsub
+strlen = str.len
+strlower = str.lower
+strrep = str.rep
+strsub = str.sub
+strupper = str.upper
+
+-------------------------------------------------------------------
+-- os library
+clock = os.clock
+date = os.date
+difftime = os.difftime
+execute = os.execute --?
+exit = os.exit
+getenv = os.getenv
+remove = os.remove
+rename = os.rename
+setlocale = os.setlocale
+time = os.time
+tmpname = os.tmpname
+
+-------------------------------------------------------------------
+-- compatibility only
+getglobal = function (n) return _G[n] end
+setglobal = function (n,v) _G[n] = v end
+
+-------------------------------------------------------------------
+
+local io, tab = io, table
+
+-- IO library (files)
+_STDIN = io.stdin
+_STDERR = io.stderr
+_STDOUT = io.stdout
+_INPUT = io.stdin
+_OUTPUT = io.stdout
+seek = io.stdin.seek -- sick ;-)
+tmpfile = io.tmpfile
+closefile = io.close
+openfile = io.open
+
+function flush (f)
+ if f then f:flush()
+ else _OUTPUT:flush()
+ end
+end
+
+function readfrom (name)
+ if name == nil then
+ local f, err, cod = io.close(_INPUT)
+ _INPUT = io.stdin
+ return f, err, cod
+ else
+ local f, err, cod = io.open(name, "r")
+ _INPUT = f or _INPUT
+ return f, err, cod
+ end
+end
+
+function writeto (name)
+ if name == nil then
+ local f, err, cod = io.close(_OUTPUT)
+ _OUTPUT = io.stdout
+ return f, err, cod
+ else
+ local f, err, cod = io.open(name, "w")
+ _OUTPUT = f or _OUTPUT
+ return f, err, cod
+ end
+end
+
+function appendto (name)
+ local f, err, cod = io.open(name, "a")
+ _OUTPUT = f or _OUTPUT
+ return f, err, cod
+end
+
+function read (...)
+ local f = _INPUT
+ if rawtype(arg[1]) == 'userdata' then
+ f = tab.remove(arg, 1)
+ end
+ return f:read(unpack(arg))
+end
+
+function write (...)
+ local f = _OUTPUT
+ if rawtype(arg[1]) == 'userdata' then
+ f = tab.remove(arg, 1)
+ end
+ return f:write(unpack(arg))
+end
+
diff --git a/lib/tolua++/src/bin/lua/container.lua b/lib/tolua++/src/bin/lua/container.lua
new file mode 100644
index 000000000..2d11db7df
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/container.lua
@@ -0,0 +1,786 @@
+-- tolua: container abstract class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+-- table to store namespaced typedefs/enums in global scope
+global_typedefs = {}
+global_enums = {}
+
+-- Container class
+-- Represents a container of features to be bound
+-- to lua.
+classContainer =
+{
+ curr = nil,
+}
+classContainer.__index = classContainer
+setmetatable(classContainer,classFeature)
+
+-- output tags
+function classContainer:decltype ()
+ push(self)
+ local i=1
+ while self[i] do
+ self[i]:decltype()
+ i = i+1
+ end
+ pop()
+end
+
+
+-- write support code
+function classContainer:supcode ()
+
+ if not self:check_public_access() then
+ return
+ end
+
+ push(self)
+ local i=1
+ while self[i] do
+ if self[i]:check_public_access() then
+ self[i]:supcode()
+ end
+ i = i+1
+ end
+ pop()
+end
+
+function classContainer:hasvar ()
+ local i=1
+ while self[i] do
+ if self[i]:isvariable() then
+ return 1
+ end
+ i = i+1
+ end
+ return 0
+end
+
+-- Internal container constructor
+function _Container (self)
+ setmetatable(self,classContainer)
+ self.n = 0
+ self.typedefs = {tolua_n=0}
+ self.usertypes = {}
+ self.enums = {tolua_n=0}
+ self.lnames = {}
+ return self
+end
+
+-- push container
+function push (t)
+ t.prox = classContainer.curr
+ classContainer.curr = t
+end
+
+-- pop container
+function pop ()
+--print("name",classContainer.curr.name)
+--foreach(classContainer.curr.usertypes,print)
+--print("______________")
+ classContainer.curr = classContainer.curr.prox
+end
+
+-- get current namespace
+function getcurrnamespace ()
+ return getnamespace(classContainer.curr)
+end
+
+-- append to current container
+function append (t)
+ return classContainer.curr:append(t)
+end
+
+-- append typedef to current container
+function appendtypedef (t)
+ return classContainer.curr:appendtypedef(t)
+end
+
+-- append usertype to current container
+function appendusertype (t)
+ return classContainer.curr:appendusertype(t)
+end
+
+-- append enum to current container
+function appendenum (t)
+ return classContainer.curr:appendenum(t)
+end
+
+-- substitute typedef
+function applytypedef (mod,type)
+ return classContainer.curr:applytypedef(mod,type)
+end
+
+-- check if is type
+function findtype (type)
+ local t = classContainer.curr:findtype(type)
+ return t
+end
+
+-- check if is typedef
+function istypedef (type)
+ return classContainer.curr:istypedef(type)
+end
+
+-- get fulltype (with namespace)
+function fulltype (t)
+ local curr = classContainer.curr
+ while curr do
+ if curr then
+ if curr.typedefs and curr.typedefs[t] then
+ return curr.typedefs[t]
+ elseif curr.usertypes and curr.usertypes[t] then
+ return curr.usertypes[t]
+ end
+ end
+ curr = curr.prox
+ end
+ return t
+end
+
+-- checks if it requires collection
+function classContainer:requirecollection (t)
+ push(self)
+ local i=1
+ local r = false
+ while self[i] do
+ r = self[i]:requirecollection(t) or r
+ i = i+1
+ end
+ pop()
+ return r
+end
+
+
+-- get namesapce
+function getnamespace (curr)
+ local namespace = ''
+ while curr do
+ if curr and
+ ( curr.classtype == 'class' or curr.classtype == 'namespace')
+ then
+ namespace = (curr.original_name or curr.name) .. '::' .. namespace
+ --namespace = curr.name .. '::' .. namespace
+ end
+ curr = curr.prox
+ end
+ return namespace
+end
+
+-- get namespace (only namespace)
+function getonlynamespace ()
+ local curr = classContainer.curr
+ local namespace = ''
+ while curr do
+ if curr.classtype == 'class' then
+ return namespace
+ elseif curr.classtype == 'namespace' then
+ namespace = curr.name .. '::' .. namespace
+ end
+ curr = curr.prox
+ end
+ return namespace
+end
+
+-- check if is enum
+function isenum (type)
+ return classContainer.curr:isenum(type)
+end
+
+-- append feature to container
+function classContainer:append (t)
+ self.n = self.n + 1
+ self[self.n] = t
+ t.parent = self
+end
+
+-- append typedef
+function classContainer:appendtypedef (t)
+ local namespace = getnamespace(classContainer.curr)
+ self.typedefs.tolua_n = self.typedefs.tolua_n + 1
+ self.typedefs[self.typedefs.tolua_n] = t
+ self.typedefs[t.utype] = namespace .. t.utype
+ global_typedefs[namespace..t.utype] = t
+ t.ftype = findtype(t.type) or t.type
+ --print("appending typedef "..t.utype.." as "..namespace..t.utype.." with ftype "..t.ftype)
+ append_global_type(namespace..t.utype)
+ if t.ftype and isenum(t.ftype) then
+
+ global_enums[namespace..t.utype] = true
+ end
+end
+
+-- append usertype: return full type
+function classContainer:appendusertype (t)
+ local container
+ if t == (self.original_name or self.name) then
+ container = self.prox
+ else
+ container = self
+ end
+ local ft = getnamespace(container) .. t
+ container.usertypes[t] = ft
+ _usertype[ft] = ft
+ return ft
+end
+
+-- append enum
+function classContainer:appendenum (t)
+ local namespace = getnamespace(classContainer.curr)
+ self.enums.tolua_n = self.enums.tolua_n + 1
+ self.enums[self.enums.tolua_n] = t
+ global_enums[namespace..t.name] = t
+end
+
+-- determine lua function name overload
+function classContainer:overload (lname)
+ if not self.lnames[lname] then
+ self.lnames[lname] = 0
+ else
+ self.lnames[lname] = self.lnames[lname] + 1
+ end
+ return format("%02d",self.lnames[lname])
+end
+
+-- applies typedef: returns the 'the facto' modifier and type
+function classContainer:applytypedef (mod,type)
+ if global_typedefs[type] then
+ --print("found typedef "..global_typedefs[type].type)
+ local mod1, type1 = global_typedefs[type].mod, global_typedefs[type].ftype
+ local mod2, type2 = applytypedef(mod.." "..mod1, type1)
+ --return mod2 .. ' ' .. mod1, type2
+ return mod2, type2
+ end
+ do return mod,type end
+end
+
+-- check if it is a typedef
+function classContainer:istypedef (type)
+ local env = self
+ while env do
+ if env.typedefs then
+ local i=1
+ while env.typedefs[i] do
+ if env.typedefs[i].utype == type then
+ return type
+ end
+ i = i+1
+ end
+ end
+ env = env.parent
+ end
+ return nil
+end
+
+function find_enum_var(var)
+
+ if tonumber(var) then return var end
+
+ local c = classContainer.curr
+ while c do
+ local ns = getnamespace(c)
+ for k,v in pairs(_global_enums) do
+ if match_type(var, v, ns) then
+ return v
+ end
+ end
+ if c.base and c.base ~= '' then
+ c = _global_classes[c:findtype(c.base)]
+ else
+ c = nil
+ end
+ end
+
+ return var
+end
+
+-- check if is a registered type: return full type or nil
+function classContainer:findtype (t)
+
+ t = string.gsub(t, "=.*", "")
+ if _basic[t] then
+ return t
+ end
+
+ local _,_,em = string.find(t, "([&%*])%s*$")
+ t = string.gsub(t, "%s*([&%*])%s*$", "")
+ p = self
+ while p and type(p)=='table' do
+ local st = getnamespace(p)
+
+ for i=_global_types.n,1,-1 do -- in reverse order
+
+ if match_type(t, _global_types[i], st) then
+ return _global_types[i]..(em or "")
+ end
+ end
+ if p.base and p.base ~= '' and p.base ~= t then
+ --print("type is "..t..", p is "..p.base.." self.type is "..self.type.." self.name is "..self.name)
+ p = _global_classes[p:findtype(p.base)]
+ else
+ p = nil
+ end
+ end
+
+ return nil
+end
+
+function append_global_type(t, class)
+ _global_types.n = _global_types.n +1
+ _global_types[_global_types.n] = t
+ _global_types_hash[t] = 1
+ if class then append_class_type(t, class) end
+end
+
+function append_class_type(t,class)
+ if _global_classes[t] then
+ class.flags = _global_classes[t].flags
+ class.lnames = _global_classes[t].lnames
+ if _global_classes[t].base and (_global_classes[t].base ~= '') then
+ class.base = _global_classes[t].base or class.base
+ end
+ end
+ _global_classes[t] = class
+ class.flags = class.flags or {}
+end
+
+function match_type(childtype, regtype, st)
+--print("findtype "..childtype..", "..regtype..", "..st)
+ local b,e = string.find(regtype, childtype, -string.len(childtype), true)
+ if b then
+
+ if e == string.len(regtype) and
+ (b == 1 or (string.sub(regtype, b-1, b-1) == ':' and
+ string.sub(regtype, 1, b-1) == string.sub(st, 1, b-1))) then
+ return true
+ end
+ end
+
+ return false
+end
+
+function findtype_on_childs(self, t)
+
+ local tchild
+ if self.classtype == 'class' or self.classtype == 'namespace' then
+ for k,v in ipairs(self) do
+ if v.classtype == 'class' or v.classtype == 'namespace' then
+ if v.typedefs and v.typedefs[t] then
+ return v.typedefs[t]
+ elseif v.usertypes and v.usertypes[t] then
+ return v.usertypes[t]
+ end
+ tchild = findtype_on_childs(v, t)
+ if tchild then return tchild end
+ end
+ end
+ end
+ return nil
+
+end
+
+function classContainer:isenum (type)
+ if global_enums[type] then
+ return type
+ else
+ return false
+ end
+
+ local basetype = gsub(type,"^.*::","")
+ local env = self
+ while env do
+ if env.enums then
+ local i=1
+ while env.enums[i] do
+ if env.enums[i].name == basetype then
+ return true
+ end
+ i = i+1
+ end
+ end
+ env = env.parent
+ end
+ return false
+end
+
+methodisvirtual = false -- a global
+
+-- parse chunk
+function classContainer:doparse (s)
+--print ("parse "..s)
+
+ -- try the parser hook
+ do
+ local sub = parser_hook(s)
+ if sub then
+ return sub
+ end
+ end
+
+ -- try the null statement
+ do
+ local b,e,code = string.find(s, "^%s*;")
+ if b then
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try empty verbatim line
+ do
+ local b,e,code = string.find(s, "^%s*$\n")
+ if b then
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try Lua code
+ do
+ local b,e,code = strfind(s,"^%s*(%b\1\2)")
+ if b then
+ Code(strsub(code,2,-2))
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try C code
+ do
+ local b,e,code = strfind(s,"^%s*(%b\3\4)")
+ if b then
+ code = '{'..strsub(code,2,-2)..'\n}\n'
+ Verbatim(code,'r') -- verbatim code for 'r'egister fragment
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try C code for preamble section
+ do
+ local b,e,code = string.find(s, "^%s*(%b\5\6)")
+ if b then
+ code = string.sub(code, 2, -2).."\n"
+ Verbatim(code, '')
+ return string.sub(s, e+1)
+ end
+ end
+
+ -- try default_property directive
+ do
+ local b,e,ptype = strfind(s, "^%s*TOLUA_PROPERTY_TYPE%s*%(+%s*([^%)%s]*)%s*%)+%s*;?")
+ if b then
+ if not ptype or ptype == "" then
+ ptype = "default"
+ end
+ self:set_property_type(ptype)
+ return strsub(s, e+1)
+ end
+ end
+
+ -- try protected_destructor directive
+ do
+ local b,e = string.find(s, "^%s*TOLUA_PROTECTED_DESTRUCTOR%s*;?")
+ if b then
+ if self.set_protected_destructor then
+ self:set_protected_destructor(true)
+ end
+ return strsub(s, e+1)
+ end
+ end
+
+ -- try 'extern' keyword
+ do
+ local b,e = string.find(s, "^%s*extern%s+")
+ if b then
+ -- do nothing
+ return strsub(s, e+1)
+ end
+ end
+
+ -- try 'virtual' keyworkd
+ do
+ local b,e = string.find(s, "^%s*virtual%s+")
+ if b then
+ methodisvirtual = true
+ return strsub(s, e+1)
+ end
+ end
+
+ -- try labels (public, private, etc)
+ do
+ local b,e = string.find(s, "^%s*%w*%s*:[^:]")
+ if b then
+ return strsub(s, e) -- preserve the [^:]
+ end
+ end
+
+ -- try module
+ do
+ local b,e,name,body = strfind(s,"^%s*module%s%s*([_%w][_%w]*)%s*(%b{})%s*")
+ if b then
+ _curr_code = strsub(s,b,e)
+ Module(name,body)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try namesapce
+ do
+ local b,e,name,body = strfind(s,"^%s*namespace%s%s*([_%w][_%w]*)%s*(%b{})%s*;?")
+ if b then
+ _curr_code = strsub(s,b,e)
+ Namespace(name,body)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try define
+ do
+ local b,e,name = strfind(s,"^%s*#define%s%s*([^%s]*)[^\n]*\n%s*")
+ if b then
+ _curr_code = strsub(s,b,e)
+ Define(name)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try enumerates
+
+ do
+ local b,e,name,body,varname = strfind(s,"^%s*enum%s+(%S*)%s*(%b{})%s*([^%s;]*)%s*;?%s*")
+ if b then
+ --error("#Sorry, declaration of enums and variables on the same statement is not supported.\nDeclare your variable separately (example: '"..name.." "..varname..";')")
+ _curr_code = strsub(s,b,e)
+ Enumerate(name,body,varname)
+ return strsub(s,e+1)
+ end
+ end
+
+-- do
+-- local b,e,name,body = strfind(s,"^%s*enum%s+(%S*)%s*(%b{})%s*;?%s*")
+-- if b then
+-- _curr_code = strsub(s,b,e)
+-- Enumerate(name,body)
+-- return strsub(s,e+1)
+-- end
+-- end
+
+ do
+ local b,e,body,name = strfind(s,"^%s*typedef%s+enum[^{]*(%b{})%s*([%w_][^%s]*)%s*;%s*")
+ if b then
+ _curr_code = strsub(s,b,e)
+ Enumerate(name,body)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try operator
+ do
+ local b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&:<>,]-%s+operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
+ if not b then
+ -- try inline
+ b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&:<>,]-%s+operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)[%s\n]*%b{}%s*;?%s*")
+ end
+ if not b then
+ -- try cast operator
+ b,e,decl,kind,arg,const = strfind(s, "^%s*(operator)%s+([%w_:%d<>%*%&%s]+)%s*(%b())%s*(c?o?n?s?t?)");
+ if b then
+ local _,ie = string.find(s, "^%s*%b{}", e+1)
+ if ie then
+ e = ie
+ end
+ end
+ end
+ if b then
+ _curr_code = strsub(s,b,e)
+ Operator(decl,kind,arg,const)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try function
+ do
+ --local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w])%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
+ local b,e,decl,arg,const,virt = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)%s*(=?%s*0?)%s*;%s*")
+ if not b then
+ -- try function with template
+ b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w]%b<>)%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
+ end
+ if not b then
+ -- try a single letter function name
+ b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
+ end
+ if not b then
+ -- try function pointer
+ b,e,decl,arg,const = strfind(s,"^%s*([^%(;\n]+%b())%s*(%b())%s*;%s*")
+ if b then
+ decl = string.gsub(decl, "%(%s*%*([^%)]*)%s*%)", " %1 ")
+ end
+ end
+ if b then
+ if virt and string.find(virt, "[=0]") then
+ if self.flags then
+ self.flags.pure_virtual = true
+ end
+ end
+ _curr_code = strsub(s,b,e)
+ Function(decl,arg,const)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try inline function
+ do
+ local b,e,decl,arg,const = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)[^;{]*%b{}%s*;?%s*")
+ --local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w>])%s*(%b())%s*(c?o?n?s?t?)[^;]*%b{}%s*;?%s*")
+ if not b then
+ -- try a single letter function name
+ b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?).-%b{}%s*;?%s*")
+ end
+ if b then
+ _curr_code = strsub(s,b,e)
+ Function(decl,arg,const)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try class
+ do
+ local b,e,name,base,body
+ base = '' body = ''
+ b,e,name = strfind(s,"^%s*class%s*([_%w][_%w@]*)%s*;") -- dummy class
+ local dummy = false
+ if not b then
+ b,e,name = strfind(s,"^%s*struct%s*([_%w][_%w@]*)%s*;") -- dummy struct
+ if not b then
+ b,e,name,base,body = strfind(s,"^%s*class%s*([_%w][_%w@]*)%s*([^{]-)%s*(%b{})%s*")
+ if not b then
+ b,e,name,base,body = strfind(s,"^%s*struct%s+([_%w][_%w@]*)%s*([^{]-)%s*(%b{})%s*")
+ if not b then
+ b,e,name,base,body = strfind(s,"^%s*union%s*([_%w][_%w@]*)%s*([^{]-)%s*(%b{})%s*")
+ if not b then
+ base = ''
+ b,e,body,name = strfind(s,"^%s*typedef%s%s*struct%s%s*[_%w]*%s*(%b{})%s*([_%w][_%w@]*)%s*;")
+ end
+ end
+ end
+ else dummy = 1 end
+ else dummy = 1 end
+ if b then
+ if base ~= '' then
+ base = string.gsub(base, "^%s*:%s*", "")
+ base = string.gsub(base, "%s*public%s*", "")
+ base = split(base, ",")
+ --local b,e
+ --b,e,base = strfind(base,".-([_%w][_%w<>,:]*)$")
+ else
+ base = {}
+ end
+ _curr_code = strsub(s,b,e)
+ Class(name,base,body)
+ if not dummy then
+ varb,vare,varname = string.find(s, "^%s*([_%w]+)%s*;", e+1)
+ if varb then
+ Variable(name.." "..varname)
+ e = vare
+ end
+ end
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try typedef
+ do
+ local b,e,types = strfind(s,"^%s*typedef%s%s*(.-)%s*;%s*")
+ if b then
+ _curr_code = strsub(s,b,e)
+ Typedef(types)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try variable
+ do
+ local b,e,decl = strfind(s,"^%s*([_%w][_@%s%w%d%*&:<>,]*[_%w%d])%s*;%s*")
+ if b then
+ _curr_code = strsub(s,b,e)
+
+ local list = split_c_tokens(decl, ",")
+ Variable(list[1])
+ if list.n > 1 then
+ local _,_,type = strfind(list[1], "(.-)%s+([^%s]*)$");
+
+ local i =2;
+ while list[i] do
+ Variable(type.." "..list[i])
+ i=i+1
+ end
+ end
+ --Variable(decl)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try string
+ do
+ local b,e,decl = strfind(s,"^%s*([_%w]?[_%s%w%d]-char%s+[_@%w%d]*%s*%[%s*%S+%s*%])%s*;%s*")
+ if b then
+ _curr_code = strsub(s,b,e)
+ Variable(decl)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- try array
+ do
+ local b,e,decl = strfind(s,"^%s*([_%w][][_@%s%w%d%*&:<>]*[]_%w%d])%s*;%s*")
+ if b then
+ _curr_code = strsub(s,b,e)
+ Array(decl)
+ return strsub(s,e+1)
+ end
+ end
+
+ -- no matching
+ if gsub(s,"%s%s*","") ~= "" then
+ _curr_code = s
+ error("#parse error")
+ else
+ return ""
+ end
+
+end
+
+function classContainer:parse (s)
+
+ --self.curr_member_access = nil
+
+ while s ~= '' do
+ s = self:doparse(s)
+ methodisvirtual = false
+ end
+end
+
+
+-- property types
+
+function get_property_type()
+
+ return classContainer.curr:get_property_type()
+end
+
+function classContainer:set_property_type(ptype)
+ ptype = string.gsub(ptype, "^%s*", "")
+ ptype = string.gsub(ptype, "%s*$", "")
+
+ self.property_type = ptype
+end
+
+function classContainer:get_property_type()
+ return self.property_type or (self.parent and self.parent:get_property_type()) or "default"
+end
diff --git a/lib/tolua++/src/bin/lua/custom.lua b/lib/tolua++/src/bin/lua/custom.lua
new file mode 100644
index 000000000..de5912fb3
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/custom.lua
@@ -0,0 +1,45 @@
+
+function extract_code(fn,s)
+ local code = ""
+ if fn then
+ code = '\n$#include "'..fn..'"\n'
+ end
+ s= "\n" .. s .. "\n" -- add blank lines as sentinels
+ local _,e,c,t = strfind(s, "\n([^\n]-)SCRIPT_([%w_]*)[^\n]*\n")
+ while e do
+ t = strlower(t)
+ if t == "bind_begin" then
+ _,e,c = strfind(s,"(.-)\n[^\n]*SCRIPT_BIND_END[^\n]*\n",e)
+ if not e then
+ tolua_error("Unbalanced 'SCRIPT_BIND_BEGIN' directive in header file")
+ end
+ end
+ if t == "bind_class" or t == "bind_block" then
+ local b
+ _,e,c,b = string.find(s, "([^{]-)(%b{})", e)
+ c = c..'{\n'..extract_code(nil, b)..'\n};\n'
+ end
+ code = code .. c .. "\n"
+ _,e,c,t = strfind(s, "\n([^\n]-)SCRIPT_([%w_]*)[^\n]*\n",e)
+ end
+ return code
+end
+
+function preprocess_hook(p)
+end
+
+function preparse_hook(p)
+end
+
+function include_file_hook(p, filename)
+ do return end
+--print("FILENAME is "..filename)
+ p.code = string.gsub(p.code, "\n%s*SigC::Signal", "\n\ttolua_readonly SigC::Signal")
+ p.code = string.gsub(p.code, "#ifdef __cplusplus\nextern \"C\" {\n#endif", "")
+ p.code = string.gsub(p.code, "#ifdef __cplusplus\n};?\n#endif", "")
+ p.code = string.gsub(p.code, "DECLSPEC", "")
+ p.code = string.gsub(p.code, "SDLCALL", "")
+ p.code = string.gsub(p.code, "DLLINTERFACE", "")
+ p.code = string.gsub(p.code, "#define[^\n]*_[hH]_?%s*\n", "\n")
+--print("code is "..p.code)
+end
diff --git a/lib/tolua++/src/bin/lua/declaration.lua b/lib/tolua++/src/bin/lua/declaration.lua
new file mode 100644
index 000000000..73bbe910e
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/declaration.lua
@@ -0,0 +1,579 @@
+-- tolua: declaration class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Declaration class
+-- Represents variable, function, or argument declaration.
+-- Stores the following fields:
+-- mod = type modifiers
+-- type = type
+-- ptr = "*" or "&", if representing a pointer or a reference
+-- name = name
+-- dim = dimension, if a vector
+-- def = default value, if any (only for arguments)
+-- ret = "*" or "&", if value is to be returned (only for arguments)
+classDeclaration = {
+ mod = '',
+ type = '',
+ ptr = '',
+ name = '',
+ dim = '',
+ ret = '',
+ def = ''
+}
+classDeclaration.__index = classDeclaration
+setmetatable(classDeclaration,classFeature)
+
+-- Create an unique variable name
+function create_varname ()
+ if not _varnumber then _varnumber = 0 end
+ _varnumber = _varnumber + 1
+ return "tolua_var_".._varnumber
+end
+
+-- Check declaration name
+-- It also identifies default values
+function classDeclaration:checkname ()
+
+ if strsub(self.name,1,1) == '[' and not findtype(self.type) then
+ self.name = self.type..self.name
+ local m = split(self.mod,'%s%s*')
+ self.type = m[m.n]
+ self.mod = concat(m,1,m.n-1)
+ end
+
+ local t = split(self.name,'=')
+ if t.n==2 then
+ self.name = t[1]
+ self.def = find_enum_var(t[t.n])
+ end
+
+ local b,e,d = strfind(self.name,"%[(.-)%]")
+ if b then
+ self.name = strsub(self.name,1,b-1)
+ self.dim = find_enum_var(d)
+ end
+
+
+ if self.type ~= '' and self.type ~= 'void' and self.name == '' then
+ self.name = create_varname()
+ elseif self.kind=='var' then
+ if self.type=='' and self.name~='' then
+ self.type = self.type..self.name
+ self.name = create_varname()
+ elseif findtype(self.name) then
+ if self.type=='' then self.type = self.name
+ else self.type = self.type..' '..self.name end
+ self.name = create_varname()
+ end
+ end
+
+ -- adjust type of string
+ if self.type == 'char' and self.dim ~= '' then
+ self.type = 'char*'
+ end
+
+ if self.kind and self.kind == 'var' then
+ self.name = string.gsub(self.name, ":.*$", "") -- ???
+ end
+end
+
+-- Check declaration type
+-- Substitutes typedef's.
+function classDeclaration:checktype ()
+
+ -- check if there is a pointer to basic type
+ local basic = isbasic(self.type)
+ if self.kind == 'func' and basic=='number' and string.find(self.ptr, "%*") then
+ self.type = '_userdata'
+ self.ptr = ""
+ end
+ if basic and self.ptr~='' then
+ self.ret = self.ptr
+ self.ptr = nil
+ if isbasic(self.type) == 'number' then
+ self.return_userdata = true
+ end
+ end
+
+ -- check if there is array to be returned
+ if self.dim~='' and self.ret~='' then
+ error('#invalid parameter: cannot return an array of values')
+ end
+ -- restore 'void*' and 'string*'
+ if self.type == '_userdata' then self.type = 'void*'
+ elseif self.type == '_cstring' then self.type = 'char*'
+ elseif self.type == '_lstate' then self.type = 'lua_State*'
+ end
+
+ -- resolve types inside the templates
+ if self.type then
+ self.type = resolve_template_types(self.type)
+ end
+
+--
+-- -- if returning value, automatically set default value
+-- if self.ret ~= '' and self.def == '' then
+-- self.def = '0'
+-- end
+--
+
+end
+
+function resolve_template_types(type)
+
+ if isbasic(type) then
+ return type
+ end
+ local b,_,m = string.find(type, "(%b<>)")
+ if b then
+
+ m = split_c_tokens(string.sub(m, 2, -2), ",")
+ for i=1, table.getn(m) do
+ m[i] = string.gsub(m[i],"%s*([%*&])", "%1")
+ if not isbasic(m[i]) then
+ if not isenum(m[i]) then _, m[i] = applytypedef("", m[i]) end
+ m[i] = findtype(m[i]) or m[i]
+ m[i] = resolve_template_types(m[i])
+ end
+ end
+
+ local b,i
+ type,b,i = break_template(type)
+--print("concat is ",concat(m, 1, m.n))
+ local template_part = "<"..concat(m, 1, m.n, ",")..">"
+ type = rebuild_template(type, b, template_part)
+ type = string.gsub(type, ">>", "> >")
+ end
+ return type
+end
+
+function break_template(s)
+ local b,e,timpl = string.find(s, "(%b<>)")
+ if timpl then
+ s = string.gsub(s, "%b<>", "")
+ return s, b, timpl
+ else
+ return s, 0, nil
+ end
+end
+
+function rebuild_template(s, b, timpl)
+
+ if b == 0 then
+ return s
+ end
+
+ return string.sub(s, 1, b-1)..timpl..string.sub(s, b, -1)
+end
+
+-- Print method
+function classDeclaration:print (ident,close)
+ print(ident.."Declaration{")
+ print(ident.." mod = '"..self.mod.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.." ptr = '"..self.ptr.."',")
+ print(ident.." name = '"..self.name.."',")
+ print(ident.." dim = '"..self.dim.."',")
+ print(ident.." def = '"..self.def.."',")
+ print(ident.." ret = '"..self.ret.."',")
+ print(ident.."}"..close)
+end
+
+-- check if array of values are returned to Lua
+function classDeclaration:requirecollection (t)
+ if self.mod ~= 'const' and
+ self.dim and self.dim ~= '' and
+ not isbasic(self.type) and
+ self.ptr == '' and self:check_public_access() then
+ local type = gsub(self.type,"%s*const%s+","")
+ t[type] = "tolua_collect_" .. clean_template(type)
+ return true
+ end
+ return false
+end
+
+-- declare tag
+function classDeclaration:decltype ()
+
+ self.type = typevar(self.type)
+ if strfind(self.mod,'const') then
+ self.type = 'const '..self.type
+ self.mod = gsub(self.mod,'const%s*','')
+ end
+end
+
+
+-- output type checking
+function classDeclaration:outchecktype (narg)
+ local def
+ local t = isbasic(self.type)
+ if self.def~='' then
+ def = 1
+ else
+ def = 0
+ end
+ if self.dim ~= '' then
+ --if t=='string' then
+ -- return 'tolua_isstringarray(tolua_S,'..narg..','..def..',&tolua_err)'
+ --else
+ return '!tolua_istable(tolua_S,'..narg..',0,&tolua_err)'
+ --end
+ elseif t then
+ return '!tolua_is'..t..'(tolua_S,'..narg..','..def..',&tolua_err)'
+ else
+ local is_func = get_is_function(self.type)
+ if self.ptr == '&' or self.ptr == '' then
+ return '(tolua_isvaluenil(tolua_S,'..narg..',&tolua_err) || !'..is_func..'(tolua_S,'..narg..',"'..self.type..'",'..def..',&tolua_err))'
+ else
+ return '!'..is_func..'(tolua_S,'..narg..',"'..self.type..'",'..def..',&tolua_err)'
+ end
+ end
+end
+
+function classDeclaration:builddeclaration (narg, cplusplus)
+ local array = self.dim ~= '' and tonumber(self.dim)==nil
+ local line = ""
+ local ptr = ''
+ local mod
+ local type = self.type
+ local nctype = gsub(self.type,'const%s+','')
+ if self.dim ~= '' then
+ type = gsub(self.type,'const%s+','') -- eliminates const modifier for arrays
+ end
+ if self.ptr~='' and not isbasic(type) then ptr = '*' end
+ line = concatparam(line," ",self.mod,type,ptr)
+ if array then
+ line = concatparam(line,'*')
+ end
+ line = concatparam(line,self.name)
+ if self.dim ~= '' then
+ if tonumber(self.dim)~=nil then
+ line = concatparam(line,'[',self.dim,'];')
+ else
+ if cplusplus then
+ line = concatparam(line,' = Mtolua_new_dim(',type,ptr,', '..self.dim..');')
+ else
+ line = concatparam(line,' = (',type,ptr,'*)',
+ 'malloc((',self.dim,')*sizeof(',type,ptr,'));')
+ end
+ end
+ else
+ local t = isbasic(type)
+ line = concatparam(line,' = ')
+ if t == 'state' then
+ line = concatparam(line, 'tolua_S;')
+ else
+ --print("t is "..tostring(t)..", ptr is "..tostring(self.ptr))
+ if t == 'number' and string.find(self.ptr, "%*") then
+ t = 'userdata'
+ end
+ if not t and ptr=='' then line = concatparam(line,'*') end
+ line = concatparam(line,'((',self.mod,type)
+ if not t then
+ line = concatparam(line,'*')
+ end
+ line = concatparam(line,') ')
+ if isenum(nctype) then
+ line = concatparam(line,'(int) ')
+ end
+ local def = 0
+ if self.def ~= '' then
+ def = self.def
+ if (ptr == '' or self.ptr == '&') and not t then
+ def = "(void*)&(const "..type..")"..def
+ end
+ end
+ if t then
+ line = concatparam(line,'tolua_to'..t,'(tolua_S,',narg,',',def,'));')
+ else
+ local to_func = get_to_function(type)
+ line = concatparam(line,to_func..'(tolua_S,',narg,',',def,'));')
+ end
+ end
+ end
+ return line
+end
+
+-- Declare variable
+function classDeclaration:declare (narg)
+ if self.dim ~= '' and tonumber(self.dim)==nil then
+ output('#ifdef __cplusplus\n')
+ output(self:builddeclaration(narg,true))
+ output('#else\n')
+ output(self:builddeclaration(narg,false))
+ output('#endif\n')
+ else
+ output(self:builddeclaration(narg,false))
+ end
+end
+
+-- Get parameter value
+function classDeclaration:getarray (narg)
+ if self.dim ~= '' then
+ local type = gsub(self.type,'const ','')
+ output(' {')
+ output('#ifndef TOLUA_RELEASE\n')
+ local def; if self.def~='' then def=1 else def=0 end
+ local t = isbasic(type)
+ if (t) then
+ output(' if (!tolua_is'..t..'array(tolua_S,',narg,',',self.dim,',',def,',&tolua_err))')
+ else
+ output(' if (!tolua_isusertypearray(tolua_S,',narg,',"',type,'",',self.dim,',',def,',&tolua_err))')
+ end
+ output(' goto tolua_lerror;')
+ output(' else\n')
+ output('#endif\n')
+ output(' {')
+ output(' int i;')
+ output(' for(i=0; i<'..self.dim..';i++)')
+ local t = isbasic(type)
+ local ptr = ''
+ if self.ptr~='' then ptr = '*' end
+ output(' ',self.name..'[i] = ')
+ if not t and ptr=='' then output('*') end
+ output('((',type)
+ if not t then
+ output('*')
+ end
+ output(') ')
+ local def = 0
+ if self.def ~= '' then def = self.def end
+ if t then
+ output('tolua_tofield'..t..'(tolua_S,',narg,',i+1,',def,'));')
+ else
+ output('tolua_tofieldusertype(tolua_S,',narg,',i+1,',def,'));')
+ end
+ output(' }')
+ output(' }')
+ end
+end
+
+-- Get parameter value
+function classDeclaration:setarray (narg)
+ if not strfind(self.type,'const%s+') and self.dim ~= '' then
+ local type = gsub(self.type,'const ','')
+ output(' {')
+ output(' int i;')
+ output(' for(i=0; i<'..self.dim..';i++)')
+ local t,ct = isbasic(type)
+ if t then
+ output(' tolua_pushfield'..t..'(tolua_S,',narg,',i+1,(',ct,')',self.name,'[i]);')
+ else
+ if self.ptr == '' then
+ output(' {')
+ output('#ifdef __cplusplus\n')
+ output(' void* tolua_obj = Mtolua_new((',type,')(',self.name,'[i]));')
+ output(' tolua_pushfieldusertype_and_takeownership(tolua_S,',narg,',i+1,tolua_obj,"',type,'");')
+ output('#else\n')
+ output(' void* tolua_obj = tolua_copy(tolua_S,(void*)&',self.name,'[i],sizeof(',type,'));')
+ output(' tolua_pushfieldusertype(tolua_S,',narg,',i+1,tolua_obj,"',type,'");')
+ output('#endif\n')
+ output(' }')
+ else
+ output(' tolua_pushfieldusertype(tolua_S,',narg,',i+1,(void*)',self.name,'[i],"',type,'");')
+ end
+ end
+ output(' }')
+ end
+end
+
+-- Free dynamically allocated array
+function classDeclaration:freearray ()
+ if self.dim ~= '' and tonumber(self.dim)==nil then
+ output('#ifdef __cplusplus\n')
+ output(' Mtolua_delete_dim(',self.name,');')
+ output('#else\n')
+ output(' free(',self.name,');')
+ output('#endif\n')
+ end
+end
+
+-- Pass parameter
+function classDeclaration:passpar ()
+ if self.ptr=='&' and not isbasic(self.type) then
+ output('*'..self.name)
+ elseif self.ret=='*' then
+ output('&'..self.name)
+ else
+ output(self.name)
+ end
+end
+
+-- Return parameter value
+function classDeclaration:retvalue ()
+ if self.ret ~= '' then
+ local t,ct = isbasic(self.type)
+ if t and t~='' then
+ output(' tolua_push'..t..'(tolua_S,(',ct,')'..self.name..');')
+ else
+ local push_func = get_push_function(self.type)
+ output(' ',push_func,'(tolua_S,(void*)'..self.name..',"',self.type,'");')
+ end
+ return 1
+ end
+ return 0
+end
+
+-- Internal constructor
+function _Declaration (t)
+
+ setmetatable(t,classDeclaration)
+ t:buildnames()
+ t:checkname()
+ t:checktype()
+ local ft = findtype(t.type) or t.type
+ if not isenum(ft) then
+ t.mod, t.type = applytypedef(t.mod, ft)
+ end
+
+ if t.kind=="var" and (string.find(t.mod, "tolua_property%s") or string.find(t.mod, "tolua_property$")) then
+ t.mod = string.gsub(t.mod, "tolua_property", "tolua_property__"..get_property_type())
+ end
+
+ return t
+end
+
+-- Constructor
+-- Expects the string declaration.
+-- The kind of declaration can be "var" or "func".
+function Declaration (s,kind,is_parameter)
+
+ -- eliminate spaces if default value is provided
+ s = gsub(s,"%s*=%s*","=")
+ s = gsub(s, "%s*<", "<")
+
+ local defb,tmpdef
+ defb,_,tmpdef = string.find(s, "(=.*)$")
+ if defb then
+ s = string.gsub(s, "=.*$", "")
+ else
+ tmpdef = ''
+ end
+ if kind == "var" then
+ -- check the form: void
+ if s == '' or s == 'void' then
+ return _Declaration{type = 'void', kind = kind, is_parameter = is_parameter}
+ end
+ end
+
+ -- check the form: mod type*& name
+ local t = split_c_tokens(s,'%*%s*&')
+ if t.n == 2 then
+ if kind == 'func' then
+ error("#invalid function return type: "..s)
+ end
+ --local m = split(t[1],'%s%s*')
+ local m = split_c_tokens(t[1],'%s+')
+ return _Declaration{
+ name = t[2]..tmpdef,
+ ptr = '*',
+ ret = '&',
+ --type = rebuild_template(m[m.n], tb, timpl),
+ type = m[m.n],
+ mod = concat(m,1,m.n-1),
+ is_parameter = is_parameter,
+ kind = kind
+ }
+ end
+
+ -- check the form: mod type** name
+ t = split_c_tokens(s,'%*%s*%*')
+ if t.n == 2 then
+ if kind == 'func' then
+ error("#invalid function return type: "..s)
+ end
+ --local m = split(t[1],'%s%s*')
+ local m = split_c_tokens(t[1],'%s+')
+ return _Declaration{
+ name = t[2]..tmpdef,
+ ptr = '*',
+ ret = '*',
+ --type = rebuild_template(m[m.n], tb, timpl),
+ type = m[m.n],
+ mod = concat(m,1,m.n-1),
+ is_parameter = is_parameter,
+ kind = kind
+ }
+ end
+
+ -- check the form: mod type& name
+ t = split_c_tokens(s,'&')
+ if t.n == 2 then
+ --local m = split(t[1],'%s%s*')
+ local m = split_c_tokens(t[1],'%s+')
+ return _Declaration{
+ name = t[2]..tmpdef,
+ ptr = '&',
+ --type = rebuild_template(m[m.n], tb, timpl),
+ type = m[m.n],
+ mod = concat(m,1,m.n-1),
+ is_parameter = is_parameter,
+ kind = kind
+ }
+ end
+
+ -- check the form: mod type* name
+ local s1 = gsub(s,"(%b\[\])",function (n) return gsub(n,'%*','\1') end)
+ t = split_c_tokens(s1,'%*')
+ if t.n == 2 then
+ t[2] = gsub(t[2],'\1','%*') -- restore * in dimension expression
+ --local m = split(t[1],'%s%s*')
+ local m = split_c_tokens(t[1],'%s+')
+ return _Declaration{
+ name = t[2]..tmpdef,
+ ptr = '*',
+ type = m[m.n],
+ --type = rebuild_template(m[m.n], tb, timpl),
+ mod = concat(m,1,m.n-1) ,
+ is_parameter = is_parameter,
+ kind = kind
+ }
+ end
+
+ if kind == 'var' then
+ -- check the form: mod type name
+ --t = split(s,'%s%s*')
+ t = split_c_tokens(s,'%s+')
+ local v
+ if findtype(t[t.n]) then v = create_varname() else v = t[t.n]; t.n = t.n-1 end
+ return _Declaration{
+ name = v..tmpdef,
+ --type = rebuild_template(t[t.n], tb, timpl),
+ type = t[t.n],
+ mod = concat(t,1,t.n-1),
+ is_parameter = is_parameter,
+ kind = kind
+ }
+
+ else -- kind == "func"
+
+ -- check the form: mod type name
+ --t = split(s,'%s%s*')
+ t = split_c_tokens(s,'%s+')
+ local v = t[t.n] -- last word is the function name
+ local tp,md
+ if t.n>1 then
+ tp = t[t.n-1]
+ md = concat(t,1,t.n-2)
+ end
+ --if tp then tp = rebuild_template(tp, tb, timpl) end
+ return _Declaration{
+ name = v,
+ type = tp,
+ mod = md,
+ is_parameter = is_parameter,
+ kind = kind
+ }
+ end
+
+end
+
diff --git a/lib/tolua++/src/bin/lua/define.lua b/lib/tolua++/src/bin/lua/define.lua
new file mode 100644
index 000000000..96a28d878
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/define.lua
@@ -0,0 +1,63 @@
+-- tolua: define class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: define.lua,v 1.2 1999/07/28 22:21:08 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Define class
+-- Represents a numeric const definition
+-- The following filds are stored:
+-- name = constant name
+classDefine = {
+ name = '',
+}
+classDefine.__index = classDefine
+setmetatable(classDefine,classFeature)
+
+-- register define
+function classDefine:register (pre)
+ if not self:check_public_access() then
+ return
+ end
+
+ pre = pre or ''
+ output(pre..'tolua_constant(tolua_S,"'..self.lname..'",'..self.name..');')
+end
+
+-- Print method
+function classDefine:print (ident,close)
+ print(ident.."Define{")
+ print(ident.." name = '"..self.name.."',")
+ print(ident.." lname = '"..self.lname.."',")
+ print(ident.."}"..close)
+end
+
+
+-- Internal constructor
+function _Define (t)
+ setmetatable(t,classDefine)
+ t:buildnames()
+
+ if t.name == '' then
+ error("#invalid define")
+ end
+
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects a string representing the constant name
+function Define (n)
+ return _Define{
+ name = n
+ }
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/doit.lua b/lib/tolua++/src/bin/lua/doit.lua
new file mode 100644
index 000000000..51dd0cf3c
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/doit.lua
@@ -0,0 +1,102 @@
+-- Generate binding code
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- Last update: Apr 2003
+-- $Id: $
+
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+function parse_extra()
+
+ for k,v in ipairs(_extra_parameters or {}) do
+
+ local b,e,name,value = string.find(v, "^([^=]*)=(.*)$")
+ if b then
+ _extra_parameters[name] = value
+ else
+ _extra_parameters[v] = true
+ end
+ end
+end
+
+function doit ()
+ -- define package name, if not provided
+ if not flags.n then
+ if flags.f then
+ flags.n = gsub(flags.f,"%..*$","")
+ _,_,flags.n = string.find(flags.n, "([^/\\]*)$")
+ else
+ error("#no package name nor input file provided")
+ end
+ end
+
+ -- parse table with extra paramters
+ parse_extra()
+
+ -- do this after setting the package name
+ if flags['L'] then
+ dofile(flags['L'])
+ end
+
+ -- add cppstring
+ if not flags['S'] then
+ _basic['string'] = 'cppstring'
+ _basic['std::string'] = 'cppstring'
+ _basic['AString'] = 'cppstring'
+ _basic_ctype.cppstring = 'const char*'
+ end
+
+ -- proccess package
+ local p = Package(flags.n,flags.f)
+
+ if flags.p then
+ return -- only parse
+ end
+
+ if flags.o then
+ local st,msg = writeto(flags.o)
+ if not st then
+ error('#'..msg)
+ end
+ end
+
+ p:decltype()
+ if flags.P then
+ p:print()
+ else
+ push(p)
+ pre_output_hook(p)
+ pop()
+ p:preamble()
+ p:supcode()
+ push(p)
+ pre_register_hook(p)
+ pop()
+ p:register()
+ push(p)
+ post_output_hook(p)
+ pop()
+ end
+
+ if flags.o then
+ writeto()
+ end
+
+ -- write header file
+ if not flags.P then
+ if flags.H then
+ local st,msg = writeto(flags.H)
+ if not st then
+ error('#'..msg)
+ end
+ p:header()
+ writeto()
+ end
+ end
+end
+
diff --git a/lib/tolua++/src/bin/lua/enumerate.lua b/lib/tolua++/src/bin/lua/enumerate.lua
new file mode 100644
index 000000000..99fe74629
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/enumerate.lua
@@ -0,0 +1,106 @@
+-- tolua: enumerate class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: enumerate.lua,v 1.3 2000/01/24 20:41:15 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Enumerate class
+-- Represents enumeration
+-- The following fields are stored:
+-- {i} = list of constant names
+classEnumerate = {
+}
+classEnumerate.__index = classEnumerate
+setmetatable(classEnumerate,classFeature)
+
+-- register enumeration
+function classEnumerate:register (pre)
+ if not self:check_public_access() then
+ return
+ end
+ pre = pre or ''
+ local nspace = getnamespace(classContainer.curr)
+ local i=1
+ while self[i] do
+ if self.lnames[i] and self.lnames[i] ~= "" then
+
+ output(pre..'tolua_constant(tolua_S,"'..self.lnames[i]..'",'..nspace..self[i]..');')
+ end
+ i = i+1
+ end
+end
+
+-- Print method
+function classEnumerate:print (ident,close)
+ print(ident.."Enumerate{")
+ print(ident.." name = "..self.name)
+ local i=1
+ while self[i] do
+ print(ident.." '"..self[i].."'("..self.lnames[i].."),")
+ i = i+1
+ end
+ print(ident.."}"..close)
+end
+
+-- Internal constructor
+function _Enumerate (t,varname)
+ setmetatable(t,classEnumerate)
+ append(t)
+ appendenum(t)
+ if varname and varname ~= "" then
+ if t.name ~= "" then
+ Variable(t.name.." "..varname)
+ else
+ local ns = getcurrnamespace()
+ warning("Variable "..ns..varname.." of type <anonymous enum> is declared as read-only")
+ Variable("tolua_readonly int "..varname)
+ end
+ end
+ local parent = classContainer.curr
+ if parent then
+ t.access = parent.curr_member_access
+ t.global_access = t:check_public_access()
+ end
+return t
+end
+
+-- Constructor
+-- Expects a string representing the enumerate body
+function Enumerate (n,b,varname)
+ b = string.gsub(b, ",[%s\n]*}", "\n}") -- eliminate last ','
+ local t = split(strsub(b,2,-2),',') -- eliminate braces
+ local i = 1
+ local e = {n=0}
+ while t[i] do
+ local tt = split(t[i],'=') -- discard initial value
+ e.n = e.n + 1
+ e[e.n] = tt[1]
+ i = i+1
+ end
+ -- set lua names
+ i = 1
+ e.lnames = {}
+ local ns = getcurrnamespace()
+ while e[i] do
+ local t = split(e[i],'@')
+ e[i] = t[1]
+ if not t[2] then
+ t[2] = applyrenaming(t[1])
+ end
+ e.lnames[i] = t[2] or t[1]
+ _global_enums[ ns..e[i] ] = (ns..e[i])
+ i = i+1
+ end
+ e.name = n
+ if n ~= "" then
+ Typedef("int "..n)
+ end
+ return _Enumerate(e, varname)
+end
+
diff --git a/lib/tolua++/src/bin/lua/feature.lua b/lib/tolua++/src/bin/lua/feature.lua
new file mode 100644
index 000000000..042b5d28e
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/feature.lua
@@ -0,0 +1,139 @@
+-- tolua: abstract feature class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Feature class
+-- Represents the base class of all mapped feature.
+classFeature = {
+}
+classFeature.__index = classFeature
+
+-- write support code
+function classFeature:supcode ()
+end
+
+-- output tag
+function classFeature:decltype ()
+end
+
+-- register feature
+function classFeature:register (pre)
+end
+
+-- translate verbatim
+function classFeature:preamble ()
+end
+
+-- check if it is a variable
+function classFeature:isvariable ()
+ return false
+end
+
+-- check if it requires collection
+function classFeature:requirecollection (t)
+ return false
+end
+
+-- build names
+function classFeature:buildnames ()
+ if self.name and self.name~='' then
+ local n = split(self.name,'@')
+ self.name = n[1]
+ self.name = string.gsub(self.name, ":%d*$", "")
+ if not n[2] then
+ n[2] = applyrenaming(n[1])
+ end
+ self.lname = n[2] or gsub(n[1],"%[.-%]","")
+ self.lname = string.gsub(self.lname, ":%d*$", "")
+ self.original_name = self.name
+ self.lname = clean_template(self.lname)
+ end
+ if not self.is_parameter then
+ self.name = getonlynamespace() .. self.name
+ end
+
+ local parent = classContainer.curr
+ if parent then
+ self.access = parent.curr_member_access
+ self.global_access = self:check_public_access()
+ else
+ end
+end
+
+function classFeature:check_public_access()
+
+ if type(self.global_access) == "boolean" then
+ return self.global_access
+ end
+
+ if self.access and self.access ~= 0 then
+ return false
+ end
+
+ local parent = classContainer.curr
+ while parent do
+ if parent.access and parent.access ~= 0 then
+ return false
+ end
+ parent = parent.prox
+ end
+ return true
+end
+
+function clean_template(t)
+
+ return string.gsub(t, "[<>:, %*]", "_")
+end
+
+-- check if feature is inside a container definition
+-- it returns the container class name or nil.
+function classFeature:incontainer (which)
+ if self.parent then
+ local parent = self.parent
+ while parent do
+ if parent.classtype == which then
+ return parent.name
+ end
+ parent = parent.parent
+ end
+ end
+ return nil
+end
+
+function classFeature:inclass ()
+ return self:incontainer('class')
+end
+
+function classFeature:inmodule ()
+ return self:incontainer('module')
+end
+
+function classFeature:innamespace ()
+ return self:incontainer('namespace')
+end
+
+-- return C binding function name based on name
+-- the client specifies a prefix
+function classFeature:cfuncname (n)
+
+ if self.parent then
+ n = self.parent:cfuncname(n)
+ end
+
+ local fname = self.lname
+ if not fname or fname == '' then
+ fname = self.name
+ end
+ n = string.gsub(n..'_'.. (fname), "[<>:, \.%*&]", "_")
+
+ return n
+end
+
diff --git a/lib/tolua++/src/bin/lua/function.lua b/lib/tolua++/src/bin/lua/function.lua
new file mode 100644
index 000000000..2358e9ff7
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/function.lua
@@ -0,0 +1,577 @@
+-- tolua: function class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Function class
+-- Represents a function or a class method.
+-- The following fields are stored:
+-- mod = type modifiers
+-- type = type
+-- ptr = "*" or "&", if representing a pointer or a reference
+-- name = name
+-- lname = lua name
+-- args = list of argument declarations
+-- const = if it is a method receiving a const "this".
+classFunction = {
+ mod = '',
+ type = '',
+ ptr = '',
+ name = '',
+ args = {n=0},
+ const = '',
+}
+classFunction.__index = classFunction
+setmetatable(classFunction,classFeature)
+
+-- declare tags
+function classFunction:decltype ()
+ self.type = typevar(self.type)
+ if strfind(self.mod,'const') then
+ self.type = 'const '..self.type
+ self.mod = gsub(self.mod,'const','')
+ end
+ local i=1
+ while self.args[i] do
+ self.args[i]:decltype()
+ i = i+1
+ end
+end
+
+
+-- Write binding function
+-- Outputs C/C++ binding function.
+function classFunction:supcode (local_constructor)
+
+ local overload = strsub(self.cname,-2,-1) - 1 -- indicate overloaded func
+ local nret = 0 -- number of returned values
+ local class = self:inclass()
+ local _,_,static = strfind(self.mod,'^%s*(static)')
+ if class then
+
+ if self.name == 'new' and self.parent.flags.pure_virtual then
+ -- no constructor for classes with pure virtual methods
+ return
+ end
+
+ if local_constructor then
+ output("/* method: new_local of class ",class," */")
+ else
+ output("/* method:",self.name," of class ",class," */")
+ end
+ else
+ output("/* function:",self.name," */")
+ end
+
+ if local_constructor then
+ output("#ifndef TOLUA_DISABLE_"..self.cname.."_local")
+ output("\nstatic int",self.cname.."_local","(lua_State* tolua_S)")
+ else
+ output("#ifndef TOLUA_DISABLE_"..self.cname)
+ output("\nstatic int",self.cname,"(lua_State* tolua_S)")
+ end
+ output("{")
+
+ -- check types
+ if overload < 0 then
+ output('#ifndef TOLUA_RELEASE\n')
+ end
+ output(' tolua_Error tolua_err;')
+ output(' if (\n')
+ -- check self
+ local narg
+ if class then narg=2 else narg=1 end
+ if class then
+ local func = get_is_function(self.parent.type)
+ local type = self.parent.type
+ if self.name=='new' or static~=nil then
+ func = 'tolua_isusertable'
+ type = self.parent.type
+ end
+ if self.const ~= '' then
+ type = "const "..type
+ end
+ output(' !'..func..'(tolua_S,1,"'..type..'",0,&tolua_err) ||\n')
+ end
+ -- check args
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ local btype = isbasic(self.args[i].type)
+ if btype ~= 'value' and btype ~= 'state' then
+ output(' '..self.args[i]:outchecktype(narg)..' ||\n')
+ end
+ if btype ~= 'state' then
+ narg = narg+1
+ end
+ i = i+1
+ end
+ end
+ -- check end of list
+ output(' !tolua_isnoobj(tolua_S,'..narg..',&tolua_err)\n )')
+ output(' goto tolua_lerror;')
+
+ output(' else\n')
+ if overload < 0 then
+ output('#endif\n')
+ end
+ output(' {')
+
+ -- declare self, if the case
+ local narg
+ if class then narg=2 else narg=1 end
+ if class and self.name~='new' and static==nil then
+ output(' ',self.const,self.parent.type,'*','self = ')
+ output('(',self.const,self.parent.type,'*) ')
+ local to_func = get_to_function(self.parent.type)
+ output(to_func,'(tolua_S,1,0);')
+ elseif static then
+ _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+ end
+ -- declare parameters
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:declare(narg)
+ if isbasic(self.args[i].type) ~= "state" then
+ narg = narg+1
+ end
+ i = i+1
+ end
+ end
+
+ -- check self
+ if class and self.name~='new' and static==nil then
+ output('#ifndef TOLUA_RELEASE\n')
+ output(' if (!self) tolua_error(tolua_S,"'..output_error_hook("invalid \'self\' in function \'%s\'", self.name)..'", NULL);');
+ output('#endif\n')
+ end
+
+ -- get array element values
+ if class then narg=2 else narg=1 end
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:getarray(narg)
+ narg = narg+1
+ i = i+1
+ end
+ end
+
+ pre_call_hook(self)
+
+ local out = string.find(self.mod, "tolua_outside")
+ -- call function
+ if class and self.name=='delete' then
+ output(' Mtolua_delete(self);')
+ elseif class and self.name == 'operator&[]' then
+ if flags['1'] then -- for compatibility with tolua5 ?
+ output(' self->operator[](',self.args[1].name,'-1) = ',self.args[2].name,';')
+ else
+ output(' self->operator[](',self.args[1].name,') = ',self.args[2].name,';')
+ end
+ else
+ output(' {')
+ if self.type ~= '' and self.type ~= 'void' then
+ output(' ',self.mod,self.type,self.ptr,'tolua_ret = ')
+ output('(',self.mod,self.type,self.ptr,') ')
+ else
+ output(' ')
+ end
+ if class and self.name=='new' then
+ output('Mtolua_new((',self.type,')(')
+ elseif class and static then
+ if out then
+ output(self.name,'(')
+ else
+ output(class..'::'..self.name,'(')
+ end
+ elseif class then
+ if out then
+ output(self.name,'(')
+ else
+ if self.cast_operator then
+ --output('static_cast<',self.mod,self.type,self.ptr,' >(*self')
+ output('self->operator ',self.mod,self.type,'(')
+ else
+ output('self->'..self.name,'(')
+ end
+ end
+ else
+ output(self.name,'(')
+ end
+
+ if out and not static then
+ output('self')
+ if self.args[1] and self.args[1].name ~= '' then
+ output(',')
+ end
+ end
+ -- write parameters
+ local i=1
+ while self.args[i] do
+ self.args[i]:passpar()
+ i = i+1
+ if self.args[i] then
+ output(',')
+ end
+ end
+
+ if class and self.name == 'operator[]' and flags['1'] then
+ output('-1);')
+ else
+ if class and self.name=='new' then
+ output('));') -- close Mtolua_new(
+ else
+ output(');')
+ end
+ end
+
+ -- return values
+ if self.type ~= '' and self.type ~= 'void' then
+ nret = nret + 1
+ local t,ct = isbasic(self.type)
+ if t and self.name ~= "new" then
+ if self.cast_operator and _basic_raw_push[t] then
+ output(' ',_basic_raw_push[t],'(tolua_S,(',ct,')tolua_ret);')
+ else
+ output(' tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
+ end
+ else
+ t = self.type
+ new_t = string.gsub(t, "const%s+", "")
+ local owned = false
+ if string.find(self.mod, "tolua_owned") then
+ owned = true
+ end
+ local push_func = get_push_function(t)
+ if self.ptr == '' then
+ output(' {')
+ output('#ifdef __cplusplus\n')
+ output(' void* tolua_obj = Mtolua_new((',new_t,')(tolua_ret));')
+ output(' ',push_func,'(tolua_S,tolua_obj,"',t,'");')
+ output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
+ output('#else\n')
+ output(' void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
+ output(' ',push_func,'(tolua_S,tolua_obj,"',t,'");')
+ output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
+ output('#endif\n')
+ output(' }')
+ elseif self.ptr == '&' then
+ output(' ',push_func,'(tolua_S,(void*)&tolua_ret,"',t,'");')
+ else
+ output(' ',push_func,'(tolua_S,(void*)tolua_ret,"',t,'");')
+ if owned or local_constructor then
+ output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
+ end
+ end
+ end
+ end
+ local i=1
+ while self.args[i] do
+ nret = nret + self.args[i]:retvalue()
+ i = i+1
+ end
+ output(' }')
+
+ -- set array element values
+ if class then narg=2 else narg=1 end
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:setarray(narg)
+ narg = narg+1
+ i = i+1
+ end
+ end
+
+ -- free dynamically allocated array
+ if self.args[1].type ~= 'void' then
+ local i=1
+ while self.args[i] do
+ self.args[i]:freearray()
+ i = i+1
+ end
+ end
+ end
+
+ post_call_hook(self)
+
+ output(' }')
+ output(' return '..nret..';')
+
+ -- call overloaded function or generate error
+ if overload < 0 then
+
+ output('#ifndef TOLUA_RELEASE\n')
+ output('tolua_lerror:\n')
+ output(' tolua_error(tolua_S,"'..output_error_hook("#ferror in function \'%s\'.", self.lname)..'",&tolua_err);')
+ output(' return 0;')
+ output('#endif\n')
+ else
+ local _local = ""
+ if local_constructor then
+ _local = "_local"
+ end
+ output('tolua_lerror:\n')
+ output(' return '..strsub(self.cname,1,-3)..format("%02d",overload).._local..'(tolua_S);')
+ end
+ output('}')
+ output('#endif //#ifndef TOLUA_DISABLE\n')
+ output('\n')
+
+ -- recursive call to write local constructor
+ if class and self.name=='new' and not local_constructor then
+
+ self:supcode(1)
+ end
+
+end
+
+
+-- register function
+function classFunction:register (pre)
+
+ if not self:check_public_access() then
+ return
+ end
+
+ if self.name == 'new' and self.parent.flags.pure_virtual then
+ -- no constructor for classes with pure virtual methods
+ return
+ end
+
+ output(pre..'tolua_function(tolua_S,"'..self.lname..'",'..self.cname..');')
+ if self.name == 'new' then
+ output(pre..'tolua_function(tolua_S,"new_local",'..self.cname..'_local);')
+ output(pre..'tolua_function(tolua_S,".call",'..self.cname..'_local);')
+ --output(' tolua_set_call_event(tolua_S,'..self.cname..'_local, "'..self.parent.type..'");')
+ end
+end
+
+-- Print method
+function classFunction:print (ident,close)
+ print(ident.."Function{")
+ print(ident.." mod = '"..self.mod.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.." ptr = '"..self.ptr.."',")
+ print(ident.." name = '"..self.name.."',")
+ print(ident.." lname = '"..self.lname.."',")
+ print(ident.." const = '"..self.const.."',")
+ print(ident.." cname = '"..self.cname.."',")
+ print(ident.." lname = '"..self.lname.."',")
+ print(ident.." args = {")
+ local i=1
+ while self.args[i] do
+ self.args[i]:print(ident.." ",",")
+ i = i+1
+ end
+ print(ident.." }")
+ print(ident.."}"..close)
+end
+
+-- check if it returns an object by value
+function classFunction:requirecollection (t)
+ local r = false
+ if self.type ~= '' and not isbasic(self.type) and self.ptr=='' then
+ local type = gsub(self.type,"%s*const%s+","")
+ t[type] = "tolua_collect_" .. clean_template(type)
+ r = true
+ end
+ local i=1
+ while self.args[i] do
+ r = self.args[i]:requirecollection(t) or r
+ i = i+1
+ end
+ return r
+end
+
+-- determine lua function name overload
+function classFunction:overload ()
+ return self.parent:overload(self.lname)
+end
+
+
+function param_object(par) -- returns true if the parameter has an object as its default value
+
+ if not string.find(par, '=') then return false end -- it has no default value
+
+ local _,_,def = string.find(par, "=(.*)$")
+
+ if string.find(par, "|") then -- a list of flags
+
+ return true
+ end
+
+ if string.find(par, "%*") then -- it's a pointer with a default value
+
+ if string.find(par, '=%s*new') or string.find(par, "%(") then -- it's a pointer with an instance as default parameter.. is that valid?
+ return true
+ end
+ return false -- default value is 'NULL' or something
+ end
+
+
+ if string.find(par, "[%(&]") then
+ return true
+ end -- default value is a constructor call (most likely for a const reference)
+
+ --if string.find(par, "&") then
+
+ -- if string.find(def, ":") or string.find(def, "^%s*new%s+") then
+
+ -- -- it's a reference with default to something like Class::member, or 'new Class'
+ -- return true
+ -- end
+ --end
+
+ return false -- ?
+end
+
+function strip_last_arg(all_args, last_arg) -- strips the default value from the last argument
+
+ local _,_,s_arg = string.find(last_arg, "^([^=]+)")
+ last_arg = string.gsub(last_arg, "([%%%(%)])", "%%%1");
+ all_args = string.gsub(all_args, "%s*,%s*"..last_arg.."%s*%)%s*$", ")")
+ return all_args, s_arg
+end
+
+
+
+-- Internal constructor
+function _Function (t)
+ setmetatable(t,classFunction)
+
+ if t.const ~= 'const' and t.const ~= '' then
+ error("#invalid 'const' specification")
+ end
+
+ append(t)
+ if t:inclass() then
+ --print ('t.name is '..t.name..', parent.name is '..t.parent.name)
+ if string.gsub(t.name, "%b<>", "") == string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
+ t.name = 'new'
+ t.lname = 'new'
+ t.parent._new = true
+ t.type = t.parent.name
+ t.ptr = '*'
+ elseif string.gsub(t.name, "%b<>", "") == '~'..string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
+ t.name = 'delete'
+ t.lname = 'delete'
+ t.parent._delete = true
+ end
+ end
+ t.cname = t:cfuncname("tolua")..t:overload(t)
+ return t
+end
+
+-- Constructor
+-- Expects three strings: one representing the function declaration,
+-- another representing the argument list, and the third representing
+-- the "const" or empty string.
+function Function (d,a,c)
+ --local t = split(strsub(a,2,-2),',') -- eliminate braces
+ --local t = split_params(strsub(a,2,-2))
+
+ if not flags['W'] and string.find(a, "%.%.%.%s*%)") then
+
+ warning("Functions with variable arguments (`...') are not supported. Ignoring "..d..a..c)
+ return nil
+ end
+
+
+ local i=1
+ local l = {n=0}
+
+ a = string.gsub(a, "%s*([%(%)])%s*", "%1")
+ local t,strip,last = strip_pars(strsub(a,2,-2));
+ if strip then
+ --local ns = string.sub(strsub(a,1,-2), 1, -(string.len(last)+1))
+ local ns = join(t, ",", 1, last-1)
+
+ ns = "("..string.gsub(ns, "%s*,%s*$", "")..')'
+ --ns = strip_defaults(ns)
+
+ local f = Function(d, ns, c)
+ for i=1,last do
+ t[i] = string.gsub(t[i], "=.*$", "")
+ end
+ end
+
+ while t[i] do
+ l.n = l.n+1
+ l[l.n] = Declaration(t[i],'var',true)
+ i = i+1
+ end
+ local f = Declaration(d,'func')
+ f.args = l
+ f.const = c
+ return _Function(f)
+end
+
+function join(t, sep, first, last)
+
+ first = first or 1
+ last = last or table.getn(t)
+ local lsep = ""
+ local ret = ""
+ local loop = false
+ for i = first,last do
+
+ ret = ret..lsep..t[i]
+ lsep = sep
+ loop = true
+ end
+ if not loop then
+ return ""
+ end
+
+ return ret
+end
+
+function strip_pars(s)
+
+ local t = split_c_tokens(s, ',')
+ local strip = false
+ local last
+
+ for i=t.n,1,-1 do
+
+ if not strip and param_object(t[i]) then
+ last = i
+ strip = true
+ end
+ --if strip then
+ -- t[i] = string.gsub(t[i], "=.*$", "")
+ --end
+ end
+
+ return t,strip,last
+
+end
+
+function strip_defaults(s)
+
+ s = string.gsub(s, "^%(", "")
+ s = string.gsub(s, "%)$", "")
+
+ local t = split_c_tokens(s, ",")
+ local sep, ret = "",""
+ for i=1,t.n do
+ t[i] = string.gsub(t[i], "=.*$", "")
+ ret = ret..sep..t[i]
+ sep = ","
+ end
+
+ return "("..ret..")"
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/module.lua b/lib/tolua++/src/bin/lua/module.lua
new file mode 100644
index 000000000..57dceb7d5
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/module.lua
@@ -0,0 +1,68 @@
+-- tolua: module class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Module class
+-- Represents module.
+-- The following fields are stored:
+-- {i} = list of objects in the module.
+classModule = {
+ classtype = 'module'
+}
+classModule.__index = classModule
+setmetatable(classModule,classContainer)
+
+-- register module
+function classModule:register (pre)
+ pre = pre or ''
+ push(self)
+ output(pre..'tolua_module(tolua_S,"'..self.name..'",',self:hasvar(),');')
+ output(pre..'tolua_beginmodule(tolua_S,"'..self.name..'");')
+ local i=1
+ while self[i] do
+ self[i]:register(pre..' ')
+ i = i+1
+ end
+ output(pre..'tolua_endmodule(tolua_S);')
+ pop()
+end
+
+-- Print method
+function classModule:print (ident,close)
+ print(ident.."Module{")
+ print(ident.." name = '"..self.name.."';")
+ local i=1
+ while self[i] do
+ self[i]:print(ident.." ",",")
+ i = i+1
+ end
+ print(ident.."}"..close)
+end
+
+-- Internal constructor
+function _Module (t)
+ setmetatable(t,classModule)
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects two string representing the module name and body.
+function Module (n,b)
+ local t = _Module(_Container{name=n})
+ push(t)
+ t:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
+ pop()
+ return t
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/namespace.lua b/lib/tolua++/src/bin/lua/namespace.lua
new file mode 100644
index 000000000..6ca80e6e3
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/namespace.lua
@@ -0,0 +1,52 @@
+-- tolua: namespace class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 2003
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Namespace class
+-- Represents a namesapce definition.
+-- Stores the following fields:
+-- name = class name
+-- {i} = list of members
+classNamespace = {
+ classtype = 'namespace',
+ name = '',
+}
+classNamespace.__index = classNamespace
+setmetatable(classNamespace,classModule)
+
+-- Print method
+function classNamespace:print (ident,close)
+ print(ident.."Namespace{")
+ print(ident.." name = '"..self.name.."',")
+ local i=1
+ while self[i] do
+ self[i]:print(ident.." ",",")
+ i = i+1
+ end
+ print(ident.."}"..close)
+end
+
+-- Internal constructor
+function _Namespace (t)
+ setmetatable(t,classNamespace)
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects the name and the body of the namespace.
+function Namespace (n,b)
+ local c = _Namespace(_Container{name=n})
+ push(c)
+ c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
+ pop()
+end
+
diff --git a/lib/tolua++/src/bin/lua/operator.lua b/lib/tolua++/src/bin/lua/operator.lua
new file mode 100644
index 000000000..675027cd7
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/operator.lua
@@ -0,0 +1,220 @@
+-- tolua: operator class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Operator class
+-- Represents an operator function or a class operator method.
+-- It stores the same fields as functions do plus:
+-- kind = set of character representing the operator (as it appers in C++ code)
+classOperator = {
+ kind = '',
+}
+classOperator.__index = classOperator
+setmetatable(classOperator,classFunction)
+
+-- table to transform operator kind into the appropriate tag method name
+_TM = {['+'] = 'add',
+ ['-'] = 'sub',
+ ['*'] = 'mul',
+ ['/'] = 'div',
+ ['<'] = 'lt',
+ ['<='] = 'le',
+ ['=='] = 'eq',
+ ['[]'] = 'geti',
+ ['&[]'] = 'seti',
+ --['->'] = 'flechita',
+ }
+
+
+-- Print method
+function classOperator:print (ident,close)
+ print(ident.."Operator{")
+ print(ident.." kind = '"..self.kind.."',")
+ print(ident.." mod = '"..self.mod.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.." ptr = '"..self.ptr.."',")
+ print(ident.." name = '"..self.name.."',")
+ print(ident.." const = '"..self.const.."',")
+ print(ident.." cname = '"..self.cname.."',")
+ print(ident.." lname = '"..self.lname.."',")
+ print(ident.." args = {")
+ local i=1
+ while self.args[i] do
+ self.args[i]:print(ident.." ",",")
+ i = i+1
+ end
+ print(ident.." }")
+ print(ident.."}"..close)
+end
+
+function classOperator:supcode_tmp()
+
+ if not _TM[self.kind] then
+ return classFunction.supcode(self)
+ end
+
+ -- no overload, no parameters, always inclass
+ output("/* method:",self.name," of class ",self:inclass()," */")
+
+ output("#ifndef TOLUA_DISABLE_"..self.cname)
+ output("\nstatic int",self.cname,"(lua_State* tolua_S)")
+
+ if overload < 0 then
+ output('#ifndef TOLUA_RELEASE\n')
+ end
+ output(' tolua_Error tolua_err;')
+ output(' if (\n')
+ -- check self
+ local is_func = get_is_function(self.parent.type)
+ output(' !'..is_func..'(tolua_S,1,"'..self.parent.type..'",0,&tolua_err) ||\n')
+ output(' !tolua_isnoobj(tolua_S,2,&tolua_err)\n )')
+ output(' goto tolua_lerror;')
+
+ output(' else\n')
+ output('#endif\n') -- tolua_release
+ output(' {')
+
+ -- declare self
+ output(' ',self.const,self.parent.type,'*','self = ')
+ output('(',self.const,self.parent.type,'*) ')
+ local to_func = get_to_func(self.parent.type)
+ output(to_func,'(tolua_S,1,0);')
+
+ -- check self
+ output('#ifndef TOLUA_RELEASE\n')
+ output(' if (!self) tolua_error(tolua_S,"'..output_error_hook("invalid \'self\' in function \'%s\'", self.name)..'",NULL);');
+ output('#endif\n')
+
+ -- cast self
+ output(' ',self.mod,self.type,self.ptr,'tolua_ret = ')
+ output('(',self.mod,self.type,self.ptr,')(*self);')
+
+ -- return value
+ local t,ct = isbasic(self.type)
+ if t then
+ output(' tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
+ else
+ t = self.type
+ local push_func = get_push_function(t)
+ new_t = string.gsub(t, "const%s+", "")
+ if self.ptr == '' then
+ output(' {')
+ output('#ifdef __cplusplus\n')
+ output(' void* tolua_obj = Mtolua_new((',new_t,')(tolua_ret));')
+ output(' ',push_func,'(tolua_S,tolua_obj,"',t,'");')
+ output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
+ output('#else\n')
+ output(' void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
+ output(' ',push_func,'(tolua_S,tolua_obj,"',t,'");')
+ output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
+ output('#endif\n')
+ output(' }')
+ elseif self.ptr == '&' then
+ output(' ',push_func,'(tolua_S,(void*)&tolua_ret,"',t,'");')
+ else
+ if local_constructor then
+ output(' ',push_func,'(tolua_S,(void *)tolua_ret,"',t,'");')
+ output(' tolua_register_gc(tolua_S,lua_gettop(tolua_S));')
+ else
+ output(' ',push_func,'(tolua_S,(void*)tolua_ret,"',t,'");')
+ end
+ end
+ end
+
+ output(' }')
+ output(' return 1;')
+
+ output('#ifndef TOLUA_RELEASE\n')
+ output('tolua_lerror:\n')
+ output(' tolua_error(tolua_S,"'..output_error_hook("#ferror in function \'%s\'.", self.lname)..'",&tolua_err);')
+ output(' return 0;')
+ output('#endif\n')
+
+
+ output('}')
+ output('#endif //#ifndef TOLUA_DISABLE\n')
+ output('\n')
+end
+
+-- Internal constructor
+function _Operator (t)
+ setmetatable(t,classOperator)
+
+ if t.const ~= 'const' and t.const ~= '' then
+ error("#invalid 'const' specification")
+ end
+
+ append(t)
+ if not t:inclass() then
+ error("#operator can only be defined as class member")
+ end
+
+ --t.name = t.name .. "_" .. (_TM[t.kind] or t.kind)
+ t.cname = t:cfuncname("tolua")..t:overload(t)
+ t.name = "operator" .. t.kind -- set appropriate calling name
+ return t
+end
+
+-- Constructor
+function Operator (d,k,a,c)
+
+ local op_k = string.gsub(k, "^%s*", "")
+ op_k = string.gsub(k, "%s*$", "")
+ --if string.find(k, "^[%w_:%d<>%*%&]+$") then
+ if d == "operator" and k ~= '' then
+
+ d = k.." operator"
+ elseif not _TM[op_k] then
+
+ if flags['W'] then
+ error("tolua: no support for operator" .. f.kind)
+ else
+ warning("No support for operator "..op_k..", ignoring")
+ return nil
+ end
+ end
+
+ local ref = ''
+ local t = split_c_tokens(strsub(a,2,strlen(a)-1),',') -- eliminate braces
+ local i=1
+ local l = {n=0}
+ while t[i] do
+ l.n = l.n+1
+ l[l.n] = Declaration(t[i],'var')
+ i = i+1
+ end
+ if k == '[]' then
+ local _
+ _, _, ref = strfind(d,'(&)')
+ d = gsub(d,'&','')
+ elseif k=='&[]' then
+ l.n = l.n+1
+ l[l.n] = Declaration(d,'var')
+ l[l.n].name = 'tolua_value'
+ end
+ local f = Declaration(d,'func')
+ if k == '[]' and (l[1]==nil or isbasic(l[1].type)~='number') then
+ error('operator[] can only be defined for numeric index.')
+ end
+ f.args = l
+ f.const = c
+ f.kind = op_k
+ f.lname = "."..(_TM[f.kind] or f.kind)
+ if not _TM[f.kind] then
+ f.cast_operator = true
+ end
+ if f.kind == '[]' and ref=='&' and f.const~='const' then
+ Operator(d,'&'..k,a,c) -- create correspoding set operator
+ end
+ return _Operator(f)
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/package.lua b/lib/tolua++/src/bin/lua/package.lua
new file mode 100644
index 000000000..eec136904
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/package.lua
@@ -0,0 +1,343 @@
+-- tolua: package class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Package class
+-- Represents the whole package being bound.
+-- The following fields are stored:
+-- {i} = list of objects in the package.
+classPackage = {
+ classtype = 'package'
+}
+classPackage.__index = classPackage
+setmetatable(classPackage,classContainer)
+
+-- Print method
+function classPackage:print ()
+ print("Package: "..self.name)
+ local i=1
+ while self[i] do
+ self[i]:print("","")
+ i = i+1
+ end
+end
+
+function classPackage:preprocess ()
+
+ -- avoid preprocessing embedded Lua code
+ local L = {}
+ self.code = gsub(self.code,"\n%s*%$%[","\1") -- deal with embedded lua code
+ self.code = gsub(self.code,"\n%s*%$%]","\2")
+ self.code = gsub(self.code,"(%b\1\2)", function (c)
+ tinsert(L,c)
+ return "\n#["..getn(L).."]#"
+ end)
+ -- avoid preprocessing embedded C code
+ local C = {}
+ self.code = gsub(self.code,"\n%s*%$%<","\3") -- deal with embedded C code
+ self.code = gsub(self.code,"\n%s*%$%>","\4")
+ self.code = gsub(self.code,"(%b\3\4)", function (c)
+ tinsert(C,c)
+ return "\n#<"..getn(C)..">#"
+ end)
+ -- avoid preprocessing embedded C code
+ self.code = gsub(self.code,"\n%s*%$%{","\5") -- deal with embedded C code
+ self.code = gsub(self.code,"\n%s*%$%}","\6")
+ self.code = gsub(self.code,"(%b\5\6)", function (c)
+ tinsert(C,c)
+ return "\n#<"..getn(C)..">#"
+ end)
+
+ --self.code = gsub(self.code,"\n%s*#[^d][^\n]*\n", "\n\n") -- eliminate preprocessor directives that don't start with 'd'
+ self.code = gsub(self.code,"\n[ \t]*#[ \t]*[^d%<%[]", "\n//") -- eliminate preprocessor directives that don't start with 'd'
+
+ -- avoid preprocessing verbatim lines
+ local V = {}
+ self.code = gsub(self.code,"\n(%s*%$[^%[%]][^\n]*)",function (v)
+ tinsert(V,v)
+ return "\n#"..getn(V).."#"
+ end)
+
+ -- perform global substitution
+
+ self.code = gsub(self.code,"(//[^\n]*)","") -- eliminate C++ comments
+ self.code = gsub(self.code,"/%*","\1")
+ self.code = gsub(self.code,"%*/","\2")
+ self.code = gsub(self.code,"%b\1\2","")
+ self.code = gsub(self.code,"\1","/%*")
+ self.code = gsub(self.code,"\2","%*/")
+ self.code = gsub(self.code,"%s*@%s*","@") -- eliminate spaces beside @
+ self.code = gsub(self.code,"%s?inline(%s)","%1") -- eliminate 'inline' keyword
+ --self.code = gsub(self.code,"%s?extern(%s)","%1") -- eliminate 'extern' keyword
+ --self.code = gsub(self.code,"%s?virtual(%s)","%1") -- eliminate 'virtual' keyword
+ --self.code = gsub(self.code,"public:","") -- eliminate 'public:' keyword
+ self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
+ self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
+ self.code = gsub(self.code,"([^%w_])char%s*%*","%1_cstring ") -- substitute 'char*'
+ self.code = gsub(self.code,"([^%w_])lua_State%s*%*","%1_lstate ") -- substitute 'lua_State*'
+
+ -- restore embedded Lua code
+ self.code = gsub(self.code,"%#%[(%d+)%]%#",function (n)
+ return L[tonumber(n)]
+ end)
+ -- restore embedded C code
+ self.code = gsub(self.code,"%#%<(%d+)%>%#",function (n)
+ return C[tonumber(n)]
+ end)
+ -- restore verbatim lines
+ self.code = gsub(self.code,"%#(%d+)%#",function (n)
+ return V[tonumber(n)]
+ end)
+
+ self.code = string.gsub(self.code, "\n%s*%$([^\n]+)", function (l)
+ Verbatim(l.."\n")
+ return "\n"
+ end)
+end
+
+-- translate verbatim
+function classPackage:preamble ()
+ output('/*\n')
+ output('** Lua binding: '..self.name..'\n')
+ output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n')
+ output('*/\n\n')
+
+ output('#ifndef __cplusplus\n')
+ output('#include "stdlib.h"\n')
+ output('#endif\n')
+ output('#include "string.h"\n\n')
+ output('#include "tolua++.h"\n\n')
+
+ if not flags.h then
+ output('/* Exported function */')
+ output('TOLUA_API int tolua_'..self.name..'_open (lua_State* tolua_S);')
+ output('\n')
+ end
+
+ local i=1
+ while self[i] do
+ self[i]:preamble()
+ i = i+1
+ end
+
+ if self:requirecollection(_collect) then
+ output('\n')
+ output('/* function to release collected object via destructor */')
+ output('#ifdef __cplusplus\n')
+ for i,v in pairs(_collect) do
+ output('\nstatic int '..v..' (lua_State* tolua_S)')
+ output('{')
+ output(' '..i..'* self = ('..i..'*) tolua_tousertype(tolua_S,1,0);')
+ output(' Mtolua_delete(self);')
+ output(' return 0;')
+ output('}')
+ end
+ output('#endif\n\n')
+ end
+
+ output('\n')
+ output('/* function to register type */')
+ output('static void tolua_reg_types (lua_State* tolua_S)')
+ output('{')
+
+ if flags.t then
+ output("#ifndef Mtolua_typeid\n#define Mtolua_typeid(L,TI,T)\n#endif\n")
+ end
+ foreach(_usertype,function(n,v)
+ if (not _global_classes[v]) or _global_classes[v]:check_public_access() then
+ output(' tolua_usertype(tolua_S,"',v,'");')
+ if flags.t then
+ output(' Mtolua_typeid(tolua_S,typeid(',v,'), "',v,'");')
+ end
+ end
+ end)
+ output('}')
+ output('\n')
+end
+
+-- register package
+-- write package open function
+function classPackage:register (pre)
+ pre = pre or ''
+ push(self)
+ output(pre.."/* Open function */")
+ output(pre.."TOLUA_API int tolua_"..self.name.."_open (lua_State* tolua_S)")
+ output(pre.."{")
+ output(pre.." tolua_open(tolua_S);")
+ output(pre.." tolua_reg_types(tolua_S);")
+ output(pre.." tolua_module(tolua_S,NULL,",self:hasvar(),");")
+ output(pre.." tolua_beginmodule(tolua_S,NULL);")
+ local i=1
+ while self[i] do
+ self[i]:register(pre.." ")
+ i = i+1
+ end
+ output(pre.." tolua_endmodule(tolua_S);")
+ output(pre.." return 1;")
+ output(pre.."}")
+
+ output("\n\n")
+ output("#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501\n");
+ output(pre.."TOLUA_API int luaopen_"..self.name.." (lua_State* tolua_S) {")
+ output(pre.." return tolua_"..self.name.."_open(tolua_S);")
+ output(pre.."};")
+ output("#endif\n\n")
+
+ pop()
+end
+
+-- write header file
+function classPackage:header ()
+ output('/*\n') output('** Lua binding: '..self.name..'\n')
+ output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n')
+ output('*/\n\n')
+
+ if not flags.h then
+ output('/* Exported function */')
+ output('TOLUA_API int tolua_'..self.name..'_open (lua_State* tolua_S);')
+ output('\n')
+ end
+end
+
+-- Internal constructor
+function _Package (self)
+ setmetatable(self,classPackage)
+ return self
+end
+
+-- Parse C header file with tolua directives
+-- *** Thanks to Ariel Manzur for fixing bugs in nested directives ***
+function extract_code(fn,s)
+ local code = '\n$#include "'..fn..'"\n'
+ s= "\n" .. s .. "\n" -- add blank lines as sentinels
+ local _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n")
+ while e do
+ t = strlower(t)
+ if t == "begin" then
+ _,e,c = strfind(s,"(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n",e)
+ if not e then
+ tolua_error("Unbalanced 'tolua_begin' directive in header file")
+ end
+ end
+ code = code .. c .. "\n"
+ _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n",e)
+ end
+ return code
+end
+
+-- Constructor
+-- Expects the package name, the file extension, and the file text.
+function Package (name,fn)
+ local ext = "pkg"
+
+ -- open input file, if any
+ local st,msg
+ if fn then
+ st, msg = readfrom(flags.f)
+ if not st then
+ error('#'..msg)
+ end
+ local _; _, _, ext = strfind(fn,".*%.(.*)$")
+ end
+ local code
+ if ext == 'pkg' then
+ code = prep(st)
+ else
+ code = "\n" .. read('*a')
+ if ext == 'h' or ext == 'hpp' then
+ code = extract_code(fn,code)
+ end
+ end
+
+ -- close file
+ if fn then
+ readfrom()
+ end
+
+ -- deal with include directive
+ local nsubst
+ repeat
+ code,nsubst = gsub(code,'\n%s*%$(.)file%s*"(.-)"([^\n]*)\n',
+ function (kind,fn,extra)
+ local _, _, ext = strfind(fn,".*%.(.*)$")
+ local fp,msg = openfile(fn,'r')
+ if not fp then
+ error('#'..msg..': '..fn)
+ end
+ if kind == 'p' then
+ local s = prep(fp)
+ closefile(fp)
+ return s
+ end
+ local s = read(fp,'*a')
+ closefile(fp)
+ if kind == 'c' or kind == 'h' then
+ return extract_code(fn,s)
+ elseif kind == 'l' then
+ return "\n$[--##"..fn.."\n" .. s .. "\n$]\n"
+ elseif kind == 'i' then
+ local t = {code=s}
+ extra = string.gsub(extra, "^%s*,%s*", "")
+ local pars = split_c_tokens(extra, ",")
+ include_file_hook(t, fn, unpack(pars))
+ return "\n\n" .. t.code
+ else
+ error('#Invalid include directive (use $cfile, $pfile, $lfile or $ifile)')
+ end
+ end)
+ until nsubst==0
+
+ -- deal with renaming directive
+ repeat -- I don't know why this is necesary
+ code,nsubst = gsub(code,'\n%s*%$renaming%s*(.-)%s*\n', function (r) appendrenaming(r) return "\n" end)
+ until nsubst == 0
+
+ local t = _Package(_Container{name=name, code=code})
+ push(t)
+ preprocess_hook(t)
+ t:preprocess()
+ preparse_hook(t)
+ t:parse(t.code)
+ pop()
+ return t
+end
+
+
+setmetatable(_extra_parameters, { __index = _G })
+
+function prep(file)
+
+ local chunk = {'local __ret = {"\\n"}\n'}
+ for line in file:lines() do
+ if string.find(line, "^##") then
+ table.insert(chunk, string.sub(line, 3) .. "\n")
+ else
+ local last = 1
+ for text, expr, index in string.gfind(line, "(.-)$(%b())()") do
+ last = index
+ if text ~= "" then
+ table.insert(chunk, string.format('table.insert(__ret, %q )', text))
+ end
+ table.insert(chunk, string.format('table.insert(__ret, %s )', expr))
+ end
+ table.insert(chunk, string.format('table.insert(__ret, %q)\n',
+ string.sub(line, last).."\n"))
+ end
+ end
+ table.insert(chunk, '\nreturn table.concat(__ret)\n')
+ local f,e = loadstring(table.concat(chunk))
+ if e then
+ error("#"..e)
+ end
+ setfenv(f, _extra_parameters)
+ return f()
+end
diff --git a/lib/tolua++/src/bin/lua/template_class.lua b/lib/tolua++/src/bin/lua/template_class.lua
new file mode 100644
index 000000000..b1ed05abe
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/template_class.lua
@@ -0,0 +1,82 @@
+
+_global_templates = {}
+
+classTemplateClass = {
+
+ name = '',
+ body = '',
+ parents = {},
+ args = {}, -- the template arguments
+}
+
+classTemplateClass.__index = classTemplateClass
+
+
+function classTemplateClass:throw(types, local_scope)
+
+ --if table.getn(types) ~= table.getn(self.args) then
+ -- error("#invalid parameter count")
+ --end
+
+ -- replace
+ for i =1 , types.n do
+
+ local Il = split_c_tokens(types[i], " ")
+ if table.getn(Il) ~= table.getn(self.args) then
+ error("#invalid parameter count for "..types[i])
+ end
+ local bI = self.body
+ local pI = {}
+ for j = 1,self.args.n do
+ --Tl[j] = findtype(Tl[j]) or Tl[j]
+ bI = string.gsub(bI, "([^_%w])"..self.args[j].."([^_%w])", "%1"..Il[j].."%2")
+ if self.parents then
+ for i=1,table.getn(self.parents) do
+ pI[i] = string.gsub(self.parents[i], "([^_%w]?)"..self.args[j].."([^_%w]?)", "%1"..Il[j].."%2")
+ end
+ end
+ end
+ --local append = "<"..string.gsub(types[i], "%s+", ",")..">"
+ local append = "<"..concat(Il, 1, table.getn(Il), ",")..">"
+ append = string.gsub(append, "%s*,%s*", ",")
+ append = string.gsub(append, ">>", "> >")
+ for i=1,table.getn(pI) do
+ --pI[i] = string.gsub(pI[i], ">>", "> >")
+ pI[i] = resolve_template_types(pI[i])
+ end
+ bI = string.gsub(bI, ">>", "> >")
+ local n = self.name
+ if local_scope then
+ n = self.local_name
+ end
+
+ Class(n..append, pI, bI)
+ end
+end
+
+
+function TemplateClass(name, parents, body, parameters)
+
+ local o = {
+
+ parents = parents,
+ body = body,
+ args = parameters,
+ }
+
+ local oname = string.gsub(name, "@.*$", "")
+ oname = getnamespace(classContainer.curr)..oname
+ o.name = oname
+
+ o.local_name = name
+
+ setmetatable(o, classTemplateClass)
+
+ if _global_templates[oname] then
+ warning("Duplicate declaration of template "..oname)
+ else
+ _global_templates[oname] = o
+ end
+
+ return o
+end
diff --git a/lib/tolua++/src/bin/lua/typedef.lua b/lib/tolua++/src/bin/lua/typedef.lua
new file mode 100644
index 000000000..a78a84155
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/typedef.lua
@@ -0,0 +1,71 @@
+-- tolua: typedef class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Typedef class
+-- Represents a type synonym.
+-- The 'de facto' type replaces the typedef before the
+-- remaining code is parsed.
+-- The following fields are stored:
+-- utype = typedef name
+-- type = 'the facto' type
+-- mod = modifiers to the 'de facto' type
+classTypedef = {
+ utype = '',
+ mod = '',
+ type = ''
+}
+classTypedef.__index = classTypedef
+
+-- Print method
+function classTypedef:print (ident,close)
+ print(ident.."Typedef{")
+ print(ident.." utype = '"..self.utype.."',")
+ print(ident.." mod = '"..self.mod.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.."}"..close)
+end
+
+-- Return it's not a variable
+function classTypedef:isvariable ()
+ return false
+end
+
+-- Internal constructor
+function _Typedef (t)
+ setmetatable(t,classTypedef)
+ t.type = resolve_template_types(t.type)
+ appendtypedef(t)
+ return t
+end
+
+-- Constructor
+-- Expects one string representing the type definition.
+function Typedef (s)
+ if strfind(string.gsub(s, '%b<>', ''),'[%*&]') then
+ tolua_error("#invalid typedef: pointers (and references) are not supported")
+ end
+ local o = {mod = ''}
+ if string.find(s, "[<>]") then
+ _,_,o.type,o.utype = string.find(s, "^%s*([^<>]+%b<>[^%s]*)%s+(.-)$")
+ else
+ local t = split(gsub(s,"%s%s*"," ")," ")
+ o = {
+ utype = t[t.n],
+ type = t[t.n-1],
+ mod = concat(t,1,t.n-2),
+ }
+ end
+ return _Typedef(o)
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/variable.lua b/lib/tolua++/src/bin/lua/variable.lua
new file mode 100644
index 000000000..fbc705dd8
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/variable.lua
@@ -0,0 +1,300 @@
+-- tolua: variable class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Variable class
+-- Represents a extern variable or a public member of a class.
+-- Stores all fields present in a declaration.
+classVariable = {
+ _get = {}, -- mapped get functions
+ _set = {}, -- mapped set functions
+}
+classVariable.__index = classVariable
+setmetatable(classVariable,classDeclaration)
+
+-- Print method
+function classVariable:print (ident,close)
+ print(ident.."Variable{")
+ print(ident.." mod = '"..self.mod.."',")
+ print(ident.." type = '"..self.type.."',")
+ print(ident.." ptr = '"..self.ptr.."',")
+ print(ident.." name = '"..self.name.."',")
+ if self.dim then print(ident.." dim = '"..self.dim.."',") end
+ print(ident.." def = '"..self.def.."',")
+ print(ident.." ret = '"..self.ret.."',")
+ print(ident.."}"..close)
+end
+
+-- Generates C function name
+function classVariable:cfuncname (prefix)
+ local parent = ""
+ local unsigned = ""
+ local ptr = ""
+
+ local p = self:inmodule() or self:innamespace() or self:inclass()
+
+ if p then
+ if self.parent.classtype == 'class' then
+ parent = "_" .. self.parent.type
+ else
+ parent = "_" .. p
+ end
+ end
+
+ if strfind(self.mod,"(unsigned)") then
+ unsigned = "_unsigned"
+ end
+
+ if self.ptr == "*" then ptr = "_ptr"
+ elseif self.ptr == "&" then ptr = "_ref"
+ end
+
+ local name = prefix .. parent .. unsigned .. "_" .. gsub(self.lname or self.name,".*::","") .. ptr
+
+ name = clean_template(name)
+ return name
+
+end
+
+-- check if it is a variable
+function classVariable:isvariable ()
+ return true
+end
+
+-- get variable value
+function classVariable:getvalue (class,static, prop_get)
+
+ local name
+ if prop_get then
+
+ name = prop_get.."()"
+ else
+ name = self.name
+ end
+
+ if class and static then
+ return self.parent.type..'::'..name
+ elseif class then
+ return 'self->'..name
+ else
+ return name
+ end
+end
+
+-- get variable pointer value
+function classVariable:getpointervalue (class,static)
+ if class and static then
+ return class..'::p'
+ elseif class then
+ return 'self->p'
+ else
+ return 'p'
+ end
+end
+
+-- Write binding functions
+function classVariable:supcode ()
+
+ local class = self:inclass()
+
+ local prop_get,prop_set
+ if string.find(self.mod, 'tolua_property') then
+
+ local _,_,type = string.find(self.mod, "tolua_property__([^%s]*)")
+ type = type or "default"
+ prop_get,prop_set = get_property_methods(type, self.name)
+ self.mod = string.gsub(self.mod, "tolua_property[^%s]*", "")
+ end
+
+ -- get function ------------------------------------------------
+ if class then
+ output("/* get function:",self.name," of class ",class," */")
+ else
+ output("/* get function:",self.name," */")
+ end
+ self.cgetname = self:cfuncname("tolua_get")
+ output("#ifndef TOLUA_DISABLE_"..self.cgetname)
+ output("\nstatic int",self.cgetname,"(lua_State* tolua_S)")
+ output("{")
+
+ -- declare self, if the case
+ local _,_,static = strfind(self.mod,'^%s*(static)')
+ if class and static==nil then
+ output(' ',self.parent.type,'*','self = ')
+ output('(',self.parent.type,'*) ')
+ local to_func = get_to_function(self.parent.type)
+ output(to_func,'(tolua_S,1,0);')
+ elseif static then
+ _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+ end
+
+
+ -- check self value
+ if class and static==nil then
+ output('#ifndef TOLUA_RELEASE\n')
+ output(' if (!self) tolua_error(tolua_S,"'..output_error_hook("invalid \'self\' in accessing variable \'%s\'", self.name)..'",NULL);');
+ output('#endif\n')
+ end
+
+ -- return value
+ if string.find(self.mod, 'tolua_inherits') then
+ local push_func = get_push_function(self.type)
+ output('#ifdef __cplusplus\n')
+ output(' ',push_func,'(tolua_S,(void*)static_cast<'..self.type..'*>(self), "',self.type,'");')
+ output('#else\n')
+ output(' ',push_func,'(tolua_S,(void*)(('..self.type..'*)self), "',self.type,'");')
+ output('#endif\n')
+ else
+ local t,ct = isbasic(self.type)
+ if t then
+ output(' tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static,prop_get)..');')
+ else
+ local push_func = get_push_function(self.type)
+ t = self.type
+ if self.ptr == '&' or self.ptr == '' then
+ output(' ',push_func,'(tolua_S,(void*)&'..self:getvalue(class,static,prop_get)..',"',t,'");')
+ else
+ output(' ',push_func,'(tolua_S,(void*)'..self:getvalue(class,static,prop_get)..',"',t,'");')
+ end
+ end
+ end
+ output(' return 1;')
+ output('}')
+ output('#endif //#ifndef TOLUA_DISABLE\n')
+ output('\n')
+
+ -- set function ------------------------------------------------
+ if not (strfind(self.type,'const%s+') or string.find(self.mod, 'tolua_readonly') or string.find(self.mod, 'tolua_inherits')) then
+ if class then
+ output("/* set function:",self.name," of class ",class," */")
+ else
+ output("/* set function:",self.name," */")
+ end
+ self.csetname = self:cfuncname("tolua_set")
+ output("#ifndef TOLUA_DISABLE_"..self.csetname)
+ output("\nstatic int",self.csetname,"(lua_State* tolua_S)")
+ output("{")
+
+ -- declare self, if the case
+ if class and static==nil then
+ output(' ',self.parent.type,'*','self = ')
+ output('(',self.parent.type,'*) ')
+ local to_func = get_to_function(self.parent.type)
+ output(to_func,'(tolua_S,1,0);')
+ -- check self value
+ end
+ -- check types
+ output('#ifndef TOLUA_RELEASE\n')
+ output(' tolua_Error tolua_err;')
+ if class and static==nil then
+ output(' if (!self) tolua_error(tolua_S,"'..output_error_hook("invalid \'self\' in accessing variable \'%s\'", self.name)..'",NULL);');
+ elseif static then
+ _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+ end
+
+ -- check variable type
+ output(' if ('..self:outchecktype(2)..')')
+ output(' tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);')
+ output('#endif\n')
+
+ -- assign value
+ local def = 0
+ if self.def ~= '' then def = self.def end
+ if self.type == 'char*' and self.dim ~= '' then -- is string
+ output(' strncpy((char*)')
+ if class and static then
+ output(self.parent.type..'::'..self.name)
+ elseif class then
+ output('self->'..self.name)
+ else
+ output(self.name)
+ end
+ output(',(const char*)tolua_tostring(tolua_S,2,',def,'),',self.dim,'-1);')
+ else
+ local ptr = ''
+ if self.ptr~='' then ptr = '*' end
+ output(' ')
+ local name = prop_set or self.name
+ if class and static then
+ output(self.parent.type..'::'..name)
+ elseif class then
+ output('self->'..name)
+ else
+ output(name)
+ end
+ local t = isbasic(self.type)
+ if prop_set then
+ output('(')
+ else
+ output(' = ')
+ end
+ if not t and ptr=='' then output('*') end
+ output('((',self.mod,self.type)
+ if not t then
+ output('*')
+ end
+ output(') ')
+ if t then
+ if isenum(self.type) then
+ output('(int) ')
+ end
+ output('tolua_to'..t,'(tolua_S,2,',def,'))')
+ else
+ local to_func = get_to_function(self.type)
+ output(to_func,'(tolua_S,2,',def,'))')
+ end
+ if prop_set then
+ output(")")
+ end
+ output(";")
+ end
+ output(' return 0;')
+ output('}')
+ output('#endif //#ifndef TOLUA_DISABLE\n')
+ output('\n')
+ end
+
+end
+
+function classVariable:register (pre)
+
+ if not self:check_public_access() then
+ return
+ end
+ pre = pre or ''
+ local parent = self:inmodule() or self:innamespace() or self:inclass()
+ if not parent then
+ if classVariable._warning==nil then
+ warning("Mapping variable to global may degrade performance")
+ classVariable._warning = 1
+ end
+ end
+ if self.csetname then
+ output(pre..'tolua_variable(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');')
+ else
+ output(pre..'tolua_variable(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);')
+ end
+end
+
+-- Internal constructor
+function _Variable (t)
+ setmetatable(t,classVariable)
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects a string representing the variable declaration.
+function Variable (s)
+ return _Variable (Declaration(s,'var'))
+end
+
+
diff --git a/lib/tolua++/src/bin/lua/verbatim.lua b/lib/tolua++/src/bin/lua/verbatim.lua
new file mode 100644
index 000000000..fd3b29b35
--- /dev/null
+++ b/lib/tolua++/src/bin/lua/verbatim.lua
@@ -0,0 +1,78 @@
+-- tolua: verbatim class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: verbatim.lua,v 1.3 2000/01/24 20:41:16 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Verbatim class
+-- Represents a line translated directed to the binding file.
+-- The following filds are stored:
+-- line = line text
+classVerbatim = {
+ line = '',
+ cond = nil, -- condition: where to generate the code (s=suport, r=register)
+}
+classVerbatim.__index = classVerbatim
+setmetatable(classVerbatim,classFeature)
+
+-- preamble verbatim
+function classVerbatim:preamble ()
+ if self.cond == '' then
+ write(self.line)
+ end
+end
+
+-- support code
+function classVerbatim:supcode ()
+ if strfind(self.cond,'s') then
+ write(self.line)
+ write('\n')
+ end
+end
+
+-- register code
+function classVerbatim:register (pre)
+ if strfind(self.cond,'r') then
+ write(self.line)
+ end
+end
+
+
+-- Print method
+function classVerbatim:print (ident,close)
+ print(ident.."Verbatim{")
+ print(ident.." line = '"..self.line.."',")
+ print(ident.."}"..close)
+end
+
+
+-- Internal constructor
+function _Verbatim (t)
+ setmetatable(t,classVerbatim)
+ append(t)
+ return t
+end
+
+-- Constructor
+-- Expects a string representing the text line
+function Verbatim (l,cond)
+ if strsub(l,1,1) == "'" then
+ l = strsub(l,2)
+ elseif strsub(l,1,1) == '$' then
+ cond = 'sr' -- generates in both suport and register fragments
+ l = strsub(l,2)
+ end
+ return _Verbatim {
+ line = l,
+ cond = cond or '',
+ }
+end
+
+
diff --git a/lib/tolua++/src/lib/SCsub b/lib/tolua++/src/lib/SCsub
new file mode 100644
index 000000000..2f9a24691
--- /dev/null
+++ b/lib/tolua++/src/lib/SCsub
@@ -0,0 +1,18 @@
+Import('env')
+
+
+sources = [
+ 'tolua_event.c',
+ 'tolua_is.c',
+ 'tolua_map.c',
+ 'tolua_push.c',
+ 'tolua_to.c',
+ ]
+
+env.lib_target_static = env.Library('#/lib/'+env['tolua_lib']+'_static', sources)
+
+if env['shared']:
+ env.lib_target = env.SharedLibrary('#lib/'+env['tolua_lib'], sources)
+else:
+ env.lib_target = env.Library('#/lib/'+env['tolua_lib'], sources)
+
diff --git a/lib/tolua++/src/lib/tolua_event.c b/lib/tolua++/src/lib/tolua_event.c
new file mode 100644
index 000000000..3075a60b3
--- /dev/null
+++ b/lib/tolua++/src/lib/tolua_event.c
@@ -0,0 +1,536 @@
+/* tolua: event functions
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include <stdio.h>
+
+#include "../../include/tolua++.h"
+
+/* Store at ubox
+ * It stores, creating the corresponding table if needed,
+ * the pair key/value in the corresponding ubox table
+*/
+static void storeatubox (lua_State* L, int lo)
+{
+ #ifdef LUA_VERSION_NUM
+ lua_getfenv(L, lo);
+ if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ lua_pushvalue(L, -1);
+ lua_setfenv(L, lo); /* stack: k,v,table */
+ };
+ lua_insert(L, -3);
+ lua_settable(L, -3); /* on lua 5.1, we trade the "tolua_peers" lookup for a settable call */
+ lua_pop(L, 1);
+ #else
+ /* stack: key value (to be stored) */
+ lua_pushstring(L,"tolua_peers");
+ lua_rawget(L,LUA_REGISTRYINDEX); /* stack: k v ubox */
+ lua_pushvalue(L,lo);
+ lua_rawget(L,-2); /* stack: k v ubox ubox[u] */
+ if (!lua_istable(L,-1))
+ {
+ lua_pop(L,1); /* stack: k v ubox */
+ lua_newtable(L); /* stack: k v ubox table */
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,-2); /* stack: k v ubox table u table */
+ lua_rawset(L,-4); /* stack: k v ubox ubox[u]=table */
+ }
+ lua_insert(L,-4); /* put table before k */
+ lua_pop(L,1); /* pop ubox */
+ lua_rawset(L,-3); /* store at table */
+ lua_pop(L,1); /* pop ubox[u] */
+ #endif
+}
+
+/* Module index function
+*/
+static int module_index_event (lua_State* L)
+{
+ lua_pushstring(L,".get");
+ lua_rawget(L,-3);
+ if (lua_istable(L,-1))
+ {
+ lua_pushvalue(L,2); /* key */
+ lua_rawget(L,-2);
+ if (lua_iscfunction(L,-1))
+ {
+ lua_call(L,0,1);
+ return 1;
+ }
+ else if (lua_istable(L,-1))
+ return 1;
+ }
+ /* call old index meta event */
+ if (lua_getmetatable(L,1))
+ {
+ lua_pushstring(L,"__index");
+ lua_rawget(L,-2);
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,2);
+ if (lua_isfunction(L,-1))
+ {
+ lua_call(L,2,1);
+ return 1;
+ }
+ else if (lua_istable(L,-1))
+ {
+ lua_gettable(L,-3);
+ return 1;
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+/* Module newindex function
+*/
+static int module_newindex_event (lua_State* L)
+{
+ lua_pushstring(L,".set");
+ lua_rawget(L,-4);
+ if (lua_istable(L,-1))
+ {
+ lua_pushvalue(L,2); /* key */
+ lua_rawget(L,-2);
+ if (lua_iscfunction(L,-1))
+ {
+ lua_pushvalue(L,1); /* only to be compatible with non-static vars */
+ lua_pushvalue(L,3); /* value */
+ lua_call(L,2,0);
+ return 0;
+ }
+ }
+ /* call old newindex meta event */
+ if (lua_getmetatable(L,1) && lua_getmetatable(L,-1))
+ {
+ lua_pushstring(L,"__newindex");
+ lua_rawget(L,-2);
+ if (lua_isfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,2);
+ lua_pushvalue(L,3);
+ lua_call(L,3,0);
+ }
+ }
+ lua_settop(L,3);
+ lua_rawset(L,-3);
+ return 0;
+}
+
+/* Class index function
+ * If the object is a userdata (ie, an object), it searches the field in
+ * the alternative table stored in the corresponding "ubox" table.
+*/
+static int class_index_event (lua_State* L)
+{
+ int t = lua_type(L,1);
+ if (t == LUA_TUSERDATA)
+ {
+ /* Access alternative table */
+ #ifdef LUA_VERSION_NUM /* new macro on version 5.1 */
+ lua_getfenv(L,1);
+ if (!lua_rawequal(L, -1, TOLUA_NOPEER)) {
+ lua_pushvalue(L, 2); /* key */
+ lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */
+ if (!lua_isnil(L, -1))
+ return 1;
+ };
+ #else
+ lua_pushstring(L,"tolua_peers");
+ lua_rawget(L,LUA_REGISTRYINDEX); /* stack: obj key ubox */
+ lua_pushvalue(L,1);
+ lua_rawget(L,-2); /* stack: obj key ubox ubox[u] */
+ if (lua_istable(L,-1))
+ {
+ lua_pushvalue(L,2); /* key */
+ lua_rawget(L,-2); /* stack: obj key ubox ubox[u] value */
+ if (!lua_isnil(L,-1))
+ return 1;
+ }
+ #endif
+ lua_settop(L,2); /* stack: obj key */
+ /* Try metatables */
+ lua_pushvalue(L,1); /* stack: obj key obj */
+ while (lua_getmetatable(L,-1))
+ { /* stack: obj key obj mt */
+ lua_remove(L,-2); /* stack: obj key mt */
+ if (lua_isnumber(L,2)) /* check if key is a numeric value */
+ {
+ /* try operator[] */
+ lua_pushstring(L,".geti");
+ lua_rawget(L,-2); /* stack: obj key mt func */
+ if (lua_isfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,2);
+ lua_call(L,2,1);
+ return 1;
+ }
+ }
+ else
+ {
+ lua_pushvalue(L,2); /* stack: obj key mt key */
+ lua_rawget(L,-2); /* stack: obj key mt value */
+ if (!lua_isnil(L,-1))
+ return 1;
+ else
+ lua_pop(L,1);
+ /* try C/C++ variable */
+ lua_pushstring(L,".get");
+ lua_rawget(L,-2); /* stack: obj key mt tget */
+ if (lua_istable(L,-1))
+ {
+ lua_pushvalue(L,2);
+ lua_rawget(L,-2); /* stack: obj key mt value */
+ if (lua_iscfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,2);
+ lua_call(L,2,1);
+ return 1;
+ }
+ else if (lua_istable(L,-1))
+ {
+ /* deal with array: create table to be returned and cache it in ubox */
+ void* u = *((void**)lua_touserdata(L,1));
+ lua_newtable(L); /* stack: obj key mt value table */
+ lua_pushstring(L,".self");
+ lua_pushlightuserdata(L,u);
+ lua_rawset(L,-3); /* store usertype in ".self" */
+ lua_insert(L,-2); /* stack: obj key mt table value */
+ lua_setmetatable(L,-2); /* set stored value as metatable */
+ lua_pushvalue(L,-1); /* stack: obj key met table table */
+ lua_pushvalue(L,2); /* stack: obj key mt table table key */
+ lua_insert(L,-2); /* stack: obj key mt table key table */
+ storeatubox(L,1); /* stack: obj key mt table */
+ return 1;
+ }
+ }
+ }
+ lua_settop(L,3);
+ }
+ lua_pushnil(L);
+ return 1;
+ }
+ else if (t== LUA_TTABLE)
+ {
+ module_index_event(L);
+ return 1;
+ }
+ lua_pushnil(L);
+ return 1;
+}
+
+/* Newindex function
+ * It first searches for a C/C++ varaible to be set.
+ * Then, it either stores it in the alternative ubox table (in the case it is
+ * an object) or in the own table (that represents the class or module).
+*/
+static int class_newindex_event (lua_State* L)
+{
+ int t = lua_type(L,1);
+ if (t == LUA_TUSERDATA)
+ {
+ /* Try accessing a C/C++ variable to be set */
+ lua_getmetatable(L,1);
+ while (lua_istable(L,-1)) /* stack: t k v mt */
+ {
+ if (lua_isnumber(L,2)) /* check if key is a numeric value */
+ {
+ /* try operator[] */
+ lua_pushstring(L,".seti");
+ lua_rawget(L,-2); /* stack: obj key mt func */
+ if (lua_isfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,2);
+ lua_pushvalue(L,3);
+ lua_call(L,3,0);
+ return 0;
+ }
+ }
+ else
+ {
+ lua_pushstring(L,".set");
+ lua_rawget(L,-2); /* stack: t k v mt tset */
+ if (lua_istable(L,-1))
+ {
+ lua_pushvalue(L,2);
+ lua_rawget(L,-2); /* stack: t k v mt tset func */
+ if (lua_iscfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,3);
+ lua_call(L,2,0);
+ return 0;
+ }
+ lua_pop(L,1); /* stack: t k v mt tset */
+ }
+ lua_pop(L,1); /* stack: t k v mt */
+ if (!lua_getmetatable(L,-1)) /* stack: t k v mt mt */
+ lua_pushnil(L);
+ lua_remove(L,-2); /* stack: t k v mt */
+ }
+ }
+ lua_settop(L,3); /* stack: t k v */
+
+ /* then, store as a new field */
+ storeatubox(L,1);
+ }
+ else if (t== LUA_TTABLE)
+ {
+ module_newindex_event(L);
+ }
+ return 0;
+}
+
+static int class_call_event(lua_State* L) {
+
+ if (lua_istable(L, 1)) {
+ lua_pushstring(L, ".call");
+ lua_rawget(L, 1);
+ if (lua_isfunction(L, -1)) {
+
+ lua_insert(L, 1);
+ lua_call(L, lua_gettop(L)-1, 1);
+
+ return 1;
+ };
+ };
+ tolua_error(L,"Attempt to call a non-callable object.",NULL);
+ return 0;
+};
+
+static int do_operator (lua_State* L, const char* op)
+{
+ if (lua_isuserdata(L,1))
+ {
+ /* Try metatables */
+ lua_pushvalue(L,1); /* stack: op1 op2 */
+ while (lua_getmetatable(L,-1))
+ { /* stack: op1 op2 op1 mt */
+ lua_remove(L,-2); /* stack: op1 op2 mt */
+ lua_pushstring(L,op); /* stack: op1 op2 mt key */
+ lua_rawget(L,-2); /* stack: obj key mt func */
+ if (lua_isfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,2);
+ lua_call(L,2,1);
+ return 1;
+ }
+ lua_settop(L,3);
+ }
+ }
+ tolua_error(L,"Attempt to perform operation on an invalid operand",NULL);
+ return 0;
+}
+
+static int class_add_event (lua_State* L)
+{
+ return do_operator(L,".add");
+}
+
+static int class_sub_event (lua_State* L)
+{
+ return do_operator(L,".sub");
+}
+
+static int class_mul_event (lua_State* L)
+{
+ return do_operator(L,".mul");
+}
+
+static int class_div_event (lua_State* L)
+{
+ return do_operator(L,".div");
+}
+
+static int class_lt_event (lua_State* L)
+{
+ return do_operator(L,".lt");
+}
+
+static int class_le_event (lua_State* L)
+{
+ return do_operator(L,".le");
+}
+
+static int class_eq_event (lua_State* L)
+{
+ /* copying code from do_operator here to return false when no operator is found */
+ if (lua_isuserdata(L,1))
+ {
+ /* Try metatables */
+ lua_pushvalue(L,1); /* stack: op1 op2 */
+ while (lua_getmetatable(L,-1))
+ { /* stack: op1 op2 op1 mt */
+ lua_remove(L,-2); /* stack: op1 op2 mt */
+ lua_pushstring(L,".eq"); /* stack: op1 op2 mt key */
+ lua_rawget(L,-2); /* stack: obj key mt func */
+ if (lua_isfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_pushvalue(L,2);
+ lua_call(L,2,1);
+ return 1;
+ }
+ lua_settop(L,3);
+ }
+ }
+
+ lua_settop(L, 3);
+ lua_pushboolean(L, 0);
+ return 1;
+}
+
+/*
+static int class_gc_event (lua_State* L)
+{
+ void* u = *((void**)lua_touserdata(L,1));
+ fprintf(stderr, "collecting: looking at %p\n", u);
+ lua_pushstring(L,"tolua_gc");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L,u);
+ lua_rawget(L,-2);
+ if (lua_isfunction(L,-1))
+ {
+ lua_pushvalue(L,1);
+ lua_call(L,1,0);
+ lua_pushlightuserdata(L,u);
+ lua_pushnil(L);
+ lua_rawset(L,-3);
+ }
+ lua_pop(L,2);
+ return 0;
+}
+*/
+TOLUA_API int class_gc_event (lua_State* L)
+{
+ void* u = *((void**)lua_touserdata(L,1));
+ int top;
+ /*fprintf(stderr, "collecting: looking at %p\n", u);*/
+ /*
+ lua_pushstring(L,"tolua_gc");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ */
+ lua_pushvalue(L, lua_upvalueindex(1));
+ lua_pushlightuserdata(L,u);
+ lua_rawget(L,-2); /* stack: gc umt */
+ lua_getmetatable(L,1); /* stack: gc umt mt */
+ /*fprintf(stderr, "checking type\n");*/
+ top = lua_gettop(L);
+ if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) /* make sure we collect correct type */
+ {
+ /*fprintf(stderr, "Found type!\n");*/
+ /* get gc function */
+ lua_pushliteral(L,".collector");
+ lua_rawget(L,-2); /* stack: gc umt mt collector */
+ if (lua_isfunction(L,-1)) {
+ /*fprintf(stderr, "Found .collector!\n");*/
+ }
+ else {
+ lua_pop(L,1);
+ /*fprintf(stderr, "Using default cleanup\n");*/
+ lua_pushcfunction(L,tolua_default_collect);
+ }
+
+ lua_pushvalue(L,1); /* stack: gc umt mt collector u */
+ lua_call(L,1,0);
+
+ lua_pushlightuserdata(L,u); /* stack: gc umt mt u */
+ lua_pushnil(L); /* stack: gc umt mt u nil */
+ lua_rawset(L,-5); /* stack: gc umt mt */
+ }
+ lua_pop(L,3);
+ return 0;
+}
+
+
+/* Register module events
+ * It expects the metatable on the top of the stack
+*/
+TOLUA_API void tolua_moduleevents (lua_State* L)
+{
+ lua_pushstring(L,"__index");
+ lua_pushcfunction(L,module_index_event);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__newindex");
+ lua_pushcfunction(L,module_newindex_event);
+ lua_rawset(L,-3);
+}
+
+/* Check if the object on the top has a module metatable
+*/
+TOLUA_API int tolua_ismodulemetatable (lua_State* L)
+{
+ int r = 0;
+ if (lua_getmetatable(L,-1))
+ {
+ lua_pushstring(L,"__index");
+ lua_rawget(L,-2);
+ r = (lua_tocfunction(L,-1) == module_index_event);
+ lua_pop(L,2);
+ }
+ return r;
+}
+
+/* Register class events
+ * It expects the metatable on the top of the stack
+*/
+TOLUA_API void tolua_classevents (lua_State* L)
+{
+ lua_pushstring(L,"__index");
+ lua_pushcfunction(L,class_index_event);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__newindex");
+ lua_pushcfunction(L,class_newindex_event);
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"__add");
+ lua_pushcfunction(L,class_add_event);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__sub");
+ lua_pushcfunction(L,class_sub_event);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__mul");
+ lua_pushcfunction(L,class_mul_event);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__div");
+ lua_pushcfunction(L,class_div_event);
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"__lt");
+ lua_pushcfunction(L,class_lt_event);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__le");
+ lua_pushcfunction(L,class_le_event);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__eq");
+ lua_pushcfunction(L,class_eq_event);
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"__call");
+ lua_pushcfunction(L,class_call_event);
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"__gc");
+ lua_pushstring(L, "tolua_gc_event");
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ /*lua_pushcfunction(L,class_gc_event);*/
+ lua_rawset(L,-3);
+}
+
diff --git a/lib/tolua++/src/lib/tolua_event.h b/lib/tolua++/src/lib/tolua_event.h
new file mode 100644
index 000000000..d6b071152
--- /dev/null
+++ b/lib/tolua++/src/lib/tolua_event.h
@@ -0,0 +1,24 @@
+/* tolua: event functions
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#ifndef TOLUA_EVENT_H
+#define TOLUA_EVENT_H
+
+#include "../../include/tolua++.h"
+
+TOLUA_API void tolua_moduleevents (lua_State* L);
+TOLUA_API int tolua_ismodulemetatable (lua_State* L);
+TOLUA_API void tolua_classevents (lua_State* L);
+
+#endif
diff --git a/lib/tolua++/src/lib/tolua_is.c b/lib/tolua++/src/lib/tolua_is.c
new file mode 100644
index 000000000..b470477ff
--- /dev/null
+++ b/lib/tolua++/src/lib/tolua_is.c
@@ -0,0 +1,621 @@
+/* tolua: functions to check types.
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "../../include/tolua++.h"
+#include "../../../lua/src/lauxlib.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* a fast check if a is b, without parameter validation
+ i.e. if b is equal to a or a superclass of a. */
+TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index)
+{
+ int result;
+ if (lua_rawequal(L,mt_indexa,mt_indexb))
+ result = 1;
+ else
+ {
+ if (super_index) {
+ lua_pushvalue(L, super_index);
+ } else {
+ lua_pushliteral(L,"tolua_super");
+ lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super */
+ };
+ lua_pushvalue(L,mt_indexa); /* stack: super mta */
+ lua_rawget(L,-2); /* stack: super super[mta] */
+ lua_pushvalue(L,mt_indexb); /* stack: super super[mta] mtb */
+ lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super super[mta] typenameB */
+ lua_rawget(L,-2); /* stack: super super[mta] bool */
+ result = lua_toboolean(L,-1);
+ lua_pop(L,3);
+ }
+ return result;
+}
+
+/* Push and returns the corresponding object typename */
+TOLUA_API const char* tolua_typename (lua_State* L, int lo)
+{
+ int tag = lua_type(L,lo);
+ if (tag == LUA_TNONE)
+ lua_pushstring(L,"[no object]");
+ else if (tag != LUA_TUSERDATA && tag != LUA_TTABLE)
+ lua_pushstring(L,lua_typename(L,tag));
+ else if (tag == LUA_TUSERDATA)
+ {
+ if (!lua_getmetatable(L,lo))
+ lua_pushstring(L,lua_typename(L,tag));
+ else
+ {
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ if (!lua_isstring(L,-1))
+ {
+ lua_pop(L,1);
+ lua_pushstring(L,"[undefined]");
+ }
+ }
+ }
+ else /* is table */
+ {
+ lua_pushvalue(L,lo);
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ if (!lua_isstring(L,-1))
+ {
+ lua_pop(L,1);
+ lua_pushstring(L,"table");
+ }
+ else
+ {
+ lua_pushstring(L,"class ");
+ lua_insert(L,-2);
+ lua_concat(L,2);
+ }
+ }
+ return lua_tostring(L,-1);
+}
+
+TOLUA_API void tolua_error (lua_State* L, const char* msg, tolua_Error* err)
+{
+ if (msg[0] == '#')
+ {
+ const char* expected = err->type;
+ const char* provided = tolua_typename(L,err->index);
+ if (msg[1]=='f')
+ {
+ int narg = err->index;
+ if (err->array)
+ luaL_error(L,"%s\n argument #%d is array of '%s'; array of '%s' expected.\n",
+ msg+2,narg,provided,expected);
+ else
+ luaL_error(L,"%s\n argument #%d is '%s'; '%s' expected.\n",
+ msg+2,narg,provided,expected);
+ }
+ else if (msg[1]=='v')
+ {
+ if (err->array)
+ luaL_error(L,"%s\n value is array of '%s'; array of '%s' expected.\n",
+ msg+2,provided,expected);
+ else
+ luaL_error(L,"%s\n value is '%s'; '%s' expected.\n",
+ msg+2,provided,expected);
+ }
+ }
+ else
+ luaL_error(L,msg);
+}
+
+/* the equivalent of lua_is* for usertable */
+static int lua_isusertable (lua_State* L, int lo, const char* type)
+{
+ int r = 0;
+ if (lo < 0) lo = lua_gettop(L)+lo+1;
+ lua_pushvalue(L,lo);
+ lua_rawget(L,LUA_REGISTRYINDEX); /* get registry[t] */
+ if (lua_isstring(L,-1))
+ {
+ r = strcmp(lua_tostring(L,-1),type)==0;
+ if (!r)
+ {
+ /* try const */
+ lua_pushstring(L,"const ");
+ lua_insert(L,-2);
+ lua_concat(L,2);
+ r = lua_isstring(L,-1) && strcmp(lua_tostring(L,-1),type)==0;
+ }
+ }
+ lua_pop(L, 1);
+ return r;
+}
+
+int push_table_instance(lua_State* L, int lo) {
+
+ if (lua_istable(L, lo)) {
+
+ lua_pushstring(L, ".c_instance");
+ lua_gettable(L, lo);
+ if (lua_isuserdata(L, -1)) {
+
+ lua_replace(L, lo);
+ return 1;
+ } else {
+
+ lua_pop(L, 1);
+ return 0;
+ };
+ } else {
+ return 0;
+ };
+
+ return 0;
+};
+
+/* the equivalent of lua_is* for usertype */
+static int lua_isusertype (lua_State* L, int lo, const char* type)
+{
+ if (!lua_isuserdata(L,lo)) {
+ if (!push_table_instance(L, lo)) {
+ return 0;
+ };
+ };
+ {
+ /* check if it is of the same type */
+ int r;
+ const char *tn;
+ if (lua_getmetatable(L,lo)) /* if metatable? */
+ {
+ lua_rawget(L,LUA_REGISTRYINDEX); /* get registry[mt] */
+ tn = lua_tostring(L,-1);
+ r = tn && (strcmp(tn,type) == 0);
+ lua_pop(L, 1);
+ if (r)
+ return 1;
+ else
+ {
+ /* check if it is a specialized class */
+ lua_pushstring(L,"tolua_super");
+ lua_rawget(L,LUA_REGISTRYINDEX); /* get super */
+ lua_getmetatable(L,lo);
+ lua_rawget(L,-2); /* get super[mt] */
+ if (lua_istable(L,-1))
+ {
+ int b;
+ lua_pushstring(L,type);
+ lua_rawget(L,-2); /* get super[mt][type] */
+ b = lua_toboolean(L,-1);
+ lua_pop(L,3);
+ if (b)
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+TOLUA_API int tolua_isnoobj (lua_State* L, int lo, tolua_Error* err)
+{
+ if (lua_gettop(L)<abs(lo))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = "[no object]";
+ return 0;
+}
+
+TOLUA_API int tolua_isboolean (lua_State* L, int lo, int def, tolua_Error* err)
+{
+ if (def && lua_gettop(L)<abs(lo))
+ return 1;
+ if (lua_isnil(L,lo) || lua_isboolean(L,lo))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = "boolean";
+ return 0;
+}
+
+TOLUA_API int tolua_isnumber (lua_State* L, int lo, int def, tolua_Error* err)
+{
+ if (def && lua_gettop(L)<abs(lo))
+ return 1;
+ if (lua_isnumber(L,lo))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = "number";
+ return 0;
+}
+
+TOLUA_API int tolua_isstring (lua_State* L, int lo, int def, tolua_Error* err)
+{
+ if (def && lua_gettop(L)<abs(lo))
+ return 1;
+ if (lua_isnil(L,lo) || lua_isstring(L,lo))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = "string";
+ return 0;
+}
+
+TOLUA_API int tolua_istable (lua_State* L, int lo, int def, tolua_Error* err)
+{
+ if (def && lua_gettop(L)<abs(lo))
+ return 1;
+ if (lua_istable(L,lo))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = "table";
+ return 0;
+}
+
+TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
+{
+ if (def && lua_gettop(L)<abs(lo))
+ return 1;
+ if (lua_isusertable(L,lo,type))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = type;
+ return 0;
+}
+
+
+TOLUA_API int tolua_isuserdata (lua_State* L, int lo, int def, tolua_Error* err)
+{
+ if (def && lua_gettop(L)<abs(lo))
+ return 1;
+ if (lua_isnil(L,lo) || lua_isuserdata(L,lo))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = "userdata";
+ return 0;
+}
+
+TOLUA_API int tolua_isvaluenil (lua_State* L, int lo, tolua_Error* err) {
+
+ if (lua_gettop(L)<abs(lo))
+ return 0; /* somebody else should chack this */
+ if (!lua_isnil(L, lo))
+ return 0;
+
+ err->index = lo;
+ err->array = 0;
+ err->type = "value";
+ return 1;
+};
+
+TOLUA_API int tolua_isvalue (lua_State* L, int lo, int def, tolua_Error* err)
+{
+ if (def || abs(lo)<=lua_gettop(L)) /* any valid index */
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = "value";
+ return 0;
+}
+
+TOLUA_API int tolua_isusertype (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
+{
+ if (def && lua_gettop(L)<abs(lo))
+ return 1;
+ if (lua_isnil(L,lo) || lua_isusertype(L,lo,type))
+ return 1;
+ err->index = lo;
+ err->array = 0;
+ err->type = type;
+ return 0;
+}
+
+TOLUA_API int tolua_isvaluearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+ if (!tolua_istable(L,lo,def,err))
+ return 0;
+ else
+ return 1;
+}
+
+TOLUA_API int tolua_isbooleanarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+ if (!tolua_istable(L,lo,def,err))
+ return 0;
+ else
+ {
+ int i;
+ for (i=1; i<=dim; ++i)
+ {
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isboolean(L,-1)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "boolean";
+ return 0;
+ }
+ lua_pop(L,1);
+ }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isnumberarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+ if (!tolua_istable(L,lo,def,err))
+ return 0;
+ else
+ {
+ int i;
+ for (i=1; i<=dim; ++i)
+ {
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!lua_isnumber(L,-1) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "number";
+ return 0;
+ }
+ lua_pop(L,1);
+ }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isstringarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+ if (!tolua_istable(L,lo,def,err))
+ return 0;
+ else
+ {
+ int i;
+ for (i=1; i<=dim; ++i)
+ {
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isstring(L,-1)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "string";
+ return 0;
+ }
+ lua_pop(L,1);
+ }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_istablearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+ if (!tolua_istable(L,lo,def,err))
+ return 0;
+ else
+ {
+ int i;
+ for (i=1; i<=dim; ++i)
+ {
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (! lua_istable(L,-1) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "table";
+ return 0;
+ }
+ lua_pop(L,1);
+ }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isuserdataarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+ if (!tolua_istable(L,lo,def,err))
+ return 0;
+ else
+ {
+ int i;
+ for (i=1; i<=dim; ++i)
+ {
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "userdata";
+ return 0;
+ }
+ lua_pop(L,1);
+ }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isusertypearray
+ (lua_State* L, int lo, const char* type, int dim, int def, tolua_Error* err)
+{
+ if (!tolua_istable(L,lo,def,err))
+ return 0;
+ else
+ {
+ int i;
+ for (i=1; i<=dim; ++i)
+ {
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->type = type;
+ err->array = 1;
+ return 0;
+ }
+ lua_pop(L,1);
+ }
+ }
+ return 1;
+}
+
+#if 0
+int tolua_isbooleanfield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isboolean(L,-1)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "boolean";
+ return 0;
+ }
+ lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isnumberfield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!lua_isnumber(L,-1) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "number";
+ return 0;
+ }
+ lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isstringfield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isstring(L,-1)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "string";
+ return 0;
+ }
+ lua_pop(L,1);
+ return 1;
+}
+
+int tolua_istablefield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+ lua_pushnumber(L,i+1);
+ lua_gettable(L,lo);
+ if (! lua_istable(L,-1) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "table";
+ return 0;
+ }
+ lua_pop(L,1);
+}
+
+int tolua_isusertablefield
+ (lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
+{
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (! lua_isusertable(L,-1,type) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = type;
+ return 0;
+ }
+ lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isuserdatafield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->array = 1;
+ err->type = "userdata";
+ return 0;
+ }
+ lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isusertypefield
+ (lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
+{
+ lua_pushnumber(L,i);
+ lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isusertype(L,-1,type)) &&
+ !(def && lua_isnil(L,-1))
+ )
+ {
+ err->index = lo;
+ err->type = type;
+ err->array = 1;
+ return 0;
+ }
+ lua_pop(L,1);
+ return 1;
+}
+
+#endif
diff --git a/lib/tolua++/src/lib/tolua_map.c b/lib/tolua++/src/lib/tolua_map.c
new file mode 100644
index 000000000..937229610
--- /dev/null
+++ b/lib/tolua++/src/lib/tolua_map.c
@@ -0,0 +1,704 @@
+/* tolua: functions to map features
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "../../include/tolua++.h"
+#include "../../../lua/src/lauxlib.h"
+#include "tolua_event.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+
+/* Create metatable
+ * Create and register new metatable
+*/
+static int tolua_newmetatable (lua_State* L, const char * name)
+{
+ int r = luaL_newmetatable(L,name);
+
+ #ifdef LUA_VERSION_NUM /* only lua 5.1 */
+ if (r) {
+ lua_pushvalue(L, -1);
+ lua_pushstring(L, name);
+ lua_settable(L, LUA_REGISTRYINDEX); /* reg[mt] = type_name */
+ };
+ #endif
+
+ if (r)
+ tolua_classevents(L); /* set meta events */
+ lua_pop(L,1);
+ return r;
+}
+
+/* Map super classes
+ * It sets 'name' as being also a 'base', mapping all super classes of 'base' in 'name'
+*/
+static void mapsuper (lua_State* L, const char* name, const char* base)
+{
+ /* push registry.super */
+ lua_pushstring(L,"tolua_super");
+ lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super */
+ luaL_getmetatable(L,name); /* stack: super mt */
+ lua_rawget(L,-2); /* stack: super table */
+ if (lua_isnil(L,-1))
+ {
+ /* create table */
+ lua_pop(L,1);
+ lua_newtable(L); /* stack: super table */
+ luaL_getmetatable(L,name); /* stack: super table mt */
+ lua_pushvalue(L,-2); /* stack: super table mt table */
+ lua_rawset(L,-4); /* stack: super table */
+ }
+
+ /* set base as super class */
+ lua_pushstring(L,base);
+ lua_pushboolean(L,1);
+ lua_rawset(L,-3); /* stack: super table */
+
+ /* set all super class of base as super class of name */
+ luaL_getmetatable(L,base); /* stack: super table base_mt */
+ lua_rawget(L,-3); /* stack: super table base_table */
+ if (lua_istable(L,-1))
+ {
+ /* traverse base table */
+ lua_pushnil(L); /* first key */
+ while (lua_next(L,-2) != 0)
+ {
+ /* stack: ... base_table key value */
+ lua_pushvalue(L,-2); /* stack: ... base_table key value key */
+ lua_insert(L,-2); /* stack: ... base_table key key value */
+ lua_rawset(L,-5); /* stack: ... base_table key */
+ }
+ }
+ lua_pop(L,3); /* stack: <empty> */
+}
+
+/* creates a 'tolua_ubox' table for base clases, and
+// expects the metatable and base metatable on the stack */
+static void set_ubox(lua_State* L) {
+
+ /* mt basemt */
+ if (!lua_isnil(L, -1)) {
+ lua_pushstring(L, "tolua_ubox");
+ lua_rawget(L,-2);
+ } else {
+ lua_pushnil(L);
+ };
+ /* mt basemt base_ubox */
+ if (!lua_isnil(L,-1)) {
+ lua_pushstring(L, "tolua_ubox");
+ lua_insert(L, -2);
+ /* mt basemt key ubox */
+ lua_rawset(L,-4);
+ /* (mt with ubox) basemt */
+ } else {
+ /* mt basemt nil */
+ lua_pop(L, 1);
+ lua_pushstring(L,"tolua_ubox"); lua_newtable(L);
+ /* make weak value metatable for ubox table to allow userdata to be
+ garbage-collected */
+ lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "v"); lua_rawset(L, -3); /* stack: string ubox mt */
+ lua_setmetatable(L, -2); /* stack:mt basemt string ubox */
+ lua_rawset(L,-4);
+ };
+
+};
+
+/* Map inheritance
+ * It sets 'name' as derived from 'base' by setting 'base' as metatable of 'name'
+*/
+static void mapinheritance (lua_State* L, const char* name, const char* base)
+{
+ /* set metatable inheritance */
+ luaL_getmetatable(L,name);
+
+ if (base && *base)
+ luaL_getmetatable(L,base);
+ else {
+
+ if (lua_getmetatable(L, -1)) { /* already has a mt, we don't overwrite it */
+ lua_pop(L, 2);
+ return;
+ };
+ luaL_getmetatable(L,"tolua_commonclass");
+ };
+
+ set_ubox(L);
+
+ lua_setmetatable(L,-2);
+ lua_pop(L,1);
+}
+
+/* Object type
+*/
+static int tolua_bnd_type (lua_State* L)
+{
+ tolua_typename(L,lua_gettop(L));
+ return 1;
+}
+
+/* Take ownership
+*/
+static int tolua_bnd_takeownership (lua_State* L)
+{
+ int success = 0;
+ if (lua_isuserdata(L,1))
+ {
+ if (lua_getmetatable(L,1)) /* if metatable? */
+ {
+ lua_pop(L,1); /* clear metatable off stack */
+ /* force garbage collection to avoid C to reuse a to-be-collected address */
+ #ifdef LUA_VERSION_NUM
+ lua_gc(L, LUA_GCCOLLECT, 0);
+ #else
+ lua_setgcthreshold(L,0);
+ #endif
+
+ success = tolua_register_gc(L,1);
+ }
+ }
+ lua_pushboolean(L,success!=0);
+ return 1;
+}
+
+/* Release ownership
+*/
+static int tolua_bnd_releaseownership (lua_State* L)
+{
+ int done = 0;
+ if (lua_isuserdata(L,1))
+ {
+ void* u = *((void**)lua_touserdata(L,1));
+ /* force garbage collection to avoid releasing a to-be-collected address */
+ #ifdef LUA_VERSION_NUM
+ lua_gc(L, LUA_GCCOLLECT, 0);
+ #else
+ lua_setgcthreshold(L,0);
+ #endif
+ lua_pushstring(L,"tolua_gc");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L,u);
+ lua_rawget(L,-2);
+ lua_getmetatable(L,1);
+ if (lua_rawequal(L,-1,-2)) /* check that we are releasing the correct type */
+ {
+ lua_pushlightuserdata(L,u);
+ lua_pushnil(L);
+ lua_rawset(L,-5);
+ done = 1;
+ }
+ }
+ lua_pushboolean(L,done!=0);
+ return 1;
+}
+
+/* Type casting
+*/
+static int tolua_bnd_cast (lua_State* L)
+{
+
+/* // old code
+ void* v = tolua_tousertype(L,1,NULL);
+ const char* s = tolua_tostring(L,2,NULL);
+ if (v && s)
+ tolua_pushusertype(L,v,s);
+ else
+ lua_pushnil(L);
+ return 1;
+*/
+
+ void* v;
+ const char* s;
+ if (lua_islightuserdata(L, 1)) {
+ v = tolua_touserdata(L, 1, NULL);
+ } else {
+ v = tolua_tousertype(L, 1, 0);
+ };
+
+ s = tolua_tostring(L,2,NULL);
+ if (v && s)
+ tolua_pushusertype(L,v,s);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+/* Inheritance
+*/
+static int tolua_bnd_inherit (lua_State* L) {
+
+ /* stack: lua object, c object */
+ lua_pushstring(L, ".c_instance");
+ lua_pushvalue(L, -2);
+ lua_rawset(L, -4);
+ /* l_obj[".c_instance"] = c_obj */
+
+ return 0;
+};
+
+#ifdef LUA_VERSION_NUM /* lua 5.1 */
+static int tolua_bnd_setpeer(lua_State* L) {
+
+ /* stack: userdata, table */
+ if (!lua_isuserdata(L, -2)) {
+ lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected.");
+ lua_error(L);
+ };
+
+ if (lua_isnil(L, -1)) {
+
+ lua_pop(L, 1);
+ lua_pushvalue(L, TOLUA_NOPEER);
+ };
+ lua_setfenv(L, -2);
+
+ return 0;
+};
+
+static int tolua_bnd_getpeer(lua_State* L) {
+
+ /* stack: userdata */
+ lua_getfenv(L, -1);
+ if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
+ lua_pop(L, 1);
+ lua_pushnil(L);
+ };
+ return 1;
+};
+#endif
+
+/* static int class_gc_event (lua_State* L); */
+
+TOLUA_API void tolua_open (lua_State* L)
+{
+ int top = lua_gettop(L);
+ lua_pushstring(L,"tolua_opened");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ if (!lua_isboolean(L,-1))
+ {
+ lua_pushstring(L,"tolua_opened"); lua_pushboolean(L,1); lua_rawset(L,LUA_REGISTRYINDEX);
+
+ #ifndef LUA_VERSION_NUM /* only prior to lua 5.1 */
+ /* create peer object table */
+ lua_pushstring(L, "tolua_peers"); lua_newtable(L);
+ /* make weak key metatable for peers indexed by userdata object */
+ lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "k"); lua_rawset(L, -3); /* stack: string peers mt */
+ lua_setmetatable(L, -2); /* stack: string peers */
+ lua_rawset(L,LUA_REGISTRYINDEX);
+ #endif
+
+ /* create object ptr -> udata mapping table */
+ lua_pushstring(L,"tolua_ubox"); lua_newtable(L);
+ /* make weak value metatable for ubox table to allow userdata to be
+ garbage-collected */
+ lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "v"); lua_rawset(L, -3); /* stack: string ubox mt */
+ lua_setmetatable(L, -2); /* stack: string ubox */
+ lua_rawset(L,LUA_REGISTRYINDEX);
+
+ lua_pushstring(L,"tolua_super"); lua_newtable(L); lua_rawset(L,LUA_REGISTRYINDEX);
+ lua_pushstring(L,"tolua_gc"); lua_newtable(L);lua_rawset(L,LUA_REGISTRYINDEX);
+
+ /* create gc_event closure */
+ lua_pushstring(L, "tolua_gc_event");
+ lua_pushstring(L, "tolua_gc");
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushstring(L, "tolua_super");
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushcclosure(L, class_gc_event, 2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+
+ tolua_newmetatable(L,"tolua_commonclass");
+
+ tolua_module(L,NULL,0);
+ tolua_beginmodule(L,NULL);
+ tolua_module(L,"tolua",0);
+ tolua_beginmodule(L,"tolua");
+ tolua_function(L,"type",tolua_bnd_type);
+ tolua_function(L,"takeownership",tolua_bnd_takeownership);
+ tolua_function(L,"releaseownership",tolua_bnd_releaseownership);
+ tolua_function(L,"cast",tolua_bnd_cast);
+ tolua_function(L,"inherit", tolua_bnd_inherit);
+ #ifdef LUA_VERSION_NUM /* lua 5.1 */
+ tolua_function(L, "setpeer", tolua_bnd_setpeer);
+ tolua_function(L, "getpeer", tolua_bnd_getpeer);
+ #endif
+
+ tolua_endmodule(L);
+ tolua_endmodule(L);
+ }
+ lua_settop(L,top);
+}
+
+/* Copy a C object
+*/
+TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size)
+{
+ void* clone = (void*)malloc(size);
+ if (clone)
+ memcpy(clone,value,size);
+ else
+ tolua_error(L,"insuficient memory",NULL);
+ return clone;
+}
+
+/* Default collect function
+*/
+TOLUA_API int tolua_default_collect (lua_State* tolua_S)
+{
+ void* self = tolua_tousertype(tolua_S,1,0);
+ free(self);
+ return 0;
+}
+
+/* Do clone
+*/
+TOLUA_API int tolua_register_gc (lua_State* L, int lo)
+{
+ int success = 1;
+ void *value = *(void **)lua_touserdata(L,lo);
+ lua_pushstring(L,"tolua_gc");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L,value);
+ lua_rawget(L,-2);
+ if (!lua_isnil(L,-1)) /* make sure that object is not already owned */
+ success = 0;
+ else
+ {
+ lua_pushlightuserdata(L,value);
+ lua_getmetatable(L,lo);
+ lua_rawset(L,-4);
+ }
+ lua_pop(L,2);
+ return success;
+}
+
+/* Register a usertype
+ * It creates the correspoding metatable in the registry, for both 'type' and 'const type'.
+ * It maps 'const type' as being also a 'type'
+*/
+TOLUA_API void tolua_usertype (lua_State* L, const char* type)
+{
+ char ctype[128] = "const ";
+ strncat(ctype,type,120);
+
+ /* create both metatables */
+ if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type))
+ mapsuper(L,type,ctype); /* 'type' is also a 'const type' */
+}
+
+
+/* Begin module
+ * It pushes the module (or class) table on the stack
+*/
+TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
+{
+ if (name)
+ {
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ }
+ else
+ lua_pushvalue(L,LUA_GLOBALSINDEX);
+}
+
+/* End module
+ * It pops the module (or class) from the stack
+*/
+TOLUA_API void tolua_endmodule (lua_State* L)
+{
+ lua_pop(L,1);
+}
+
+/* Map module
+ * It creates a new module
+*/
+#if 1
+TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
+{
+ if (name)
+ {
+ /* tolua module */
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1)) /* check if module already exists */
+ {
+ lua_pop(L,1);
+ lua_newtable(L);
+ lua_pushstring(L,name);
+ lua_pushvalue(L,-2);
+ lua_rawset(L,-4); /* assing module into module */
+ }
+ }
+ else
+ {
+ /* global table */
+ lua_pushvalue(L,LUA_GLOBALSINDEX);
+ }
+ if (hasvar)
+ {
+ if (!tolua_ismodulemetatable(L)) /* check if it already has a module metatable */
+ {
+ /* create metatable to get/set C/C++ variable */
+ lua_newtable(L);
+ tolua_moduleevents(L);
+ if (lua_getmetatable(L,-2))
+ lua_setmetatable(L,-2); /* set old metatable as metatable of metatable */
+ lua_setmetatable(L,-2);
+ }
+ }
+ lua_pop(L,1); /* pop module */
+}
+#else
+TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
+{
+ if (name)
+ {
+ /* tolua module */
+ lua_pushstring(L,name);
+ lua_newtable(L);
+ }
+ else
+ {
+ /* global table */
+ lua_pushvalue(L,LUA_GLOBALSINDEX);
+ }
+ if (hasvar)
+ {
+ /* create metatable to get/set C/C++ variable */
+ lua_newtable(L);
+ tolua_moduleevents(L);
+ if (lua_getmetatable(L,-2))
+ lua_setmetatable(L,-2); /* set old metatable as metatable of metatable */
+ lua_setmetatable(L,-2);
+ }
+ if (name)
+ lua_rawset(L,-3); /* assing module into module */
+ else
+ lua_pop(L,1); /* pop global table */
+}
+#endif
+
+static void push_collector(lua_State* L, const char* type, lua_CFunction col) {
+
+ /* push collector function, but only if it's not NULL, or if there's no
+ collector already */
+ if (!col) return;
+ luaL_getmetatable(L,type);
+ lua_pushstring(L,".collector");
+ /*
+ if (!col) {
+ lua_pushvalue(L, -1);
+ lua_rawget(L, -3);
+ if (!lua_isnil(L, -1)) {
+ lua_pop(L, 3);
+ return;
+ };
+ lua_pop(L, 1);
+ };
+ // */
+ lua_pushcfunction(L,col);
+
+ lua_rawset(L,-3);
+ lua_pop(L, 1);
+};
+
+/* Map C class
+ * It maps a C class, setting the appropriate inheritance and super classes.
+*/
+TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col)
+{
+ char cname[128] = "const ";
+ char cbase[128] = "const ";
+ strncat(cname,name,120);
+ strncat(cbase,base,120);
+
+ mapinheritance(L,name,base);
+ mapinheritance(L,cname,name);
+
+ mapsuper(L,cname,cbase);
+ mapsuper(L,name,base);
+
+ lua_pushstring(L,lname);
+
+ push_collector(L, name, col);
+ /*
+ luaL_getmetatable(L,name);
+ lua_pushstring(L,".collector");
+ lua_pushcfunction(L,col);
+
+ lua_rawset(L,-3);
+ */
+
+ luaL_getmetatable(L,name);
+ lua_rawset(L,-3); /* assign class metatable to module */
+
+ /* now we also need to store the collector table for the const
+ instances of the class */
+ push_collector(L, cname, col);
+ /*
+ luaL_getmetatable(L,cname);
+ lua_pushstring(L,".collector");
+ lua_pushcfunction(L,col);
+ lua_rawset(L,-3);
+ lua_pop(L,1);
+ */
+
+
+}
+
+/* Add base
+ * It adds additional base classes to a class (for multiple inheritance)
+ * (not for now)
+TOLUA_API void tolua_addbase(lua_State* L, char* name, char* base) {
+
+ char cname[128] = "const ";
+ char cbase[128] = "const ";
+ strncat(cname,name,120);
+ strncat(cbase,base,120);
+
+ mapsuper(L,cname,cbase);
+ mapsuper(L,name,base);
+};
+*/
+
+/* Map function
+ * It assigns a function into the current module (or class)
+*/
+TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func)
+{
+ lua_pushstring(L,name);
+ lua_pushcfunction(L,func);
+ lua_rawset(L,-3);
+}
+
+/* sets the __call event for the class (expects the class' main table on top) */
+/* never really worked :(
+TOLUA_API void tolua_set_call_event(lua_State* L, lua_CFunction func, char* type) {
+
+ lua_getmetatable(L, -1);
+ //luaL_getmetatable(L, type);
+ lua_pushstring(L,"__call");
+ lua_pushcfunction(L,func);
+ lua_rawset(L,-3);
+ lua_pop(L, 1);
+};
+*/
+
+/* Map constant number
+ * It assigns a constant number into the current module (or class)
+*/
+TOLUA_API void tolua_constant (lua_State* L, const char* name, lua_Number value)
+{
+ lua_pushstring(L,name);
+ tolua_pushnumber(L,value);
+ lua_rawset(L,-3);
+}
+
+
+/* Map variable
+ * It assigns a variable into the current module (or class)
+*/
+TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
+{
+ /* get func */
+ lua_pushstring(L,".get");
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1))
+ {
+ /* create .get table, leaving it at the top */
+ lua_pop(L,1);
+ lua_newtable(L);
+ lua_pushstring(L,".get");
+ lua_pushvalue(L,-2);
+ lua_rawset(L,-4);
+ }
+ lua_pushstring(L,name);
+ lua_pushcfunction(L,get);
+ lua_rawset(L,-3); /* store variable */
+ lua_pop(L,1); /* pop .get table */
+
+ /* set func */
+ if (set)
+ {
+ lua_pushstring(L,".set");
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1))
+ {
+ /* create .set table, leaving it at the top */
+ lua_pop(L,1);
+ lua_newtable(L);
+ lua_pushstring(L,".set");
+ lua_pushvalue(L,-2);
+ lua_rawset(L,-4);
+ }
+ lua_pushstring(L,name);
+ lua_pushcfunction(L,set);
+ lua_rawset(L,-3); /* store variable */
+ lua_pop(L,1); /* pop .set table */
+ }
+}
+
+/* Access const array
+ * It reports an error when trying to write into a const array
+*/
+static int const_array (lua_State* L)
+{
+ luaL_error(L,"value of const array cannot be changed");
+ return 0;
+}
+
+/* Map an array
+ * It assigns an array into the current module (or class)
+*/
+TOLUA_API void tolua_array (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
+{
+ lua_pushstring(L,".get");
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1))
+ {
+ /* create .get table, leaving it at the top */
+ lua_pop(L,1);
+ lua_newtable(L);
+ lua_pushstring(L,".get");
+ lua_pushvalue(L,-2);
+ lua_rawset(L,-4);
+ }
+ lua_pushstring(L,name);
+
+ lua_newtable(L); /* create array metatable */
+ lua_pushvalue(L,-1);
+ lua_setmetatable(L,-2); /* set the own table as metatable (for modules) */
+ lua_pushstring(L,"__index");
+ lua_pushcfunction(L,get);
+ lua_rawset(L,-3);
+ lua_pushstring(L,"__newindex");
+ lua_pushcfunction(L,set?set:const_array);
+ lua_rawset(L,-3);
+
+ lua_rawset(L,-3); /* store variable */
+ lua_pop(L,1); /* pop .get table */
+}
+
+
+TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, const char* name) {
+
+ #ifdef LUA_VERSION_NUM /* lua 5.1 */
+ luaL_loadbuffer(L, B, size, name) || lua_pcall(L, 0, 0, 0);
+ #else
+ lua_dobuffer(L, B, size, name);
+ #endif
+};
+
diff --git a/lib/tolua++/src/lib/tolua_push.c b/lib/tolua++/src/lib/tolua_push.c
new file mode 100644
index 000000000..947f0e7a5
--- /dev/null
+++ b/lib/tolua++/src/lib/tolua_push.c
@@ -0,0 +1,171 @@
+/* tolua: functions to push C values.
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "../../include/tolua++.h"
+#include "../../../lua/src/lauxlib.h"
+
+#include <stdlib.h>
+
+TOLUA_API void tolua_pushvalue (lua_State* L, int lo)
+{
+ lua_pushvalue(L,lo);
+}
+
+TOLUA_API void tolua_pushboolean (lua_State* L, int value)
+{
+ lua_pushboolean(L,value);
+}
+
+TOLUA_API void tolua_pushnumber (lua_State* L, lua_Number value)
+{
+ lua_pushnumber(L,value);
+}
+
+TOLUA_API void tolua_pushstring (lua_State* L, const char* value)
+{
+ if (value == NULL)
+ lua_pushnil(L);
+ else
+ lua_pushstring(L,value);
+}
+
+TOLUA_API void tolua_pushuserdata (lua_State* L, void* value)
+{
+ if (value == NULL)
+ lua_pushnil(L);
+ else
+ lua_pushlightuserdata(L,value);
+}
+
+TOLUA_API void tolua_pushusertype (lua_State* L, void* value, const char* type)
+{
+ if (value == NULL)
+ lua_pushnil(L);
+ else
+ {
+ luaL_getmetatable(L, type);
+ lua_pushstring(L,"tolua_ubox");
+ lua_rawget(L,-2); /* stack: mt ubox */
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ lua_pushstring(L, "tolua_ubox");
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ };
+ lua_pushlightuserdata(L,value);
+ lua_rawget(L,-2); /* stack: mt ubox ubox[u] */
+ if (lua_isnil(L,-1))
+ {
+ lua_pop(L,1); /* stack: mt ubox */
+ lua_pushlightuserdata(L,value);
+ *(void**)lua_newuserdata(L,sizeof(void *)) = value; /* stack: mt ubox u newud */
+ lua_pushvalue(L,-1); /* stack: mt ubox u newud newud */
+ lua_insert(L,-4); /* stack: mt newud ubox u newud */
+ lua_rawset(L,-3); /* stack: mt newud ubox */
+ lua_pop(L,1); /* stack: mt newud */
+ /*luaL_getmetatable(L,type);*/
+ lua_pushvalue(L, -2); /* stack: mt newud mt */
+ lua_setmetatable(L,-2); /* stack: mt newud */
+
+ #ifdef LUA_VERSION_NUM
+ lua_pushvalue(L, TOLUA_NOPEER);
+ lua_setfenv(L, -2);
+ #endif
+ }
+ else
+ {
+ /* check the need of updating the metatable to a more specialized class */
+ lua_insert(L,-2); /* stack: mt ubox[u] ubox */
+ lua_pop(L,1); /* stack: mt ubox[u] */
+ lua_pushstring(L,"tolua_super");
+ lua_rawget(L,LUA_REGISTRYINDEX); /* stack: mt ubox[u] super */
+ lua_getmetatable(L,-2); /* stack: mt ubox[u] super mt */
+ lua_rawget(L,-2); /* stack: mt ubox[u] super super[mt] */
+ if (lua_istable(L,-1))
+ {
+ lua_pushstring(L,type); /* stack: mt ubox[u] super super[mt] type */
+ lua_rawget(L,-2); /* stack: mt ubox[u] super super[mt] flag */
+ if (lua_toboolean(L,-1) == 1) /* if true */
+ {
+ lua_pop(L,3); /* mt ubox[u]*/
+ lua_remove(L, -2);
+ return;
+ }
+ }
+ /* type represents a more specilized type */
+ /*luaL_getmetatable(L,type); // stack: mt ubox[u] super super[mt] flag mt */
+ lua_pushvalue(L, -5); /* stack: mt ubox[u] super super[mt] flag mt */
+ lua_setmetatable(L,-5); /* stack: mt ubox[u] super super[mt] flag */
+ lua_pop(L,3); /* stack: mt ubox[u] */
+ }
+ lua_remove(L, -2); /* stack: ubox[u]*/
+ }
+}
+
+TOLUA_API void tolua_pushusertype_and_takeownership (lua_State* L, void* value, const char* type)
+{
+ tolua_pushusertype(L,value,type);
+ tolua_register_gc(L,lua_gettop(L));
+}
+
+TOLUA_API void tolua_pushfieldvalue (lua_State* L, int lo, int index, int v)
+{
+ lua_pushnumber(L,index);
+ lua_pushvalue(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldboolean (lua_State* L, int lo, int index, int v)
+{
+ lua_pushnumber(L,index);
+ lua_pushboolean(L,v);
+ lua_settable(L,lo);
+}
+
+
+TOLUA_API void tolua_pushfieldnumber (lua_State* L, int lo, int index, lua_Number v)
+{
+ lua_pushnumber(L,index);
+ tolua_pushnumber(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldstring (lua_State* L, int lo, int index, const char* v)
+{
+ lua_pushnumber(L,index);
+ tolua_pushstring(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfielduserdata (lua_State* L, int lo, int index, void* v)
+{
+ lua_pushnumber(L,index);
+ tolua_pushuserdata(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldusertype (lua_State* L, int lo, int index, void* v, const char* type)
+{
+ lua_pushnumber(L,index);
+ tolua_pushusertype(L,v,type);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldusertype_and_takeownership (lua_State* L, int lo, int index, void* v, const char* type)
+{
+ lua_pushnumber(L,index);
+ tolua_pushusertype(L,v,type);
+ tolua_register_gc(L,lua_gettop(L));
+ lua_settable(L,lo);
+}
+
diff --git a/lib/tolua++/src/lib/tolua_to.c b/lib/tolua++/src/lib/tolua_to.c
new file mode 100644
index 000000000..04132e901
--- /dev/null
+++ b/lib/tolua++/src/lib/tolua_to.c
@@ -0,0 +1,133 @@
+/* tolua: funcitons to convert to C types
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "../../include/tolua++.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+TOLUA_API lua_Number tolua_tonumber (lua_State* L, int narg, lua_Number def)
+{
+ return lua_gettop(L)<abs(narg) ? def : lua_tonumber(L,narg);
+}
+
+TOLUA_API const char* tolua_tostring (lua_State* L, int narg, const char* def)
+{
+ return lua_gettop(L)<abs(narg) ? def : lua_tostring(L,narg);
+}
+
+TOLUA_API void* tolua_touserdata (lua_State* L, int narg, void* def)
+{
+
+ /* return lua_gettop(L)<abs(narg) ? def : lua_touserdata(L,narg); */
+
+ if (lua_gettop(L)<abs(narg)) {
+ return def;
+ };
+
+ if (lua_islightuserdata(L, narg)) {
+
+ return lua_touserdata(L,narg);
+ };
+
+ return tolua_tousertype(L, narg, def);
+}
+
+extern int push_table_instance(lua_State* L, int lo);
+
+TOLUA_API void* tolua_tousertype (lua_State* L, int narg, void* def)
+{
+ if (lua_gettop(L)<abs(narg))
+ return def;
+ else
+ {
+ void* u;
+ if (!lua_isuserdata(L, narg)) {
+ if (!push_table_instance(L, narg)) return NULL;
+ };
+ u = lua_touserdata(L,narg);
+ return (u==NULL) ? NULL : *((void**)u); /* nil represents NULL */
+ }
+}
+
+TOLUA_API int tolua_tovalue (lua_State* L, int narg, int def)
+{
+ return lua_gettop(L)<abs(narg) ? def : narg;
+}
+
+TOLUA_API int tolua_toboolean (lua_State* L, int narg, int def)
+{
+ return lua_gettop(L)<abs(narg) ? def : lua_toboolean(L,narg);
+}
+
+TOLUA_API lua_Number tolua_tofieldnumber (lua_State* L, int lo, int index, lua_Number def)
+{
+ double v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lua_tonumber(L,-1);
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API const char* tolua_tofieldstring
+(lua_State* L, int lo, int index, const char* def)
+{
+ const char* v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lua_tostring(L,-1);
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API void* tolua_tofielduserdata (lua_State* L, int lo, int index, void* def)
+{
+ void* v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lua_touserdata(L,-1);
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API void* tolua_tofieldusertype (lua_State* L, int lo, int index, void* def)
+{
+ void* v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : (*(void **)(lua_touserdata(L, -1))); /* lua_unboxpointer(L,-1); */
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API int tolua_tofieldvalue (lua_State* L, int lo, int index, int def)
+{
+ int v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lo;
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API int tolua_getfieldboolean (lua_State* L, int lo, int index, int def)
+{
+ int v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? 0 : lua_toboolean(L,-1);
+ lua_pop(L,1);
+ return v;
+}
diff --git a/lib/tolua++/win32/tolualib/tolualib.vcproj b/lib/tolua++/win32/tolualib/tolualib.vcproj
new file mode 100644
index 000000000..598b2d6fe
--- /dev/null
+++ b/lib/tolua++/win32/tolualib/tolualib.vcproj
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="tolualib"
+ ProjectGUID="{9DDCB327-0D20-460F-A7F8-DE038163CD63}"
+ RootNamespace="tolualib"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;../../../lua-5.1.4/src&quot;;../../include"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="&quot;../../../lua-5.1.4/src&quot;;../../include"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalLibraryDirectories="C:\Program Files (x86)\Lua\5.1\lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\src\lib\tolua_event.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_is.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_map.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_push.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_to.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\src\lib\tolua_event.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/tolua++/win32/tolualib/tolualib.vcproj.LAPTOPF.Kevin.user b/lib/tolua++/win32/tolualib/tolualib.vcproj.LAPTOPF.Kevin.user
new file mode 100644
index 000000000..eaf548aa5
--- /dev/null
+++ b/lib/tolua++/win32/tolualib/tolualib.vcproj.LAPTOPF.Kevin.user
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioUserFile
+ ProjectType="Visual C++"
+ Version="9,00"
+ ShowAllFiles="false"
+ >
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="LAPTOPF"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ >
+ <DebugSettings
+ Command=""
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="LAPTOPF"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ </Configurations>
+</VisualStudioUserFile>
diff --git a/lib/tolua++/win32/tolualib/tolualib.vcxproj b/lib/tolua++/win32/tolualib/tolualib.vcxproj
new file mode 100644
index 000000000..f12bfda86
--- /dev/null
+++ b/lib/tolua++/win32/tolualib/tolualib.vcxproj
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AB745E71-04B2-454F-A806-A0D553DAE08C}</ProjectGuid>
+ <RootNamespace>tolualib</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>tolua++</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>../../include;C:\Program Files (x86)\Lua\5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>C:\Program Files (x86)\Lua\5.1\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>lua51.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\tolua_event.c" />
+ <ClCompile Include="..\..\src\lib\tolua_is.c" />
+ <ClCompile Include="..\..\src\lib\tolua_map.c" />
+ <ClCompile Include="..\..\src\lib\tolua_push.c" />
+ <ClCompile Include="..\..\src\lib\tolua_to.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\tolua_event.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/lib/tolua++/win32/tolualib/tolualib.vcxproj.filters b/lib/tolua++/win32/tolualib/tolualib.vcxproj.filters
new file mode 100644
index 000000000..99f8ce3b6
--- /dev/null
+++ b/lib/tolua++/win32/tolualib/tolualib.vcxproj.filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\tolua_event.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_is.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_map.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_push.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_to.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\tolua_event.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/lib/tolua++/win32/tolualib/tolualib.vcxproj.user b/lib/tolua++/win32/tolualib/tolualib.vcxproj.user
new file mode 100644
index 000000000..4c1e1937c
--- /dev/null
+++ b/lib/tolua++/win32/tolualib/tolualib.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/lib/tolua++/win32/vc7/clean.bat b/lib/tolua++/win32/vc7/clean.bat
new file mode 100644
index 000000000..b8f4f2b2f
--- /dev/null
+++ b/lib/tolua++/win32/vc7/clean.bat
@@ -0,0 +1,15 @@
+del *.ncb
+del *.ilk
+del *.lib
+del *.exp
+del *.map
+del *.pdb
+del *.bsc
+del applog.txt
+del tmpl83.00c.vcproj.LAPTOPF.Kevin.user
+del *.suo /AH
+del debug\*.* /Q
+del release\*.* /Q
+rd release /Q
+rd debug /Q
+
diff --git a/lib/tolua++/win32/vc7/toluapp.sln b/lib/tolua++/win32/vc7/toluapp.sln
new file mode 100644
index 000000000..1ab8be380
--- /dev/null
+++ b/lib/tolua++/win32/vc7/toluapp.sln
@@ -0,0 +1,48 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "toluapp", "toluapp.vcproj", "{71891C1A-E328-4258-AC3F-6F9698C6D8B4}"
+ ProjectSection(ProjectDependencies) = postProject
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63} = {9DDCB327-0D20-460F-A7F8-DE038163CD63}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tolualib", "..\tolualib\tolualib.vcproj", "{9DDCB327-0D20-460F-A7F8-DE038163CD63}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ withLua50_Debug|Win32 = withLua50_Debug|Win32
+ withLua50_Release|Win32 = withLua50_Release|Win32
+ withLua51_Debug|Win32 = withLua51_Debug|Win32
+ withLua51_Release|Win32 = withLua51_Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.Debug|Win32.ActiveCfg = withLua51_Debug|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.Debug|Win32.Build.0 = withLua51_Debug|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.Release|Win32.ActiveCfg = withLua51_Release|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.Release|Win32.Build.0 = withLua51_Release|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua50_Debug|Win32.ActiveCfg = withLua51_Release|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua50_Debug|Win32.Build.0 = withLua51_Release|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua50_Release|Win32.ActiveCfg = withLua51_Release|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua50_Release|Win32.Build.0 = withLua51_Release|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua51_Debug|Win32.ActiveCfg = withLua51_Debug|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua51_Debug|Win32.Build.0 = withLua51_Debug|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua51_Release|Win32.ActiveCfg = withLua51_Release|Win32
+ {71891C1A-E328-4258-AC3F-6F9698C6D8B4}.withLua51_Release|Win32.Build.0 = withLua51_Release|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.Debug|Win32.Build.0 = Debug|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.Release|Win32.ActiveCfg = Release|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.Release|Win32.Build.0 = Release|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua50_Debug|Win32.ActiveCfg = Debug|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua50_Debug|Win32.Build.0 = Debug|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua50_Release|Win32.ActiveCfg = Release|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua50_Release|Win32.Build.0 = Release|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua51_Debug|Win32.ActiveCfg = Debug|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua51_Debug|Win32.Build.0 = Debug|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua51_Release|Win32.ActiveCfg = Release|Win32
+ {9DDCB327-0D20-460F-A7F8-DE038163CD63}.withLua51_Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/lib/tolua++/win32/vc7/toluapp.vcproj b/lib/tolua++/win32/vc7/toluapp.vcproj
new file mode 100644
index 000000000..285bd2d42
--- /dev/null
+++ b/lib/tolua++/win32/vc7/toluapp.vcproj
@@ -0,0 +1,439 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="toluapp"
+ ProjectGUID="{71891C1A-E328-4258-AC3F-6F9698C6D8B4}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="withLua51_Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;../../../lua-5.1.4/src&quot;;../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="..\..\bin\tolua++_d.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="..\..\lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/tolua++.pdb"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="withLua51_Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;../../../lua-5.1.4/src&quot;;../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="..\..\bin\tolua++.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\..\lib;&quot;C:\Program Files (x86)\Lua\5.1\lib&quot;"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="source files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\src\bin\tolua.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_event.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_event.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_is.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_map.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_push.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\lib\tolua_to.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\bin\toluabind.c"
+ >
+ </File>
+ <Filter
+ Name="Lua"
+ >
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lapi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lapi.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lauxlib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lauxlib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lbaselib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lcode.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lcode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ldblib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ldebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ldebug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ldo.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ldo.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ldump.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lfunc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lfunc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lgc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lgc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\linit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\liolib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\llex.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\llex.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\llimits.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lmathlib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lmem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lmem.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\loadlib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lobject.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lobject.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lopcodes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lopcodes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\loslib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lparser.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lparser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lstate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lstate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lstring.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lstring.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lstrlib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ltable.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ltable.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ltablib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ltm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\ltm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\luac.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\luaconf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lualib.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lundump.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lundump.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lvm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lvm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lzio.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\lzio.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\Makefile"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\lua-5.1.4\src\print.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/tolua++/win32/vc7/toluapp.vcproj.LAPTOPF.Kevin.user b/lib/tolua++/win32/vc7/toluapp.vcproj.LAPTOPF.Kevin.user
new file mode 100644
index 000000000..a2de0fbb2
--- /dev/null
+++ b/lib/tolua++/win32/vc7/toluapp.vcproj.LAPTOPF.Kevin.user
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioUserFile
+ ProjectType="Visual C++"
+ Version="9,00"
+ ShowAllFiles="false"
+ >
+ <Configurations>
+ <Configuration
+ Name="withLua50_Debug|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="LAPTOPF"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="withLua50_Release|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="LAPTOPF"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="withLua51_Debug|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="LAPTOPF"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="withLua51_Release|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="LAPTOPF"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ </Configurations>
+</VisualStudioUserFile>
diff --git a/lib/tolua++/win32/vc7/toluapp.vcxproj b/lib/tolua++/win32/vc7/toluapp.vcxproj
new file mode 100644
index 000000000..45601b36f
--- /dev/null
+++ b/lib/tolua++/win32/vc7/toluapp.vcxproj
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="withLua50_Debug|Win32">
+ <Configuration>withLua50_Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="withLua50_Release|Win32">
+ <Configuration>withLua50_Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="withLua51_Debug|Win32">
+ <Configuration>withLua51_Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="withLua51_Release|Win32">
+ <Configuration>withLua51_Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{71891C1A-E328-4258-AC3F-6F9698C6D8B4}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='withLua51_Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='withLua51_Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='withLua50_Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='withLua50_Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='withLua51_Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='withLua51_Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='withLua50_Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='withLua50_Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='withLua50_Debug|Win32'">Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='withLua50_Debug|Win32'">Debug\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='withLua50_Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='withLua50_Release|Win32'">Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='withLua50_Release|Win32'">Release\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='withLua50_Release|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='withLua51_Debug|Win32'">$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='withLua51_Debug|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='withLua51_Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='withLua51_Release|Win32'">$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='withLua51_Release|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='withLua51_Release|Win32'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='withLua50_Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>lua50.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>..\..\bin\tolua++_d.exe</OutputFile>
+ <AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)tolua++.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='withLua50_Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>lua50.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>..\..\bin\tolua++.exe</OutputFile>
+ <AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='withLua51_Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>Lua5.1.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>..\..\bin\tolua++_d.exe</OutputFile>
+ <AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)tolua++.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='withLua51_Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\include;C:\Program Files (x86)\Lua\5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>lua5.1.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>..\..\bin\tolua++.exe</OutputFile>
+ <AdditionalLibraryDirectories>..\..\lib;C:\Program Files (x86)\Lua\5.1\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\tolua.c" />
+ <ClCompile Include="..\..\src\lib\tolua_event.c" />
+ <ClCompile Include="..\..\src\lib\tolua_is.c" />
+ <ClCompile Include="..\..\src\lib\tolua_map.c" />
+ <ClCompile Include="..\..\src\lib\tolua_push.c" />
+ <ClCompile Include="..\..\src\lib\tolua_to.c" />
+ <ClCompile Include="..\..\src\bin\toluabind.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\tolua_event.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/lib/tolua++/win32/vc7/toluapp.vcxproj.filters b/lib/tolua++/win32/vc7/toluapp.vcxproj.filters
new file mode 100644
index 000000000..c23b20870
--- /dev/null
+++ b/lib/tolua++/win32/vc7/toluapp.vcxproj.filters
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="ソース ファイル">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="ヘッダー ファイル">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="リソース ファイル">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\tolua.c">
+ <Filter>ソース ファイル</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_event.c">
+ <Filter>ソース ファイル</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_is.c">
+ <Filter>ソース ファイル</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_map.c">
+ <Filter>ソース ファイル</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_push.c">
+ <Filter>ソース ファイル</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\tolua_to.c">
+ <Filter>ソース ファイル</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\toluabind.c">
+ <Filter>ソース ファイル</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\tolua_event.h">
+ <Filter>ソース ファイル</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/lib/tolua++/win32/vc7/toluapp.vcxproj.user b/lib/tolua++/win32/vc7/toluapp.vcxproj.user
new file mode 100644
index 000000000..4c1e1937c
--- /dev/null
+++ b/lib/tolua++/win32/vc7/toluapp.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/lib/zlib/adler32.c b/lib/zlib/adler32.c
new file mode 100644
index 000000000..a868f073d
--- /dev/null
+++ b/lib/zlib/adler32.c
@@ -0,0 +1,179 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2011 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#define local static
+
+local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
+
+#define BASE 65521 /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware --
+ try it both ways to see which is faster */
+#ifdef NO_DIVIDE
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+ (thank you to John Reiser for pointing this out) */
+# define CHOP(a) \
+ do { \
+ unsigned long tmp = a >> 16; \
+ a &= 0xffffUL; \
+ a += (tmp << 4) - tmp; \
+ } while (0)
+# define MOD28(a) \
+ do { \
+ CHOP(a); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD(a) \
+ do { \
+ CHOP(a); \
+ MOD28(a); \
+ } while (0)
+# define MOD63(a) \
+ do { /* this assumes a is not negative */ \
+ z_off64_t tmp = a >> 32; \
+ a &= 0xffffffffL; \
+ a += (tmp << 8) - (tmp << 5) + tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD28(a) a %= BASE
+# define MOD63(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD28(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off64_t len2;
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* for negative len, return invalid adler32 as a clue for debugging */
+ if (len2 < 0)
+ return 0xffffffffUL;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ MOD63(len2); /* assumes len2 >= 0 */
+ rem = (unsigned)len2;
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
+ if (sum2 >= BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off_t len2;
+{
+ return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off64_t len2;
+{
+ return adler32_combine_(adler1, adler2, len2);
+}
diff --git a/lib/zlib/compress.c b/lib/zlib/compress.c
new file mode 100644
index 000000000..ea4dfbe9d
--- /dev/null
+++ b/lib/zlib/compress.c
@@ -0,0 +1,80 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+ int level;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (sourceLen)
+ uLong sourceLen;
+{
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13;
+}
diff --git a/lib/zlib/crc32.c b/lib/zlib/crc32.c
new file mode 100644
index 000000000..979a7190a
--- /dev/null
+++ b/lib/zlib/crc32.c
@@ -0,0 +1,425 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors. This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id$ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+
+ DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for STDC and FAR definitions */
+
+#define local static
+
+/* Definitions for doing the crc four data bytes at a time. */
+#if !defined(NOBYFOUR) && defined(Z_U4)
+# define BYFOUR
+#endif
+#ifdef BYFOUR
+ local unsigned long crc32_little OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+ local unsigned long crc32_big OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+# define TBLS 8
+#else
+# define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+ unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
+
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local z_crc_t FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+ local void write_table OF((FILE *, const z_crc_t FAR *));
+#endif /* MAKECRCH */
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The first table is simply the CRC of all possible eight bit values. This is
+ all the information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes. The remaining tables
+ allow for word-at-a-time CRC calculation for both big-endian and little-
+ endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+ z_crc_t c;
+ int n, k;
+ z_crc_t poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static volatile int first = 1; /* flag to limit concurrent making */
+ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* See if another task is already doing this (not thread-safe, but better
+ than nothing -- significantly reduces duration of vulnerability in
+ case the advice about DYNAMIC_CRC_TABLE is ignored) */
+ if (first) {
+ first = 0;
+
+ /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+ poly = 0;
+ for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
+ poly |= (z_crc_t)1 << (31 - p[n]);
+
+ /* generate a crc for every 8-bit value */
+ for (n = 0; n < 256; n++) {
+ c = (z_crc_t)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[0][n] = c;
+ }
+
+#ifdef BYFOUR
+ /* generate crc for each value followed by one, two, and three zeros,
+ and then the byte reversal of those as well as the first table */
+ for (n = 0; n < 256; n++) {
+ c = crc_table[0][n];
+ crc_table[4][n] = ZSWAP32(c);
+ for (k = 1; k < 4; k++) {
+ c = crc_table[0][c & 0xff] ^ (c >> 8);
+ crc_table[k][n] = c;
+ crc_table[k + 4][n] = ZSWAP32(c);
+ }
+ }
+#endif /* BYFOUR */
+
+ crc_table_empty = 0;
+ }
+ else { /* not first */
+ /* wait for the other guy to finish (not efficient, but rare) */
+ while (crc_table_empty)
+ ;
+ }
+
+#ifdef MAKECRCH
+ /* write out CRC tables to crc32.h */
+ {
+ FILE *out;
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+ fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+ fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+ fprintf(out, "local const z_crc_t FAR ");
+ fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
+ write_table(out, crc_table[0]);
+# ifdef BYFOUR
+ fprintf(out, "#ifdef BYFOUR\n");
+ for (k = 1; k < 8; k++) {
+ fprintf(out, " },\n {\n");
+ write_table(out, crc_table[k]);
+ }
+ fprintf(out, "#endif\n");
+# endif /* BYFOUR */
+ fprintf(out, " }\n};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+ FILE *out;
+ const z_crc_t FAR *table;
+{
+ int n;
+
+ for (n = 0; n < 256; n++)
+ fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
+ (unsigned long)(table[n]),
+ n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const z_crc_t FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const z_crc_t FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ uInt len;
+{
+ if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ z_crc_t endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffffUL;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register z_crc_t c;
+ register const z_crc_t FAR *buf4;
+
+ c = (z_crc_t)crc;
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ len--;
+ }
+
+ buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
+ while (len >= 32) {
+ DOLIT32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOLIT4;
+ len -= 4;
+ }
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register z_crc_t c;
+ register const z_crc_t FAR *buf4;
+
+ c = ZSWAP32((z_crc_t)crc);
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ len--;
+ }
+
+ buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
+ buf4--;
+ while (len >= 32) {
+ DOBIG32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOBIG4;
+ len -= 4;
+ }
+ buf4++;
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)(ZSWAP32(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+ unsigned long *mat;
+ unsigned long vec;
+{
+ unsigned long sum;
+
+ sum = 0;
+ while (vec) {
+ if (vec & 1)
+ sum ^= *mat;
+ vec >>= 1;
+ mat++;
+ }
+ return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+ unsigned long *square;
+ unsigned long *mat;
+{
+ int n;
+
+ for (n = 0; n < GF2_DIM; n++)
+ square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+local uLong crc32_combine_(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off64_t len2;
+{
+ int n;
+ unsigned long row;
+ unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
+ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
+
+ /* degenerate case (also disallow negative lengths) */
+ if (len2 <= 0)
+ return crc1;
+
+ /* put operator for one zero bit in odd */
+ odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
+ row = 1;
+ for (n = 1; n < GF2_DIM; n++) {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ /* put operator for two zero bits in even */
+ gf2_matrix_square(even, odd);
+
+ /* put operator for four zero bits in odd */
+ gf2_matrix_square(odd, even);
+
+ /* apply len2 zeros to crc1 (first square will put the operator for one
+ zero byte, eight zero bits, in even) */
+ do {
+ /* apply zeros operator for this bit of len2 */
+ gf2_matrix_square(even, odd);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(even, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ if (len2 == 0)
+ break;
+
+ /* another iteration of the loop with odd and even swapped */
+ gf2_matrix_square(odd, even);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(odd, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ } while (len2 != 0);
+
+ /* return combined crc */
+ crc1 ^= crc2;
+ return crc1;
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off_t len2;
+{
+ return crc32_combine_(crc1, crc2, len2);
+}
+
+uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off64_t len2;
+{
+ return crc32_combine_(crc1, crc2, len2);
+}
diff --git a/lib/zlib/crc32.h b/lib/zlib/crc32.h
new file mode 100644
index 000000000..9e0c77810
--- /dev/null
+++ b/lib/zlib/crc32.h
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const z_crc_t FAR crc_table[TBLS][256] =
+{
+ {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dUL
+#ifdef BYFOUR
+ },
+ {
+ 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+ 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+ 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+ 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+ 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+ 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+ 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+ 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+ 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+ 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+ 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+ 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+ 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+ 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+ 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+ 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+ 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+ 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+ 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+ 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+ 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+ 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+ 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+ 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+ 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+ 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+ 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+ 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+ 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+ 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+ 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+ 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+ 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+ 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+ 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+ 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+ 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+ 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+ 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+ 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+ 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+ 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+ 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+ 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+ 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+ 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+ 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+ 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+ 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+ 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+ 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+ 0x9324fd72UL
+ },
+ {
+ 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+ 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+ 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+ 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+ 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+ 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+ 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+ 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+ 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+ 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+ 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+ 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+ 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+ 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+ 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+ 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+ 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+ 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+ 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+ 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+ 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+ 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+ 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+ 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+ 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+ 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+ 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+ 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+ 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+ 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+ 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+ 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+ 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+ 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+ 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+ 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+ 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+ 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+ 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+ 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+ 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+ 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+ 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+ 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+ 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+ 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+ 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+ 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+ 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+ 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+ 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+ 0xbe9834edUL
+ },
+ {
+ 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+ 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+ 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+ 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+ 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+ 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+ 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+ 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+ 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+ 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+ 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+ 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+ 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+ 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+ 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+ 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+ 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+ 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+ 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+ 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+ 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+ 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+ 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+ 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+ 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+ 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+ 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+ 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+ 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+ 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+ 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+ 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+ 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+ 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+ 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+ 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+ 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+ 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+ 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+ 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+ 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+ 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+ 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+ 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+ 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+ 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+ 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+ 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+ 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+ 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+ 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+ 0xde0506f1UL
+ },
+ {
+ 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+ 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+ 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+ 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+ 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+ 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+ 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+ 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+ 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+ 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+ 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+ 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+ 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+ 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+ 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+ 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+ 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+ 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+ 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+ 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+ 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+ 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+ 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+ 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+ 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+ 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+ 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+ 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+ 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+ 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+ 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+ 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+ 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+ 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+ 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+ 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+ 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+ 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+ 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+ 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+ 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+ 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+ 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+ 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+ 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+ 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+ 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+ 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+ 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+ 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+ 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+ 0x8def022dUL
+ },
+ {
+ 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+ 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+ 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+ 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+ 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+ 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+ 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+ 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+ 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+ 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+ 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+ 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+ 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+ 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+ 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+ 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+ 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+ 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+ 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+ 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+ 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+ 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+ 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+ 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+ 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+ 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+ 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+ 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+ 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+ 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+ 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+ 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+ 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+ 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+ 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+ 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+ 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+ 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+ 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+ 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+ 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+ 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+ 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+ 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+ 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+ 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+ 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+ 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+ 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+ 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+ 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+ 0x72fd2493UL
+ },
+ {
+ 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+ 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+ 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+ 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+ 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+ 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+ 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+ 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+ 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+ 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+ 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+ 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+ 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+ 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+ 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+ 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+ 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+ 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+ 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+ 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+ 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+ 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+ 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+ 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+ 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+ 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+ 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+ 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+ 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+ 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+ 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+ 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+ 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+ 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+ 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+ 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+ 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+ 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+ 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+ 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+ 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+ 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+ 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+ 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+ 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+ 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+ 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+ 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+ 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+ 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+ 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+ 0xed3498beUL
+ },
+ {
+ 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+ 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+ 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+ 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+ 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+ 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+ 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+ 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+ 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+ 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+ 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+ 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+ 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+ 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+ 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+ 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+ 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+ 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+ 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+ 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+ 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+ 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+ 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+ 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+ 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+ 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+ 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+ 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+ 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+ 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+ 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+ 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+ 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+ 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+ 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+ 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+ 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+ 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+ 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+ 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+ 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+ 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+ 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+ 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+ 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+ 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+ 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+ 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+ 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+ 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+ 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+ 0xf10605deUL
+#endif
+ }
+};
diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c
new file mode 100644
index 000000000..9e4c2cbc8
--- /dev/null
+++ b/lib/zlib/deflate.c
@@ -0,0 +1,1965 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://tools.ietf.org/html/rfc1951
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.2.7 Copyright 1995-2012 Jean-loup Gailly and Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow OF((deflate_state *s, int flush));
+#endif
+local block_state deflate_rle OF((deflate_state *s, int flush));
+local block_state deflate_huff OF((deflate_state *s, int flush));
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+ uInt longest_match OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
+#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0))
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->high_water = 0; /* nothing written to s->window yet */
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt str, n;
+ int wrap;
+ unsigned avail;
+ unsigned char *next;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
+ return Z_STREAM_ERROR;
+ s = strm->state;
+ wrap = s->wrap;
+ if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
+ return Z_STREAM_ERROR;
+
+ /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+ if (wrap == 1)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+ s->wrap = 0; /* avoid computing Adler-32 in read_buf */
+
+ /* if dictionary would fill window, just replace the history */
+ if (dictLength >= s->w_size) {
+ if (wrap == 0) { /* already empty otherwise */
+ CLEAR_HASH(s);
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ dictionary += dictLength - s->w_size; /* use the tail */
+ dictLength = s->w_size;
+ }
+
+ /* insert dictionary into window and hash */
+ avail = strm->avail_in;
+ next = strm->next_in;
+ strm->avail_in = dictLength;
+ strm->next_in = (Bytef *)dictionary;
+ fill_window(s);
+ while (s->lookahead >= MIN_MATCH) {
+ str = s->strstart;
+ n = s->lookahead - (MIN_MATCH-1);
+ do {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ } while (--n);
+ s->strstart = str;
+ s->lookahead = MIN_MATCH-1;
+ fill_window(s);
+ }
+ s->strstart += s->lookahead;
+ s->block_start = (long)s->strstart;
+ s->insert = s->lookahead;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ strm->next_in = next;
+ strm->avail_in = avail;
+ s->wrap = wrap;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateResetKeep (strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+ z_streamp strm;
+{
+ int ret;
+
+ ret = deflateResetKeep(strm);
+ if (ret == Z_OK)
+ lm_init(strm->state);
+ return ret;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+ z_streamp strm;
+ gz_headerp head;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePending (strm, pending, bits)
+ unsigned *pending;
+ int *bits;
+ z_streamp strm;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (pending != Z_NULL)
+ *pending = strm->state->pending;
+ if (bits != Z_NULL)
+ *bits = strm->state->bi_valid;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+ z_streamp strm;
+ int bits;
+ int value;
+{
+ deflate_state *s;
+ int put;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
+ return Z_BUF_ERROR;
+ do {
+ put = Buf_size - s->bi_valid;
+ if (put > bits)
+ put = bits;
+ s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
+ s->bi_valid += put;
+ _tr_flush_bits(s);
+ value >>= put;
+ bits -= put;
+ } while (bits);
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if ((strategy != s->strategy || func != configuration_table[level].func) &&
+ strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_BLOCK);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+ z_streamp strm;
+ int good_length;
+ int max_lazy;
+ int nice_length;
+ int max_chain;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = good_length;
+ s->max_lazy_match = max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well. The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds for
+ * every combination of windowBits and memLevel. But even the conservative
+ * upper bound of about 14% expansion does not seem onerous for output buffer
+ * allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+ z_streamp strm;
+ uLong sourceLen;
+{
+ deflate_state *s;
+ uLong complen, wraplen;
+ Bytef *str;
+
+ /* conservative upper bound for compressed data */
+ complen = sourceLen +
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
+
+ /* if can't get parameters, return conservative bound plus zlib wrapper */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return complen + 6;
+
+ /* compute wrapper length */
+ s = strm->state;
+ switch (s->wrap) {
+ case 0: /* raw deflate */
+ wraplen = 0;
+ break;
+ case 1: /* zlib wrapper */
+ wraplen = 6 + (s->strstart ? 4 : 0);
+ break;
+ case 2: /* gzip wrapper */
+ wraplen = 18;
+ if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
+ if (s->gzhead->extra != Z_NULL)
+ wraplen += 2 + s->gzhead->extra_len;
+ str = s->gzhead->name;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ str = s->gzhead->comment;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ if (s->gzhead->hcrc)
+ wraplen += 2;
+ }
+ break;
+ default: /* for compiler happiness */
+ wraplen = 6;
+ }
+
+ /* if not default parameters, return conservative bound */
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return complen + wraplen;
+
+ /* default settings: return tight bound for that case */
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len;
+ deflate_state *s = strm->state;
+
+ _tr_flush_bits(s);
+ len = s->pending;
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, s->pending_out, len);
+ strm->next_out += len;
+ s->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ s->pending -= len;
+ if (s->pending == 0) {
+ s->pending_out = s->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_BLOCK || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the header */
+ if (s->status == INIT_STATE) {
+#ifdef GZIP
+ if (s->wrap == 2) {
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == Z_NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != Z_NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ else
+#endif
+ {
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ }
+ }
+#ifdef GZIP
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != Z_NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+
+ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size)
+ break;
+ }
+ put_byte(s, s->gzhead->extra[s->gzindex]);
+ s->gzindex++;
+ }
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (s->gzindex == s->gzhead->extra_len) {
+ s->gzindex = 0;
+ s->status = NAME_STATE;
+ }
+ }
+ else
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != Z_NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0) {
+ s->gzindex = 0;
+ s->status = COMMENT_STATE;
+ }
+ }
+ else
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != Z_NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0)
+ s->status = HCRC_STATE;
+ }
+ else
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size)
+ flush_pending(strm);
+ if (s->pending + 2 <= s->pending_buf_size) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+ }
+ }
+ else
+ s->status = BUSY_STATE;
+ }
+#endif
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+ (s->strategy == Z_RLE ? deflate_rle(s, flush) :
+ (*(configuration_table[s->level].func))(s, flush));
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ if (s->lookahead == 0) {
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+ if (status != INIT_STATE &&
+ status != EXTRA_STATE &&
+ status != NAME_STATE &&
+ status != COMMENT_STATE &&
+ status != HCRC_STATE &&
+ status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+ ds->pending_buf = (uchf *) overlay;
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+ z_streamp strm;
+ Bytef *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ zmemcpy(buf, strm->next_in, len);
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, buf, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, buf, len);
+ }
+#endif
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->insert = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) break;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead + s->insert >= MIN_MATCH) {
+ uInt str = s->strstart - s->insert;
+ s->ins_h = s->window[str];
+ UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ while (s->insert) {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ s->insert--;
+ if (s->lookahead + s->insert < MIN_MATCH)
+ break;
+ }
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+ /* If the WIN_INIT bytes after the end of the current data have never been
+ * written, then zero those bytes in order to avoid memory check reports of
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by
+ * the longest match routines. Update the high water mark for the next
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+ */
+ if (s->high_water < s->window_size) {
+ ulg curr = s->strstart + (ulg)(s->lookahead);
+ ulg init;
+
+ if (s->high_water < curr) {
+ /* Previous high water mark below current data -- zero WIN_INIT
+ * bytes or up to end of window, whichever is less.
+ */
+ init = s->window_size - curr;
+ if (init > WIN_INIT)
+ init = WIN_INIT;
+ zmemzero(s->window + curr, (unsigned)init);
+ s->high_water = curr + init;
+ }
+ else if (s->high_water < (ulg)curr + WIN_INIT) {
+ /* High water mark at or above current data, but below current data
+ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+ * to end of window, whichever is less.
+ */
+ init = (ulg)curr + WIN_INIT - s->high_water;
+ if (init > s->window_size - s->high_water)
+ init = s->window_size - s->high_water;
+ zmemzero(s->window + s->high_water, (unsigned)init);
+ s->high_water += init;
+ }
+ }
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "not enough room for search");
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (last)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+ FLUSH_BLOCK_ONLY(s, last); \
+ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if ((long)s->strstart > s->block_start)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->last_lit)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ s->match_available = 0;
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->last_lit)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan, *strend; /* scan goes up to strend for length of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest run, plus one for the unrolled loop.
+ */
+ if (s->lookahead <= MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ s->match_length = 0;
+ if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+ scan = s->window + s->strstart - 1;
+ prev = *scan;
+ if (prev == *++scan && prev == *++scan && prev == *++scan) {
+ strend = s->window + s->strstart + MAX_MATCH;
+ do {
+ } while (prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ scan < strend);
+ s->match_length = MAX_MATCH - (int)(strend - scan);
+ if (s->match_length > s->lookahead)
+ s->match_length = s->lookahead;
+ }
+ Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+ _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->last_lit)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we have a literal to write. */
+ if (s->lookahead == 0) {
+ fill_window(s);
+ if (s->lookahead == 0) {
+ if (flush == Z_NO_FLUSH)
+ return need_more;
+ break; /* flush the current block */
+ }
+ }
+
+ /* Output a literal byte */
+ s->match_length = 0;
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->last_lit)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
diff --git a/lib/zlib/deflate.h b/lib/zlib/deflate.h
new file mode 100644
index 000000000..fbac44d90
--- /dev/null
+++ b/lib/zlib/deflate.h
@@ -0,0 +1,346 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2012 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define Buf_size 16
+/* size of bit buffer in bi_buf */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to suppress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ uInt insert; /* bytes at end of window left to insert */
+
+#ifdef DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+ ulg high_water;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+ memory checker errors from longest match routines */
+
+ /* in trees.c */
+void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
+int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
+ ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+ ulg stored_len, int last));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch ZLIB_INTERNAL _length_code[];
+ extern uch ZLIB_INTERNAL _dist_code[];
+#else
+ extern const uch ZLIB_INTERNAL _length_code[];
+ extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/lib/zlib/example.c b/lib/zlib/example.c
new file mode 100644
index 000000000..f515a4853
--- /dev/null
+++ b/lib/zlib/example.c
@@ -0,0 +1,601 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-2006, 2011 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+#include <stdio.h>
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+# define TESTFILE "foo-gz"
+#else
+# define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_deflate OF((Byte *compr, uLong comprLen));
+void test_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_flush OF((Byte *compr, uLong *comprLen));
+void test_sync OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate OF((Byte *compr, uLong comprLen));
+void test_dict_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+int main OF((int argc, char *argv[]));
+
+
+#ifdef Z_SOLO
+
+void *myalloc OF((void *, unsigned, unsigned));
+void myfree OF((void *, void *));
+
+void *myalloc(q, n, m)
+ void *q;
+ unsigned n, m;
+{
+ q = Z_NULL;
+ return calloc(n, m);
+}
+
+void myfree(void *q, void *p)
+{
+ q = Z_NULL;
+ free(p);
+}
+
+static alloc_func zalloc = myalloc;
+static free_func zfree = myfree;
+
+#else /* !Z_SOLO */
+
+static alloc_func zalloc = (alloc_func)0;
+static free_func zfree = (free_func)0;
+
+void test_compress OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_gzio OF((const char *fname,
+ Byte *uncompr, uLong uncomprLen));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ uLong len = (uLong)strlen(hello)+1;
+
+ err = compress(compr, &comprLen, (const Bytef*)hello, len);
+ CHECK_ERR(err, "compress");
+
+ strcpy((char*)uncompr, "garbage");
+
+ err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+ CHECK_ERR(err, "uncompress");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad uncompress\n");
+ exit(1);
+ } else {
+ printf("uncompress(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(fname, uncompr, uncomprLen)
+ const char *fname; /* compressed file name */
+ Byte *uncompr;
+ uLong uncomprLen;
+{
+#ifdef NO_GZCOMPRESS
+ fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
+#else
+ int err;
+ int len = (int)strlen(hello)+1;
+ gzFile file;
+ z_off_t pos;
+
+ file = gzopen(fname, "wb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+ gzputc(file, 'h');
+ if (gzputs(file, "ello") != 4) {
+ fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (gzprintf(file, ", %s!", "hello") != 8) {
+ fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+ gzclose(file);
+
+ file = gzopen(fname, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+ strcpy((char*)uncompr, "garbage");
+
+ if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
+ fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+ exit(1);
+ } else {
+ printf("gzread(): %s\n", (char*)uncompr);
+ }
+
+ pos = gzseek(file, -8L, SEEK_CUR);
+ if (pos != 6 || gztell(file) != pos) {
+ fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+ (long)pos, (long)gztell(file));
+ exit(1);
+ }
+
+ if (gzgetc(file) != ' ') {
+ fprintf(stderr, "gzgetc error\n");
+ exit(1);
+ }
+
+ if (gzungetc(' ', file) != ' ') {
+ fprintf(stderr, "gzungetc error\n");
+ exit(1);
+ }
+
+ gzgets(file, (char*)uncompr, (int)uncomprLen);
+ if (strlen((char*)uncompr) != 7) { /* " hello!" */
+ fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello + 6)) {
+ fprintf(stderr, "bad gzgets after gzseek\n");
+ exit(1);
+ } else {
+ printf("gzgets() after gzseek: %s\n", (char*)uncompr);
+ }
+
+ gzclose(file);
+#endif
+}
+
+#endif /* Z_SOLO */
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ uLong len = (uLong)strlen(hello)+1;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+
+ while (c_stream.total_in != len && c_stream.total_out < comprLen) {
+ c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ }
+ /* Finish the stream, still forcing small buffers: */
+ for (;;) {
+ c_stream.avail_out = 1;
+ err = deflate(&c_stream, Z_FINISH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "deflate");
+ }
+
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 0;
+ d_stream.next_out = uncompr;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+ d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate\n");
+ exit(1);
+ } else {
+ printf("inflate(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_SPEED);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ /* At this point, uncompr is still mostly zeroes, so it should compress
+ * very well:
+ */
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ if (c_stream.avail_in != 0) {
+ fprintf(stderr, "deflate not greedy\n");
+ exit(1);
+ }
+
+ /* Feed in already compressed data and switch to no compression: */
+ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ c_stream.next_in = compr;
+ c_stream.avail_in = (uInt)comprLen/2;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ /* Switch back to compressing mode: */
+ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ for (;;) {
+ d_stream.next_out = uncompr; /* discard the output */
+ d_stream.avail_out = (uInt)uncomprLen;
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "large inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+ fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+ exit(1);
+ } else {
+ printf("large_inflate(): OK\n");
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+ Byte *compr;
+ uLong *comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ uInt len = (uInt)strlen(hello)+1;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+ c_stream.avail_in = 3;
+ c_stream.avail_out = (uInt)*comprLen;
+ err = deflate(&c_stream, Z_FULL_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ compr[3]++; /* force an error in first compressed block */
+ c_stream.avail_in = len - 3;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ CHECK_ERR(err, "deflate");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+
+ *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 2; /* just read the zlib header */
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ inflate(&d_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "inflate");
+
+ d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
+ err = inflateSync(&d_stream); /* but skip the damaged part */
+ CHECK_ERR(err, "inflateSync");
+
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_DATA_ERROR) {
+ fprintf(stderr, "inflate should report DATA_ERROR\n");
+ /* Because of incorrect adler32 */
+ exit(1);
+ }
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = zalloc;
+ c_stream.zfree = zfree;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ err = deflateSetDictionary(&c_stream,
+ (const Bytef*)dictionary, (int)sizeof(dictionary));
+ CHECK_ERR(err, "deflateSetDictionary");
+
+ dictId = c_stream.adler;
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.avail_in = (uInt)strlen(hello)+1;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = zalloc;
+ d_stream.zfree = zfree;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ for (;;) {
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ if (err == Z_NEED_DICT) {
+ if (d_stream.adler != dictId) {
+ fprintf(stderr, "unexpected dictionary");
+ exit(1);
+ }
+ err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+ (int)sizeof(dictionary));
+ }
+ CHECK_ERR(err, "inflate with dict");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate with dict\n");
+ exit(1);
+ } else {
+ printf("inflate with dictionary: %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Usage: example [output.gz [input.gz]]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ Byte *compr, *uncompr;
+ uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+ uLong uncomprLen = comprLen;
+ static const char* myVersion = ZLIB_VERSION;
+
+ if (zlibVersion()[0] != myVersion[0]) {
+ fprintf(stderr, "incompatible zlib version\n");
+ exit(1);
+
+ } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+ fprintf(stderr, "warning: different zlib version\n");
+ }
+
+ printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
+ ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
+
+ compr = (Byte*)calloc((uInt)comprLen, 1);
+ uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
+ /* compr and uncompr are cleared to avoid reading uninitialized
+ * data and to ensure that uncompr compresses well.
+ */
+ if (compr == Z_NULL || uncompr == Z_NULL) {
+ printf("out of memory\n");
+ exit(1);
+ }
+
+#ifdef Z_SOLO
+ argc = strlen(argv[0]);
+#else
+ test_compress(compr, comprLen, uncompr, uncomprLen);
+
+ test_gzio((argc > 1 ? argv[1] : TESTFILE),
+ uncompr, uncomprLen);
+#endif
+
+ test_deflate(compr, comprLen);
+ test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_flush(compr, &comprLen);
+ test_sync(compr, comprLen, uncompr, uncomprLen);
+ comprLen = uncomprLen;
+
+ test_dict_deflate(compr, comprLen);
+ test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ free(compr);
+ free(uncompr);
+
+ return 0;
+}
diff --git a/lib/zlib/gzclose.c b/lib/zlib/gzclose.c
new file mode 100644
index 000000000..caeb99a31
--- /dev/null
+++ b/lib/zlib/gzclose.c
@@ -0,0 +1,25 @@
+/* gzclose.c -- zlib gzclose() function
+ * Copyright (C) 2004, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* gzclose() is in a separate file so that it is linked in only if it is used.
+ That way the other gzclose functions can be used instead to avoid linking in
+ unneeded compression or decompression routines. */
+int ZEXPORT gzclose(file)
+ gzFile file;
+{
+#ifndef NO_GZCOMPRESS
+ gz_statep state;
+
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
+#else
+ return gzclose_r(file);
+#endif
+}
diff --git a/lib/zlib/gzguts.h b/lib/zlib/gzguts.h
new file mode 100644
index 000000000..ee3f281aa
--- /dev/null
+++ b/lib/zlib/gzguts.h
@@ -0,0 +1,193 @@
+/* gzguts.h -- zlib internal header definitions for gz* operations
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef _LARGEFILE64_SOURCE
+# ifndef _LARGEFILE_SOURCE
+# define _LARGEFILE_SOURCE 1
+# endif
+# ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+# endif
+#endif
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include <stdio.h>
+#include "zlib.h"
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+# include <limits.h>
+#endif
+#include <fcntl.h>
+
+#ifdef _WIN32
+# include <stddef.h>
+#endif
+
+#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
+# include <io.h>
+#endif
+
+#ifdef NO_DEFLATE /* for compatibility with old definition */
+# define NO_GZCOMPRESS
+#endif
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+# ifdef VMS
+# define NO_vsnprintf
+# endif
+# ifdef __OS400__
+# define NO_vsnprintf
+# endif
+# ifdef __MVS__
+# define NO_vsnprintf
+# endif
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+/* gz* functions always use library allocation functions */
+#ifndef STDC
+ extern voidp malloc OF((uInt size));
+ extern void free OF((voidpf ptr));
+#endif
+
+/* get errno and strerror definition */
+#if defined UNDER_CE
+# include <windows.h>
+# define zstrerror() gz_strwinerror((DWORD)GetLastError())
+#else
+# ifndef NO_STRERROR
+# include <errno.h>
+# define zstrerror() strerror(errno)
+# else
+# define zstrerror() "stdio error (consult errno)"
+# endif
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+ ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+#endif
+
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+
+/* default i/o buffer size -- double this for output when reading */
+#define GZBUFSIZE 8192
+
+/* gzip modes, also provide a little integrity check on the passed structure */
+#define GZ_NONE 0
+#define GZ_READ 7247
+#define GZ_WRITE 31153
+#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
+
+/* values for gz_state how */
+#define LOOK 0 /* look for a gzip header */
+#define COPY 1 /* copy input directly */
+#define GZIP 2 /* decompress a gzip stream */
+
+/* internal gzip file state data structure */
+typedef struct {
+ /* exposed contents for gzgetc() macro */
+ struct gzFile_s x; /* "x" for exposed */
+ /* x.have: number of bytes available at x.next */
+ /* x.next: next output data to deliver or write */
+ /* x.pos: current position in uncompressed data */
+ /* used for both reading and writing */
+ int mode; /* see gzip modes above */
+ int fd; /* file descriptor */
+ char *path; /* path or fd for error messages */
+ unsigned size; /* buffer size, zero if not allocated yet */
+ unsigned want; /* requested buffer size, default is GZBUFSIZE */
+ unsigned char *in; /* input buffer */
+ unsigned char *out; /* output buffer (double-sized when reading) */
+ int direct; /* 0 if processing gzip, 1 if transparent */
+ /* just for reading */
+ int how; /* 0: get header, 1: copy, 2: decompress */
+ z_off64_t start; /* where the gzip data started, for rewinding */
+ int eof; /* true if end of input file reached */
+ int past; /* true if read requested past end */
+ /* just for writing */
+ int level; /* compression level */
+ int strategy; /* compression strategy */
+ /* seek request */
+ z_off64_t skip; /* amount to skip (already rewound if backwards) */
+ int seek; /* true if seek request pending */
+ /* error information */
+ int err; /* error code */
+ char *msg; /* error message */
+ /* zlib inflate or deflate stream */
+ z_stream strm; /* stream structure in-place (not a pointer) */
+} gz_state;
+typedef gz_state FAR *gz_statep;
+
+/* shared functions */
+void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
+#if defined UNDER_CE
+char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
+#endif
+
+/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
+ value -- needed when comparing unsigned to z_off64_t, which is signed
+ (possible z_off64_t types off_t, off64_t, and long are all signed) */
+#ifdef INT_MAX
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
+#else
+unsigned ZLIB_INTERNAL gz_intmax OF((void));
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
+#endif
diff --git a/lib/zlib/gzlib.c b/lib/zlib/gzlib.c
new file mode 100644
index 000000000..ca55c6ea9
--- /dev/null
+++ b/lib/zlib/gzlib.c
@@ -0,0 +1,620 @@
+/* gzlib.c -- zlib functions common to reading and writing gzip files
+ * Copyright (C) 2004, 2010, 2011, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+#if defined(_WIN32) && !defined(__BORLANDC__)
+# define LSEEK _lseeki64
+#else
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+# define LSEEK lseek64
+#else
+# define LSEEK lseek
+#endif
+#endif
+
+/* Local functions */
+local void gz_reset OF((gz_statep));
+local gzFile gz_open OF((const void *, int, const char *));
+
+#if defined UNDER_CE
+
+/* Map the Windows error number in ERROR to a locale-dependent error message
+ string and return a pointer to it. Typically, the values for ERROR come
+ from GetLastError.
+
+ The string pointed to shall not be modified by the application, but may be
+ overwritten by a subsequent call to gz_strwinerror
+
+ The gz_strwinerror function does not change the current setting of
+ GetLastError. */
+char ZLIB_INTERNAL *gz_strwinerror (error)
+ DWORD error;
+{
+ static char buf[1024];
+
+ wchar_t *msgbuf;
+ DWORD lasterr = GetLastError();
+ DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ error,
+ 0, /* Default language */
+ (LPVOID)&msgbuf,
+ 0,
+ NULL);
+ if (chars != 0) {
+ /* If there is an \r\n appended, zap it. */
+ if (chars >= 2
+ && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > sizeof (buf) - 1) {
+ chars = sizeof (buf) - 1;
+ msgbuf[chars] = 0;
+ }
+
+ wcstombs(buf, msgbuf, chars + 1);
+ LocalFree(msgbuf);
+ }
+ else {
+ sprintf(buf, "unknown win32 error (%ld)", error);
+ }
+
+ SetLastError(lasterr);
+ return buf;
+}
+
+#endif /* UNDER_CE */
+
+/* Reset gzip file state */
+local void gz_reset(state)
+ gz_statep state;
+{
+ state->x.have = 0; /* no output data available */
+ if (state->mode == GZ_READ) { /* for reading ... */
+ state->eof = 0; /* not at end of file */
+ state->past = 0; /* have not read past end yet */
+ state->how = LOOK; /* look for gzip header */
+ }
+ state->seek = 0; /* no seek request pending */
+ gz_error(state, Z_OK, NULL); /* clear error */
+ state->x.pos = 0; /* no uncompressed data yet */
+ state->strm.avail_in = 0; /* no input data yet */
+}
+
+/* Open a gzip file either by name or file descriptor. */
+local gzFile gz_open(path, fd, mode)
+ const void *path;
+ int fd;
+ const char *mode;
+{
+ gz_statep state;
+ size_t len;
+ int oflag;
+#ifdef O_CLOEXEC
+ int cloexec = 0;
+#endif
+#ifdef O_EXCL
+ int exclusive = 0;
+#endif
+
+ /* check input */
+ if (path == NULL)
+ return NULL;
+
+ /* allocate gzFile structure to return */
+ state = malloc(sizeof(gz_state));
+ if (state == NULL)
+ return NULL;
+ state->size = 0; /* no buffers allocated yet */
+ state->want = GZBUFSIZE; /* requested buffer size */
+ state->msg = NULL; /* no error message yet */
+
+ /* interpret mode */
+ state->mode = GZ_NONE;
+ state->level = Z_DEFAULT_COMPRESSION;
+ state->strategy = Z_DEFAULT_STRATEGY;
+ state->direct = 0;
+ while (*mode) {
+ if (*mode >= '0' && *mode <= '9')
+ state->level = *mode - '0';
+ else
+ switch (*mode) {
+ case 'r':
+ state->mode = GZ_READ;
+ break;
+#ifndef NO_GZCOMPRESS
+ case 'w':
+ state->mode = GZ_WRITE;
+ break;
+ case 'a':
+ state->mode = GZ_APPEND;
+ break;
+#endif
+ case '+': /* can't read and write at the same time */
+ free(state);
+ return NULL;
+ case 'b': /* ignore -- will request binary anyway */
+ break;
+#ifdef O_CLOEXEC
+ case 'e':
+ cloexec = 1;
+ break;
+#endif
+#ifdef O_EXCL
+ case 'x':
+ exclusive = 1;
+ break;
+#endif
+ case 'f':
+ state->strategy = Z_FILTERED;
+ break;
+ case 'h':
+ state->strategy = Z_HUFFMAN_ONLY;
+ break;
+ case 'R':
+ state->strategy = Z_RLE;
+ break;
+ case 'F':
+ state->strategy = Z_FIXED;
+ case 'T':
+ state->direct = 1;
+ default: /* could consider as an error, but just ignore */
+ ;
+ }
+ mode++;
+ }
+
+ /* must provide an "r", "w", or "a" */
+ if (state->mode == GZ_NONE) {
+ free(state);
+ return NULL;
+ }
+
+ /* can't force transparent read */
+ if (state->mode == GZ_READ) {
+ if (state->direct) {
+ free(state);
+ return NULL;
+ }
+ state->direct = 1; /* for empty file */
+ }
+
+ /* save the path name for error messages */
+#ifdef _WIN32
+ if (fd == -2) {
+ len = wcstombs(NULL, path, 0);
+ if (len == (size_t)-1)
+ len = 0;
+ }
+ else
+#endif
+ len = strlen(path);
+ state->path = malloc(len + 1);
+ if (state->path == NULL) {
+ free(state);
+ return NULL;
+ }
+#ifdef _WIN32
+ if (fd == -2)
+ if (len)
+ wcstombs(state->path, path, len + 1);
+ else
+ *(state->path) = 0;
+ else
+#endif
+ strcpy(state->path, path);
+
+ /* compute the flags for open() */
+ oflag =
+#ifdef O_LARGEFILE
+ O_LARGEFILE |
+#endif
+#ifdef O_BINARY
+ O_BINARY |
+#endif
+#ifdef O_CLOEXEC
+ (cloexec ? O_CLOEXEC : 0) |
+#endif
+ (state->mode == GZ_READ ?
+ O_RDONLY :
+ (O_WRONLY | O_CREAT |
+#ifdef O_EXCL
+ (exclusive ? O_EXCL : 0) |
+#endif
+ (state->mode == GZ_WRITE ?
+ O_TRUNC :
+ O_APPEND)));
+
+ /* open the file with the appropriate flags (or just use fd) */
+ state->fd = fd > -1 ? fd : (
+#ifdef _WIN32
+ fd == -2 ? _wopen(path, oflag, 0666) :
+#endif
+ open(path, oflag, 0666));
+ if (state->fd == -1) {
+ free(state->path);
+ free(state);
+ return NULL;
+ }
+ if (state->mode == GZ_APPEND)
+ state->mode = GZ_WRITE; /* simplify later checks */
+
+ /* save the current position for rewinding (only if reading) */
+ if (state->mode == GZ_READ) {
+ state->start = LSEEK(state->fd, 0, SEEK_CUR);
+ if (state->start == -1) state->start = 0;
+ }
+
+ /* initialize stream */
+ gz_reset(state);
+
+ /* return stream */
+ return (gzFile)state;
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen(path, mode)
+ const char *path;
+ const char *mode;
+{
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen64(path, mode)
+ const char *path;
+ const char *mode;
+{
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzdopen(fd, mode)
+ int fd;
+ const char *mode;
+{
+ char *path; /* identifier for error messages */
+ gzFile gz;
+
+ if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
+ return NULL;
+ sprintf(path, "<fd:%d>", fd); /* for debugging */
+ gz = gz_open(path, fd, mode);
+ free(path);
+ return gz;
+}
+
+/* -- see zlib.h -- */
+#ifdef _WIN32
+gzFile ZEXPORT gzopen_w(path, mode)
+ const wchar_t *path;
+ const char *mode;
+{
+ return gz_open(path, -2, mode);
+}
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzbuffer(file, size)
+ gzFile file;
+ unsigned size;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* make sure we haven't already allocated memory */
+ if (state->size != 0)
+ return -1;
+
+ /* check and set requested size */
+ if (size < 2)
+ size = 2; /* need two bytes to check magic header */
+ state->want = size;
+ return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzrewind(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* back up and start over */
+ if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
+ return -1;
+ gz_reset(state);
+ return 0;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzseek64(file, offset, whence)
+ gzFile file;
+ z_off64_t offset;
+ int whence;
+{
+ unsigned n;
+ z_off64_t ret;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* check that there's no error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+
+ /* can only seek from start or relative to current position */
+ if (whence != SEEK_SET && whence != SEEK_CUR)
+ return -1;
+
+ /* normalize offset to a SEEK_CUR specification */
+ if (whence == SEEK_SET)
+ offset -= state->x.pos;
+ else if (state->seek)
+ offset += state->skip;
+ state->seek = 0;
+
+ /* if within raw area while reading, just go there */
+ if (state->mode == GZ_READ && state->how == COPY &&
+ state->x.pos + offset >= 0) {
+ ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
+ if (ret == -1)
+ return -1;
+ state->x.have = 0;
+ state->eof = 0;
+ state->past = 0;
+ state->seek = 0;
+ gz_error(state, Z_OK, NULL);
+ state->strm.avail_in = 0;
+ state->x.pos += offset;
+ return state->x.pos;
+ }
+
+ /* calculate skip amount, rewinding if needed for back seek when reading */
+ if (offset < 0) {
+ if (state->mode != GZ_READ) /* writing -- can't go backwards */
+ return -1;
+ offset += state->x.pos;
+ if (offset < 0) /* before start of file! */
+ return -1;
+ if (gzrewind(file) == -1) /* rewind, then skip to offset */
+ return -1;
+ }
+
+ /* if reading, skip what's in output buffer (one less gzgetc() check) */
+ if (state->mode == GZ_READ) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
+ (unsigned)offset : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ offset -= n;
+ }
+
+ /* request skip (if not zero) */
+ if (offset) {
+ state->seek = 1;
+ state->skip = offset;
+ }
+ return state->x.pos + offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzseek(file, offset, whence)
+ gzFile file;
+ z_off_t offset;
+ int whence;
+{
+ z_off64_t ret;
+
+ ret = gzseek64(file, (z_off64_t)offset, whence);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gztell64(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* return position */
+ return state->x.pos + (state->seek ? state->skip : 0);
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gztell(file)
+ gzFile file;
+{
+ z_off64_t ret;
+
+ ret = gztell64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzoffset64(file)
+ gzFile file;
+{
+ z_off64_t offset;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* compute and return effective offset in file */
+ offset = LSEEK(state->fd, 0, SEEK_CUR);
+ if (offset == -1)
+ return -1;
+ if (state->mode == GZ_READ) /* reading */
+ offset -= state->strm.avail_in; /* don't count buffered input */
+ return offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzoffset(file)
+ gzFile file;
+{
+ z_off64_t ret;
+
+ ret = gzoffset64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzeof(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return 0;
+
+ /* return end-of-file state */
+ return state->mode == GZ_READ ? state->past : 0;
+}
+
+/* -- see zlib.h -- */
+const char * ZEXPORT gzerror(file, errnum)
+ gzFile file;
+ int *errnum;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return NULL;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return NULL;
+
+ /* return error information */
+ if (errnum != NULL)
+ *errnum = state->err;
+ return state->msg == NULL ? "" : state->msg;
+}
+
+/* -- see zlib.h -- */
+void ZEXPORT gzclearerr(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return;
+
+ /* clear error and end-of-file */
+ if (state->mode == GZ_READ) {
+ state->eof = 0;
+ state->past = 0;
+ }
+ gz_error(state, Z_OK, NULL);
+}
+
+/* Create an error message in allocated memory and set state->err and
+ state->msg accordingly. Free any previous error message already there. Do
+ not try to free or allocate space if the error is Z_MEM_ERROR (out of
+ memory). Simply save the error message as a static string. If there is an
+ allocation failure constructing the error message, then convert the error to
+ out of memory. */
+void ZLIB_INTERNAL gz_error(state, err, msg)
+ gz_statep state;
+ int err;
+ const char *msg;
+{
+ /* free previously allocated message and clear */
+ if (state->msg != NULL) {
+ if (state->err != Z_MEM_ERROR)
+ free(state->msg);
+ state->msg = NULL;
+ }
+
+ /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
+ if (err != Z_OK && err != Z_BUF_ERROR)
+ state->x.have = 0;
+
+ /* set error code, and if no message, then done */
+ state->err = err;
+ if (msg == NULL)
+ return;
+
+ /* for an out of memory error, save as static string */
+ if (err == Z_MEM_ERROR) {
+ state->msg = (char *)msg;
+ return;
+ }
+
+ /* construct error message with path */
+ if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
+ state->err = Z_MEM_ERROR;
+ state->msg = (char *)"out of memory";
+ return;
+ }
+ strcpy(state->msg, state->path);
+ strcat(state->msg, ": ");
+ strcat(state->msg, msg);
+ return;
+}
+
+#ifndef INT_MAX
+/* portably return maximum value for an int (when limits.h presumed not
+ available) -- we need to do this to cover cases where 2's complement not
+ used, since C standard permits 1's complement and sign-bit representations,
+ otherwise we could just use ((unsigned)-1) >> 1 */
+unsigned ZLIB_INTERNAL gz_intmax()
+{
+ unsigned p, q;
+
+ p = 1;
+ do {
+ q = p;
+ p <<= 1;
+ p++;
+ } while (p > q);
+ return q >> 1;
+}
+#endif
diff --git a/lib/zlib/gzread.c b/lib/zlib/gzread.c
new file mode 100644
index 000000000..3493d34d4
--- /dev/null
+++ b/lib/zlib/gzread.c
@@ -0,0 +1,589 @@
+/* gzread.c -- zlib functions for reading gzip files
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Local functions */
+local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
+local int gz_avail OF((gz_statep));
+local int gz_look OF((gz_statep));
+local int gz_decomp OF((gz_statep));
+local int gz_fetch OF((gz_statep));
+local int gz_skip OF((gz_statep, z_off64_t));
+
+/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
+ state->fd, and update state->eof, state->err, and state->msg as appropriate.
+ This function needs to loop on read(), since read() is not guaranteed to
+ read the number of bytes requested, depending on the type of descriptor. */
+local int gz_load(state, buf, len, have)
+ gz_statep state;
+ unsigned char *buf;
+ unsigned len;
+ unsigned *have;
+{
+ int ret;
+
+ *have = 0;
+ do {
+ ret = read(state->fd, buf + *have, len - *have);
+ if (ret <= 0)
+ break;
+ *have += ret;
+ } while (*have < len);
+ if (ret < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ if (ret == 0)
+ state->eof = 1;
+ return 0;
+}
+
+/* Load up input buffer and set eof flag if last data loaded -- return -1 on
+ error, 0 otherwise. Note that the eof flag is set when the end of the input
+ file is reached, even though there may be unused data in the buffer. Once
+ that data has been used, no more attempts will be made to read the file.
+ If strm->avail_in != 0, then the current data is moved to the beginning of
+ the input buffer, and then the remainder of the buffer is loaded with the
+ available data from the input file. */
+local int gz_avail(state)
+ gz_statep state;
+{
+ unsigned got;
+ z_streamp strm = &(state->strm);
+
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+ if (state->eof == 0) {
+ if (strm->avail_in) { /* copy what's there to the start */
+ unsigned char *p = state->in, *q = strm->next_in;
+ unsigned n = strm->avail_in;
+ do {
+ *p++ = *q++;
+ } while (--n);
+ }
+ if (gz_load(state, state->in + strm->avail_in,
+ state->size - strm->avail_in, &got) == -1)
+ return -1;
+ strm->avail_in += got;
+ strm->next_in = state->in;
+ }
+ return 0;
+}
+
+/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
+ If this is the first time in, allocate required memory. state->how will be
+ left unchanged if there is no more input data available, will be set to COPY
+ if there is no gzip header and direct copying will be performed, or it will
+ be set to GZIP for decompression. If direct copying, then leftover input
+ data from the input buffer will be copied to the output buffer. In that
+ case, all further file reads will be directly to either the output buffer or
+ a user buffer. If decompressing, the inflate state will be initialized.
+ gz_look() will return 0 on success or -1 on failure. */
+local int gz_look(state)
+ gz_statep state;
+{
+ z_streamp strm = &(state->strm);
+
+ /* allocate read buffers and inflate memory */
+ if (state->size == 0) {
+ /* allocate buffers */
+ state->in = malloc(state->want);
+ state->out = malloc(state->want << 1);
+ if (state->in == NULL || state->out == NULL) {
+ if (state->out != NULL)
+ free(state->out);
+ if (state->in != NULL)
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ state->size = state->want;
+
+ /* allocate inflate memory */
+ state->strm.zalloc = Z_NULL;
+ state->strm.zfree = Z_NULL;
+ state->strm.opaque = Z_NULL;
+ state->strm.avail_in = 0;
+ state->strm.next_in = Z_NULL;
+ if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
+ free(state->out);
+ free(state->in);
+ state->size = 0;
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ }
+
+ /* get at least the magic bytes in the input buffer */
+ if (strm->avail_in < 2) {
+ if (gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0)
+ return 0;
+ }
+
+ /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
+ a logical dilemma here when considering the case of a partially written
+ gzip file, to wit, if a single 31 byte is written, then we cannot tell
+ whether this is a single-byte file, or just a partially written gzip
+ file -- for here we assume that if a gzip file is being written, then
+ the header will be written in a single operation, so that reading a
+ single byte is sufficient indication that it is not a gzip file) */
+ if (strm->avail_in > 1 &&
+ strm->next_in[0] == 31 && strm->next_in[1] == 139) {
+ inflateReset(strm);
+ state->how = GZIP;
+ state->direct = 0;
+ return 0;
+ }
+
+ /* no gzip header -- if we were decoding gzip before, then this is trailing
+ garbage. Ignore the trailing garbage and finish. */
+ if (state->direct == 0) {
+ strm->avail_in = 0;
+ state->eof = 1;
+ state->x.have = 0;
+ return 0;
+ }
+
+ /* doing raw i/o, copy any leftover input to output -- this assumes that
+ the output buffer is larger than the input buffer, which also assures
+ space for gzungetc() */
+ state->x.next = state->out;
+ if (strm->avail_in) {
+ memcpy(state->x.next, strm->next_in, strm->avail_in);
+ state->x.have = strm->avail_in;
+ strm->avail_in = 0;
+ }
+ state->how = COPY;
+ state->direct = 1;
+ return 0;
+}
+
+/* Decompress from input to the provided next_out and avail_out in the state.
+ On return, state->x.have and state->x.next point to the just decompressed
+ data. If the gzip stream completes, state->how is reset to LOOK to look for
+ the next gzip stream or raw data, once state->x.have is depleted. Returns 0
+ on success, -1 on failure. */
+local int gz_decomp(state)
+ gz_statep state;
+{
+ int ret = Z_OK;
+ unsigned had;
+ z_streamp strm = &(state->strm);
+
+ /* fill output buffer up to end of deflate stream */
+ had = strm->avail_out;
+ do {
+ /* get more input for inflate() */
+ if (strm->avail_in == 0 && gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0) {
+ gz_error(state, Z_BUF_ERROR, "unexpected end of file");
+ break;
+ }
+
+ /* decompress and handle errors */
+ ret = inflate(strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: inflate stream corrupt");
+ return -1;
+ }
+ if (ret == Z_MEM_ERROR) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
+ gz_error(state, Z_DATA_ERROR,
+ strm->msg == NULL ? "compressed data error" : strm->msg);
+ return -1;
+ }
+ } while (strm->avail_out && ret != Z_STREAM_END);
+
+ /* update available output */
+ state->x.have = had - strm->avail_out;
+ state->x.next = strm->next_out - state->x.have;
+
+ /* if the gzip stream completed successfully, look for another */
+ if (ret == Z_STREAM_END)
+ state->how = LOOK;
+
+ /* good decompression */
+ return 0;
+}
+
+/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
+ Data is either copied from the input file or decompressed from the input
+ file depending on state->how. If state->how is LOOK, then a gzip header is
+ looked for to determine whether to copy or decompress. Returns -1 on error,
+ otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
+ end of the input file has been reached and all data has been processed. */
+local int gz_fetch(state)
+ gz_statep state;
+{
+ z_streamp strm = &(state->strm);
+
+ do {
+ switch(state->how) {
+ case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
+ if (gz_look(state) == -1)
+ return -1;
+ if (state->how == LOOK)
+ return 0;
+ break;
+ case COPY: /* -> COPY */
+ if (gz_load(state, state->out, state->size << 1, &(state->x.have))
+ == -1)
+ return -1;
+ state->x.next = state->out;
+ return 0;
+ case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
+ strm->avail_out = state->size << 1;
+ strm->next_out = state->out;
+ if (gz_decomp(state) == -1)
+ return -1;
+ }
+ } while (state->x.have == 0 && (!state->eof || strm->avail_in));
+ return 0;
+}
+
+/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
+local int gz_skip(state, len)
+ gz_statep state;
+ z_off64_t len;
+{
+ unsigned n;
+
+ /* skip over len bytes or reach end-of-file, whichever comes first */
+ while (len)
+ /* skip over whatever is in output buffer */
+ if (state->x.have) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
+ (unsigned)len : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ len -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && state->strm.avail_in == 0)
+ break;
+
+ /* need more data to skip -- load up output buffer */
+ else {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzread(file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
+{
+ unsigned got, n;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids the flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
+ return -1;
+ }
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* get len bytes to buf, or less than len if at the end */
+ got = 0;
+ do {
+ /* first just try copying data from the output buffer */
+ if (state->x.have) {
+ n = state->x.have > len ? len : state->x.have;
+ memcpy(buf, state->x.next, n);
+ state->x.next += n;
+ state->x.have -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && strm->avail_in == 0) {
+ state->past = 1; /* tried to read past end */
+ break;
+ }
+
+ /* need output data -- for small len or new stream load up our output
+ buffer */
+ else if (state->how == LOOK || len < (state->size << 1)) {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return -1;
+ continue; /* no progress yet -- go back to copy above */
+ /* the copy above assures that we will leave with space in the
+ output buffer, allowing at least one gzungetc() to succeed */
+ }
+
+ /* large len -- read directly into user buffer */
+ else if (state->how == COPY) { /* read directly */
+ if (gz_load(state, buf, len, &n) == -1)
+ return -1;
+ }
+
+ /* large len -- decompress directly into user buffer */
+ else { /* state->how == GZIP */
+ strm->avail_out = len;
+ strm->next_out = buf;
+ if (gz_decomp(state) == -1)
+ return -1;
+ n = state->x.have;
+ state->x.have = 0;
+ }
+
+ /* update progress */
+ len -= n;
+ buf = (char *)buf + n;
+ got += n;
+ state->x.pos += n;
+ } while (len);
+
+ /* return number of bytes read into user buffer (will fit in int) */
+ return (int)got;
+}
+
+/* -- see zlib.h -- */
+#undef gzgetc
+int ZEXPORT gzgetc(file)
+ gzFile file;
+{
+ int ret;
+ unsigned char buf[1];
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* try output buffer (no need to check for skip request) */
+ if (state->x.have) {
+ state->x.have--;
+ state->x.pos++;
+ return *(state->x.next)++;
+ }
+
+ /* nothing there -- try gzread() */
+ ret = gzread(file, buf, 1);
+ return ret < 1 ? -1 : buf[0];
+}
+
+int ZEXPORT gzgetc_(file)
+gzFile file;
+{
+ return gzgetc(file);
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzungetc(c, file)
+ int c;
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* can't push EOF */
+ if (c < 0)
+ return -1;
+
+ /* if output buffer empty, put byte at end (allows more pushing) */
+ if (state->x.have == 0) {
+ state->x.have = 1;
+ state->x.next = state->out + (state->size << 1) - 1;
+ state->x.next[0] = c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+ }
+
+ /* if no room, give up (must have already done a gzungetc()) */
+ if (state->x.have == (state->size << 1)) {
+ gz_error(state, Z_DATA_ERROR, "out of room to push characters");
+ return -1;
+ }
+
+ /* slide output data if needed and insert byte before existing data */
+ if (state->x.next == state->out) {
+ unsigned char *src = state->out + state->x.have;
+ unsigned char *dest = state->out + (state->size << 1);
+ while (src > state->out)
+ *--dest = *--src;
+ state->x.next = dest;
+ }
+ state->x.have++;
+ state->x.next--;
+ state->x.next[0] = c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+}
+
+/* -- see zlib.h -- */
+char * ZEXPORT gzgets(file, buf, len)
+ gzFile file;
+ char *buf;
+ int len;
+{
+ unsigned left, n;
+ char *str;
+ unsigned char *eol;
+ gz_statep state;
+
+ /* check parameters and get internal structure */
+ if (file == NULL || buf == NULL || len < 1)
+ return NULL;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return NULL;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return NULL;
+ }
+
+ /* copy output bytes up to new line or len - 1, whichever comes first --
+ append a terminating zero to the string (we don't check for a zero in
+ the contents, let the user worry about that) */
+ str = buf;
+ left = (unsigned)len - 1;
+ if (left) do {
+ /* assure that something is in the output buffer */
+ if (state->x.have == 0 && gz_fetch(state) == -1)
+ return NULL; /* error */
+ if (state->x.have == 0) { /* end of file */
+ state->past = 1; /* read past end */
+ break; /* return what we have */
+ }
+
+ /* look for end-of-line in current output buffer */
+ n = state->x.have > left ? left : state->x.have;
+ eol = memchr(state->x.next, '\n', n);
+ if (eol != NULL)
+ n = (unsigned)(eol - state->x.next) + 1;
+
+ /* copy through end-of-line, or remainder if not found */
+ memcpy(buf, state->x.next, n);
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ left -= n;
+ buf += n;
+ } while (left && eol == NULL);
+
+ /* return terminated string, or if nothing, end of file */
+ if (buf == str)
+ return NULL;
+ buf[0] = 0;
+ return str;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzdirect(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* if the state is not known, but we can find out, then do so (this is
+ mainly for right after a gzopen() or gzdopen()) */
+ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+ (void)gz_look(state);
+
+ /* return 1 if transparent, 0 if processing a gzip stream */
+ return state->direct;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_r(file)
+ gzFile file;
+{
+ int ret, err;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're reading */
+ if (state->mode != GZ_READ)
+ return Z_STREAM_ERROR;
+
+ /* free memory and close file */
+ if (state->size) {
+ inflateEnd(&(state->strm));
+ free(state->out);
+ free(state->in);
+ }
+ err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ ret = close(state->fd);
+ free(state);
+ return ret ? Z_ERRNO : err;
+}
diff --git a/lib/zlib/gzwrite.c b/lib/zlib/gzwrite.c
new file mode 100644
index 000000000..27cb3428e
--- /dev/null
+++ b/lib/zlib/gzwrite.c
@@ -0,0 +1,565 @@
+/* gzwrite.c -- zlib functions for writing gzip files
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Local functions */
+local int gz_init OF((gz_statep));
+local int gz_comp OF((gz_statep, int));
+local int gz_zero OF((gz_statep, z_off64_t));
+
+/* Initialize state for writing a gzip file. Mark initialization by setting
+ state->size to non-zero. Return -1 on failure or 0 on success. */
+local int gz_init(state)
+ gz_statep state;
+{
+ int ret;
+ z_streamp strm = &(state->strm);
+
+ /* allocate input buffer */
+ state->in = malloc(state->want);
+ if (state->in == NULL) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* only need output buffer and deflate state if compressing */
+ if (!state->direct) {
+ /* allocate output buffer */
+ state->out = malloc(state->want);
+ if (state->out == NULL) {
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* allocate deflate memory, set up for gzip compression */
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ ret = deflateInit2(strm, state->level, Z_DEFLATED,
+ MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
+ if (ret != Z_OK) {
+ free(state->out);
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ }
+
+ /* mark state as initialized */
+ state->size = state->want;
+
+ /* initialize write buffer if compressing */
+ if (!state->direct) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ state->x.next = strm->next_out;
+ }
+ return 0;
+}
+
+/* Compress whatever is at avail_in and next_in and write to the output file.
+ Return -1 if there is an error writing to the output file, otherwise 0.
+ flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
+ then the deflate() state is reset to start a new gzip stream. If gz->direct
+ is true, then simply write to the output file without compressing, and
+ ignore flush. */
+local int gz_comp(state, flush)
+ gz_statep state;
+ int flush;
+{
+ int ret, got;
+ unsigned have;
+ z_streamp strm = &(state->strm);
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return -1;
+
+ /* write directly if requested */
+ if (state->direct) {
+ got = write(state->fd, strm->next_in, strm->avail_in);
+ if (got < 0 || (unsigned)got != strm->avail_in) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ strm->avail_in = 0;
+ return 0;
+ }
+
+ /* run deflate() on provided input until it produces no more output */
+ ret = Z_OK;
+ do {
+ /* write out current buffer contents if full, or if flushing, but if
+ doing Z_FINISH then don't write until we get to Z_STREAM_END */
+ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
+ (flush != Z_FINISH || ret == Z_STREAM_END))) {
+ have = (unsigned)(strm->next_out - state->x.next);
+ if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
+ (unsigned)got != have)) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ if (strm->avail_out == 0) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ }
+ state->x.next = strm->next_out;
+ }
+
+ /* compress */
+ have = strm->avail_out;
+ ret = deflate(strm, flush);
+ if (ret == Z_STREAM_ERROR) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: deflate stream corrupt");
+ return -1;
+ }
+ have -= strm->avail_out;
+ } while (have);
+
+ /* if that completed a deflate stream, allow another to start */
+ if (flush == Z_FINISH)
+ deflateReset(strm);
+
+ /* all done, no errors */
+ return 0;
+}
+
+/* Compress len zeros to output. Return -1 on error, 0 on success. */
+local int gz_zero(state, len)
+ gz_statep state;
+ z_off64_t len;
+{
+ int first;
+ unsigned n;
+ z_streamp strm = &(state->strm);
+
+ /* consume whatever's left in the input buffer */
+ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+
+ /* compress len zeros (len guaranteed > 0) */
+ first = 1;
+ while (len) {
+ n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
+ (unsigned)len : state->size;
+ if (first) {
+ memset(state->in, 0, n);
+ first = 0;
+ }
+ strm->avail_in = n;
+ strm->next_in = state->in;
+ state->x.pos += n;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+ len -= n;
+ }
+ return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzwrite(file, buf, len)
+ gzFile file;
+ voidpc buf;
+ unsigned len;
+{
+ unsigned put = len;
+ unsigned n;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids the flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
+ return 0;
+ }
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return 0;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* for small len, copy to input buffer, otherwise compress directly */
+ if (len < state->size) {
+ /* copy to input buffer, compress when full */
+ do {
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ n = state->size - strm->avail_in;
+ if (n > len)
+ n = len;
+ memcpy(strm->next_in + strm->avail_in, buf, n);
+ strm->avail_in += n;
+ state->x.pos += n;
+ buf = (char *)buf + n;
+ len -= n;
+ if (len && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ } while (len);
+ }
+ else {
+ /* consume whatever's left in the input buffer */
+ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+
+ /* directly compress user buffer to file */
+ strm->avail_in = len;
+ strm->next_in = (voidp)buf;
+ state->x.pos += len;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ }
+
+ /* input was all buffered or compressed (put will fit in int) */
+ return (int)put;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputc(file, c)
+ gzFile file;
+ int c;
+{
+ unsigned char buf[1];
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return -1;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* try writing to input buffer for speed (state->size == 0 if buffer not
+ initialized) */
+ if (strm->avail_in < state->size) {
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ strm->next_in[strm->avail_in++] = c;
+ state->x.pos++;
+ return c & 0xff;
+ }
+
+ /* no room in buffer or not initialized, use gz_write() */
+ buf[0] = c;
+ if (gzwrite(file, buf, 1) != 1)
+ return -1;
+ return c & 0xff;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputs(file, str)
+ gzFile file;
+ const char *str;
+{
+ int ret;
+ unsigned len;
+
+ /* write string */
+ len = (unsigned)strlen(str);
+ ret = gzwrite(file, str, len);
+ return ret == 0 && len != 0 ? -1 : ret;
+}
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#include <stdarg.h>
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
+{
+ int size, len;
+ gz_statep state;
+ z_streamp strm;
+ va_list va;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return 0;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* consume whatever's left in the input buffer */
+ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+
+ /* do the printf() into the input buffer, put length in len */
+ size = (int)(state->size);
+ state->in[size - 1] = 0;
+ va_start(va, format);
+#ifdef NO_vsnprintf
+# ifdef HAS_vsprintf_void
+ (void)vsprintf((char *)(state->in), format, va);
+ va_end(va);
+ for (len = 0; len < size; len++)
+ if (state->in[len] == 0) break;
+# else
+ len = vsprintf((char *)(state->in), format, va);
+ va_end(va);
+# endif
+#else
+# ifdef HAS_vsnprintf_void
+ (void)vsnprintf((char *)(state->in), size, format, va);
+ va_end(va);
+ len = strlen((char *)(state->in));
+# else
+ len = vsnprintf((char *)(state->in), size, format, va);
+ va_end(va);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, defer compression until needed */
+ strm->avail_in = (unsigned)len;
+ strm->next_in = state->in;
+ state->x.pos += len;
+ return len;
+}
+
+#else /* !STDC && !Z_HAVE_STDARG_H */
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+ gzFile file;
+ const char *format;
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+ int size, len;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that can really pass pointer in ints */
+ if (sizeof(int) != sizeof(void *))
+ return 0;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return 0;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* consume whatever's left in the input buffer */
+ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+
+ /* do the printf() into the input buffer, put length in len */
+ size = (int)(state->size);
+ state->in[size - 1] = 0;
+#ifdef NO_snprintf
+# ifdef HAS_sprintf_void
+ sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+ for (len = 0; len < size; len++)
+ if (state->in[len] == 0) break;
+# else
+ len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#else
+# ifdef HAS_snprintf_void
+ snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+ len = strlen((char *)(state->in));
+# else
+ len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
+ a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
+ a19, a20);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, defer compression until needed */
+ strm->avail_in = (unsigned)len;
+ strm->next_in = state->in;
+ state->x.pos += len;
+ return len;
+}
+
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzflush(file, flush)
+ gzFile file;
+ int flush;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* check flush parameter */
+ if (flush < 0 || flush > Z_FINISH)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* compress remaining data with requested flush */
+ gz_comp(state, flush);
+ return state->err;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzsetparams(file, level, strategy)
+ gzFile file;
+ int level;
+ int strategy;
+{
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* if no change is requested, then do nothing */
+ if (level == state->level && strategy == state->strategy)
+ return Z_OK;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* change compression parameters for subsequent input */
+ if (state->size) {
+ /* flush previous input with previous parameters before changing */
+ if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
+ return state->err;
+ deflateParams(strm, level, strategy);
+ }
+ state->level = level;
+ state->strategy = strategy;
+ return Z_OK;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_w(file)
+ gzFile file;
+{
+ int ret = Z_OK;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're writing */
+ if (state->mode != GZ_WRITE)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ ret = state->err;
+ }
+
+ /* flush, free memory, and close file */
+ if (state->size) {
+ if (gz_comp(state, Z_FINISH) == -1)
+ ret = state->err;
+ if (!state->direct) {
+ (void)deflateEnd(&(state->strm));
+ free(state->out);
+ }
+ free(state->in);
+ }
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ if (close(state->fd) == -1)
+ ret = Z_ERRNO;
+ free(state);
+ return ret;
+}
diff --git a/lib/zlib/infback.c b/lib/zlib/infback.c
new file mode 100644
index 000000000..981aff17c
--- /dev/null
+++ b/lib/zlib/infback.c
@@ -0,0 +1,640 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2011 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ This code is largely copied from inflate.c. Normally either infback.o or
+ inflate.o would be linked into an application--not both. The interface
+ with inffast.c is retained so that optimized assembler-coded versions of
+ inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+ strm provides memory allocation functions in zalloc and zfree, or
+ Z_NULL to use the library memory allocation functions.
+
+ windowBits is in the range 8..15, and window is a user-supplied
+ window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
+z_streamp strm;
+int windowBits;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL || window == Z_NULL ||
+ windowBits < 8 || windowBits > 15)
+ return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+ sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = windowBits;
+ state->wsize = 1U << windowBits;
+ state->window = window;
+ state->wnext = 0;
+ state->whave = 0;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Assure that some input is available. If input is requested, but denied,
+ then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+ do { \
+ if (have == 0) { \
+ have = in(in_desc, &next); \
+ if (have == 0) { \
+ next = Z_NULL; \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+ with an error if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ PULL(); \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflateBack() with
+ an error. */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Assure that some output space is available, by writing out the window
+ if it's full. If the write fails, return from inflateBack() with a
+ Z_BUF_ERROR. */
+#define ROOM() \
+ do { \
+ if (left == 0) { \
+ put = state->window; \
+ left = state->wsize; \
+ state->whave = left; \
+ if (out(out_desc, put, left)) { \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/*
+ strm provides the memory allocation functions and window buffer on input,
+ and provides information on the unused input on return. For Z_DATA_ERROR
+ returns, strm will also provide an error message.
+
+ in() and out() are the call-back input and output functions. When
+ inflateBack() needs more input, it calls in(). When inflateBack() has
+ filled the window with output, or when it completes with data in the
+ window, it calls out() to write out the data. The application must not
+ change the provided input until in() is called again or inflateBack()
+ returns. The application must not change the window/output buffer until
+ inflateBack() returns.
+
+ in() and out() are called with a descriptor parameter provided in the
+ inflateBack() call. This parameter can be a structure that provides the
+ information required to do the read or write, as well as accumulated
+ information on the input and output such as totals and check values.
+
+ in() should return zero on failure. out() should return non-zero on
+ failure. If either in() or out() fails, than inflateBack() returns a
+ Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
+ was in() or out() that caused in the error. Otherwise, inflateBack()
+ returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+ error, or Z_MEM_ERROR if it could not allocate memory for the state.
+ inflateBack() can also return Z_STREAM_ERROR if the input parameters
+ are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
+z_streamp strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ /* Check that the strm exists and that the state was initialized */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* Reset the state */
+ strm->msg = Z_NULL;
+ state->mode = TYPE;
+ state->last = 0;
+ state->whave = 0;
+ next = strm->next_in;
+ have = next != Z_NULL ? strm->avail_in : 0;
+ hold = 0;
+ bits = 0;
+ put = state->window;
+ left = state->wsize;
+
+ /* Inflate until end of block marked as last */
+ for (;;)
+ switch (state->mode) {
+ case TYPE:
+ /* determine and dispatch block type */
+ if (state->last) {
+ BYTEBITS();
+ state->mode = DONE;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+
+ case STORED:
+ /* get and verify stored block length */
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+
+ /* copy stored block from input to output */
+ while (state->length != 0) {
+ copy = state->length;
+ PULL();
+ ROOM();
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+
+ case TABLE:
+ /* get dynamic table entries descriptor */
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+
+ /* get code length code lengths (not a typo) */
+ state->have = 0;
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+
+ /* get length and distance code code lengths */
+ state->have = 0;
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = (unsigned)(state->lens[state->have - 1]);
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+
+ case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
+ /* get a literal, length, or end-of-block code */
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ state->length = (unsigned)here.val;
+
+ /* process literal */
+ if (here.op == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ ROOM();
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ }
+
+ /* process end of block */
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+
+ /* invalid code */
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+
+ /* length code -- get extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+
+ /* get distance code */
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+
+ /* get distance extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+
+ /* copy match from window to output */
+ do {
+ ROOM();
+ copy = state->wsize - state->offset;
+ if (copy < left) {
+ from = put + copy;
+ copy = left - copy;
+ }
+ else {
+ from = put - state->offset;
+ copy = left;
+ }
+ if (copy > state->length) copy = state->length;
+ state->length -= copy;
+ left -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ } while (state->length != 0);
+ break;
+
+ case DONE:
+ /* inflate stream terminated properly -- write leftover output */
+ ret = Z_STREAM_END;
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left))
+ ret = Z_BUF_ERROR;
+ }
+ goto inf_leave;
+
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+
+ default: /* can't happen, but makes compilers happy */
+ ret = Z_STREAM_ERROR;
+ goto inf_leave;
+ }
+
+ /* Return unused input */
+ inf_leave:
+ strm->next_in = next;
+ strm->avail_in = have;
+ return ret;
+}
+
+int ZEXPORT inflateBackEnd(strm)
+z_streamp strm;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c
new file mode 100644
index 000000000..2f1d60b43
--- /dev/null
+++ b/lib/zlib/inffast.c
@@ -0,0 +1,340 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2008, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void ZLIB_INTERNAL inflate_fast(strm, start)
+z_streamp strm;
+unsigned start; /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code here; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wnext = state->wnext;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ here = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(here.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ PUP(out) = (unsigned char)(here.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(here.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ here = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(here.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(here.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state->sane) {
+ strm->msg =
+ (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ if (len <= op - whave) {
+ do {
+ PUP(out) = 0;
+ } while (--len);
+ continue;
+ }
+ len -= op - whave;
+ do {
+ PUP(out) = 0;
+ } while (--op > whave);
+ if (op == 0) {
+ from = out - dist;
+ do {
+ PUP(out) = PUP(from);
+ } while (--len);
+ continue;
+ }
+#endif
+ }
+ from = window - OFF;
+ if (wnext == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (wnext < op) { /* wrap around window */
+ from += wsize + wnext - op;
+ op -= wnext;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (wnext < len) { /* some from start of window */
+ op = wnext;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += wnext - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ here = dcode[here.val + (hold & ((1U << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ here = lcode[here.val + (hold & ((1U << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and wnext == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/lib/zlib/inffast.h b/lib/zlib/inffast.h
new file mode 100644
index 000000000..e5c1aa4ca
--- /dev/null
+++ b/lib/zlib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/lib/zlib/inffixed.h b/lib/zlib/inffixed.h
new file mode 100644
index 000000000..d62832776
--- /dev/null
+++ b/lib/zlib/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications.
+ It is part of the implementation of this library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/lib/zlib/inflate.c b/lib/zlib/inflate.c
new file mode 100644
index 000000000..47418a1e1
--- /dev/null
+++ b/lib/zlib/inflate.c
@@ -0,0 +1,1496 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+ unsigned len));
+
+int ZEXPORT inflateResetKeep(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ if (state->wrap) /* to support ill-conceived Java test suite */
+ strm->adler = state->wrap & 1;
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ state->sane = 1;
+ state->back = -1;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ state->wsize = 0;
+ state->whave = 0;
+ state->wnext = 0;
+ return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+ int wrap;
+ struct inflate_state FAR *state;
+
+ /* get the state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* extract wrap request from windowBits parameter */
+ if (windowBits < 0) {
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48)
+ windowBits &= 15;
+#endif
+ }
+
+ /* set number of window bits, free window if different */
+ if (windowBits && (windowBits < 8 || windowBits > 15))
+ return Z_STREAM_ERROR;
+ if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+ ZFREE(strm, state->window);
+ state->window = Z_NULL;
+ }
+
+ /* update state and reset the rest of it */
+ state->wrap = wrap;
+ state->wbits = (unsigned)windowBits;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+ int ret;
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->window = Z_NULL;
+ ret = inflateReset2(strm, windowBits);
+ if (ret != Z_OK) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ }
+ return ret;
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits < 0) {
+ state->hold = 0;
+ state->bits = 0;
+ return Z_OK;
+ }
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed()
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+ state.lencode[low].bits, state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->wnext = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->wnext = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->wnext;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->wnext = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->wnext += dist;
+ if (state->wnext == state->wsize) state->wnext = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (state->wbits == 0)
+ state->wbits = len;
+ else if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = ZSWAP32(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN_; /* decode codes */
+ if (flush == Z_TREES) {
+ DROPBITS(2);
+ goto inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY_;
+ if (flush == Z_TREES) goto inf_leave;
+ case COPY_:
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN_;
+ if (flush == Z_TREES) goto inf_leave;
+ case LEN_:
+ state->mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ if (state->mode == TYPE)
+ state->back = -1;
+ break;
+ }
+ state->back = 0;
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ state->length = (unsigned)here.val;
+ if ((int)(here.op) == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ state->mode = LIT;
+ break;
+ }
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->back = -1;
+ state->mode = TYPE;
+ break;
+ }
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->was = state->length;
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->whave) {
+ if (state->sane) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ Trace((stderr, "inflate.c too far\n"));
+ copy -= state->whave;
+ if (copy > state->length) copy = state->length;
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = 0;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+#endif
+ }
+ if (copy > state->wnext) {
+ copy -= state->wnext;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->wnext - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ ZSWAP32(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffffUL)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+ (state->mode < CHECK || flush != Z_FINISH)))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0) +
+ (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ struct inflate_state FAR *state;
+ unsigned long dictid;
+ unsigned char *next;
+ unsigned avail;
+ int ret;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary identifier */
+ if (state->mode == DICT) {
+ dictid = adler32(0L, Z_NULL, 0);
+ dictid = adler32(dictid, dictionary, dictLength);
+ if (dictid != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window using updatewindow(), which will amend the
+ existing dictionary if appropriate */
+ next = strm->next_out;
+ avail = strm->avail_out;
+ strm->next_out = (Bytef *)dictionary + dictLength;
+ strm->avail_out = 0;
+ ret = updatewindow(strm, dictLength);
+ strm->avail_out = avail;
+ strm->next_out = next;
+ if (ret) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+ source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+ zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ state->sane = !subvert;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ return Z_OK;
+#else
+ state->sane = 1;
+ return Z_DATA_ERROR;
+#endif
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
+ state = (struct inflate_state FAR *)strm->state;
+ return ((long)(state->back) << 16) +
+ (state->mode == COPY ? state->length :
+ (state->mode == MATCH ? state->was - state->length : 0));
+}
diff --git a/lib/zlib/inflate.h b/lib/zlib/inflate.h
new file mode 100644
index 000000000..95f4986d4
--- /dev/null
+++ b/lib/zlib/inflate.h
@@ -0,0 +1,122 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2009 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY_, /* i/o: same as COPY below, but only first time in */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN_, /* i: same as LEN below, but only first time in */
+ LEN, /* i: waiting for length/lit/eob code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib) or (raw)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+ HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ (raw) -> TYPEDO
+ Read deflate blocks:
+ TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+ STORED -> COPY_ -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN_
+ LEN_ -> LEN
+ Read deflate codes in fixed or dynamic block:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 10K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+ int sane; /* if false, allow invalid distance too far */
+ int back; /* bits back of last unprocessed length/lit */
+ unsigned was; /* initial length of match */
+};
diff --git a/lib/zlib/inftrees.c b/lib/zlib/inftrees.c
new file mode 100644
index 000000000..abcd7c45e
--- /dev/null
+++ b/lib/zlib/inftrees.c
@@ -0,0 +1,306 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.7 Copyright 1995-2012 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code here; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 78, 68};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)1;
+ here.val = (unsigned short)0;
+ *(*table)++ = here; /* make a table to force an error */
+ *(*table)++ = here;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min < max; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked for LENS and DIST tables against
+ the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+ the initial root table size constants. See the comments in inftrees.h
+ for more information.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if ((type == LENS && used >= ENOUGH_LENS) ||
+ (type == DISTS && used >= ENOUGH_DISTS))
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ here.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ here.op = (unsigned char)0;
+ here.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ here.op = (unsigned char)(extra[work[sym]]);
+ here.val = base[work[sym]];
+ }
+ else {
+ here.op = (unsigned char)(32 + 64); /* end of block */
+ here.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = here;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if ((type == LENS && used >= ENOUGH_LENS) ||
+ (type == DISTS && used >= ENOUGH_DISTS))
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /* fill in remaining table entry if code is incomplete (guaranteed to have
+ at most one remaining entry, since if the code is incomplete, the
+ maximum code length that was allowed to get this far is one bit) */
+ if (huff != 0) {
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)(len - drop);
+ here.val = (unsigned short)0;
+ next[huff] = here;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/lib/zlib/inftrees.h b/lib/zlib/inftrees.h
new file mode 100644
index 000000000..baa53a0b1
--- /dev/null
+++ b/lib/zlib/inftrees.h
@@ -0,0 +1,62 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table. The maximum number of code structures is
+ 1444, which is the sum of 852 for literal/length codes and 592 for distance
+ codes. These values were found by exhaustive searches using the program
+ examples/enough.c found in the zlib distribtution. The arguments to that
+ program are the number of symbols, the initial root table size, and the
+ maximum bit length of a code. "enough 286 9 15" for literal/length codes
+ returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+ The initial root table size (9 or 6) is found in the fifth argument of the
+ inflate_table() calls in inflate.c and infback.c. If the root table size is
+ changed, then these maximum sizes would be need to be recalculated and
+ updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
diff --git a/lib/zlib/minigzip.c b/lib/zlib/minigzip.c
new file mode 100644
index 000000000..aa7ac7a04
--- /dev/null
+++ b/lib/zlib/minigzip.c
@@ -0,0 +1,631 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+#include <stdio.h>
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifdef USE_MMAP
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+#endif
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+# include <fcntl.h>
+# include <io.h>
+# ifdef UNDER_CE
+# include <stdlib.h>
+# endif
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+# define unlink delete
+# define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+# define unlink remove
+# define GZ_SUFFIX "-gz"
+# define fileno(file) file->__file
+#endif
+#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fileno */
+#endif
+
+#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
+#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
+ extern int unlink OF((const char *));
+#endif
+#endif
+
+#if defined(UNDER_CE)
+# include <windows.h>
+# define perror(s) pwinerror(s)
+
+/* Map the Windows error number in ERROR to a locale-dependent error
+ message string and return a pointer to it. Typically, the values
+ for ERROR come from GetLastError.
+
+ The string pointed to shall not be modified by the application,
+ but may be overwritten by a subsequent call to strwinerror
+
+ The strwinerror function does not change the current setting
+ of GetLastError. */
+
+static char *strwinerror (error)
+ DWORD error;
+{
+ static char buf[1024];
+
+ wchar_t *msgbuf;
+ DWORD lasterr = GetLastError();
+ DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ error,
+ 0, /* Default language */
+ (LPVOID)&msgbuf,
+ 0,
+ NULL);
+ if (chars != 0) {
+ /* If there is an \r\n appended, zap it. */
+ if (chars >= 2
+ && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > sizeof (buf) - 1) {
+ chars = sizeof (buf) - 1;
+ msgbuf[chars] = 0;
+ }
+
+ wcstombs(buf, msgbuf, chars + 1);
+ LocalFree(msgbuf);
+ }
+ else {
+ sprintf(buf, "unknown win32 error (%ld)", error);
+ }
+
+ SetLastError(lasterr);
+ return buf;
+}
+
+static void pwinerror (s)
+ const char *s;
+{
+ if (s && *s)
+ fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
+ else
+ fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
+}
+
+#endif /* UNDER_CE */
+
+#ifndef GZ_SUFFIX
+# define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
+
+#define BUFLEN 16384
+#define MAX_NAME_LEN 1024
+
+#ifdef MAXSEG_64K
+# define local static
+ /* Needed for systems with limitation on stack size. */
+#else
+# define local
+#endif
+
+#ifdef Z_SOLO
+/* for Z_SOLO, create simplified gz* functions using deflate and inflate */
+
+#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
+# include <unistd.h> /* for unlink() */
+#endif
+
+void *myalloc OF((void *, unsigned, unsigned));
+void myfree OF((void *, void *));
+
+void *myalloc(q, n, m)
+ void *q;
+ unsigned n, m;
+{
+ q = Z_NULL;
+ return calloc(n, m);
+}
+
+void myfree(q, p)
+ void *q, *p;
+{
+ q = Z_NULL;
+ free(p);
+}
+
+typedef struct gzFile_s {
+ FILE *file;
+ int write;
+ int err;
+ char *msg;
+ z_stream strm;
+} *gzFile;
+
+gzFile gzopen OF((const char *, const char *));
+gzFile gzdopen OF((int, const char *));
+gzFile gz_open OF((const char *, int, const char *));
+
+gzFile gzopen(path, mode)
+const char *path;
+const char *mode;
+{
+ return gz_open(path, -1, mode);
+}
+
+gzFile gzdopen(fd, mode)
+int fd;
+const char *mode;
+{
+ return gz_open(NULL, fd, mode);
+}
+
+gzFile gz_open(path, fd, mode)
+ const char *path;
+ int fd;
+ const char *mode;
+{
+ gzFile gz;
+ int ret;
+
+ gz = malloc(sizeof(struct gzFile_s));
+ if (gz == NULL)
+ return NULL;
+ gz->write = strchr(mode, 'w') != NULL;
+ gz->strm.zalloc = myalloc;
+ gz->strm.zfree = myfree;
+ gz->strm.opaque = Z_NULL;
+ if (gz->write)
+ ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
+ else {
+ gz->strm.next_in = 0;
+ gz->strm.avail_in = Z_NULL;
+ ret = inflateInit2(&(gz->strm), 15 + 16);
+ }
+ if (ret != Z_OK) {
+ free(gz);
+ return NULL;
+ }
+ gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
+ fopen(path, gz->write ? "wb" : "rb");
+ if (gz->file == NULL) {
+ gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
+ free(gz);
+ return NULL;
+ }
+ gz->err = 0;
+ gz->msg = "";
+ return gz;
+}
+
+int gzwrite OF((gzFile, const void *, unsigned));
+
+int gzwrite(gz, buf, len)
+ gzFile gz;
+ const void *buf;
+ unsigned len;
+{
+ z_stream *strm;
+ unsigned char out[BUFLEN];
+
+ if (gz == NULL || !gz->write)
+ return 0;
+ strm = &(gz->strm);
+ strm->next_in = (void *)buf;
+ strm->avail_in = len;
+ do {
+ strm->next_out = out;
+ strm->avail_out = BUFLEN;
+ (void)deflate(strm, Z_NO_FLUSH);
+ fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
+ } while (strm->avail_out == 0);
+ return len;
+}
+
+int gzread OF((gzFile, void *, unsigned));
+
+int gzread(gz, buf, len)
+ gzFile gz;
+ void *buf;
+ unsigned len;
+{
+ int ret;
+ unsigned got;
+ unsigned char in[1];
+ z_stream *strm;
+
+ if (gz == NULL || gz->write)
+ return 0;
+ if (gz->err)
+ return 0;
+ strm = &(gz->strm);
+ strm->next_out = (void *)buf;
+ strm->avail_out = len;
+ do {
+ got = fread(in, 1, 1, gz->file);
+ if (got == 0)
+ break;
+ strm->next_in = in;
+ strm->avail_in = 1;
+ ret = inflate(strm, Z_NO_FLUSH);
+ if (ret == Z_DATA_ERROR) {
+ gz->err = Z_DATA_ERROR;
+ gz->msg = strm->msg;
+ return 0;
+ }
+ if (ret == Z_STREAM_END)
+ inflateReset(strm);
+ } while (strm->avail_out);
+ return len - strm->avail_out;
+}
+
+int gzclose OF((gzFile));
+
+int gzclose(gz)
+ gzFile gz;
+{
+ z_stream *strm;
+ unsigned char out[BUFLEN];
+
+ if (gz == NULL)
+ return Z_STREAM_ERROR;
+ strm = &(gz->strm);
+ if (gz->write) {
+ strm->next_in = Z_NULL;
+ strm->avail_in = 0;
+ do {
+ strm->next_out = out;
+ strm->avail_out = BUFLEN;
+ (void)deflate(strm, Z_FINISH);
+ fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
+ } while (strm->avail_out == 0);
+ deflateEnd(strm);
+ }
+ else
+ inflateEnd(strm);
+ fclose(gz->file);
+ free(gz);
+ return Z_OK;
+}
+
+const char *gzerror OF((gzFile, int *));
+
+const char *gzerror(gz, err)
+ gzFile gz;
+ int *err;
+{
+ *err = gz->err;
+ return gz->msg;
+}
+
+#endif
+
+char *prog;
+
+void error OF((const char *msg));
+void gz_compress OF((FILE *in, gzFile out));
+#ifdef USE_MMAP
+int gz_compress_mmap OF((FILE *in, gzFile out));
+#endif
+void gz_uncompress OF((gzFile in, FILE *out));
+void file_compress OF((char *file, char *mode));
+void file_uncompress OF((char *file));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+ const char *msg;
+{
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+
+void gz_compress(in, out)
+ FILE *in;
+ gzFile out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+#ifdef USE_MMAP
+ /* Try first compressing with mmap. If mmap fails (minigzip used in a
+ * pipe), use the normal fread loop.
+ */
+ if (gz_compress_mmap(in, out) == Z_OK) return;
+#endif
+ for (;;) {
+ len = (int)fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+ }
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
+
+/* Try compressing the input file at once using mmap. Return Z_OK if
+ * if success, Z_ERRNO otherwise.
+ */
+int gz_compress_mmap(in, out)
+ FILE *in;
+ gzFile out;
+{
+ int len;
+ int err;
+ int ifd = fileno(in);
+ caddr_t buf; /* mmap'ed buffer for the entire input file */
+ off_t buf_len; /* length of the input file */
+ struct stat sb;
+
+ /* Determine the size of the file, needed for mmap: */
+ if (fstat(ifd, &sb) < 0) return Z_ERRNO;
+ buf_len = sb.st_size;
+ if (buf_len <= 0) return Z_ERRNO;
+
+ /* Now do the actual mmap: */
+ buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
+ if (buf == (caddr_t)(-1)) return Z_ERRNO;
+
+ /* Compress the whole file at once: */
+ len = gzwrite(out, (char *)buf, (unsigned)buf_len);
+
+ if (len != (int)buf_len) error(gzerror(out, &err));
+
+ munmap(buf, buf_len);
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+ return Z_OK;
+}
+#endif /* USE_MMAP */
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+ gzFile in;
+ FILE *out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = gzread(in, buf, sizeof(buf));
+ if (len < 0) error (gzerror(in, &err));
+ if (len == 0) break;
+
+ if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+ error("failed fwrite");
+ }
+ }
+ if (fclose(out)) error("failed fclose");
+
+ if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file, mode)
+ char *file;
+ char *mode;
+{
+ local char outfile[MAX_NAME_LEN];
+ FILE *in;
+ gzFile out;
+
+ if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
+ fprintf(stderr, "%s: filename too long\n", prog);
+ exit(1);
+ }
+
+ strcpy(outfile, file);
+ strcat(outfile, GZ_SUFFIX);
+
+ in = fopen(file, "rb");
+ if (in == NULL) {
+ perror(file);
+ exit(1);
+ }
+ out = gzopen(outfile, mode);
+ if (out == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+ exit(1);
+ }
+ gz_compress(in, out);
+
+ unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+ char *file;
+{
+ local char buf[MAX_NAME_LEN];
+ char *infile, *outfile;
+ FILE *out;
+ gzFile in;
+ size_t len = strlen(file);
+
+ if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
+ fprintf(stderr, "%s: filename too long\n", prog);
+ exit(1);
+ }
+
+ strcpy(buf, file);
+
+ if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+ infile = file;
+ outfile = buf;
+ outfile[len-3] = '\0';
+ } else {
+ outfile = file;
+ infile = buf;
+ strcat(infile, GZ_SUFFIX);
+ }
+ in = gzopen(infile, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+ exit(1);
+ }
+ out = fopen(outfile, "wb");
+ if (out == NULL) {
+ perror(file);
+ exit(1);
+ }
+
+ gz_uncompress(in, out);
+
+ unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
+ * -c : write to standard output
+ * -d : decompress
+ * -f : compress with Z_FILTERED
+ * -h : compress with Z_HUFFMAN_ONLY
+ * -r : compress with Z_RLE
+ * -1 to -9 : compression level
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int copyout = 0;
+ int uncompr = 0;
+ gzFile file;
+ char *bname, outmode[20];
+
+ strcpy(outmode, "wb6 ");
+
+ prog = argv[0];
+ bname = strrchr(argv[0], '/');
+ if (bname)
+ bname++;
+ else
+ bname = argv[0];
+ argc--, argv++;
+
+ if (!strcmp(bname, "gunzip"))
+ uncompr = 1;
+ else if (!strcmp(bname, "zcat"))
+ copyout = uncompr = 1;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "-c") == 0)
+ copyout = 1;
+ else if (strcmp(*argv, "-d") == 0)
+ uncompr = 1;
+ else if (strcmp(*argv, "-f") == 0)
+ outmode[3] = 'f';
+ else if (strcmp(*argv, "-h") == 0)
+ outmode[3] = 'h';
+ else if (strcmp(*argv, "-r") == 0)
+ outmode[3] = 'R';
+ else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
+ (*argv)[2] == 0)
+ outmode[2] = (*argv)[1];
+ else
+ break;
+ argc--, argv++;
+ }
+ if (outmode[3] == ' ')
+ outmode[3] = 0;
+ if (argc == 0) {
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+ if (uncompr) {
+ file = gzdopen(fileno(stdin), "rb");
+ if (file == NULL) error("can't gzdopen stdin");
+ gz_uncompress(file, stdout);
+ } else {
+ file = gzdopen(fileno(stdout), outmode);
+ if (file == NULL) error("can't gzdopen stdout");
+ gz_compress(stdin, file);
+ }
+ } else {
+ if (copyout) {
+ SET_BINARY_MODE(stdout);
+ }
+ do {
+ if (uncompr) {
+ if (copyout) {
+ file = gzopen(*argv, "rb");
+ if (file == NULL)
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
+ else
+ gz_uncompress(file, stdout);
+ } else {
+ file_uncompress(*argv);
+ }
+ } else {
+ if (copyout) {
+ FILE * in = fopen(*argv, "rb");
+
+ if (in == NULL) {
+ perror(*argv);
+ } else {
+ file = gzdopen(fileno(stdout), outmode);
+ if (file == NULL) error("can't gzdopen stdout");
+
+ gz_compress(in, file);
+ }
+
+ } else {
+ file_compress(*argv, outmode);
+ }
+ }
+ } while (argv++, --argc);
+ }
+ return 0;
+}
diff --git a/lib/zlib/trees.c b/lib/zlib/trees.c
new file mode 100644
index 000000000..8c32b214b
--- /dev/null
+++ b/lib/zlib/trees.c
@@ -0,0 +1,1224 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2012 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local int detect_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (ush)val << s->bi_valid;\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (ush)(value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header,
+ "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int last; /* one if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */
+#ifdef DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+#endif
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
+ */
+void ZLIB_INTERNAL _tr_flush_bits(s)
+ deflate_state *s;
+{
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ */
+void ZLIB_INTERNAL _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int last; /* one if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (s->strm->data_type == Z_UNKNOWN)
+ s->strm->data_type = detect_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, last);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+last, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1)+last, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (last) {
+ bi_windup(s);
+#ifdef DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally (s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+#ifdef TRUNCATE_BLOCK
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+#endif
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ ct_data *ltree; /* literal tree */
+ ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+ "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ * a) There are no non-portable control characters belonging to the
+ * "black list" (0..6, 14..25, 28..31).
+ * b) There is at least one printable character belonging to the
+ * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(s)
+ deflate_state *s;
+{
+ /* black_mask is the bit mask of black-listed bytes
+ * set bits 0..6, 14..25, and 28..31
+ * 0xf3ffc07f = binary 11110011111111111100000001111111
+ */
+ unsigned long black_mask = 0xf3ffc07fUL;
+ int n;
+
+ /* Check for non-textual ("black-listed") bytes. */
+ for (n = 0; n <= 31; n++, black_mask >>= 1)
+ if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ return Z_BINARY;
+
+ /* Check for textual ("white-listed") bytes. */
+ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+ || s->dyn_ltree[13].Freq != 0)
+ return Z_TEXT;
+ for (n = 32; n < LITERALS; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ return Z_TEXT;
+
+ /* There are no "black-listed" or "white-listed" bytes:
+ * this stream either is empty or has tolerated ("gray-listed") bytes only.
+ */
+ return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+ deflate_state *s;
+ charf *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/lib/zlib/trees.h b/lib/zlib/trees.h
new file mode 100644
index 000000000..d35639d82
--- /dev/null
+++ b/lib/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/lib/zlib/uncompr.c b/lib/zlib/uncompr.c
new file mode 100644
index 000000000..ad98be3a5
--- /dev/null
+++ b/lib/zlib/uncompr.c
@@ -0,0 +1,59 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+ return Z_DATA_ERROR;
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/lib/zlib/zconf.h b/lib/zlib/zconf.h
new file mode 100644
index 000000000..8a46a58b3
--- /dev/null
+++ b/lib/zlib/zconf.h
@@ -0,0 +1,506 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2012 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateResetKeep z_inflateResetKeep
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+# if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# define Z_ARG(args) args
+# else
+# define Z_ARG(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+/* ./configure may #define Z_U4 here */
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# else
+# if (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# else
+# if (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+# endif
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include <sys/types.h> /* for off_t */
+# endif
+#endif
+
+#ifdef _WIN32
+# include <stddef.h> /* for wchar_t */
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+# define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H) || defined(LARGEFILE64_SOURCE)
+# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/lib/zlib/zlib.h b/lib/zlib/zlib.h
new file mode 100644
index 000000000..3edf3acdb
--- /dev/null
+++ b/lib/zlib/zlib.h
@@ -0,0 +1,1744 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.7, May 2nd, 2012
+
+ Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.7"
+#define ZLIB_VERNUM 0x1270
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 7
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed data.
+ This version of the library supports only one compression method (deflation)
+ but other algorithms will be added later and will have the same stream
+ interface.
+
+ Compression can be done in a single step if the buffers are large enough,
+ or can be done by repeated calls of the compression function. In the latter
+ case, the application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never crash
+ even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ z_const Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total number of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total number of bytes output so far */
+
+ z_const char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has dropped
+ to zero. It must update next_out and avail_out when avail_out has dropped
+ to zero. The application must initialize zalloc, zfree and opaque before
+ calling the init function. All other fields are set by the compression
+ library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this if
+ the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers
+ returned by zalloc for objects of exactly 65536 bytes *must* have their
+ offset normalized to zero. The default allocation function provided by this
+ library ensures this (see zutil.c). To reduce memory requirements and avoid
+ any allocation of 64K objects, at the expense of compression ratio, compile
+ the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or progress
+ reports. After compression, total_in holds the total size of the
+ uncompressed data and may be saved for use in the decompressor (particularly
+ if the decompressor wants to decompress everything in a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+#define Z_TREES 6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is not
+ compatible with the zlib.h header file used by the application. This check
+ is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+ allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at all
+ (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION
+ requests a default compromise between speed and compression (currently
+ equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if level is not a valid compression level, or
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION). msg is set to null
+ if there is no error message. deflateInit does not perform any compression:
+ this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications). Some
+ output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating avail_in or avail_out accordingly; avail_out should
+ never be zero before the call. The application can consume the compressed
+ output when it wants, for example when the output buffer is full (avail_out
+ == 0), or after each call of deflate(). If deflate returns Z_OK and with
+ zero avail_out, it must be called again after making room in the output
+ buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumulate before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In
+ particular avail_in is zero after the call if enough output space has been
+ provided before the call.) Flushing may degrade compression for some
+ compression algorithms and so it should be used only when necessary. This
+ completes the current deflate block and follows it with an empty stored block
+ that is three bits plus filler bits to the next byte, followed by four bytes
+ (00 00 ff ff).
+
+ If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+ output buffer, but the output is not aligned to a byte boundary. All of the
+ input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+ This completes the current deflate block and follows it with an empty fixed
+ codes block that is 10 bits long. This assures that enough bytes are output
+ in order for the decompressor to finish the block before the empty fixed code
+ block.
+
+ If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+ for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+ seven bits of the current block are held to be written as the next byte after
+ the next deflate block is completed. In this case, the decompressor may not
+ be provided enough bits at this point in order to complete decompression of
+ the data provided so far to the compressor. It may need to wait for the next
+ block to be emitted. This is for advanced applications that need to control
+ the emission of deflate blocks.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there was
+ enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the stream
+ are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least the
+ value returned by deflateBound (see below). Then deflate is guaranteed to
+ return Z_STREAM_END. If not enough output space is provided, deflate will
+ not return Z_STREAM_END, and it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect the
+ compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case, msg
+ may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the
+ exact value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit() does not process any header information -- that is deferred
+ until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing will
+ resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there is
+ no more input data or no more space in the output buffer (see below about
+ the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating the next_* and avail_* values accordingly. The
+ application can consume the uncompressed output when it wants, for example
+ when the output buffer is full (avail_out == 0), or after each call of
+ inflate(). If inflate returns Z_OK and with zero avail_out, it must be
+ called again after making room in the output buffer because there might be
+ more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+ Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate()
+ stop if and when it gets to the next deflate block boundary. When decoding
+ the zlib or gzip format, this will cause inflate() to return immediately
+ after the header and before the first block. When doing a raw inflate,
+ inflate() will go ahead and process the first block, and will return when it
+ gets to the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64 if
+ inflate() is currently decoding the last block in the deflate stream, plus
+ 128 if inflate() returned immediately after decoding an end-of-block code or
+ decoding the complete header up to just before the first byte of the deflate
+ stream. The end-of-block will not be indicated until all of the uncompressed
+ data from that block has been written to strm->next_out. The number of
+ unused bits may in general be greater than seven, except when bit 7 of
+ data_type is set, in which case the number of unused bits will be less than
+ eight. data_type is set as noted here every time inflate() returns for all
+ flush options, and so can be used to determine the amount of currently
+ consumed input in bits.
+
+ The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+ end of each deflate block header is reached, before any actual data in that
+ block is decoded. This allows the caller to determine the length of the
+ deflate block header for later use in random access within a deflate block.
+ 256 is added to the value of strm->data_type when inflate() returns
+ immediately after reaching the end of the deflate block header.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step (a
+ single call of inflate), the parameter flush should be set to Z_FINISH. In
+ this case all pending input is processed and all pending output is flushed;
+ avail_out must be large enough to hold all of the uncompressed data for the
+ operation to complete. (The size of the uncompressed data may have been
+ saved by the compressor for this purpose.) The use of Z_FINISH is not
+ required to perform an inflation in one step. However it may be used to
+ inform inflate that a faster approach can be used for the single inflate()
+ call. Z_FINISH also informs inflate to not maintain a sliding window if the
+ stream completes, which reduces inflate's memory footprint. If the stream
+ does not complete, either because not all of the stream is provided or not
+ enough output space is provided, then a sliding window will be allocated and
+ inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+ been used.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the effects of the flush parameter in this implementation are
+ on the return value of inflate() as noted below, when inflate() returns early
+ when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+ memory for a sliding window when Z_FINISH is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the Adler-32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically, if requested when
+ initializing with inflateInit2(). Any information contained in the gzip
+ header is not retained, so applications that need that information should
+ instead use raw inflate, see inflateInit2() below, or inflateBack() and
+ perform their own processing of the gzip header and trailer. When processing
+ gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+ producted so far. The CRC-32 is checked against the gzip trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may
+ then call inflateSync() to look for a good compression block if a partial
+ recovery of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by the
+ caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero), no
+ header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. The default value is 8. See zconf.h for total memory usage
+ as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
+ fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
+ strategy parameter only affects the compression ratio but not the
+ correctness of the compressed output even if it is not set appropriately.
+ Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+ decoder for special applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+ method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is
+ set to null if there is no error message. deflateInit2 does not perform any
+ compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. When using the zlib format, this
+ function must be called immediately after deflateInit, deflateInit2 or
+ deflateReset, and before any call of deflate. When doing raw deflate, this
+ function must be called either before any call of deflate, or immediately
+ after the completion of a deflate block, i.e. after all input has been
+ consumed and all output has been delivered when using any of the flush
+ options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
+ compressor and decompressor must use exactly the same dictionary (see
+ inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size
+ provided in deflateInit or deflateInit2. Thus the strings most likely to be
+ useful should be put at the end of the dictionary, not at the front. In
+ addition, the current implementation of deflate will use at most the window
+ size minus 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if not at a block boundary for raw deflate). deflateSetDictionary does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and can
+ consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state. The
+ stream will keep the same compression level and any other attributes that
+ may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different strategy.
+ If the compression level is changed, the input available so far is
+ compressed with the old level (and may be flushed); the new level will take
+ effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to be
+ compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+ strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit() or
+ deflateInit2(), and after deflateSetHeader(), if used. This would be used
+ to allocate an output buffer for deflation in a single pass, and so would be
+ called before deflate(). If that first deflate() call is provided the
+ sourceLen input bytes, an output buffer allocated to the size returned by
+ deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+ to return Z_STREAM_END. Note that it is possible for the compressed size to
+ be larger than the value returned by deflateBound() if flush options other
+ than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+ unsigned *pending,
+ int *bits));
+/*
+ deflatePending() returns the number of bytes and bits of output that have
+ been generated, but not yet provided in the available output. The bytes not
+ provided would be due to the available output space having being consumed.
+ The number of bits of output not provided are between 0 and 7, where they
+ await more bits to join them in order to fill out a full byte. If pending
+ or bits are Z_NULL, then those values are not set.
+
+ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the bits
+ leftover from a previous deflate stream when appending to it. As such, this
+ function can only be used for raw deflate, and must be used before the first
+ deflate() call after a deflateInit2() or deflateReset(). bits must be less
+ than or equal to 16, and that many of the least significant bits of value
+ will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+ room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be zero to request that inflate use the window size in
+ the zlib header of the compressed stream.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
+ crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit2 does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit2() does not process any header information -- that is
+ deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called at any
+ time to set the dictionary. If the provided dictionary is smaller than the
+ window and there is already data in the window, then the provided dictionary
+ will amend what's there. The application must insure that the dictionary
+ that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a possible full flush point (see above
+ for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+ All full flush points have this pattern, but not all occurences of this
+ pattern are full flush points.
+
+ inflateSync returns Z_OK if a possible full flush point has been found,
+ Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+ has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+ In the success case, the application may save the current current value of
+ total_in which indicates where valid compressed data was found. In the
+ error case, the application may repeatedly call inflateSync, providing more
+ input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state. The
+ stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+ int windowBits));
+/*
+ This function is the same as inflateReset, but it also permits changing
+ the wrap and window size requests. The windowBits parameter is interpreted
+ the same as it is for inflateInit2.
+
+ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+ the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ If bits is negative, then the input stream bit buffer is emptied. Then
+ inflatePrime() can be called again to put bits in the buffer. This is used
+ to clear out bits leftover after feeding inflate a block description prior
+ to feeding inflate codes.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+ This function returns two values, one in the lower 16 bits of the return
+ value, and the other in the remaining upper bits, obtained by shifting the
+ return value down 16 bits. If the upper value is -1 and the lower value is
+ zero, then inflate() is currently decoding information outside of a block.
+ If the upper value is -1 and the lower value is non-zero, then inflate is in
+ the middle of a stored block, with the lower value equaling the number of
+ bytes from the input remaining to copy. If the upper value is not -1, then
+ it is the number of bits back from the current bit position in the input of
+ the code (literal or length/distance pair) currently being processed. In
+ that case the lower value is the number of bytes already emitted for that
+ code.
+
+ A code is being processed if inflate is waiting for more input to complete
+ decoding of the code, or if it has completed decoding but is waiting for
+ more output space to write the literal or match data.
+
+ inflateMark() is used to mark locations in the input data for random
+ access, which may be at bit positions, and to note those cases where the
+ output of a code may span boundaries of random access blocks. The current
+ location in the input stream can be determined from avail_in and data_type
+ as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+ inflateMark returns the value noted above or -1 << 16 if the provided
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
+ used to force inflate() to return immediately after header processing is
+ complete and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When any
+ of extra, name, or comment are not Z_NULL and the respective field is not
+ present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+ allocated, or Z_VERSION_ERROR if the version of the library does not match
+ the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free the
+ allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects only
+ the raw deflate stream to decompress. This is different from the normal
+ behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+ in the deflate stream (in which case strm->msg is set to indicate the nature
+ of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+ In the case of Z_BUF_ERROR, an input or output error can be distinguished
+ using strm->next_in which will be Z_NULL only if in() returned an error. If
+ strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+ non-zero. (in() will always be called before out(), so strm->next_in is
+ assured to be defined if out() returns non-zero.) Note that inflateBack()
+ cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the basic
+ stream-oriented functions. To simplify the interface, some default options
+ are assumed (compression level and memory usage, standard memory allocation
+ functions). The source code of these utility functions can be modified if
+ you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before a
+ compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit, destLen
+ is the actual size of the uncompressed buffer.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
+ the case where there is not enough room, uncompress() will fill the output
+ buffer with the uncompressed data up to that point.
+*/
+
+ /* gzip file access functions */
+
+/*
+ This library supports reading and writing files in gzip (.gz) format with
+ an interface similar to that of stdio, using the functions that start with
+ "gz". The gzip format is different from the zlib format. gzip is a gzip
+ wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+ Opens a gzip (.gz) file for reading or writing. The mode parameter is as
+ in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+ a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+ compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+ for fixed code compression as in "wb9F". (See the description of
+ deflateInit2 for more information about the strategy parameter.) 'T' will
+ request transparent writing or appending with no compression and not using
+ the gzip format.
+
+ "a" can be used instead of "w" to request that the gzip stream that will
+ be written be appended to the file. "+" will result in an error, since
+ reading and writing to the same gzip file is not supported. The addition of
+ "x" when writing will create the file exclusively, which fails if the file
+ already exists. On systems that support it, the addition of "e" when
+ reading or writing will set the flag to close the file on an execve() call.
+
+ These functions, as well as gzip, will read and decode a sequence of gzip
+ streams in a file. The append function of gzopen() can be used to create
+ such a file. (Also see gzflush() for another way to do this.) When
+ appending, gzopen does not test whether the file begins with a gzip stream,
+ nor does it look for the end of the gzip streams to begin appending. gzopen
+ will simply append a gzip stream to the existing file.
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression. When
+ reading, this will be detected automatically by looking for the magic two-
+ byte gzip header.
+
+ gzopen returns NULL if the file could not be opened, if there was
+ insufficient memory to allocate the gzFile state, or if an invalid mode was
+ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+ errno can be checked to determine if the reason gzopen failed was that the
+ file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen associates a gzFile with the file descriptor fd. File descriptors
+ are obtained from calls like open, dup, creat, pipe or fileno (if the file
+ has been previously opened with fopen). The mode parameter is as in gzopen.
+
+ The next call of gzclose on the returned gzFile will also close the file
+ descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+ fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+ mode);. The duplicated descriptor should be saved to avoid a leak, since
+ gzdopen does not close fd if it fails. If you are using fileno() to get the
+ file descriptor from a FILE *, then you will have to use dup() to avoid
+ double-close()ing the file descriptor. Both gzclose() and fclose() will
+ close the associated file descriptor, so they need to have different file
+ descriptors.
+
+ gzdopen returns NULL if there was insufficient memory to allocate the
+ gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+ provided, or '+' was provided), or if fd is -1. The file descriptor is not
+ used until the next gz* read, write, seek, or close operation, so gzdopen
+ will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+ Set the internal buffer size used by this library's functions. The
+ default buffer size is 8192 bytes. This function must be called after
+ gzopen() or gzdopen(), and before any other calls that read or write the
+ file. The buffer memory allocation is always deferred to the first read or
+ write. Two buffers are allocated, either both of the specified size when
+ writing, or one of the specified size and the other twice that size when
+ reading. A larger buffer size of, for example, 64K or 128K bytes will
+ noticeably increase the speed of decompression (reading).
+
+ The new buffer size also affects the maximum length for gzprintf().
+
+ gzbuffer() returns 0 on success, or -1 on failure, such as being called
+ too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file. If
+ the input file is not in gzip format, gzread copies the given number of
+ bytes into the buffer directly from the file.
+
+ After reaching the end of a gzip stream in the input, gzread will continue
+ to read, looking for another gzip stream. Any number of gzip streams may be
+ concatenated in the input file, and will all be decompressed by gzread().
+ If something other than a gzip stream is encountered after a gzip stream,
+ that remaining trailing garbage is ignored (and no error is returned).
+
+ gzread can be used to read a gzip file that is being concurrently written.
+ Upon reaching the end of the input, gzread will return with the available
+ data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+ gzclearerr can be used to clear the end of file indicator in order to permit
+ gzread to be tried again. Z_OK indicates that a gzip stream was completed
+ on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
+ middle of a gzip stream. Note that gzread does not return -1 in the event
+ of an incomplete gzip stream. This error is deferred until gzclose(), which
+ will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+ stream. Alternatively, gzerror can be used before gzclose to detect this
+ case.
+
+ gzread returns the number of uncompressed bytes actually read, less than
+ len for end of file, or -1 for error.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes written or 0 in case of
+ error.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the arguments to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written, or 0 in case of error. The number of
+ uncompressed bytes written is limited to 8191, or one less than the buffer
+ size given to gzbuffer(). The caller should assure that this limit is not
+ exceeded. If it is exceeded, then gzprintf() will return an error (0) with
+ nothing written. In this case, there may also be a buffer overflow with
+ unpredictable consequences, which is possible only if zlib was compiled with
+ the insecure functions sprintf() or vsprintf() because the secure snprintf()
+ or vsnprintf() functions were not available. This can be determined using
+ zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or a
+ newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. If any characters are read or if len == 1, the
+ string is terminated with a null character. If no characters are read due
+ to an end-of-file or len < 1, then the buffer is left untouched.
+
+ gzgets returns buf which is a null-terminated string, or it returns NULL
+ for end-of-file or in case of error. If there was an error, the contents at
+ buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file. gzputc
+ returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte or -1
+ in case of end of file or error. This is implemented as a macro for speed.
+ As such, it does not do all of the checking the other functions do. I.e.
+ it does not check to see if file is NULL, nor whether the structure file
+ points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read as the first character
+ on the next read. At least one character of push-back is allowed.
+ gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
+ fail if c is -1, and may fail if a character has been pushed but not read
+ yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
+ output buffer size of pushed characters is allowed. (See gzbuffer above.)
+ The pushed character will be discarded if the stream is repositioned with
+ gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter flush
+ is as in the deflate() function. The return value is the zlib error number
+ (see function gzerror below). gzflush is only permitted when writing.
+
+ If the flush parameter is Z_FINISH, the remaining data is written and the
+ gzip stream is completed in the output. If gzwrite() is called again, a new
+ gzip stream will be started in the output. gzread() is able to read such
+ concatented gzip streams.
+
+ gzflush should be called only when strictly necessary because it will
+ degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+
+ Sets the starting position for the next gzread or gzwrite on the given
+ compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+
+ Returns the starting position for the next gzread or gzwrite on the given
+ compressed file. This position represents a number of bytes in the
+ uncompressed data stream, and is zero when starting, even if appending or
+ reading a gzip stream from the middle of a file using gzdopen().
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+ Returns the current offset in the file being read or written. This offset
+ includes the count of bytes that precede the gzip stream, for example when
+ appending or when using gzdopen() for reading. When reading, the offset
+ does not include as yet unused buffered input. This information can be used
+ for a progress indicator. On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns true (1) if the end-of-file indicator has been set while reading,
+ false (0) otherwise. Note that the end-of-file indicator is set only if the
+ read tried to go past the end of the input, but came up short. Therefore,
+ just like feof(), gzeof() may return false even if there is no more data to
+ read, in the event that the last read request was for the exact number of
+ bytes remaining in the input file. This will happen if the input file size
+ is an exact multiple of the buffer size.
+
+ If gzeof() returns true, then the read functions will return no more data,
+ unless the end-of-file indicator is reset by gzclearerr() and the input file
+ has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns true (1) if file is being copied directly while reading, or false
+ (0) if file is a gzip stream being decompressed.
+
+ If the input file is empty, gzdirect() will return true, since the input
+ does not contain a gzip stream.
+
+ If gzdirect() is used immediately after gzopen() or gzdopen() it will
+ cause buffers to be allocated to allow reading the file to determine if it
+ is a gzip file. Therefore if gzbuffer() is used, it should be called before
+ gzdirect().
+
+ When writing, gzdirect() returns true (1) if transparent writing was
+ requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
+ gzdirect() is not needed when writing. Transparent writing must be
+ explicitly requested, so the application already knows the answer. When
+ linking statically, using gzdirect() will include all of the zlib code for
+ gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file and
+ deallocates the (de)compression state. Note that once file is closed, you
+ cannot call gzerror with file, since its structures have been deallocated.
+ gzclose must not be called more than once on the same file, just as free
+ must not be called more than once on the same allocation.
+
+ gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+ file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+ last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+ Same as gzclose(), but gzclose_r() is only for use when reading, and
+ gzclose_w() is only for use when writing or appending. The advantage to
+ using these instead of gzclose() is that they avoid linking in zlib
+ compression or decompression code that is not used when only reading or only
+ writing respectively. If gzclose() is used, then both compression and
+ decompression code will be included the application when linking to a static
+ zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the given
+ compressed file. errnum is set to zlib error number. If an error occurred
+ in the file system and not in the compression library, errnum is set to
+ Z_ERRNO and the application may consult errno to get the exact error code.
+
+ The application must not modify the returned string. Future calls to
+ this function may invalidate the previously returned string. If file is
+ closed, then the string previously returned by gzerror will no longer be
+ available.
+
+ gzerror() should be used to distinguish errors from end-of-file for those
+ functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the compression
+ library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is Z_NULL, this function returns the
+ required initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster.
+
+ Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is Z_NULL, this function returns the required
+ initial value for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure. Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro. The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously. They can
+ * only be used by the gzgetc() macro. You have been warned.
+ */
+struct gzFile_s {
+ unsigned have;
+ unsigned char *next;
+ z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+# define z_gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#else
+# define gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+ ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+# ifdef Z_PREFIX_SET
+# define z_gzopen z_gzopen64
+# define z_gzseek z_gzseek64
+# define z_gztell z_gztell64
+# define z_gzoffset z_gzoffset64
+# define z_adler32_combine z_adler32_combine64
+# define z_crc32_combine z_crc32_combine64
+# else
+# define gzopen gzopen64
+# define gzseek gzseek64
+# define gztell gztell64
+# define gzoffset gzoffset64
+# define adler32_combine adler32_combine64
+# define crc32_combine crc32_combine64
+# endif
+# ifndef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+# endif
+#else
+ ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* hack for buggy compilers */
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;};
+#endif
+
+/* undocumented functions */
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
+ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
+ const char *mode));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/lib/zlib/zutil.c b/lib/zlib/zutil.c
new file mode 100644
index 000000000..65e0d3b72
--- /dev/null
+++ b/lib/zlib/zutil.c
@@ -0,0 +1,324 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+#ifndef Z_SOLO
+# include "gzguts.h"
+#endif
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+ uLong flags;
+
+ flags = 0;
+ switch ((int)(sizeof(uInt))) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch ((int)(sizeof(uLong))) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch ((int)(sizeof(voidpf))) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch ((int)(sizeof(z_off_t))) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef DEBUG
+ flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef DEBUG
+
+# ifndef verbose
+# define verbose 0
+# endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error (m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+ int err;
+{
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifndef Z_SOLO
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/lib/zlib/zutil.h b/lib/zlib/zutil.h
new file mode 100644
index 000000000..4e3dcc6ae
--- /dev/null
+++ b/lib/zlib/zutil.h
@@ -0,0 +1,252 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2012 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#if defined(STDC) && !defined(Z_SOLO)
+# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifdef Z_SOLO
+ typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# ifndef Z_SOLO
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+# if defined(M_I86) && !defined(Z_SOLO)
+# include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# ifndef Z_SOLO
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+# endif
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifdef WIN32
+# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
+# define OS_CODE 0x0b
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# ifndef _PTRDIFF_T_DEFINED
+ typedef int ptrdiff_t;
+# define _PTRDIFF_T_DEFINED
+# endif
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+#if defined(__BORLANDC__) && !defined(MSDOS)
+ #pragma warn -8004
+ #pragma warn -8008
+ #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(pyr) || defined(Z_SOLO)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# include <stdio.h>
+ extern int ZLIB_INTERNAL z_verbose;
+ extern void ZLIB_INTERNAL z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+#ifndef Z_SOLO
+ voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+ unsigned size));
+ void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
+#endif
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+#endif /* ZUTIL_H */